def calc_building_geometry_surroundings(name, building_solid): facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces(building_solid) geometry_3D_surroundings = {"name": name, "windows": [], "walls": facade_list, "roofs": roof_list, "footprint": footprint_list, "orientation_walls": [], "orientation_windows": [], "normals_windows": [], "normals_walls": [], "intersect_windows": [], "intersect_walls": []} return geometry_3D_surroundings
def calc_building_geometry_surroundings(name, building_solid, geometry_pickle_dir): facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces( building_solid) geometry_3D_surroundings = { "name": name, "windows": [], "walls": facade_list, "roofs": roof_list, "footprint": footprint_list, "orientation_walls": [], "orientation_windows": [], "normals_windows": [], "normals_walls": [], "intersect_walls": [] } building_geometry = BuildingGeometry(**geometry_3D_surroundings) building_geometry.save( os.path.join(geometry_pickle_dir, 'surroundings', str(name))) return name
moved_pt2 = py3dmodel.modify.move_pt(midpt, (0, 0, 1), 7) occface3 = py3dmodel.modify.move(midpt, moved_pt2, occface) scaled_occface3 = py3dmodel.modify.uniform_scale(occface3, 0.5, 0.5, 1, moved_pt2) loft = py3dmodel.construct.make_loft( [occface, scaled_occface2, scaled_occface3]) occface_list = py3dmodel.fetch.topo_explorer(loft, "face") occface_list.append(occface) occface_list.append(scaled_occface3) shell_list = py3dmodel.construct.sew_faces(occface_list) fixed_occshell = py3dmodel.modify.fix_shell_orientation(shell_list[0]) occsolid = py3dmodel.construct.make_solid(fixed_occshell) occsolid = py3dmodel.modify.fix_close_solid(occsolid) facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces( occsolid) win_occface_list = [] wall_occface_list = [] shade_occface_list = [] for facade in facade_list: fmidpt = py3dmodel.calculate.face_midpt(facade) fnrml = py3dmodel.calculate.face_normal(facade) fnrml = (round(fnrml[0], 2), round(fnrml[1], 2), round(fnrml[2], 2)) win_occface = py3dmodel.fetch.topo2topotype( py3dmodel.modify.uniform_scale(facade, 0.1, 0.1, 0.1, fmidpt)) wall_occface = py3dmodel.construct.boolean_difference(facade, win_occface) tri_wall_occface_list = py3dmodel.construct.simple_mesh(wall_occface) new_tri_wall_occface_list = [] for tri_face in tri_wall_occface_list:
def generate_design_variant(ftprint_pt1, ftprint_pt2, ftprint_pt3, ftprint_pt4, courtyard_size, wwr, shade_strategy): #constraints npts_grid_edge = 5 #procedure #first generate the grid grid_occface = py3dmodel.construct.make_rectangle(80, 60) occedge_list = py3dmodel.fetch.topo_explorer(grid_occface, "edge") edge_pt_list = [] pts_grid_edge_list = [ftprint_pt1, ftprint_pt2, ftprint_pt3, ftprint_pt4] #subdivide the edge into equal distance points edge_cnt = 0 for occedge in occedge_list: lbound, ubound = py3dmodel.fetch.edge_domain(occedge) domain_range = ubound - lbound interval = domain_range / float(npts_grid_edge - 1) i = pts_grid_edge_list[edge_cnt] u = lbound + (i * interval) edge_pt = py3dmodel.calculate.edgeparameter2pt(u, occedge) edge_pt_list.append(edge_pt) edge_cnt += 1 ftprint = py3dmodel.construct.make_polygon(edge_pt_list) ftprint = py3dmodel.modify.reverse_face(ftprint) #generate the courtyard ftprint_midpt = find_footprint_midpt(ftprint) courtyard = py3dmodel.modify.uniform_scale(ftprint, courtyard_size, courtyard_size, courtyard_size, ftprint_midpt) #fullfill the floor area requirement, far of 3.5 flr_area_requirement = 16800 ftprint_area = py3dmodel.calculate.face_area(ftprint) flr_area = ftprint_area flr2flr_height = 4.0 wall_list = [] flr_list = [] roof_list = [] win_list = [] bldg_shade_list = [] fcnt = 0 while flr_area < flr_area_requirement: loc_pt = py3dmodel.modify.move_pt(ftprint_midpt, (0, 0, 1), flr2flr_height * fcnt) nxt_flr = py3dmodel.modify.move(ftprint_midpt, loc_pt, ftprint) nxt_flr = py3dmodel.fetch.topo2topotype(nxt_flr) nxt_courtyard = py3dmodel.modify.move(ftprint_midpt, loc_pt, courtyard) nxt_courtyard = py3dmodel.fetch.topo2topotype(nxt_courtyard) flr_courtyard = py3dmodel.construct.boolean_difference( nxt_flr, nxt_courtyard) flr_courtyard = py3dmodel.fetch.topo_explorer(flr_courtyard, "face")[0] flr_list.append(flr_courtyard) extruded_flr = py3dmodel.construct.extrude(nxt_flr, (0, 0, 1), flr2flr_height) external_wall_list, up_list, down_list = urbangeom.identify_building_surfaces( extruded_flr) extruded_courtyard = py3dmodel.construct.extrude( nxt_courtyard, (0, 0, 1), flr2flr_height) courtyard_wall_list, up_list, down_list = urbangeom.identify_building_surfaces( extruded_courtyard) for external_wall in external_wall_list: ew_midpt = py3dmodel.calculate.face_midpt(external_wall) external_win = py3dmodel.modify.uniform_scale( external_wall, 0.98, 0.98, wwr / 0.98, ew_midpt) external_win = py3dmodel.fetch.topo2topotype(external_win) win_list.append(external_win) tri_external_wall = triangulate_wall_with_hole( external_wall, external_win) wall_list.extend(tri_external_wall) #create the shade if shade_strategy != 0: shade_list = create_win_shades(external_win) bldg_shade_list.extend(shade_list) for courtyard_wall in courtyard_wall_list: courtyard_wall = py3dmodel.modify.reverse_face(courtyard_wall) cw_midpt = py3dmodel.calculate.face_midpt(courtyard_wall) courtyard_win = py3dmodel.modify.uniform_scale( courtyard_wall, 0.98, 0.98, wwr / 0.98, cw_midpt) courtyard_win = py3dmodel.fetch.topo2topotype(courtyard_win) win_list.append(courtyard_win) tri_courtyard_wall = triangulate_wall_with_hole( courtyard_wall, courtyard_win) wall_list.extend(tri_courtyard_wall) #create the shade if shade_strategy == 2: shade_list = create_win_shades(courtyard_win) bldg_shade_list.extend(shade_list) if fcnt != 0: nxt_flr_area = py3dmodel.calculate.face_area(flr_courtyard) flr_area = flr_area + nxt_flr_area fcnt += 1 nflrs = len(flr_list) loc_pt = py3dmodel.modify.move_pt(ftprint_midpt, (0, 0, 1), nflrs * flr2flr_height) roof = py3dmodel.modify.move(ftprint_midpt, loc_pt, flr_list[0]) roof = py3dmodel.fetch.topo2topotype(roof) #roof = py3dmodel.modify.reverse_face(roof) roof_list.append(roof) return wall_list, flr_list, roof_list, win_list, bldg_shade_list
def create_win_shades(win): nrml = py3dmodel.calculate.face_normal(win) shade_extrude = py3dmodel.construct.extrude(win, nrml, 1) vert_list, shade_list, down_list = urbangeom.identify_building_surfaces( shade_extrude) return shade_list
def building2d23d(locator, geometry_terrain, settings, height_col, nfloor_col): """ :param locator: InputLocator - provides paths to files in a scenario :type locator: cea.inputlocator.InputLocator :param settings: parameters that configure the level of simplification of geometry :type settings: cea.config.Section :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: """ 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 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 = locator.get_zone_building_names() 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 face_footprint = burn_buildings(geometry, terrain_intersection_curves) # create floors and form a solid building_solid = calc_solid(face_footprint, range_floors, flr2flr_height) # 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}) # DO this to visualize progress while debugging!: # edges1 = calculate.visualise_face_normal_as_edges(wall_list,5) # edges2 = calculate.visualise_face_normal_as_edges(roof_list, 5) # edges3 = calculate.visualise_face_normal_as_edges(footprint_list, 5) # construct.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}) ## DO this to visualize progress while debugging!: # edges1 = calculate.visualise_face_normal_as_edges(wall_list,5) # edges2 = calculate.visualise_face_normal_as_edges(roof_list, 5) # edges3 = calculate.visualise_face_normal_as_edges(footprint_list, 5) # construct.visualise([wall_list, roof_list ,footprint_list , edges1, edges2, edges3],["WHITE","WHITE","WHITE","BLACK", "BLACK","BLACK"]) return geometry_3D_zone, geometry_3D_surroundings
current_path = os.path.dirname(__file__) parent_path = os.path.abspath(os.path.join(current_path, os.pardir, os.pardir)) base_file_path = os.path.join(parent_path, "example_scripts", "py2energyplus", "base.idf") weather_file_path = os.path.join(parent_path, "example_files", "weatherfile", "SGP_Singapore.486980_IWEC.epw") data_folder_path = os.path.join(parent_path, "example_scripts", "py2energyplus", "ep_data") time1 = time.clock() #construct the bldg to be analysed rec1 = py3dmodel.construct.make_rectangle(10, 10) extrude1 = py3dmodel.construct.extrude(rec1, (0, 0, 1), 4) rec1_midpt = py3dmodel.calculate.face_midpt(rec1) facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces( extrude1) chosen_facade = facade_list[0] facade_midpt = py3dmodel.calculate.face_midpt(chosen_facade) window = py3dmodel.modify.uniform_scale(facade_list[0], 0.95, 0.95, 0.4, facade_midpt) window = py3dmodel.fetch.topo2topotype(window) win_nrml = py3dmodel.calculate.face_normal(window) win_extrude = py3dmodel.construct.extrude(window, win_nrml, 1) vertical, shade_list, down = urbangeom.identify_building_surfaces(win_extrude) time2 = time.clock() print "CONSTRUCTED MODEL", (time2 - time1) / 60.0 idf_obj = py2energyplus.Idf() idf_obj.set_version("8.7.0") idf_obj.set_time_step("15")
min_z = min(z_list) #print min_z face = face_list[fcnt] face_midpt = py3dmodel.calculate.face_midpt(face) bldg_loc_pt = [face_midpt[0], face_midpt[1], min_z] bsolid = solid_list[fcnt] m_bsolid = py3dmodel.modify.move(face_midpt, bldg_loc_pt, bsolid) msolid_list.append(m_bsolid) fcnt += 1 print "CLASSFYING THE BUILDING SURFACES ... ..." total_facade_list = [] total_roof_list = [] total_footprint_list = [] for solid in msolid_list: facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces( solid) total_facade_list.extend(facade_list) total_roof_list.extend(roof_list) total_footprint_list.extend(footprint_list) n_list, s_list, e_list, w_list = urbangeom.identify_surface_direction( total_facade_list) print "WRITING THE BUILDING SURFACES ... ..." py3dmodel.export_collada.write_2_collada(n_list, north_facade_collada_filepath) py3dmodel.export_collada.write_2_collada(s_list, south_facade_collada_filepath) py3dmodel.export_collada.write_2_collada(e_list, east_facade_collada_filepath) py3dmodel.export_collada.write_2_collada(w_list, west_facade_collada_filepath) py3dmodel.export_collada.write_2_collada(total_roof_list, roof_collada_filepath) py3dmodel.export_collada.write_2_collada(total_footprint_list,
def convert(self): import time QtGui.QApplication.processEvents() self.progress = 0 self.update_bar() self.params.param('Result View').param('Progress').setValue("") #get the shpfile height_attrib = str( self.params.param('Height Attrib').param( 'Height Attribute').value()) bldg_footprint_shp_file = self.params.param('Shape File').param( 'Shapefile Loaded').value() dtm_tif_file = self.params.param('DTM File').param( 'DTM Loaded').value() result_directory = self.params.param('Result Directory').param( 'Result Directory Chosen').value() #viewer = self.params.param('Interactive View').param('Viewer On').value() self.timer.timeout.connect(self.update_bar) self.timer.start(20) #=========================================================================================== #FUNCTIONS #=========================================================================================== def raster_reader(input_terrain_raster): ''' __author__ = "Paul Neitzel, Kian Wee Chen" __copyright__ = "Copyright 2016, Architecture and Building Systems - ETH Zurich" __credits__ = ["Paul Neitzel", "Jimeno A. Fonseca"] __license__ = "MIT" __version__ = "0.1" __maintainer__ = "Daren Thomas" __email__ = "*****@*****.**" __status__ = "Production" ''' # read raster records raster_dataset = gdal.Open(input_terrain_raster) band = raster_dataset.GetRasterBand(1) a = band.ReadAsArray(0, 0, raster_dataset.RasterXSize, raster_dataset.RasterYSize) (y_index, x_index) = np.nonzero(a >= 0) (upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = raster_dataset.GetGeoTransform() x_coords = x_index * x_size + upper_left_x + ( x_size / 2) # add half the cell size y_coords = y_index * y_size + upper_left_y + ( y_size / 2) # to centre the point return [(x, y, z) for x, y, z in zip(x_coords, y_coords, a[y_index, x_index])] #=========================================================================================== #THE RESULT FILES #=========================================================================================== north_facade_collada_filepath = os.path.join(result_directory, "north_facade.dae") south_facade_collada_filepath = os.path.join(result_directory, "south_facade.dae") east_facade_collada_filepath = os.path.join(result_directory, "east_facade.dae") west_facade_collada_filepath = os.path.join(result_directory, "west_facade.dae") roof_collada_filepath = os.path.join(result_directory, "roof.dae") footprint_collada_filepath = os.path.join(result_directory, "footprint.dae") terrain_collada_filepath = os.path.join(result_directory, "terrain.dae") try: #=========================================================================================== #CONSTRUCT THE TERRAIN #=========================================================================================== time1 = time.clock() display_2dlist = [] #read the tif terrain file and create a tin from it pyptlist = raster_reader(dtm_tif_file) QtGui.QApplication.processEvents() self.params.param('Result View').param('Progress').setValue( "Constructing the Terrain ... ...") self.progress = 10 tin_occface_list = py3dmodel.construct.delaunay3d(pyptlist) terrain_shell = py3dmodel.construct.sew_faces(tin_occface_list)[0] #=========================================================================================== #EXTRUDE THE BUILDING #=========================================================================================== sf = shapefile.Reader(bldg_footprint_shp_file) shapeRecs = sf.shapeRecords() attrib_name_list = shp2citygml.get_field_name_list(sf) height_index = attrib_name_list.index(height_attrib) - 1 solid_list = [] face_list = [] QtGui.QApplication.processEvents() self.params.param('Result View').param('Progress').setValue( "Extruding the Buildings ... ...") self.progress = 20 cnt = 0 for rec in shapeRecs: QtGui.QApplication.processEvents() poly_attribs = rec.record height = poly_attribs[height_index] pypolygon_list2d = shp2citygml.get_geometry(rec) if pypolygon_list2d: pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d( pypolygon_list2d, 0.0) occface_list = shp2citygml.shp_pypolygon_list3d_2_occface_list( pypolygon_list3d) for occface in occface_list: if height > 0: occsolid = py3dmodel.construct.extrude( occface, (0, 0, 1), height) solid_list.append(occsolid) face_list.append(occface) cnt += 1 #move all the faces to a very high elevation and project them down onto the terrain so that we know where to place the buildings face_cmpd = py3dmodel.construct.make_compound(face_list) f_midpt = py3dmodel.calculate.get_centre_bbox(face_cmpd) loc_pt = [f_midpt[0], f_midpt[1], 1000] t_face_cmpd = py3dmodel.modify.move(f_midpt, loc_pt, face_cmpd) face_list2 = py3dmodel.fetch.topo_explorer(t_face_cmpd, "face") #face_list2 = face_list2[0:10] msolid_list = [] QtGui.QApplication.processEvents() self.params.param('Result View').param('Progress').setValue( "Placing the Buildings ... ...") self.progress = 50 fcnt = 0 for face2 in face_list2: pyptlist = py3dmodel.fetch.points_frm_occface(face2) #print "NUM PTS:", len(pyptlist) z_list = [] for pypt in pyptlist: QtGui.QApplication.processEvents() interpt, interface = py3dmodel.calculate.intersect_shape_with_ptdir( terrain_shell, pypt, (0, 0, -1)) if interpt: z = interpt[2] z_list.append(z) if z_list: min_z = min(z_list) #print min_z face = face_list[fcnt] face_midpt = py3dmodel.calculate.face_midpt(face) bldg_loc_pt = [face_midpt[0], face_midpt[1], min_z] bsolid = solid_list[fcnt] m_bsolid = py3dmodel.modify.move(face_midpt, bldg_loc_pt, bsolid) msolid_list.append(m_bsolid) fcnt += 1 self.params.param('Result View').param('Progress').setValue( "Classfying the Building Surfaces ... ...") QtGui.QApplication.processEvents() self.progress = 70 total_facade_list = [] total_roof_list = [] total_footprint_list = [] for solid in msolid_list: QtGui.QApplication.processEvents() facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces( solid) total_facade_list.extend(facade_list) total_roof_list.extend(roof_list) total_footprint_list.extend(footprint_list) n_list, s_list, e_list, w_list = urbangeom.identify_surface_direction( total_facade_list) QtGui.QApplication.processEvents() self.params.param('Result View').param('Progress').setValue( "Writing the Building Surfaces ... ...") self.progress = 100 py3dmodel.export_collada.write_2_collada( n_list, north_facade_collada_filepath) py3dmodel.export_collada.write_2_collada( s_list, south_facade_collada_filepath) py3dmodel.export_collada.write_2_collada( e_list, east_facade_collada_filepath) py3dmodel.export_collada.write_2_collada( w_list, west_facade_collada_filepath) py3dmodel.export_collada.write_2_collada(total_roof_list, roof_collada_filepath) py3dmodel.export_collada.write_2_collada( total_footprint_list, footprint_collada_filepath) py3dmodel.export_collada.write_2_collada([terrain_shell], terrain_collada_filepath) time2 = time.clock() time = (time2 - time1) / 60.0 time_str = "Total Processing Time: " + str(round(time, 2)) + " mins" QtGui.QApplication.processEvents() self.progress = 100 self.params.param('Result View').param('Progress').setValue( time_str) #if viewer == True: # cmpd = pyliburo.py3dmodel.construct.make_compound(msolid_list) # display_2dlist.append([cmpd]) # display_2dlist.append([terrain_shell]) # pyliburo.py3dmodel.construct.visualise(display_2dlist, ["RED", "WHITE"]) self.timer.stop() except: if self.progress == 10: self.params.param('Result View').param('Progress').setValue( str("there is an error at terrain construction !!!")) if self.progress == 20: self.params.param('Result View').param('Progress').setValue( str("there is an error at building extrusion !!!")) if self.progress == 50: self.params.param('Result View').param('Progress').setValue( str("there is an error at building placement !!!")) if self.progress == 70: self.params.param('Result View').param('Progress').setValue( str("there is an error at building classification !!!")) self.timer.stop()