From 3b386516093525c22751d1852a05f5add750fb93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Bra=C3=B1a?= Date: Tue, 11 Mar 2025 21:18:59 +0100 Subject: [PATCH] =?UTF-8?q?primera=20versi=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Utils/PVPlantDownloadOrtophoto.py | 97 +++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 Utils/PVPlantDownloadOrtophoto.py diff --git a/Utils/PVPlantDownloadOrtophoto.py b/Utils/PVPlantDownloadOrtophoto.py new file mode 100644 index 0000000..3f7df9a --- /dev/null +++ b/Utils/PVPlantDownloadOrtophoto.py @@ -0,0 +1,97 @@ +import FreeCAD +import Part +import math +import requests +from io import BytesIO +from PIL import Image +import numpy as np + +# ================================================================== +# CONFIGURACIÓN INICIAL (AJUSTAR ESTOS VALORES) +# ================================================================== +lat_min = 40.4165 # Latitud mínima (Ej: Madrid) +lat_max = 40.4300 +lon_min = -3.7150 # Longitud mínima +lon_max = -3.6900 +zoom = 16 # Nivel de zoom (13-19 para mejor resolución) +terrain_resolution = 50 # Puntos por eje en la malla del terreno + + +# ================================================================== +def download_tile(lon_deg, lat_deg, zoom): + """Descarga un tile de OpenStreetMap""" + xtile = int((lon_deg + 180) / 360 * (2 ** zoom)) + ytile = int((1 - math.log(math.tan(math.radians(lat_deg)) + 1 / math.cos(math.radians(lat_deg))) / math.pi) / 2 * ( + 2 ** zoom)) + + url = f"https://tile.openstreetmap.org/{zoom}/{xtile}/{ytile}.png" + response = requests.get(url) + return Image.open(BytesIO(response.content)) + + +def get_tile_grid(lon_min, lon_max, lat_min, lat_max, zoom): + """Calcula la cuadrícula de tiles necesarios""" + xtile_min = int((lon_min + 180) / 360 * (2 ** zoom)) + xtile_max = int((lon_max + 180) / 360 * (2 ** zoom)) + + ytile_min = int((1 - math.log(math.tan(math.radians(lat_min)) + 1 / math.cos(math.radians(lat_min))) / math.pi) / 2 * (2 ** zoom)) + ytile_max = int((1 - math.log(math.tan(math.radians(lat_max)) + 1 / math.cos(math.radians(lat_max))) / math.pi) / 2 * (2 ** zoom)) + + return range(xtile_min, xtile_max + 1), range(ytile_min, ytile_max + 1) + + +def create_stitched_image(xtiles, ytiles, zoom): + """Une los tiles en una sola imagen""" + tile_size = 256 + full_image = Image.new('RGB', (len(xtiles) * tile_size, len(ytiles) * tile_size)) + + for i, x in enumerate(xtiles): + for j, y in enumerate(ytiles): + tile = download_tile(x, y, zoom) + full_image.paste(tile, (i * tile_size, j * tile_size)) + + return full_image + + +def create_parametric_terrain(lon_min, lon_max, lat_min, lat_max, resolution): + """Crea una superficie paramétrica basada en coordenadas geográficas""" + points = [] + for i in np.linspace(lat_min, lat_max, resolution): + row = [] + for j in np.linspace(lon_min, lon_max, resolution): + row.append(FreeCAD.Vector(j, i, 0)) # Añadir altura aquí si hay datos de elevación + points.append(row) + + terrain = Part.makeFilledFace([points]) + obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Terrain") + obj.Shape = terrain + return obj + + +def apply_texture(obj, image_path): + """Aplica la textura al objeto en FreeCAD""" + obj.ViewObject.TextureMode = "EMBEDDED" + obj.ViewObject.TextureImage = image_path + obj.ViewObject.DisplayMode = "Shaded" + + +# Ejecución principal +'''if __name__ == "__main__": + # Paso 1: Descargar y unir tiles + xtiles, ytiles = get_tile_grid(lon_min, lon_max, lat_min, lat_max, zoom) + stitched_image = create_stitched_image(xtiles, ytiles, zoom) + texture_path = "/tmp/combined_texture.png" + stitched_image.save(texture_path) + + # Paso 2: Crear terreno + doc = FreeCAD.newDocument() + terrain = create_parametric_terrain(lon_min, lon_max, lat_min, lat_max, terrain_resolution) + + # Paso 3: Aplicar textura + apply_texture(terrain, texture_path) + + # Ajustar vista + FreeCAD.Gui.SendMsgToActiveView("ViewFit") + FreeCAD.Gui.updateGui() + +print("¡Proceso completado!")''' \ No newline at end of file