def generate_area_3d_apply_elevation(self, area_2d, area_3d): apply_layer_height = True if area_3d.mesh or area_3d.children: #height = area_2d.extra.get('ddd:height', 0.2) area_elevation = area_2d.extra.get('ddd:area:elevation', 'geotiff') if area_elevation == 'geotiff': area_3d = terrain.terrain_geotiff_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'min': area_3d = terrain.terrain_geotiff_min_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'max': area_3d = terrain.terrain_geotiff_max_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'path': # logger.debug("3D layer transition: %s", way) # if way.extra['ddd:layer_transition']: if ('way_1d' in area_3d.extra): path = area_3d.extra['way_1d'] vertex_func = self.osm.ways1.get_height_apply_func(path) area_3d = area_3d.vertex_func(vertex_func) apply_layer_height = False # ddd:height:base is also not applied, as it is applied during area creation (extruded, to avoid area_3d = terrain.terrain_geotiff_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'water': apply_layer_height = False pass elif area_elevation == 'none': pass else: raise AssertionError() if apply_layer_height: layer = str( area_3d.extra.get('ddd:layer', area_3d.extra.get('osm:layer', 0))) # TODO: This ddd:base_height conflicts with ddd:height:base? base_height = float( area_3d.extra.get('ddd:base_height', self.osm.ways1.layer_height(layer))) area_3d = area_3d.translate([0, 0, base_height]) # Commented as ways were using this but they are extruded to height #base_height = area_2d.get('ddd:height:base', None) #if base_height: # area_3d = area_3d.translate([0, 0, base_height]) return area_3d
def generate_area_3d_apply_elevation(self, area_2d, area_3d): apply_layer_height = True if area_3d.mesh or area_3d.children: #height = area_2d.extra.get('ddd:height', 0.2) area_elevation = area_2d.extra.get('ddd:area:elevation', 'geotiff') if area_elevation == 'geotiff': area_3d = terrain.terrain_geotiff_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'min': area_3d = terrain.terrain_geotiff_min_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'max': area_3d = terrain.terrain_geotiff_max_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'path': # logger.debug("3D layer transition: %s", way) # if way.extra['ddd:layer_transition']: if ('way_1d' in area_3d.extra): path = area_3d.extra['way_1d'] vertex_func = self.osm.ways1.get_height_apply_func(path) area_3d = area_3d.vertex_func(vertex_func) apply_layer_height = False area_3d = terrain.terrain_geotiff_elevation_apply( area_3d, self.osm.ddd_proj) elif area_elevation == 'water': apply_layer_height = False pass elif area_elevation == 'none': pass else: raise AssertionError() if apply_layer_height: layer = str( area_3d.extra.get('ddd:layer', area_3d.extra.get('osm:layer', 0))) base_height = float( area_3d.extra.get('ddd:base_height', self.osm.ways1.layer_height(layer))) area_3d = area_3d.translate([0, 0, base_height]) return area_3d
def osm_model_generate_structures(osm, root, pipeline, logger): """ TODO: Generate structures as a whole, without dealing with individual types, using metadata. """ structures = ddd.group3(name="Structures3") #sidewalks_3d = objsidewalks_2d.extrude(0.3).translate([0, 0, -5]).material(ddd.mats.sidewalk) walls = root.find("/Structures2/Walls") if walls: walls_3d = walls.extrude(5.5).translate([0, 0, -6]).material(ddd.mats.cement) walls_3d = terrain.terrain_geotiff_elevation_apply( walls_3d, osm.ddd_proj) if int(ddd.data.get('ddd:area:subdivide', 0)) > 0: walls_3d = ddd.meshops.subdivide_to_grid( walls_3d, float(ddd.data.get('ddd:area:subdivide'))) walls_3d = ddd.uv.map_cubic(walls_3d) structures.append(walls_3d) ceilings = root.find("/Structures2/Ceilings") if ceilings: ceilings_3d = ceilings.extrude(0.5).translate([0, 0, -1.0]).material( ddd.mats.cement) ceilings_3d = terrain.terrain_geotiff_elevation_apply( ceilings_3d, osm.ddd_proj) if int(ddd.data.get('ddd:area:subdivide', 0)) > 0: ceilings_3d = ddd.meshops.subdivide_to_grid( ceilings_3d, float(ddd.data.get('ddd:area:subdivide'))) ceilings_3d = ddd.uv.map_cubic(ceilings_3d) structures.append(ceilings_3d) #sidewalks_3d = terrain.terrain_geotiff_elevation_apply(sidewalks_3d, self.osm.ddd_proj) #sidewalks_3d = ddd.uv.map_cubic(sidewalks_3d) #floors_3d = floors_2d.extrude(-0.3).translate([0, 0, -5]).material(ddd.mats.sidewalk) #floors_3d = floors_2d.triangulate().translate([0, 0, -5]).material(ddd.mats.sidewalk) #floors_3d = terrain.terrain_geotiff_elevation_apply(floors_3d, osm.ddd_proj) #subway = ddd.group([sidewalks_3d, walls_3d, floors_3d, ceilings_3d], empty=3).translate([0, 0, -0.2]) #self.osm.other_3d.children.append(subway) root.append(structures)
def generate_ways_3d_subways(self): """ Generates boxing for sub ways. """ logger.info("Generating subways.") logger.warn("IMPLEMENT 2D/3D separation for this, as it needs to be cropped, and it's being already cropped earlier") # Take roads ways = [w for w in self.osm.ways_2d["-1a"].children] + [w for w in self.osm.ways_2d["-1"].children] union = self.osm.ways_2d["-1"].union() union_with_transitions = ddd.group(ways, empty="2").union() union_sidewalks = union_with_transitions.buffer(0.6, cap_style=2, join_style=2) sidewalks_2d = union_sidewalks.subtract(union_with_transitions) # we include transitions walls_2d = sidewalks_2d.buffer(0.5, cap_style=2, join_style=2).subtract(union_sidewalks) floors_2d = union_sidewalks.copy() ceilings_2d = union.buffer(0.6, cap_style=2, join_style=2).subtract(self.osm.ways_2d["-1a"]) # FIXME: Move cropping to generic site, use interintermediatemediate osm.something for storage crop = ddd.shape(self.osm.area_crop) sidewalks_2d = sidewalks_2d.intersection(crop) walls_2d = walls_2d.intersection(crop) floors_2d = floors_2d.intersection(crop) ceilings_2d = ceilings_2d.intersection(crop) sidewalks_3d = sidewalks_2d.extrude(0.3).translate([0, 0, -5]).material(ddd.mats.sidewalk) walls_3d = walls_2d.extrude(5).translate([0, 0, -5]).material(ddd.mats.cement) #floors_3d = floors_2d.extrude(-0.3).translate([0, 0, -5]).material(ddd.mats.sidewalk) floors_3d = floors_2d.triangulate().translate([0, 0, -5]).material(ddd.mats.sidewalk) ceilings_3d = ceilings_2d.extrude(0.5).translate([0, 0, -1.0]).material(ddd.mats.cement) sidewalks_3d = terrain.terrain_geotiff_elevation_apply(sidewalks_3d, self.osm.ddd_proj) sidewalks_3d = ddd.uv.map_cubic(sidewalks_3d) walls_3d = terrain.terrain_geotiff_elevation_apply(walls_3d, self.osm.ddd_proj) walls_3d = ddd.uv.map_cubic(walls_3d) floors_3d = terrain.terrain_geotiff_elevation_apply(floors_3d, self.osm.ddd_proj) ceilings_3d = terrain.terrain_geotiff_elevation_apply(ceilings_3d, self.osm.ddd_proj) ceilings_3d = ddd.uv.map_cubic(ceilings_3d) subway = ddd.group([sidewalks_3d, walls_3d, floors_3d, ceilings_3d], empty=3).translate([0, 0, -0.2]) self.osm.other_3d.children.append(subway)
def generate_area_3d_pitch(self, area_2d): if area_2d.geom is None or area_2d.geom.is_empty: return None area_2d_orig = area_2d.extra.get('ddd:crop:original') #, area_2d) #logger.debug("Pitch: %s", area_2d) area_3d = self.generate_area_3d_gen(area_2d) # TODO: pass size then adapt to position and orientation, easier to construct and reuse # TODO: get area uncropped (create a cropping utility that stores the original area) sport_full = area_2d.extra.get('ddd:sport', None) sport = sport_full.split(";")[0] # Get first value if multivalued lines = None if sport == 'tennis': lines = sports.field_lines_area(area_2d_orig, sports.tennis_field_lines, padding=2.5) elif sport == 'basketball': lines = sports.field_lines_area(area_2d_orig, sports.basketball_field_lines, padding=1) elif sport == 'gymnastics': #lines = sports.field_lines_area(area_2d_orig, sports.basketball_field_lines, padding=2.0) lines = ddd.group3() elif sport in ('handball'): lines = sports.field_lines_area(area_2d_orig, sports.handball_field_lines, padding=1) elif sport in ('soccer', 'futsal'): lines = sports.field_lines_area(area_2d_orig, sports.football_field_lines, padding=1) else: # No sport assigned lines = ddd.group3() if lines: lines = terrain.terrain_geotiff_elevation_apply( lines, self.osm.ddd_proj) #.translate([0, 0, 0.01]) height = area_2d.extra.get('ddd:height', 0.0) lines = lines.translate([0, 0, height]) area_3d = ddd.group3([area_3d, lines]) else: logger.debug("No pitch lines generated.") return area_3d
def generate_customs_3d(self): logger.info("Generating 3D custom items (from %d customs_1d)", len(self.osm.customs_1d.children)) for custom_2d in self.osm.customs_1d.children: #if custom_2d.geom.empty: continue custom_3d = self.generate_custom_3d(custom_2d) if custom_3d: custom_3d.name = custom_3d.name if custom_3d.name else custom_2d.name logger.debug("Generated custom item: %s", custom_3d) self.osm.customs_3d.children.append(custom_3d) # FIXME: Do not alter every vertex, move the entire object instead self.osm.customs_3d = terrain.terrain_geotiff_elevation_apply( self.osm.customs_3d, self.osm.ddd_proj)
def osm_model_generate_coastline(osm, root, obj, logger): # Crop this feature as it has not been cropped area_crop = osm.area_crop2 if osm.area_crop2 else osm.area_filter2 coastlines_3d = obj.intersection(area_crop).union().clean() if not coastlines_3d.geom: return coastlines_3d = coastlines_3d.individualize().extrude( 15.0).flip_faces().translate([0, 0, -15.0]) # Subdivide if int(ddd.data.get('ddd:area:subdivide', 0)) > 0: logger.debug("Subdividing coastline meshes: %s", obj) coastlines_3d = ddd.meshops.subdivide_to_grid( coastlines_3d, float(ddd.data.get('ddd:area:subdivide'))) coastlines_3d = terrain.terrain_geotiff_elevation_apply( coastlines_3d, osm.ddd_proj) coastlines_3d = coastlines_3d.material(ddd.mats.rock) coastlines_3d = ddd.uv.map_cubic(coastlines_3d) coastlines_3d.name = 'Coastline: %s' % coastlines_3d.name root.find("/Other3").append(coastlines_3d)
def generate_item_3d(self, item_2d): # TODO! Move to pipeline or at least call from pipeline #if 'osm:feature' in item_2d.extra: # if ("Julio Verne" in item_2d.extra['osm:feature']['properties'].get('name', "")): # print(item_2d) item_3d = None if item_2d.extra.get('osm:amenity', None) == 'fountain': item_3d = self.generate_item_3d_fountain(item_2d) elif item_2d.extra.get( 'osm:amenity', None) == 'bench': # not to be confused with seat item_3d = self.generate_item_3d_bench(item_2d) elif item_2d.extra.get('osm:amenity', None) == 'drinking_water': item_3d = self.generate_item_3d_generic(item_2d, urban.drinking_water, "Drinking water") elif item_2d.extra.get('osm:amenity', None) == 'post_box': #item_3d = self.generate_item_3d_post_box(item_2d) operator = item_2d.extra['osm:feature'].get('operator', None) item_3d = self.generate_item_3d_generic_catalog( "post_box-default-1", item_2d, urban.post_box, "Postbox") item_3d.name = 'Postbox (%s): %s' % (operator, item_2d.name) elif item_2d.extra.get('osm:amenity', None) == 'table': item_3d = self.generate_item_3d_generic(item_2d, urban.patio_table, "Table") elif item_2d.extra.get( 'osm:amenity', None) == 'seat': # not to be confused with bench item_3d = self.generate_item_3d_generic(item_2d, urban.patio_chair, "Seat") elif item_2d.extra.get('osmext:amenity', None) == 'umbrella': item_3d = self.generate_item_3d_generic(item_2d, urban.patio_umbrella, "Umbrella") #elif item_2d.extra.get('osm:amenity', None) == 'taxi': # item_3d = self.generate_item_3d_taxi(item_2d) #elif item_2d.extra.get('osm:amenity', None) == 'toilets': # item_3d = self.generate_item_3d_taxi(item_2d) elif item_2d.extra.get('osm:amenity', None) == 'waste_basket': item_3d = self.generate_item_3d_waste_basket(item_2d) elif item_2d.extra.get('osm:amenity', None) == 'waste_disposal': if random.choice([1, 2]) == 1: item_3d = self.generate_item_3d_generic_catalog( "waste-disposal-1", item_2d, urban.waste_container, "Waste Disposal") else: item_3d = self.generate_item_3d_generic_catalog( "waste-disposal-closed-1", item_2d, urban.waste_container_with_lid_closed, "Waste Disposal (C)") elif item_2d.extra.get('osm:amenity', None) == 'recycling': item_3d = self.generate_item_3d_generic_catalog( "waste-container-dome-1", item_2d, urban.waste_container_dome, "Recycling") elif item_2d.extra.get('osm:amenity', None) == 'bicycle_parking': #item_3d = self.generate_item_3d_waste_disposal(item_2d) item_2d.set('ddd:angle', item_2d.get('ddd:angle') + math.pi / 2) item_3d = self.generate_item_3d_generic_catalog( "bicycle-parking-bar-u", item_2d, common.bar_u, "Bicycle Parking Bar U") elif item_2d.extra.get('osm:emergency', None) == 'fire_hydrant': item_3d = self.generate_item_3d_generic_catalog( "fire_hydrant-default-1", item_2d, urban.fire_hydrant, "Fire Hydrant") elif item_2d.extra.get('osm:natural', None) == 'tree': # TODO: Do decimations in the pipeline (if at all) self.tree_decimate_idx += 1 if self.tree_decimate <= 1 or self.tree_decimate_idx % self.tree_decimate == 0: #item_3d = random.choice(self.pool['tree']).instance() #coords = item_2d.geom.coords[0] #item_3d = item_3d.translate([coords[0], coords[1], 0.0]) item_3d = self.generate_item_3d_tree(item_2d) elif item_2d.extra.get('osm:natural', None) == 'rock' or item_2d.extra.get( 'ddd:item', None) == 'natural_rock': # TODO: Use a generic metadata-based catalog/instnacing key and arguments (and grouping by arguments for instancing) bounds = [ random.uniform(2, 4), random.uniform(1, 3), random.uniform(1, 2) ] variant = random.choice(range(4)) + 1 item_3d = self.generate_item_3d_generic_catalog( "natural-rock-%d" % variant, item_2d, lambda: landscape.rock(bounds), "Rock") item_3d = item_3d.translate([0, 0, random.uniform(-0.5, 0.0)]) elif item_2d.extra.get('osm:natural', None) == 'stone': #item_3d = self.generate_item_3d_generic_catalog("natural-stone-1", item_2d, lambda: landscape.rock([4, 4.5, 4.0]), "Stone") item_3d = self.generate_item_3d_generic( item_2d, lambda: landscape.rock([4, 4.5, 4.0]), "Stone") item_3d = item_3d.translate([0, 0, -random.uniform(0.0, 1.0)]) elif item_2d.extra.get('osm:tourism', None) == 'artwork' and item_2d.extra.get( 'osm:artwork_type', None) == 'sculpture': item_3d = self.generate_item_3d_sculpture(item_2d) elif item_2d.extra.get('osm:tourism', None) == 'artwork' and item_2d.extra.get( 'osm:artwork_type', None) == 'statue': item_3d = self.generate_item_3d_sculpture(item_2d) elif item_2d.extra.get('osm:tourism', None) == 'artwork' and item_2d.extra.get( 'osm:artwork_type', None) == None: item_3d = self.generate_item_3d_sculpture(item_2d) elif item_2d.extra.get('osm:historic', None) == 'monument': # Large monument item_3d = self.generate_item_3d_monument(item_2d) elif item_2d.extra.get('osm:historic', None) == 'memorial': item_3d = self.generate_item_3d_monument(item_2d) elif item_2d.extra.get('osm:historic', None) == 'wayside_cross': item_3d = self.generate_item_3d_wayside_cross(item_2d) elif item_2d.extra.get('osm:historic', None) == 'archaeological_site': item_3d = self.generate_item_3d_historic_archaeological_site( item_2d) elif item_2d.extra.get('osm:man_made', None) == 'crane': item_3d = self.generate_item_3d_crane(item_2d) elif item_2d.extra.get('osm:man_made', None) == 'lighthouse': item_3d = self.generate_item_3d_lighthouse(item_2d) elif item_2d.extra.get('osm:man_made', None) == 'tower' and item_2d.extra.get( 'osm:tower:type', None) == 'communication': item_3d = self.generate_item_3d_man_made_tower_communication( item_2d) elif item_2d.extra.get('osm:highway', None) == 'bus_stop': item_3d = self.generate_item_3d_bus_stop(item_2d) elif item_2d.extra.get('osm:power', None) == 'tower': item_3d = self.generate_item_3d_powertower(item_2d) elif item_2d.extra.get('osm:power', None) == 'pole': item_3d = self.generate_item_3d_powerpole(item_2d) elif item_2d.extra.get('osm:power', None) == 'catenary_mast': logger.warn( "Using temporary object: powerpole (for catenary_mast)") item_3d = self.generate_item_3d_powerpole(item_2d) elif item_2d.extra.get('osm:barrier', None) == 'fence': item_3d = self.generate_item_3d_fence(item_2d) elif item_2d.extra.get('osm:barrier', None) == 'hedge': item_3d = self.generate_item_3d_hedge(item_2d) elif item_2d.extra.get('osm:barrier', None) == 'bollard': item_3d = self.generate_item_3d_generic(item_2d, urban.bollard, "Bollard") #elif item_2d.extra.get('osm:leisure', None) == 'playground': elif item_2d.extra.get('osm:playground', None) == 'swing': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_swingset, "Playground Swings") elif item_2d.extra.get('osm:playground', None) == 'sandbox': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_sandbox, "Playground Sandbox") elif item_2d.extra.get('osm:playground', None) == 'slide': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_slide, "Playground Slide") elif item_2d.extra.get('osm:playground', None) == 'monkey_bar': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_arc, "Playground Monkey Bar Arc") elif item_2d.extra.get('osm:power', None) in ('line', 'minor_line'): # TODO: Tilt objects using a generic tilting mechanism (also, this one may be also based on terrain gradient) item_3d = self.generate_item_3d_powerline(item_2d) elif item_2d.extra.get('osm:golf', None) == 'hole': # TODO: Tilt objects using a generic tilting mechanism (also, this one may be also based on terrain gradient) item_3d = self.generate_item_3d_generic(item_2d, sports.golf_flag, "Golf Flag") elif item_2d.extra.get('osm:highway', None) == 'street_lamp' and item_2d.get( 'osm:lamp_mount', None) == 'high_mast': item_3d = self.generate_item_3d_street_lamp_high_mast(item_2d) elif item_2d.extra.get('osm:highway', None) == 'street_lamp': item_3d = self.generate_item_3d_street_lamp(item_2d) elif item_2d.extra.get('osm:highway', None) == 'traffic_signals': item_3d = self.generate_item_3d_traffic_signals(item_2d) elif item_2d.extra.get('osm:traffic_sign', None) is not None or any( [k.startswith('osm:traffic_sign:') for k in item_2d.extra.keys()]): item_3d = self.generate_item_3d_traffic_sign(item_2d) elif item_2d.extra.get('ddd:road_marking', None): item_3d = self.generate_item_3d_road_marking(item_2d) elif item_2d.get('ddd:item', None) == 'grass_blade': item_3d = self.generate_item_3d_grass_blade(item_2d) elif item_2d.get('ddd:item', None) == 'flowers': item_3d = self.generate_item_3d_flowers(item_2d) elif item_2d.get('ddd:ladder', None) == 'swimming_pool': item_3d = self.generate_item_3d_generic(item_2d, landscape.ladder_pool, "Swimming Pool Ladder") else: logger.debug("Unknown item: %s", item_2d.extra) # TODO: Apply height via tags, similar approach to areas if item_3d: # Copy item_2d attributes # TODO: shall this be guaranteed by the generators? for k, v in item_2d.extra.items(): item_3d.set(k, default=v, children=True) #data = dict(item_2d.extra) #data.update(item_3d.extra) #item_3d.extra = data # Apply height # TODO: Rename this property to either ddd:item... or to a common mechanism for areas, items... height_mapping = item_3d.get( 'ddd:item:elevation', item_3d.get('_height_mapping', 'terrain_geotiff_min_elevation_apply')) if height_mapping == 'terrain_geotiff_elevation_apply': item_3d = terrain.terrain_geotiff_elevation_apply( item_3d, self.osm.ddd_proj) elif height_mapping == 'terrain_geotiff_incline_elevation_apply': item_3d = terrain.terrain_geotiff_min_elevation_apply( item_3d, self.osm.ddd_proj) elif height_mapping == 'terrain_geotiff_and_path_apply': path = item_3d.extra['way_1d'] vertex_func = self.osm.ways.get_height_apply_func(path) item_3d = item_3d.vertex_func(vertex_func) item_3d = terrain.terrain_geotiff_min_elevation_apply( item_3d, self.osm.ddd_proj) elif height_mapping == 'none': # building... pass elif height_mapping == 'building': # building... pass else: item_3d = terrain.terrain_geotiff_min_elevation_apply( item_3d, self.osm.ddd_proj) # Apply base height base_height = item_2d.get('ddd:height:base', None) if base_height: item_3d = item_3d.translate([0, 0, base_height]) return item_3d
def generate_ways_3d_elevated(self): logger.info("Generating elevated ways.") logger.warn( "IMPLEMENT 2D/3D separation for this, as it needs to be cropped") elevated = [] # Walk roads ways = ([w for w in self.osm.ways_2d["1"].children] + [w for w in self.osm.ways_2d["0a"].children] + [w for w in self.osm.ways_2d["-1a"].children]) # ways_union = ddd.group(ways).union() sidewalk_width = 0.4 elevated_union = DDDObject2() for way in ways: # way_longer = way.buffer(0.3, cap_style=1, join_style=2) if 'intersection' in way.extra: continue way_with_sidewalk_2d = way.buffer(sidewalk_width, cap_style=2, join_style=2) #way_with_sidewalk_2d_extended = osmops.extend_way(way).buffer(sidewalk_width, cap_style=2, join_style=2) sidewalk_2d = way_with_sidewalk_2d.subtract(way).material( ddd.mats.sidewalk) wall_2d = way_with_sidewalk_2d.buffer( 0.25, cap_style=2, join_style=2).subtract(way_with_sidewalk_2d).buffer( 0.001, cap_style=2, join_style=2).material(ddd.mats.cement) floor_2d = way_with_sidewalk_2d.buffer( 0.3, cap_style=2, join_style=2).buffer(0.001, cap_style=2, join_style=2).material(ddd.mats.cement) sidewalk_2d.extra['way_2d'] = way wall_2d.extra['way_2d'] = way floor_2d.extra['way_2d'] = way # Get connected ways connected = self.osm.ways1.follow_way(way.extra['way_1d'], 1) connected_2d = ddd.group( [self.osm.ways2.get_way_2d(c) for c in connected]) if 'intersection_start_2d' in way.extra['way_1d'].extra: connected_2d.append( way.extra['way_1d'].extra['intersection_start_2d']) if 'intersection_end_2d' in way.extra['way_1d'].extra: connected_2d.append( way.extra['way_1d'].extra['intersection_end_2d']) # print(connected) sidewalk_2d = sidewalk_2d.subtract(connected_2d).buffer(0.001) wall_2d = wall_2d.subtract(connected_2d.buffer(sidewalk_width)) # TODO: Subtract floors from connected or resolve intersections wall_2d = wall_2d.subtract(elevated_union) # FIXME: Move cropping to generic site, use itermediate osm.something for storage crop = ddd.shape(self.osm.area_crop) sidewalk_2d = sidewalk_2d.intersection( crop.buffer(-0.003)).clean(eps=0.01) wall_2d = wall_2d.intersection(crop.buffer(-0.003)).clean(eps=0.01) floor_2d = floor_2d.intersection( crop.buffer(-0.003)).clean(eps=0.01) #FIXME: TODO: this shal be done earlier, before generating the path #if way.extra.get('ddd:way:elevated:material', None): # way.extra['way_2d'].material(way.extra.get('ddd:way:elevated:material')) # ddd.group((sidewalk_2d, wall_2d)).show() if way.extra.get('ddd:way:elevated:border', None) == 'fence': fence_2d = wall_2d.outline().clean() fence_2d = fence_2d.material(ddd.mats.fence) #fence_2d.dump() #wall_2d.show() fence_2d.extra['ddd:item'] = True fence_2d.extra['ddd:item:height'] = 1.2 fence_2d.extra['ddd:height'] = 1.2 fence_2d.extra['barrier'] = "fence" fence_2d.extra[ '_height_mapping'] = "terrain_geotiff_and_path_apply" fence_2d.extra['way_1d'] = way.extra['way_1d'] self.osm.items_1d.append(fence_2d) elevated.append((sidewalk_2d, None, floor_2d)) else: elevated.append((sidewalk_2d, wall_2d, floor_2d)) elevated_union = elevated_union.union( ddd.group([sidewalk_2d, wall_2d, floor_2d])) # Bridge piers path = way.extra['way_1d'] if path.geom.length > 15.0: # and path.extra['ddd:bridge:posts']: # Generate posts interval = 35.0 length = path.geom.length numposts = int(length / interval) idx = 0 logger.debug("Piers for bridge (length=%s, num=%d, way=%s)", length, numposts, way) for d in numpy.linspace(0.0, length, numposts, endpoint=False): if d == 0.0: continue # Calculate left and right perpendicular intersections with sidewalk, park, land... p, segment_idx, segment_coords_a, segment_coords_b = path.interpolate_segment( d) # FIXME: Use items and crop in a generic way (same for subways) (so ignore below in common etc) if not self.osm.area_crop.contains(ddd.point(p).geom): continue dir_vec = (segment_coords_b[0] - segment_coords_a[0], segment_coords_b[1] - segment_coords_a[1]) dir_vec_length = math.sqrt(dir_vec[0]**2 + dir_vec[1]**2) dir_vec = (dir_vec[0] / dir_vec_length, dir_vec[1] / dir_vec_length) angle = math.atan2(dir_vec[1], dir_vec[0]) idx = idx + 1 if len(p) < 3: logger.error( "Bridge path with less than 3 components when building bridge piers." ) continue if p[2] > 1.0: # If no height, no pilar, but should be a margin and also corrected by base_height item = ddd.rect([ -way.extra['ddd:way:width'] * 0.3, -0.5, way.extra['ddd:way:width'] * 0.3, 0.5 ], name="Bridge Post %s" % way.name) item = item.extrude(-(math.fabs(p[2]) - 0.5)).material( ddd.mats.cement) item = ddd.uv.map_cubic(item) item = item.rotate([0, 0, angle - math.pi / 2 ]).translate([p[0], p[1], 0]) vertex_func = self.get_height_apply_func(path) item = item.vertex_func(vertex_func) item = terrain.terrain_geotiff_elevation_apply( item, self.osm.ddd_proj) item = item.translate([0, 0, -0.8]) item.extra['way_2d'] = way item.extra['ddd:bridge:post'] = True self.osm.other_3d.children.append(item) elevated_3d = [] for item in elevated: sidewalk_2d, wall_2d, floor_2d = item sidewalk_3d = sidewalk_2d.extrude(0.2).translate([0, 0, -0.2]) wall_3d = wall_2d.extrude(0.6) if wall_2d else None floor_3d = floor_2d.extrude(-0.5).translate([0, 0, -0.2]) # extra_height = way_2d.extra['extra_height'] # way_3d = way_2d.extrude(-0.2 - extra_height).translate([0, 0, extra_height]) # + layer_height sidewalk_3d = ddd.uv.map_cubic(sidewalk_3d) wall_3d = ddd.uv.map_cubic(wall_3d) if wall_3d else None floor_3d = ddd.uv.map_cubic(floor_3d) elevated_3d.append(sidewalk_3d) elevated_3d.append(floor_3d) if wall_3d: elevated_3d.append(wall_3d) # Raise items to their way height position nitems = [] for item in elevated_3d: # print(item.extra) path = item.extra['way_1d'] vertex_func = self.osm.ways1.get_height_apply_func(path) nitem = item.vertex_func(vertex_func) nitems.append(nitem) result = ddd.group(nitems, empty=3) result = terrain.terrain_geotiff_elevation_apply( result, self.osm.ddd_proj) self.osm.other_3d.children.append(result)
def generate_area_3d_underwater(self, area_2d): logger.info("Generating underwater for: %s", area_2d) #area_2d.dump() areas_2d = area_2d.individualize().flatten().clean() #area_2d.show() result = ddd.group3() for area_2d in areas_2d.children: area_2d = area_2d.clean() try: area_2d.validate() except DDDException as e: logger.error( "Could not generate underwater area (invalid area %s): %s", area_2d, e) continue if area_2d.geom.type == "LineString": logger.error( "Could not generate underwater area (area is line): %s", area_2d) continue try: area_3d = area_2d.extrude_step( area_2d.buffer(-1.0), -0.3, base=False, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-2.0), -0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-4.0), -1.0, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-6.0), -0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-9.0), -0.4, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-12.0), -0.3, method=ddd.EXTRUSION_METHOD_SUBTRACT) except Exception as e: logger.warn( "Exception extruding underwater area (reduced LinearRings need caring): %s", e) print(area_2d.geom) print(area_2d.buffer(-1.0).geom) area_3d = None if area_3d is None or area_3d.extra['_extrusion_steps'] < 3: logger.debug( "Could not extrude underwater area softly. Extruding abruptly." ) area_3d = area_2d.extrude_step( area_2d.buffer(-0.05), -1.0, base=False, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-0.15), -0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-0.3), -0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT) area_3d = area_3d.extrude_step( area_2d.buffer(-1.0), -0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT) if area_3d.extra['_extrusion_steps'] < 1: logger.warn("Could not extrude underwater area: %s", area_3d) area_3d = area_3d.translate([0, 0, -1.0]) if area_3d: result.append(area_3d) result = terrain.terrain_geotiff_elevation_apply( result, self.osm.ddd_proj) #result.show() return result
def generate_item_3d(self, item_2d): # TODO! Move to pipeline or at least call from pipeline #if 'osm:feature' in item_2d.extra: # if ("Julio Verne" in item_2d.extra['osm:feature']['properties'].get('name', "")): # print(item_2d) item_3d = None if item_2d.extra.get('osm:amenity', None) == 'fountain': item_3d = self.generate_item_3d_fountain(item_2d) elif item_2d.extra.get( 'osm:amenity', None) == 'bench': # not to be confused with seat item_3d = self.generate_item_3d_bench(item_2d) elif item_2d.extra.get('osm:amenity', None) == 'drinking_water': item_3d = self.generate_item_3d_generic(item_2d, urban.drinking_water, "Drinking water") elif item_2d.extra.get('osm:amenity', None) == 'post_box': item_3d = self.generate_item_3d_post_box(item_2d) elif item_2d.extra.get('osm:amenity', None) == 'table': item_3d = self.generate_item_3d_generic(item_2d, urban.patio_table, "Table") elif item_2d.extra.get( 'osm:amenity', None) == 'seat': # not to be confused with bench item_3d = self.generate_item_3d_generic(item_2d, urban.patio_chair, "Seat") elif item_2d.extra.get('osmext:amenity', None) == 'umbrella': item_3d = self.generate_item_3d_generic(item_2d, urban.patio_umbrella, "Umbrella") #elif item_2d.extra.get('osm:amenity', None) == 'taxi': # item_3d = self.generate_item_3d_taxi(item_2d) #elif item_2d.extra.get('osm:amenity', None) == 'toilets': # item_3d = self.generate_item_3d_taxi(item_2d) elif item_2d.extra.get('osm:amenity', None) == 'waste_basket': item_3d = self.generate_item_3d_waste_basket(item_2d) #elif item_2d.extra.get('osm:amenity', None) == 'waste_disposal': # item_3d = self.generate_item_3d_waste_disposal(item_2d) #elif item_2d.extra.get('osm:amenity', None) == 'recycling': # item_3d = self.generate_item_3d_waste_disposal(item_2d) #elif item_2d.extra.get('osm:amenity', None) == 'bicycle_parking': # item_3d = self.generate_item_3d_waste_disposal(item_2d) elif item_2d.extra.get('osm:emergency', None) == 'fire_hydrant': item_3d = self.generate_item_3d_generic(item_2d, urban.fire_hydrant, "Fire Hydrant") #elif item_2d.extra.get('osm:natural', None) == 'coastline': # item_3d = self.generate_item_3d_coastline(item_2d) elif item_2d.extra.get('osm:natural', None) == 'tree': self.tree_decimate_idx += 1 if self.tree_decimate <= 1 or self.tree_decimate_idx % self.tree_decimate == 0: #item_3d = random.choice(self.pool['tree']).instance() #coords = item_2d.geom.coords[0] #item_3d = item_3d.translate([coords[0], coords[1], 0.0]) item_3d = self.generate_item_3d_tree(item_2d) elif item_2d.extra.get('osm:tourism', None) == 'artwork' and item_2d.extra.get( 'osm:artwork_type', None) == 'sculpture': item_3d = self.generate_item_3d_sculpture(item_2d) elif item_2d.extra.get('osm:tourism', None) == 'artwork' and item_2d.extra.get( 'osm:artwork_type', None) == 'statue': item_3d = self.generate_item_3d_sculpture(item_2d) elif item_2d.extra.get('osm:historic', None) == 'monument': # Large monument item_3d = self.generate_item_3d_monument(item_2d) elif item_2d.extra.get('osm:historic', None) == 'memorial': item_3d = self.generate_item_3d_monument(item_2d) elif item_2d.extra.get('osm:historic', None) == 'wayside_cross': item_3d = self.generate_item_3d_wayside_cross(item_2d) elif item_2d.extra.get('osm:man_made', None) == 'lighthouse': item_3d = self.generate_item_3d_lighthouse(item_2d) elif item_2d.extra.get('osm:man_made', None) == 'crane': item_3d = self.generate_item_3d_crane(item_2d) elif item_2d.extra.get('osm:highway', None) == 'bus_stop': item_3d = self.generate_item_3d_bus_stop(item_2d) elif item_2d.extra.get('osm:power', None) == 'tower': item_3d = self.generate_item_3d_powertower(item_2d) elif item_2d.extra.get('osm:power', None) == 'pole': item_3d = self.generate_item_3d_powerpole(item_2d) elif item_2d.extra.get('osm:barrier', None) == 'fence': item_3d = self.generate_item_3d_fence(item_2d) elif item_2d.extra.get('osm:barrier', None) == 'hedge': item_3d = self.generate_item_3d_hedge(item_2d) elif item_2d.extra.get('osm:barrier', None) == 'bollard': item_3d = self.generate_item_3d_generic(item_2d, urban.bollard, "Bollard") #elif item_2d.extra.get('osm:leisure', None) == 'playground': elif item_2d.extra.get('osm:playground', None) == 'swing': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_swingset, "Playground Swings") elif item_2d.extra.get('osm:playground', None) == 'sandbox': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_sandbox, "Playground Sandbox") elif item_2d.extra.get('osm:playground', None) == 'slide': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_slide, "Playground Slide") elif item_2d.extra.get('osm:playground', None) == 'monkey_bar': item_3d = self.generate_item_3d_generic( item_2d, urban.childrens_playground_arc, "Playground Monkey Bar Arc") elif item_2d.extra.get('osm:highway', None) == 'street_lamp': item_3d = self.generate_item_3d_street_lamp(item_2d) elif item_2d.extra.get('osm:highway', None) == 'traffic_signals': item_3d = self.generate_item_3d_traffic_signals(item_2d) elif item_2d.extra.get('osm:traffic_sign', None) is not None or any( [k.startswith('osm:traffic_sign:') for k in item_2d.extra.keys()]): item_3d = self.generate_item_3d_traffic_sign(item_2d) elif item_2d.get('ddd:item', None) == 'grass_blade': item_3d = self.generate_item_3d_grass_blade(item_2d) elif item_2d.get('ddd:item', None) == 'flowers': item_3d = self.generate_item_3d_flowers(item_2d) else: logger.debug("Unknown item: %s", item_2d.extra) # TODO: Apply height via tags, similar approach to areas if item_3d: # Apply height height_mapping = item_3d.extra.get( '_height_mapping', 'terrain_geotiff_min_elevation_apply') if height_mapping == 'terrain_geotiff_elevation_apply': item_3d = terrain.terrain_geotiff_elevation_apply( item_3d, self.osm.ddd_proj) elif height_mapping == 'terrain_geotiff_incline_elevation_apply': item_3d = terrain.terrain_geotiff_min_elevation_apply( item_3d, self.osm.ddd_proj) elif height_mapping == 'terrain_geotiff_and_path_apply': path = item_3d.extra['way_1d'] vertex_func = self.osm.ways.get_height_apply_func(path) item_3d = item_3d.vertex_func(vertex_func) item_3d = terrain.terrain_geotiff_min_elevation_apply( item_3d, self.osm.ddd_proj) elif height_mapping == 'none': # building... pass elif height_mapping == 'building': # building... pass else: item_3d = terrain.terrain_geotiff_min_elevation_apply( item_3d, self.osm.ddd_proj) # Apply base height base_height = item_2d.get('ddd:height:base', None) if base_height: item_3d = item_3d.translate([0, 0, base_height]) # Copy item_2d attributes for k, v in item_2d.extra.items(): item_3d.set(k, default=v, children=True) #data = dict(item_2d.extra) #data.update(item_3d.extra) #item_3d.extra = data return item_3d
def osm_model_elevation_apply_terrain(obj, osm, root): obj = terrain.terrain_geotiff_elevation_apply(obj, osm.ddd_proj) return obj