def getAreaOfGML(poly, height=True): """Function which reads <gml:Polygon> and returns its area. The function also accounts for the interior and checks for the validity of the polygon.""" exteriorarea = 0.0 interiorarea = 0.0 #-- Decompose the exterior and interior boundary e, i = markup3dmodule.polydecomposer(poly) #-- Extract points in the <gml:LinearRing> of <gml:exterior> epoints = markup3dmodule.GMLpoints(e[0]) if isPolyValid(epoints): if height: exteriorarea += get3DArea(epoints) else: exteriorarea += get2DArea(epoints) for idx, iring in enumerate(i): #-- Extract points in the <gml:LinearRing> of <gml:interior> ipoints = markup3dmodule.GMLpoints(iring) if isPolyValid(ipoints): if height: interiorarea += get3DArea(ipoints) else: interiorarea += get2DArea(ipoints) #-- Account for the interior area = exteriorarea - interiorarea #-- Area in dimensionless units (coordinate units) return area
def extract_polys(polys, label, vertices_all, faces_all): """ extract polygons and their semantic information from GML and output to dictionaries @ param polys: list of Element. Returned by markup3dmodule.polygonFinder() function. @ param label: which label should we give to the polygon? e.g. "All", "WallSurface", etc @ param vertices_all: place to store vertices @ paramfaces_all : place to store faces """ for poly in polys: #-- Decompose the polygon into exterior and interior e, i = markup3dmodule.polydecomposer(poly) #-- Points forming the exterior LinearRing epoints = markup3dmodule.GMLpoints(e[0]) #-- Clean recurring points, including the last one # last_ep = epoints[-1] epoints_clean = list(remove_reccuring(epoints)) # epoints_clean.append(last_ep) #-- Check the exterior polygon # valid = polygon3dmodule.isPolyValid(epoints_clean, True) valid = True if valid: vertices_all.extend( epoints_clean) # do not add the final points to obj faces_all[label].append(epoints_clean) else: pass return vertices_all, faces_all
def solarinfo(self): """Computes the area, azimuth, and tilt for each roof surface (id compulsory).""" place = (52.01, 4.36) for roofsurface in self.roofsurfaces: #-- Skip the openings if roofsurface.attrib['{%s}id' %ns_gml] in self.listOfOpenings: continue #-- Add it to the list listofxmlroofsurfaces.append(roofsurface) #-- gml:id of the polygon pid = roofsurface.attrib['{%s}id' %ns_gml] #-- Area area = polygon3dmodule.getAreaOfGML(roofsurface, True) #-- Compute the normal norm = polygon3dmodule.getNormal(markup3dmodule.GMLpoints(markup3dmodule.polydecomposer(roofsurface)[0][0])) #-- Get the azimuth and tilt from the surface normal az, tilt = polygon3dmodule.getAngles(norm) az = round(az, 3) #-- 360 -> 0 degrees if az == 360.0: az = 0.0 tilt = round(tilt, 3) #-- Peculiar problems with the normals, with a cheap solution. Luckily very uncommon. if tilt == 180: tilt = 0.0 if tilt >= 180: tilt = tilt - 180.01 elif tilt > 90: tilt = tilt - 90.01 elif tilt == 90: tilt = 89.9 #-- Flat surfaces always have the azimuth zero if tilt == 0.0: az = 0.0 #-- If the TOF file is loaded, sample the irradiance if loadDict: irradiation = irr_from_tof(tilt, az) #-- If the TOF file is not loaded, estimate the values else: irradiation = irr.yearly_total_irr(place, az, tilt) #-- Add the values self.roofdata[pid] = {'area' : area, 'azimuth' : az, 'tilt' : tilt, 'irradiation' : irradiation, 'total_irradiation' : irradiation*area} roofsurfacedata[pid] = {'area' : area, 'azimuth' : az, 'tilt' : tilt, 'irradiation' : irradiation, 'total_irradiation' : irradiation*area} #self.roofdata.append([self.id, pid, area, az, tilt, irradiation, irradiation*area]) self.sumIrr = 0 #-- Sum the values for the building for rs in self.roofdata: self.sumIrr += self.roofdata[rs]['total_irradiation']
def roofarea(self): """The total area of RoofSurface.""" self.roofs = [] self.roofsurfaces = [] roofarea = 0.0 openings = 0.0 for child in self.xml.getiterator(): if child.tag == '{%s}RoofSurface' %ns_bldg: self.roofs.append(child) openings += oparea(child) for surface in self.roofs: for w in surface.findall('.//{%s}Polygon' %ns_gml): self.roofsurfaces.append(w) for roofsurface in self.roofsurfaces: roofarea += polygon3dmodule.getAreaOfGML(roofsurface, True) #-- Compute the normal norm = polygon3dmodule.getNormal(markup3dmodule.GMLpoints(markup3dmodule.polydecomposer(roofsurface)[0][0])) polygon3dmodule.getAngles(norm) return roofarea - openings
def roofarea(self): """The total area of RoofSurface.""" self.roofs = [] self.roofsurfaces = [] roofarea = 0.0 openings = 0.0 for child in self.xml.getiterator(): if child.tag == '{%s}RoofSurface' % ns_bldg: self.roofs.append(child) openings += oparea(child) for surface in self.roofs: for w in surface.findall('.//{%s}Polygon' % ns_gml): self.roofsurfaces.append(w) for roofsurface in self.roofsurfaces: roofarea += polygon3dmodule.getAreaOfGML(roofsurface, True) #-- Compute the normal norm = polygon3dmodule.getNormal( markup3dmodule.GMLpoints( markup3dmodule.polydecomposer(roofsurface)[0][0])) polygon3dmodule.getAngles(norm) return roofarea - openings
def poly_to_obj(poly, cl, material=None): """Main conversion function of one polygon to one or more faces in OBJ, in a specific semantic class. Supports assigning a material.""" global local_vertices global vertices global face_output #-- Decompose the polygon into exterior and interior e, i = markup3dmodule.polydecomposer(poly) #-- Points forming the exterior LinearRing epoints = markup3dmodule.GMLpoints(e[0]) #-- Clean recurring points, except the last one last_ep = epoints[-1] epoints_clean = list(remove_reccuring(epoints)) epoints_clean.append(last_ep) # print epoints # print epoints_clean # print #-- LinearRing(s) forming the interior irings = [] for iring in i: ipoints = markup3dmodule.GMLpoints(iring) #-- Clean them in the same manner as the exterior ring last_ip = ipoints[-1] ipoints_clean = list(remove_reccuring(ipoints)) ipoints_clean.append(last_ip) irings.append(ipoints_clean) #-- If the polygon validation option is enabled if VALIDATION: #-- Check the polygon valid = polygon3dmodule.isPolyValid(epoints_clean, True) if valid: for iring in irings: if not polygon3dmodule.isPolyValid(iring, False): valid = False #-- If everything is valid send them to the Delaunay triangulation if valid: if SKIPTRI: #-- Triangulation is skipped, polygons are converted directly to faces #-- The last point is removed since it's equal to the first one t = [epoints_clean[:-1]] else: #-- Triangulate polys # t = polygon3dmodule.triangulation(epoints, irings) try: t = polygon3dmodule.triangulation(epoints_clean, irings) except: t = [] #-- Process the triangles/polygons for tri in t: #-- Face marker f = "f " #-- For each point in the triangle/polygon (face) get the index "v" or add it to the index for ep in range(0, len(tri)): v, local_vertices[cl] = get_index(tri[ep], local_vertices[cl], len(vertices[cl])) f += str(v) + " " #-- Add the material if invoked if material: face_output[cl].append("usemtl " + str(mtl(material, min_value, max_value, res)) + str("\n")) #-- Store all together face_output[cl].append(f + "\n") else: # Get the gml:id of the Polygon if it exists polyid = poly.xpath("@g:id", namespaces={'g' : ns_gml}) if polyid: polyid = polyid[0] print "\t\t!! Detected an invalid polygon (%s). Skipping..." %polyid else: print "\t\t!! Detected an invalid polygon. Skipping..." else: #-- Do exactly the same, but without the validation try: if SKIPTRI: t = [epoints_clean[:-1]] else: t = polygon3dmodule.triangulation(epoints_clean, irings) except: t = [] for tri in t: f = "f " for ep in range(0, len(tri)): v, local_vertices[cl] = get_index(tri[ep], local_vertices[cl], len(vertices[cl])) f += str(v) + " " if material: face_output[cl].append("usemtl " + str(mtl(material, min_value, max_value, res)) + str("\n")) face_output[cl].append(f + "\n")
def solarinfo(self): """Computes the area, azimuth, and tilt for each roof surface (id compulsory).""" place = (52.01, 4.36) for roofsurface in self.roofsurfaces: #-- Skip the openings if roofsurface.attrib['{%s}id' % ns_gml] in self.listOfOpenings: continue #-- Add it to the list listofxmlroofsurfaces.append(roofsurface) #-- gml:id of the polygon pid = roofsurface.attrib['{%s}id' % ns_gml] #-- Area area = polygon3dmodule.getAreaOfGML(roofsurface, True) #-- Compute the normal norm = polygon3dmodule.getNormal( markup3dmodule.GMLpoints( markup3dmodule.polydecomposer(roofsurface)[0][0])) #-- Get the azimuth and tilt from the surface normal az, tilt = polygon3dmodule.getAngles(norm) az = round(az, 3) #-- 360 -> 0 degrees if az == 360.0: az = 0.0 tilt = round(tilt, 3) #-- Peculiar problems with the normals, with a cheap solution. Luckily very uncommon. if tilt == 180: tilt = 0.0 if tilt >= 180: tilt = tilt - 180.01 elif tilt > 90: tilt = tilt - 90.01 elif tilt == 90: tilt = 89.9 #-- Flat surfaces always have the azimuth zero if tilt == 0.0: az = 0.0 #-- If the TOF file is loaded, sample the irradiance if loadDict: irradiation = irr_from_tof(tilt, az) #-- If the TOF file is not loaded, estimate the values else: irradiation = irr.yearly_total_irr(place, az, tilt) #-- Add the values self.roofdata[pid] = { 'area': area, 'azimuth': az, 'tilt': tilt, 'irradiation': irradiation, 'total_irradiation': irradiation * area } roofsurfacedata[pid] = { 'area': area, 'azimuth': az, 'tilt': tilt, 'irradiation': irradiation, 'total_irradiation': irradiation * area } #self.roofdata.append([self.id, pid, area, az, tilt, irradiation, irradiation*area]) self.sumIrr = 0 #-- Sum the values for the building for rs in self.roofdata: self.sumIrr += self.roofdata[rs]['total_irradiation']