def calc_solid(face_footprint, range_floors, flr2flr_height): # create faces for every floor and extrude the solid moved_face_list = [] for floor_counter in range_floors: dist2mve = floor_counter * flr2flr_height # get midpt of face orig_pt = calculate.face_midpt(face_footprint) # 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_footprint) moved_face_list.append(moved_face) # make checks to satisfy a closed geometry also called a shell 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) building_shell_list = construct.sew_faces(all_faces) # make sure all the normals are correct (they are pointing out) bldg_solid = construct.make_solid(building_shell_list[0]) bldg_solid = modify.fix_close_solid(bldg_solid) ##dO this to visualize progress while debugging!: #face_list = fetch.geom_explorer(bldg_solid, "face") # edges = calculate.visualise_face_normal_as_edges(face_list,5) # construct.visualise([face_list,edges],["WHITE","BLACK"]) return bldg_solid
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