def calc_solid(face_footprint, range_floors, flr2flr_height, config): # 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) if config.general.debug: # visualize building progress while debugging face_list = fetch.topo_explorer(bldg_solid, "face") edges = calculate.face_normal_as_edges(face_list, 5) utility.visualise([face_list, edges], ["WHITE", "BLACK"]) return bldg_solid
] walls_s = [ val for sublist in geometry_3D_surroundings for val in sublist['walls'] ] windows_s = [ val for sublist in geometry_3D_surroundings for val in sublist['windows'] ] roof_s = [ val for sublist in geometry_3D_surroundings for val in sublist['roofs'] ] geometry_buildings_nonop.extend(windows) geometry_buildings_nonop.extend(windows_s) geometry_buildings.extend(walls) geometry_buildings.extend(roofs) geometry_buildings.extend(footprint) geometry_buildings.extend(walls_s) geometry_buildings.extend(roof_s) normals_terrain = calculate.face_normal_as_edges(geometry_terrain, 5) utility.visualise([ geometry_terrain, geometry_buildings, geometry_buildings_nonop, walls_intercept ], ["GREEN", "WHITE", "BLUE", "RED"]) # install Wxpython utility.visualise([walls_intercept], ["RED"]) utility.visualise([walls], ["RED"]) utility.visualise([windows], ["RED"])
def building2d23d(locator, geometry_terrain, config, height_col, nfloor_col): """ :param locator: InputLocator - provides paths to files in a scenario :type locator: cea.inputlocator.InputLocator :param config: the configuration object to use :type config: cea.config.Configuration :param height_col: name of the columns storing the height of buildings :param nfloor_col: name ofthe column storing the number of floors in buildings. :return: """ # settings: parameters that configure the level of simplification of geometry settings = config.radiation_daysim consider_windows = True #legacy from config file. now it is always true district_shp_path = locator.get_district_geometry() # path to zone geometry database zone_shp_path = locator.get_zone_geometry() # path to database of architecture properties architecture_dbf_path = locator.get_building_architecture() # read district shapefile and names of buildings of the district and the zone of analysis district_building_records = gdf.from_file(district_shp_path) zone_building_records = gdf.from_file(zone_shp_path) zone_building_names = zone_building_records['Name'].values #calculate district geometry (These are the surroundings of the zone oif interest and we simplify it to speet up computations) #first make sure that the district file does not contain buildings in the zone, if it does then erase them district_building_records = district_building_records.loc[ ~district_building_records["Name"].isin(zone_building_names)] district_building_records.reset_index(inplace=True, drop=True) #now append to the district building records, those of the zone district_building_records = district_building_records.append( zone_building_records, ignore_index=True) district_building_records.set_index('Name', inplace=True) district_building_names = district_building_records.index.values # Read architecture properties architecture_wwr = gdf.from_file(architecture_dbf_path).set_index('Name') #make shell out of tin_occface_list and create OCC object terrain_shell = construct.make_shell(geometry_terrain) terrain_intersection_curves = IntCurvesFace_ShapeIntersector() terrain_intersection_curves.Load(terrain_shell, 1e-6) #empty list where to store the closed geometries geometry_3D_zone = [] geometry_3D_surroundings = [] for name in district_building_names: print('Generating geometry for building %(name)s' % locals()) height = float(district_building_records.loc[name, height_col]) nfloors = int(district_building_records.loc[name, nfloor_col]) # simplify geometry tol =1 for buildings of interest, tol = 5 for surroundings if (name in zone_building_names) and settings.consider_floors: range_floors = range(nfloors + 1) flr2flr_height = height / nfloors geometry = district_building_records.ix[name].geometry.simplify( settings.zone_geometry, preserve_topology=True) else: range_floors = [0, 1] flr2flr_height = height geometry = district_building_records.ix[name].geometry.simplify( settings.surrounding_geometry, preserve_topology=True) # burn buildings footprint into the terrain and return the location of the new face print('burning building ', name) face_footprint = burn_buildings(geometry, terrain_intersection_curves) # create floors and form a solid building_solid = calc_solid(face_footprint, range_floors, flr2flr_height, config) # now get all surfaces and create windows only if the buildings are in the area of study window_list = [] wall_list = [] orientation = [] orientation_win = [] normals_w = [] normals_win = [] if (name in zone_building_names): if (consider_windows): # identify building surfaces according to angle: face_list = py3dmodel.fetch.faces_frm_solid(building_solid) facade_list_north, facade_list_west, \ facade_list_east, facade_list_south, roof_list, footprint_list = identify_surfaces_type(face_list) # get window properties wwr_west = architecture_wwr.ix[name, "wwr_west"] wwr_east = architecture_wwr.ix[name, "wwr_east"] wwr_north = architecture_wwr.ix[name, "wwr_north"] wwr_south = architecture_wwr.ix[name, "wwr_south"] window_west, wall_west, normals_windows, normals_walls = calc_windows_walls( facade_list_west, wwr_west) if len(window_west) != 0: window_list.extend(window_west) orientation_win.extend(['west'] * len(window_west)) normals_win.extend(normals_windows) wall_list.extend(wall_west) orientation.extend(['west'] * len(wall_west)) normals_w.extend(normals_walls) window_east, wall_east, normals_windows, normals_walls = calc_windows_walls( facade_list_east, wwr_east) if len(window_east) != 0: window_list.extend(window_east) orientation_win.extend(['east'] * len(window_east)) normals_win.extend(normals_windows) wall_list.extend(wall_east) orientation.extend(['east'] * len(wall_east)) normals_w.extend(normals_walls) window_north, wall_north, normals_windows_north, normals_walls_north = calc_windows_walls( facade_list_north, wwr_north) if len(window_north) != 0: window_list.extend(window_north) orientation_win.extend(['north'] * len(window_north)) normals_win.extend(normals_windows_north) wall_list.extend(wall_north) orientation.extend(['north'] * len(wall_north)) normals_w.extend(normals_walls_north) window_south, wall_south, normals_windows_south, normals_walls_south = calc_windows_walls( facade_list_south, wwr_south) if len(window_south) != 0: window_list.extend(window_south) orientation_win.extend(['south'] * len(window_south)) normals_win.extend(normals_windows_south) wall_list.extend(wall_south) orientation.extend(['south'] * len(wall_south)) normals_w.extend(normals_walls_south) geometry_3D_zone.append({ "name": name, "windows": window_list, "walls": wall_list, "roofs": roof_list, "footprint": footprint_list, "orientation_walls": orientation, "orientation_windows": orientation_win, "normals_windows": normals_win, "normals_walls": normals_w }) else: facade_list, roof_list, footprint_list = gml3dmodel.identify_building_surfaces( building_solid) wall_list = facade_list geometry_3D_zone.append({ "name": name, "windows": window_list, "walls": wall_list, "roofs": roof_list, "footprint": footprint_list, "orientation_walls": orientation, "orientation_windows": orientation_win, "normals_windows": normals_win, "normals_walls": normals_w }) if config.general.debug: # visualize building progress while debugging edges1 = calculate.face_normal_as_edges(wall_list, 5) edges2 = calculate.face_normal_as_edges(roof_list, 5) edges3 = calculate.face_normal_as_edges(footprint_list, 5) utility.visualise([ wall_list, roof_list, footprint_list, edges1, edges2, edges3 ], ["WHITE", "WHITE", "WHITE", "BLACK", "BLACK", "BLACK"]) else: facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces( building_solid) wall_list = facade_list geometry_3D_surroundings.append({ "name": name, "windows": window_list, "walls": wall_list, "roofs": roof_list, "footprint": footprint_list, "orientation_walls": orientation, "orientation_windows": orientation_win, "normals_windows": normals_win, "normals_walls": normals_w }) if config.general.debug: # visualize building progress while debugging edges1 = calculate.face_normal_as_edges(wall_list, 5) edges2 = calculate.face_normal_as_edges(roof_list, 5) edges3 = calculate.face_normal_as_edges(footprint_list, 5) utility.visualise([ wall_list, roof_list, footprint_list, edges1, edges2, edges3 ], ["WHITE", "WHITE", "WHITE", "BLACK", "BLACK", "BLACK"]) return geometry_3D_zone, geometry_3D_surroundings