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!")'''