def daebldglist2gmlbuildings(daebldg_shelllist, citygml_writer): bldg_cnt = 0 for building in daebldg_shelllist: bldg_lod = "lod1" bldg_name = "building" + str(bldg_cnt) bldg_str_abv_grd = "30" bfacelist = py3dmodel.fetch.topo_explorer(building, "face") footprint, roof = get_footprint_roof(building) bldg_geometry_list = gml3dmodel.write_gml_srf_member(bfacelist) heightpt1 = py3dmodel.calculate.face_midpt(footprint) heightpt2 = py3dmodel.calculate.face_midpt(roof) height = py3dmodel.calculate.distance_between_2_pts( heightpt1, heightpt2) bldg_height = height citygml_writer.add_building(bldg_lod, bldg_name, bldg_geometry_list, height=str(bldg_height), stry_abv_grd=str(bldg_str_abv_grd)) bldg_cnt += 1
def building_2d_to_3d(citygml_writer, zone_shp_path, district_shp_path, tin_occface_list, height_col, nfloor_col): """ This script extrudes buildings from the shapefile and creates intermediate floors. :param citygml_writer: the cityGML object to which the buildings are gonna be created. :param district_shp_path: path to the shapefile to be extruded of the district :param tin_occface_list: the faces of the terrain, to be used to put the buildings on top. :param height_col: :param nfloor_col: :return: """ # read district shapefile and names of buildings of the zone of analysis district_building_records = gdf.from_file(district_shp_path).set_index( 'Name') district_building_names = district_building_records.index.values zone_building_names = gdf.from_file(zone_shp_path)['Name'].values #make shell out of tin_occface_list and create OCC object terrain_shell = construct.sew_faces(tin_occface_list)[0] terrain_intersection_curves = IntCurvesFace_ShapeIntersector() terrain_intersection_curves.Load(terrain_shell, 1e-6) bsolid_list = [] #create the buildings in 3D for name in district_building_names: height = float(district_building_records.loc[name, height_col]) nfloors = int(district_building_records.loc[name, nfloor_col]) # Make floors only for the buildings of the zone of interest # for the rest just consider one high floor. # simplify geometry tol =1 for buildings of interest, tol = 5 for surroundings if name in zone_building_names: range_floors = range(nfloors + 1) floor_to_floor_height = height / nfloors geometry = district_building_records.ix[name].geometry.simplify( 1, preserve_topology=True) else: range_floors = [0, 1] floor_to_floor_height = height geometry = district_building_records.ix[name].geometry.simplify( 5, preserve_topology=True) point_list_2D = list(geometry.exterior.coords) point_list_3D = [(a, b, 0) for (a, b) in point_list_2D] # add 0 elevation #creating floor surface in pythonocc face = construct.make_polygon(point_list_3D) #get the midpt of the face face_midpt = calculate.face_midpt(face) #project the face_midpt to the terrain and get the elevation inter_pt, inter_face = calc_intersection(terrain_intersection_curves, face_midpt, (0, 0, 1)) loc_pt = (inter_pt.X(), inter_pt.Y(), inter_pt.Z()) #reconstruct the footprint with the elevation face = fetch.topo2topotype(modify.move(face_midpt, loc_pt, face)) moved_face_list = [] for floor_counter in range_floors: dist2mve = floor_counter * floor_to_floor_height #get midpt of face orig_pt = calculate.face_midpt(face) #move the pt 1 level up dest_pt = modify.move_pt(orig_pt, (0, 0, 1), dist2mve) moved_face = modify.move(orig_pt, dest_pt, face) moved_face_list.append(moved_face) #loft all the faces and form a solid vertical_shell = construct.make_loft(moved_face_list) vertical_face_list = fetch.topo_explorer(vertical_shell, "face") roof = moved_face_list[-1] footprint = moved_face_list[0] all_faces = [] all_faces.append(footprint) all_faces.extend(vertical_face_list) all_faces.append(roof) bldg_shell_list = construct.sew_faces(all_faces) # make sure all the normals are correct (they are pointing out) if bldg_shell_list: bldg_solid = construct.make_solid(bldg_shell_list[0]) bldg_solid = modify.fix_close_solid(bldg_solid) bsolid_list.append(bldg_solid) occface_list = fetch.topo_explorer(bldg_solid, "face") geometry_list = gml3dmodel.write_gml_srf_member(occface_list) citygml_writer.add_building("lod1", name, geometry_list) return bsolid_list
def convert_ptshpfile(field_name_list, shapeRecs, citygml): name_index = field_name_list.index("name") - 1 station_index = field_name_list.index("station") - 1 highway_index = field_name_list.index("highway") - 1 trpst_bldg_list = [] for rec in shapeRecs: poly_attribs = rec.record highway = poly_attribs[highway_index] highway.strip() station = poly_attribs[station_index] station.strip() name = poly_attribs[name_index] name.strip() if highway == "bus_stop": if name.isspace(): name = "bus_stop" + str(uuid.uuid1()) generic_attrib_dict = {"highway": highway} #transform to the location of the bus stop bus_stop_box = py3dmodel.construct.make_box(5, 2, 3) shp_pts = rec.shape.points for pt in shp_pts: pt3d = shp2citygml.pypt2d_2_3d(pt, 0.0) stopbox = shp2citygml.create_transit_stop_geometry( bus_stop_box, pt3d) face_list = py3dmodel.fetch.faces_frm_solid(stopbox) #get the surfaces from the solid geometry_list = gml3dmodel.write_gml_srf_member(face_list) citygml.add_cityfurniture("lod1", name, geometry_list, furn_class="1000", function="1110", generic_attrib_dict=generic_attrib_dict) if not station.isspace(): if name.isspace(): name = station + str(uuid.uuid1()) generic_attrib_dict = {"station": station} #create a bus stop geometry based on the point station_height = 8 station_storey = 2 storey_blw_grd = 0 #transform to the location of the bus stop transit_station_box = py3dmodel.construct.make_box(5, 20, 3) shp_pts = rec.shape.points for pt in shp_pts: pt3d = shp2citygml.pypt2d_2_3d(pt, 0.0) stationbox = shp2citygml.create_transit_stop_geometry( transit_station_box, pt3d) face_list = py3dmodel.fetch.faces_frm_solid(stationbox) #get the surfaces from the solid geometry_list = gml3dmodel.write_gml_srf_member(face_list) trpst_bldg_list.append(name) citygml.add_building("lod1", name, geometry_list, bldg_class="1170", function="2480", usage="2480", rooftype="1000", height=str(station_height), stry_abv_grd=str(station_storey), stry_blw_grd=str(storey_blw_grd), generic_attrib_dict=generic_attrib_dict) return trpst_bldg_list
def convert_apolygon_origlvl(rec, landuse_index, building_index, name_index, plot_ratio_index, count_shapes, citygml, building_list): poly_attribs = rec.record landuse = poly_attribs[landuse_index] landuse.strip() building = poly_attribs[building_index] building.strip() name = poly_attribs[name_index] name.strip() total_build_up = 0 constr_buildings = [] blevel_list = [] #print "CONDITIONS:", building, landuse #======================================================================================================= #if the polygon has no building attrib and has no landuse attribute it is a boundary #======================================================================================================= if building == "" and landuse == "": pypolygon_list2d = shp2citygml.get_geometry(rec) if pypolygon_list2d: pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d( pypolygon_list2d, 0.0) occface_list = py3dmodel.construct.make_occfaces_frm_pypolygons( pypolygon_list3d) occface_list2 = [] for occface in occface_list: pyptlist = py3dmodel.fetch.points_frm_occface(occface) is_anticlockwise = py3dmodel.calculate.is_anticlockwise( pyptlist, (0, 0, 1)) if is_anticlockwise: r_face = py3dmodel.modify.reverse_face(occface) #nrml = py3dmodel.calculate.face_normal(r_face) occface_list2.append(r_face) else: occface_list2.append(occface) geometry_list = gml3dmodel.write_gml_triangle(occface_list2) citygml.add_tin_relief("lod1", "terrain", geometry_list) #======================================================================================================= #if the polygon has no building attrib and has a landuse attribute it is a landuse #======================================================================================================= if building == "" and landuse != "": #the geometry is stored in parts and points pypolygon_list2d = shp2citygml.get_geometry(rec) if pypolygon_list2d: pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d( pypolygon_list2d, 0.0) occface_list = py3dmodel.construct.make_occfaces_frm_pypolygons( pypolygon_list3d) geometry_list = gml3dmodel.write_gml_srf_member(occface_list) if name.isspace(): name = "plot" + str(count_shapes) function = shp2citygml.map_osm2citygml_landuse_function(landuse) generic_attrib_dict = {"landuse": landuse} plot_ratio = poly_attribs[plot_ratio_index] if plot_ratio != None: generic_attrib_dict["plot_ratio"] = plot_ratio plot_area = shp2citygml.get_plot_area(rec) generic_attrib_dict["plot_area"] = plot_area citygml.add_landuse("lod1", name, geometry_list, function=function, generic_attrib_dict=generic_attrib_dict) #======================================================================================================= #find the buildings that belong to this plot #======================================================================================================= buildings_on_plot_list = shp2citygml.buildings_on_plot( rec, building_list) in_construction = False #check if any of the buildings are under construction for cbuilding in buildings_on_plot_list: if cbuilding["building"] == "construction": in_construction = True constr_buildings.append(cbuilding) if not in_construction: #then separate the buildings that are parkings and usable floor area parking_list = [] not_parking_list = list(buildings_on_plot_list) for building in buildings_on_plot_list: if "amenity" in building: if building["amenity"] == "parking" or building[ "amenity"] == "carpark": parking_list.append(building) not_parking_list.remove(building) #then measure the total building footprint on this plot build_footprint = 0 for not_parking in not_parking_list: bgeom_list = not_parking["geometry"] for bgeom in bgeom_list: build_footprint = build_footprint + py3dmodel.calculate.face_area( bgeom) #then measure the total parking footprint on this plot multi_parking_footprint = 0 for parking in parking_list: bgeom_list = parking["geometry"] for bgeom in bgeom_list: multi_parking_footprint = multi_parking_footprint + py3dmodel.calculate.face_area( bgeom) #base on the footprints calculate how many storeys are the buildings if build_footprint != 0: residential_height = 3 commercial_height = 4 if plot_ratio != None: total_build_up = total_build_up + (plot_area * plot_ratio) num_storeys = int( round(total_build_up / build_footprint)) if landuse == "residential": height = num_storeys * residential_height if multi_parking_footprint != 0: #base on the parking footprint estimate how high the multistorey carpark should be total_parking_area = shp2citygml.calc_residential_parking_area( total_build_up) parking_storeys = int( round(total_parking_area / multi_parking_footprint)) parking_storey_height = 2.5 parking_height = parking_storey_height * parking_storeys #write the carparks as buildings for parking in parking_list: if "building_l" in parking: blevel_list.append(parking) parking_storeys = parking["building_l"] parking_height = parking_storey_height * parking_storeys shp2citygml.building2citygml( parking, parking_height, citygml, landuse, parking_storeys) else: shp2citygml.building2citygml( parking, parking_height, citygml, landuse, parking_storeys, ) #TODO: calculate for commercial buildings in terms of parking space too else: height = num_storeys * commercial_height for not_parking in not_parking_list: if "building_l" in not_parking: blevel_list.append(not_parking) num_storeys = not_parking["building_l"] if landuse == "residential": height = residential_height * num_storeys else: height = commercial_height * num_storeys shp2citygml.building2citygml( not_parking, height, citygml, landuse, num_storeys) else: shp2citygml.building2citygml( not_parking, height, citygml, landuse, num_storeys) #================================================================================================================ #for those plots without plot ratio and might be educational or civic buildings #================================================================================================================ else: if landuse == "transport" or landuse == "recreation_ground" or landuse == "civic" or landuse == "place_of_worship" or landuse == "utility" or landuse == "health": num_storeys = 2 elif landuse == "education" or landuse == "commercial": num_storeys = 4 elif landuse == "residential": num_storeys = 10 elif landuse == "reserve": num_storeys = 1 else: num_storeys = 1 for not_parking in not_parking_list: if "building_l" in not_parking: blevel_list.append(not_parking) num_storeys = not_parking["building_l"] height = commercial_height * num_storeys shp2citygml.building2citygml( not_parking, height, citygml, landuse, num_storeys) else: height = num_storeys * commercial_height shp2citygml.building2citygml( not_parking, height, citygml, landuse, num_storeys) return total_build_up, constr_buildings, blevel_list