update
This commit is contained in:
@@ -9,6 +9,7 @@ import urllib.request
|
||||
import math
|
||||
import utm
|
||||
from collections import defaultdict
|
||||
import PVPlantImportGrid as ImportElevation
|
||||
|
||||
scale = 1000.0
|
||||
|
||||
@@ -42,8 +43,10 @@ class OSMImporter:
|
||||
self.ssl_context = ssl.create_default_context(cafile=certifi.where())
|
||||
|
||||
def transform_from_latlon(self, lat, lon):
|
||||
x, y, _, _ = utm.from_latlon(lat, lon)
|
||||
return FreeCAD.Vector(x, y, .0) * scale - self.Origin
|
||||
point = ImportElevation.getElevationFromOE([[lat, lon], ])
|
||||
return FreeCAD.Vector(point[0].x, point[0].y, point[0].z) * scale - self.Origin
|
||||
'''x, y, _, _ = utm.from_latlon(lat, lon)
|
||||
return FreeCAD.Vector(x, y, .0) * scale - self.Origin'''
|
||||
|
||||
def get_osm_data(self, bbox):
|
||||
query = f"""
|
||||
@@ -148,7 +151,6 @@ class OSMImporter:
|
||||
polyline.addProperty("App::PropertyFloat", "Width", "Metadata", "Ancho de la vía").Width = width
|
||||
layer.addObject(polyline)
|
||||
|
||||
|
||||
def create_railway(self, nodes, layer, name=""):
|
||||
points = [n for n in nodes]
|
||||
rail_line = Draft.make_wire(points, closed=False, face=False)
|
||||
@@ -737,27 +739,163 @@ class OSMImporter:
|
||||
def create_vegetation(self):
|
||||
vegetation_layer = self.create_layer("Vegetation")
|
||||
|
||||
# Árboles individuales
|
||||
for node_id, coords in self.nodes.items():
|
||||
# Verificar si es un árbol
|
||||
# (Necesitarías procesar los tags de los nodos, implementación simplificada)
|
||||
cylinder = Part.makeCylinder(0.5, 5.0, FreeCAD.Vector(coords[0], coords[1], 0))# * scale - self.Origin )
|
||||
tree = FreeCAD.ActiveDocument.addObject("Part::Feature", "Tree")
|
||||
vegetation_layer.addObject(tree)
|
||||
tree.Shape = cylinder
|
||||
tree.ViewObject.ShapeColor = self.feature_colors['vegetation']
|
||||
# Procesar nodos de vegetación individual
|
||||
for way_id, tags in self.ways_data.items():
|
||||
coords = self.nodes.get(way_id)
|
||||
if not coords:
|
||||
continue
|
||||
|
||||
# Áreas verdes
|
||||
pos = FreeCAD.Vector(*coords)
|
||||
|
||||
if tags.get('natural') == 'tree':
|
||||
self.create_tree(pos, tags, vegetation_layer)
|
||||
elif tags.get('natural') == 'shrub':
|
||||
self.create_shrub(pos, tags, vegetation_layer)
|
||||
"""elif tags.get('natural') == 'tree_stump':
|
||||
self.create_tree_stump(pos, vegetation_layer)"""
|
||||
|
||||
# Procesar áreas vegetales
|
||||
for way_id, data in self.ways_data.items():
|
||||
if 'natural' in data['tags'] or 'landuse' in data['tags']:
|
||||
nodes = [self.nodes[ref] for ref in data['nodes'] if ref in self.nodes]
|
||||
if len(nodes) > 2:
|
||||
polygon_points = [n for n in nodes]
|
||||
polygon = Part.makePolygon(polygon_points)
|
||||
face = Part.Face(polygon)
|
||||
area = vegetation_layer.addObject("Part::Feature", "GreenArea")
|
||||
area.Shape = face
|
||||
area.ViewObject.ShapeColor = self.feature_colors['vegetation']
|
||||
tags = data['tags']
|
||||
nodes = [self.nodes[ref] for ref in data['nodes'] if ref in self.nodes]
|
||||
|
||||
if not nodes or len(nodes) < 3:
|
||||
continue
|
||||
|
||||
if tags.get('natural') == 'wood' or tags.get('landuse') == 'forest':
|
||||
self.create_forest(nodes, tags, vegetation_layer)
|
||||
elif tags.get('natural') == 'grassland':
|
||||
self.create_grassland(nodes, vegetation_layer)
|
||||
elif tags.get('natural') == 'heath':
|
||||
self.create_heathland(nodes, vegetation_layer)
|
||||
elif tags.get('natural') == 'scrub':
|
||||
self.create_scrub_area(nodes, vegetation_layer)
|
||||
|
||||
def create_tree(self, position, tags, layer):
|
||||
"""Crea un árbol individual con propiedades basadas en etiquetas OSM"""
|
||||
height = float(tags.get('height', 10.0))
|
||||
trunk_radius = float(tags.get('circumference', 1.0)) / (2 * math.pi)
|
||||
canopy_radius = float(tags.get('diameter_crown', 4.0)) / 2
|
||||
|
||||
# Crear tronco
|
||||
trunk = Part.makeCylinder(trunk_radius, height, position)
|
||||
|
||||
# Crear copa (forma cónica)
|
||||
canopy_center = position + FreeCAD.Vector(0, 0, height)
|
||||
canopy = Part.makeCone(canopy_radius, canopy_radius * 0.7, canopy_radius * 1.5, canopy_center)
|
||||
|
||||
tree = trunk.fuse(canopy)
|
||||
tree_obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Tree")
|
||||
layer.addObject(tree_obj)
|
||||
tree_obj.Shape = tree
|
||||
tree_obj.ViewObject.ShapeColor = (0.3, 0.6, 0.2) # Verde bosque
|
||||
|
||||
# Añadir metadatos
|
||||
for prop in ['genus', 'species', 'leaf_type', 'height']:
|
||||
if prop in tags:
|
||||
tree_obj.addProperty("App::PropertyString", prop.capitalize(), "Botany",
|
||||
"Botanical property").__setattr__(prop.capitalize(), tags[prop])
|
||||
|
||||
def create_forest(self, nodes, tags, layer):
|
||||
"""Crea un área boscosa con densidad variable"""
|
||||
polygon_points = [FreeCAD.Vector(*n) for n in nodes]
|
||||
if polygon_points[0] != polygon_points[-1]:
|
||||
polygon_points.append(polygon_points[0])
|
||||
|
||||
# Crear base del bosque
|
||||
polygon = Part.makePolygon(polygon_points)
|
||||
face = Part.Face(polygon)
|
||||
forest_base = FreeCAD.ActiveDocument.addObject("Part::Feature", "Forest_Base")
|
||||
layer.addObject(forest_base)
|
||||
forest_base.Shape = face
|
||||
forest_base.ViewObject.ShapeColor = (0.15, 0.4, 0.1) # Verde oscuro
|
||||
|
||||
# Generar árboles aleatorios dentro del polígono
|
||||
density = float(tags.get('density', 0.5)) # Árboles por m²
|
||||
area = face.Area
|
||||
num_trees = int(area * density)
|
||||
|
||||
for _ in range(num_trees):
|
||||
rand_point = self.random_point_in_polygon(polygon_points)
|
||||
self.create_tree(rand_point, {}, layer)
|
||||
|
||||
def create_grassland(self, nodes, layer):
|
||||
"""Crea un área de pastizales"""
|
||||
polygon_points = [FreeCAD.Vector(*n) for n in nodes]
|
||||
if polygon_points[0] != polygon_points[-1]:
|
||||
polygon_points.append(polygon_points[0])
|
||||
|
||||
polygon = Part.makePolygon(polygon_points)
|
||||
face = Part.Face(polygon)
|
||||
grassland = FreeCAD.ActiveDocument.addObject("Part::Feature", "Grassland")
|
||||
layer.addObject(grassland)
|
||||
grassland.Shape = face.extrude(FreeCAD.Vector(0, 0, 0.1))
|
||||
grassland.ViewObject.ShapeColor = (0.5, 0.7, 0.3) # Verde pasto
|
||||
|
||||
def create_heathland(self, nodes, layer):
|
||||
"""Crea un área de brezales con vegetación baja"""
|
||||
polygon_points = [FreeCAD.Vector(*n) for n in nodes]
|
||||
if polygon_points[0] != polygon_points[-1]:
|
||||
polygon_points.append(polygon_points[0])
|
||||
|
||||
polygon = Part.makePolygon(polygon_points)
|
||||
face = Part.Face(polygon)
|
||||
heath = FreeCAD.ActiveDocument.addObject("Part::Feature", "Heathland")
|
||||
layer.addObject(heath)
|
||||
heath.Shape = face
|
||||
heath.ViewObject.ShapeColor = (0.6, 0.5, 0.4) # Color terroso
|
||||
|
||||
# Añadir arbustos dispersos
|
||||
for _ in range(int(face.Area * 0.1)): # 1 arbusto cada 10m²
|
||||
rand_point = self.random_point_in_polygon(polygon_points)
|
||||
self.create_shrub(rand_point, {}, layer)
|
||||
|
||||
def create_shrub(self, position, tags, layer):
|
||||
"""Crea un arbusto individual"""
|
||||
height = float(tags.get('height', 1.5))
|
||||
radius = float(tags.get('diameter_crown', 1.0)) / 2
|
||||
|
||||
# Crear forma de arbusto (cono invertido)
|
||||
base_center = position + FreeCAD.Vector(0, 0, height / 2)
|
||||
shrub = Part.makeCone(radius, radius * 1.5, height, base_center)
|
||||
|
||||
shrub_obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Shrub")
|
||||
layer.addObject(shrub_obj)
|
||||
shrub_obj.Shape = shrub
|
||||
shrub_obj.ViewObject.ShapeColor = (0.4, 0.5, 0.3) # Verde arbusto
|
||||
|
||||
# Añadir metadatos si existen
|
||||
if 'genus' in tags:
|
||||
shrub_obj.addProperty("App::PropertyString", "Genus", "Botany", "Plant genus").Genus = tags['genus']
|
||||
|
||||
def create_tree_stump(self, position, layer):
|
||||
"""Crea un tocón de árbol"""
|
||||
height = 0.4
|
||||
radius = 0.5
|
||||
|
||||
stump = Part.makeCylinder(radius, height, position)
|
||||
stump_obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Tree_Stump")
|
||||
layer.addObject(stump_obj)
|
||||
stump_obj.Shape = stump
|
||||
stump_obj.ViewObject.ShapeColor = (0.3, 0.2, 0.1) # Marrón madera
|
||||
|
||||
def random_point_in_polygon(self, polygon_points):
|
||||
"""Genera un punto aleatorio dentro de un polígono"""
|
||||
min_x = min(p.x for p in polygon_points)
|
||||
max_x = max(p.x for p in polygon_points)
|
||||
min_y = min(p.y for p in polygon_points)
|
||||
max_y = max(p.y for p in polygon_points)
|
||||
|
||||
while True:
|
||||
rand_x = random.uniform(min_x, max_x)
|
||||
rand_y = random.uniform(min_y, max_y)
|
||||
rand_point = FreeCAD.Vector(rand_x, rand_y, 0)
|
||||
|
||||
# Verificar si el punto está dentro del polígono
|
||||
polygon = Part.makePolygon(polygon_points)
|
||||
face = Part.Face(polygon)
|
||||
if face.isInside(rand_point, 0.1, True):
|
||||
return rand_point
|
||||
|
||||
def create_water_bodies(self):
|
||||
water_layer = self.create_layer("Water")
|
||||
@@ -769,7 +907,8 @@ class OSMImporter:
|
||||
polygon_points = [n for n in nodes]
|
||||
polygon = Part.makePolygon(polygon_points)
|
||||
face = Part.Face(polygon)
|
||||
water = water_layer.addObject("Part::Feature", "WaterBody")
|
||||
water = FreeCAD.ActiveDocument.addObject("Part::Feature", "WaterBody")
|
||||
water_layer.addObject(water)
|
||||
water.Shape = face.extrude(FreeCAD.Vector(0, 0, 0.1))# * scale - self.Origin )
|
||||
water.ViewObject.ShapeColor = self.feature_colors['water']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user