Arch: Handle cloning of BuildingParts

This commit is contained in:
Yorik van Havre
2018-06-29 12:12:54 -03:00
parent 43bf3bc0cb
commit 1314210a4c
6 changed files with 74 additions and 31 deletions

View File

@@ -164,14 +164,14 @@ class BuildingPart:
obj.addProperty("App::PropertyEnumeration","IfcRole","Component",QT_TRANSLATE_NOOP("App::Property","The role of this object"))
import ArchComponent
obj.IfcRole = ArchComponent.IfcRoles
if not "CloneOf" in pl:
obj.addProperty("App::PropertyLink","CloneOf","Component",QT_TRANSLATE_NOOP("App::Property","The object this component is cloning"))
if not "Description" in pl:
obj.addProperty("App::PropertyString","Description","Component",QT_TRANSLATE_NOOP("App::Property","An optional description for this component"))
if not "Tag" in pl:
obj.addProperty("App::PropertyString","Tag","Component",QT_TRANSLATE_NOOP("App::Property","An optional tag for this component"))
if not "IfcAttributes" in pl:
obj.addProperty("App::PropertyMap","IfcAttributes","Component",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes"))
if not "Shape" in pl:
obj.addProperty("Part::PropertyPartShape","Shape","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The shape of this object"))
self.Type = "BuildingPart"
def onDocumentRestored(self,obj):
@@ -197,28 +197,42 @@ class BuildingPart:
for child in obj.Group:
if Draft.getType(child) in ["Wall","Structure"]:
if not child.Height.Value:
#print("Executing ",child.Label)
child.Proxy.execute(child)
elif prop == "Placement":
if hasattr(self,"oldPlacement"):
if self.oldPlacement:
v = FreeCAD.Vector(0,0,1)
deltap = obj.Placement.Base.sub(self.oldPlacement.Base)
if deltap.Length == 0:
deltap = None
deltar = FreeCAD.Rotation(self.oldPlacement.Rotation.multVec(v),obj.Placement.Rotation.multVec(v))
if deltar.Angle < 0.001:
deltar = self.oldPlacement.Rotation.multiply(obj.Placement.Rotation)
#print "Rotation",deltar.Axis,deltar.Angle
if deltar.Angle < 0.0001:
deltar = None
for child in obj.Group:
if ((not hasattr(child,"MoveWithHost")) or child.MoveWithHost) and hasattr(child,"Placement"):
print "moving ",child.Label
#print "moving ",child.Label
if deltap:
child.Placement.move(deltap)
if deltar:
child.Placement.Rotation = child.Placement.Rotation.multiply(deltar)
#child.Placement.Rotation = child.Placement.Rotation.multiply(deltar) - not enough, child must also move
# use shape methods to obtain a correct placement
import Part,math
shape = Part.Shape()
shape.Placement = child.Placement
shape.rotate(DraftVecUtils.tup(obj.Placement.Base), DraftVecUtils.tup(deltar.Axis), math.degrees(deltar.Angle))
child.Placement = shape.Placement
def execute(self,obj):
pass
# gather all the child shapes into a compound
shapes = []
for o in obj.Group:
if o.isDerivedFrom("Part::Feature") and o.Shape and (not o.Shape.isNull()):
shapes.append(o.Shape)
if shapes:
import Part
obj.Shape = Part.makeCompound(shapes)
def getSpaces(self,obj):
@@ -278,6 +292,9 @@ class ViewProviderBuildingPart:
vobj.addProperty("App::PropertyFloatList","ViewData","BuildingPart",QT_TRANSLATE_NOOP("App::Property","Camera position data associated with this object"))
if not "RestoreView" in pl:
vobj.addProperty("App::PropertyBool","RestoreView","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If set, the view stored in this object will be restored on double-click"))
if not "DiffuseColor" in pl:
vobj.addProperty("App::PropertyColorList","DiffuseColor","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The individual face colors"))
def onDocumentRestored(self,vobj):
@@ -342,6 +359,18 @@ class ViewProviderBuildingPart:
if prop in ["Placement","LevelOffset"]:
self.onChanged(obj.ViewObject,"OverrideUnit")
elif prop == "Shape":
# gather all the child shapes
cols = []
for o in obj.Group:
if o.isDerivedFrom("Part::Feature") and o.Shape and (not o.Shape.isNull()):
if len(o.ViewObject.DiffuseColor) == len(o.Shape.Faces):
cols.extend(o.ViewObject.DiffuseColor)
else:
c = o.ViewObject.ShapeColor[:3]+(obj.ViewObject.Transparency/100.0,)
for i in range(len(o.Shape.Faces)):
cols.append(c)
obj.ViewObject.DiffuseColor = cols
def onChanged(self,vobj,prop):

View File

@@ -508,7 +508,7 @@ class Component:
"if this object is a clone, sets the shape. Returns True if this is the case"
if hasattr(obj,"CloneOf"):
if obj.CloneOf:
if (Draft.getType(obj.CloneOf) == Draft.getType(obj)) or (Draft.getType(obj) == "Component"):
if (Draft.getType(obj.CloneOf) == Draft.getType(obj)) or (Draft.getType(obj) in ["Component","BuildingPart"]):
pl = obj.Placement
obj.Shape = obj.CloneOf.Shape.copy()
obj.Placement = pl
@@ -1071,8 +1071,23 @@ class ViewProviderComponent:
menu.addAction(action1)
def toggleSubcomponents(self):
FreeCADGui.runCommand("Arch_ToggleSubs")
def areDifferentColors(self,a,b):
if len(a) != len(b):
return True
for i in range(len(a)):
if abs(sum(a[i]) - sum(b[i])) > 0.00001:
return True
return False
def colorize(self,obj,force=False):
if obj.CloneOf:
if self.areDifferentColors(obj.ViewObject.DiffuseColor,obj.CloneOf.ViewObject.DiffuseColor) or force:
obj.ViewObject.DiffuseColor = obj.CloneOf.ViewObject.DiffuseColor
class ArchSelectionObserver:

View File

@@ -578,7 +578,7 @@ class _Structure(ArchComponent.Component):
normal = None
if not height:
for p in obj.InList:
if Draft.getType(p) == "Floor":
if Draft.getType(p) in ["Floor","BuildingPart"]:
if p.Height.Value:
height = p.Height.Value
base = None

View File

@@ -750,7 +750,7 @@ class _Wall(ArchComponent.Component):
height = obj.Height.Value
if not height:
for p in obj.InList:
if Draft.getType(p) == "Floor":
if Draft.getType(p) in ["Floor","BuildingPart"]:
if p.Height.Value:
height = p.Height.Value
if not height:

View File

@@ -1451,15 +1451,6 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
if self.areDifferentColors(colors,obj.ViewObject.DiffuseColor) or force:
obj.ViewObject.DiffuseColor = colors
def areDifferentColors(self,a,b):
if len(a) != len(b):
return True
for i in range(len(a)):
if abs(sum(a[i]) - sum(b[i])) > 0.00001:
return True
return False
class _ArchWindowTaskPanel:

View File

@@ -649,7 +649,7 @@ def getMovableChildren(objectslist,recursive=True):
if not isinstance(objectslist,list):
objectslist = [objectslist]
for obj in objectslist:
if not (getType(obj) in ["Clone","SectionPlane","Facebinder"]):
if not (getType(obj) in ["Clone","SectionPlane","Facebinder","BuildingPart"]):
# objects that should never move their children
children = obj.OutList
if hasattr(obj,"Proxy"):
@@ -3118,8 +3118,10 @@ def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5):
return obj
def makeShapeString(String,FontFile,Size = 100,Tracking = 0):
'''ShapeString(Text,FontFile,Height,Track): Turns a text string
into a Compound Shape'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -3140,11 +3142,13 @@ def makeShapeString(String,FontFile,Size = 100,Tracking = 0):
return obj
def clone(obj,delta=None,forcedraft=False):
'''clone(obj,[delta,forcedraft]): makes a clone of the given object(s). The clone is an exact,
linked copy of the given object. If the original object changes, the final object
changes too. Optionally, you can give a delta Vector to move the clone from the
original position. If forcedraft is True, the resulting object is a Draft clone
even if the input object is an Arch object.'''
prefix = getParam("ClonePrefix","")
if prefix:
prefix = prefix.strip()+" "
@@ -3153,14 +3157,18 @@ def clone(obj,delta=None,forcedraft=False):
if (len(obj) == 1) and obj[0].isDerivedFrom("Part::Part2DObject"):
cl = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Clone2D")
cl.Label = prefix + obj[0].Label + " (2D)"
elif (len(obj) == 1) and hasattr(obj[0],"CloneOf") and (not forcedraft):
elif (len(obj) == 1) and (hasattr(obj[0],"CloneOf") or (getType(obj[0]) == "BuildingPart")) and (not forcedraft):
# arch objects can be clones
import Arch
cl = getattr(Arch,"make"+obj[0].Proxy.Type)()
if getType(obj[0]) == "BuildingPart":
cl = Arch.makeComponent()
else:
cl = getattr(Arch,"make"+obj[0].Proxy.Type)()
base = getCloneBase(obj[0])
cl.Label = prefix + base.Label
cl.CloneOf = base
cl.Placement = obj[0].Placement
if getType(obj[0]) != "BuildingPart":
cl.Placement = obj[0].Placement
try:
cl.Role = base.Role
cl.Description = base.Description
@@ -3169,7 +3177,7 @@ def clone(obj,delta=None,forcedraft=False):
pass
if gui:
cl.ViewObject.DiffuseColor = base.ViewObject.DiffuseColor
if obj[0].Proxy.Type == "Window":
if getType(obj[0]) in ["Window","BuildingPart"]:
from DraftGui import todo
todo.delay(Arch.recolorize,cl)
select(cl)
@@ -6103,7 +6111,7 @@ class _PointArray(_DraftObject):
obj.addProperty("App::PropertyLink","Base","Draft",QT_TRANSLATE_NOOP("App::Property","Base")).Base = bobj
obj.addProperty("App::PropertyLink","PointList","Draft",QT_TRANSLATE_NOOP("App::Property","PointList")).PointList = ptlst
obj.addProperty("App::PropertyInteger","Count","Draft",QT_TRANSLATE_NOOP("App::Property","Count")).Count = 0
obj.setEditorMode("Count", 1)
obj.setEditorMode("Count", 1)
def execute(self, obj):
import Part
@@ -6118,18 +6126,18 @@ class _PointArray(_DraftObject):
pls = opl.Links
elif hasattr(opl, 'Components'):
pls = opl.Components
base = []
i = 0
if hasattr(obj.Base, 'Shape'):
for pts in pls:
#print pts # inspect the objects
#print pts # inspect the objects
if hasattr(pts, 'X') and hasattr(pts, 'Y') and hasattr(pts, 'Y'):
nshape = obj.Base.Shape.copy()
if hasattr(pts, 'Placement'):
place = pts.Placement
nshape.translate(place.Base)
nshape.rotate(place.Base, place.Rotation.Axis, place.Rotation.Angle * 180 / math.pi )
nshape.rotate(place.Base, place.Rotation.Axis, place.Rotation.Angle * 180 / math.pi )
nshape.translate(Base.Vector(pts.X,pts.Y,pts.Z))
i += 1
base.append(nshape)
@@ -6314,7 +6322,7 @@ class _ViewProviderDraftArray(_ViewProviderDraft):
if hasattr(self.Object,"ArrayType"):
return ":/icons/Draft_Array.svg"
elif hasattr(self.Object,"PointList"):
return ":/icons/Draft_PointArray.svg"
return ":/icons/Draft_PointArray.svg"
return ":/icons/Draft_PathArray.svg"
def resetColors(self, vobj):
@@ -6494,7 +6502,7 @@ class _Facebinder(_DraftObject):
obj.addProperty("App::PropertyBool","RemoveSplitter","Draft",QT_TRANSLATE_NOOP("App::Property","Specifies if splitter lines must be removed"))
obj.addProperty("App::PropertyDistance","Extrusion","Draft",QT_TRANSLATE_NOOP("App::Property","An optional extrusion value to be applied to all faces"))
obj.addProperty("App::PropertyBool","Sew","Draft",QT_TRANSLATE_NOOP("App::Property","This specifies if the shapes sew"))
def execute(self,obj):
import Part