diff --git a/PVPlantSite.py b/PVPlantSite.py index 242b666..2602f15 100644 --- a/PVPlantSite.py +++ b/PVPlantSite.py @@ -182,16 +182,14 @@ def makeSolarDiagram(longitude, latitude, scale=1, complete=False, tz=None): import ladybug from ladybug import location from ladybug import sunpath - except: - # TODO - remove pysolar dependency - # FreeCAD.Console.PrintWarning("Ladybug module not found, using pysolar instead. Warning, this will be deprecated in the future\n") + except ImportError: ladybug = False try: import pysolar - except: + except ImportError: try: import Pysolar as pysolar - except: + except ImportError: FreeCAD.Console.PrintError("The pysolar module was not found. Unable to generate solar diagrams\n") return None else: @@ -361,7 +359,7 @@ def makeWindRose(epwfile, scale=1, sectors=24): try: import ladybug from ladybug import epw - except: + except ImportError: FreeCAD.Console.PrintError("The ladybug module was not found. Unable to generate solar diagrams\n") return None if not epwfile: @@ -667,23 +665,22 @@ class _PVPlantSite(ArchSite._Site): self.computeAreas(obj) def computeAreas(self, obj): + """ + Compute areas, perimeter and volumes. + Override to add custom logic after parent computation. + """ ArchSite._Site.computeAreas(self, obj) - return if not obj.Shape: return - - if obj.Shape.isNull(): + if obj.Shape.isNull() or not obj.Shape.isValid() or not obj.Shape.Faces: return - if not obj.Shape.isValid(): - return - if not obj.Shape.Faces: - return - if not hasattr(obj, "Perimeter"): # check we have a latest version site + if not hasattr(obj, "Perimeter"): return if not obj.Terrain: return - # compute area + + # Compute projected area (horizontal projection of all near-horizontal faces) fset = [] for f in obj.Shape.Faces: if f.normalAt(0, 0).getAngle(FreeCAD.Vector(0, 0, 1)) < 1.5707: @@ -694,13 +691,11 @@ class _PVPlantSite(ArchSite._Site): for f in fset: try: pf = Part.Face(Part.Wire(Drawing.project(f, FreeCAD.Vector(0, 0, 1))[0].Edges)) - except Part.OCCError: - # error in computing the area. Better set it to zero than show a wrong value - if obj.ProjectedArea.Value != 0: - print("Error computing areas for ", obj.Label) - obj.ProjectedArea = 0 - else: pset.append(pf) + except Part.OCCError: + if getattr(obj, 'ProjectedArea', None) and obj.ProjectedArea.Value != 0: + FreeCAD.Console.PrintWarning(f"Error computing projected area for {obj.Label}\n") + obj.ProjectedArea = 0 if pset: self.flatarea = pset.pop() for f in pset: @@ -708,28 +703,27 @@ class _PVPlantSite(ArchSite._Site): self.flatarea = self.flatarea.removeSplitter() if obj.ProjectedArea.Value != self.flatarea.Area: obj.ProjectedArea = self.flatarea.Area - # compute perimeter + + # Compute perimeter (border edges only) lut = {} for e in obj.Shape.Edges: lut.setdefault(e.hashCode(), []).append(e) - l = 0 - for e in lut.values(): - if len(e) == 1: # keep only border edges - l += e[0].Length - if l: - if obj.Perimeter.Value != l: - obj.Perimeter = l - # compute volumes - if obj.Terrain.Shape.Solids: - shapesolid = obj.Terrain.Shape.copy() - else: - shapesolid = obj.Terrain.Shape.extrude(obj.ExtrusionVector) - addvol = 0 - subvol = 0 - for sub in obj.Subtractions: - subvol += sub.Shape.common(shapesolid).Volume - for sub in obj.Additions: - addvol += sub.Shape.cut(shapesolid).Volume + perimeter = sum(e[0].Length for e in lut.values() if len(e) == 1) + if perimeter and obj.Perimeter.Value != perimeter: + obj.Perimeter = perimeter + + # Compute cut/fill volumes relative to terrain + try: + if obj.Terrain.Shape.Solids: + shapesolid = obj.Terrain.Shape.copy() + else: + shapesolid = obj.Terrain.Shape.extrude(obj.ExtrusionVector) + except Exception: + return + + subvol = sum(sub.Shape.common(shapesolid).Volume for sub in obj.Subtractions) + addvol = sum(sub.Shape.cut(shapesolid).Volume for sub in obj.Additions) + if obj.SubtractionVolume.Value != subvol: obj.SubtractionVolume = subvol if obj.AdditionVolume.Value != addvol: @@ -1056,7 +1050,7 @@ class _ViewProviderSite: if hasattr(vobj.Object,"EPWFile") and vobj.Object.EPWFile: try: import ladybug - except: + except ImportError: pass else: self.windrosenode = makeWindRose(vobj.Object.EPWFile,vobj.SolarDiagramScale)