Arch: New-style Arch Site - fixes #2634

This commit is contained in:
Yorik van Havre 2016-10-04 16:04:09 -03:00
parent 35811f7e3c
commit ebc1d92893
2 changed files with 168 additions and 5 deletions

View File

@ -97,8 +97,10 @@ Floor creation aborted.\n" )
class _Floor:
"The Floor object"
def __init__(self,obj):
obj.addProperty("App::PropertyLength","Height","Arch","The height of this floor")
obj.addProperty("App::PropertyPlacement","Placement","Arch","The placement of this group")
obj.addProperty("App::PropertyLength","Height","Arch","The height of this object")
if not hasattr(obj,"Placement"):
# obj can be a Part Feature and already has a placement
obj.addProperty("App::PropertyPlacement","Placement","Arch","The placement of this object")
self.Type = "Floor"
obj.Proxy = self
self.Object = obj

View File

@ -36,10 +36,13 @@ __title__="FreeCAD Site"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"
def makeSite(objectslist=None,baseobj=None,name="Site"):
'''makeBuilding(objectslist): creates a site including the
objects from the given list.'''
obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name)
import Part
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
obj.Label = translate("Arch",name)
_Site(obj)
if FreeCAD.GuiUp:
@ -50,6 +53,8 @@ def makeSite(objectslist=None,baseobj=None,name="Site"):
obj.Terrain = baseobj
return obj
class _CommandSite:
"the Arch Site command definition"
def GetResources(self):
@ -96,11 +101,16 @@ Site creation aborted." )
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
class _Site(ArchFloor._Floor):
"The Site object"
def __init__(self,obj):
ArchFloor._Floor.__init__(self,obj)
obj.addProperty("App::PropertyLink","Terrain","Arch","The terrain of this site")
obj.addProperty("App::PropertyLink","Terrain","Arch","The base terrain of this site")
obj.addProperty("App::PropertyString","Address","Arch","The street and housenumber of this site")
obj.addProperty("App::PropertyString","PostalCode","Arch","The postal or zip code of this site")
obj.addProperty("App::PropertyString","City","Arch","The city of this site")
@ -108,11 +118,141 @@ class _Site(ArchFloor._Floor):
obj.addProperty("App::PropertyFloat","Latitude","Arch","The latitude of this site")
obj.addProperty("App::PropertyFloat","Longitude","Arch","The latitude of this site")
obj.addProperty("App::PropertyString","Url","Arch","An url that shows this site in a mapping website")
obj.addProperty("App::PropertyLinkList","Group","Arch","The objects that are part of this site")
obj.addProperty("App::PropertyLinkList","Additions","Arch","Other shapes that are appended to this object")
obj.addProperty("App::PropertyLinkList","Subtractions","Arch","Other shapes that are subtracted from this object")
obj.addProperty("App::PropertyArea","ProjectedArea","Arch","The area of the projection of this object onto the XY plane")
obj.addProperty("App::PropertyLength","Perimeter","Arch","The perimeter length of this terrain")
obj.addProperty("App::PropertyVolume","AdditionVolume","Arch","The volume of earth to be added to this terrain")
obj.addProperty("App::PropertyVolume","SubtractionVolume","Arch","The volume of earth to be removed from this terrain")
obj.addProperty("App::PropertyVector","ExtrusionVector","Arch","An extrusion vector to use when performing boolean operations")
obj.addProperty("App::PropertyBool","RemoveSplitter","Arch","Remove splitters from the resulting shape")
self.Type = "Site"
obj.setEditorMode('Height',2)
obj.ExtrusionVector = FreeCAD.Vector(0,0,-100000)
def execute(self,obj):
ArchFloor._Floor.execute(self,obj)
if not obj.isDerivedFrom("Part::Feature"): # old-style Site
return
pl = obj.Placement
shape = None
if obj.Terrain:
if obj.Terrain.isDerivedFrom("Part::Feature"):
if obj.Terrain.Shape:
if not obj.Terrain.Shape.isNull():
shape = obj.Terrain.Shape.copy()
if shape:
shells = []
for sub in obj.Subtractions:
if sub.isDerivedFrom("Part::Feature"):
if sub.Shape:
if sub.Shape.Solids:
for sol in sub.Shape.Solids:
rest = shape.cut(sol)
shells.append(sol.Shells[0].common(shape.extrude(obj.ExtrusionVector)))
shape = rest
for sub in obj.Additions:
if sub.isDerivedFrom("Part::Feature"):
if sub.Shape:
if sub.Shape.Solids:
for sol in sub.Shape.Solids:
rest = shape.cut(sol)
shells.append(sol.Shells[0].cut(shape.extrude(obj.ExtrusionVector)))
shape = rest
if not shape.isNull():
if shape.isValid():
for shell in shells:
shape = shape.fuse(shell)
if obj.RemoveSplitter:
shape = shape.removeSplitter()
obj.Shape = shape
if not pl.isNull():
obj.Placement = pl
self.computeAreas(obj)
def onChanged(self,obj,prop):
ArchFloor._Floor.onChanged(self,obj,prop)
if prop == "Terrain":
if obj.Terrain:
if FreeCAD.GuiUp:
obj.Terrain.ViewObject.hide()
self.execute(obj)
def computeAreas(self,obj):
if not obj.Shape:
return
if obj.Shape.isNull():
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
return
if not obj.Terrain:
return
# compute area
fset = []
for f in obj.Shape.Faces:
if f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1)) < 1.5707:
fset.append(f)
if fset:
import Drawing,Part
pset = []
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)
if pset:
self.flatarea = pset.pop()
for f in pset:
self.flatarea = self.flatarea.fuse(f)
self.flatarea = self.flatarea.removeSplitter()
if obj.ProjectedArea.Value != self.flatarea.Area:
obj.ProjectedArea = self.flatarea.Area
# compute perimeter
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
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
if obj.SubtractionVolume.Value != subvol:
obj.SubtractionVolume = subvol
if obj.AdditionVolume.Value != addvol:
obj.AdditionVolume = addvol
class _ViewProviderSite(ArchFloor._ViewProviderFloor):
"A View Provider for the Site object"
def __init__(self,vobj):
ArchFloor._ViewProviderFloor.__init__(self,vobj)
@ -121,7 +261,28 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
return ":/icons/Arch_Site_Tree.svg"
def claimChildren(self):
return self.Object.Group+[self.Object.Terrain]
objs = self.Object.Group+[self.Object.Terrain]
prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
if hasattr(self.Object,"Additions") and prefs.GetBool("swallowAdditions",True):
objs.extend(self.Object.Additions)
if hasattr(self.Object,"Subtractions") and prefs.GetBool("swallowSubtractions",True):
objs.extend(self.Object.Subtractions)
return objs
def setEdit(self,vobj,mode):
if mode == 0:
import ArchComponent
taskd = ArchComponent.ComponentTaskPanel()
taskd.obj = self.Object
taskd.update()
FreeCADGui.Control.showDialog(taskd)
return True
return False
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return False
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Site',_CommandSite())