Arch: separate properties creation in own methods and check properties at file load

This commit is contained in:
Yorik van Havre
2018-06-01 19:36:35 -03:00
parent 27e80d0c69
commit e49a5af3ae
18 changed files with 1950 additions and 551 deletions

View File

@@ -50,8 +50,10 @@ __url__ = "http://www.freecadweb.org"
def makeAxis(num=5,size=1000,name="Axes"):
'''makeAxis(num,size): makes an Axis set
based on the given number of axes and interval distances'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -76,7 +78,9 @@ def makeAxis(num=5,size=1000,name="Axes"):
def makeAxisSystem(axes,name="Axis System"):
'''makeAxisSystem(axes): makes a system from the given list of axes'''
if not isinstance(axes,list):
axes = [axes]
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",name)
@@ -90,7 +94,9 @@ def makeAxisSystem(axes,name="Axis System"):
def makeGrid(name="Grid"):
'''makeGrid(): makes a grid object'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
obj.Label = translate("Arch",name)
ArchGrid(obj)
@@ -102,14 +108,18 @@ def makeGrid(name="Grid"):
class _CommandAxis:
"the Arch Axis command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Axis',
'MenuText': QT_TRANSLATE_NOOP("Arch_Axis","Axis"),
'Accel': "A, X",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Axis","Creates a set of axes")}
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Axis"))
FreeCADGui.addModule("Arch")
@@ -117,18 +127,23 @@ class _CommandAxis:
FreeCAD.ActiveDocument.commitTransaction()
def IsActive(self):
return not FreeCAD.ActiveDocument is None
class _CommandAxisSystem:
"the Arch Axis System command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Axis_System',
'MenuText': QT_TRANSLATE_NOOP("Arch_AxisSystem","Axis System"),
'Accel': "X, S",
'ToolTip': QT_TRANSLATE_NOOP("Arch_AxisSystem","Creates an axis system from a set of axes")}
def Activated(self):
if FreeCADGui.Selection.getSelection():
import Draft
s = "["
@@ -146,18 +161,23 @@ class _CommandAxisSystem:
FreeCAD.Console.PrintError(translate("Arch","Please select at least one axis")+"\n")
def IsActive(self):
return not FreeCAD.ActiveDocument is None
class CommandArchGrid:
"the Arch Grid command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Grid',
'MenuText': QT_TRANSLATE_NOOP("Arch_Axis","Grid"),
'Accel': "A, X",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Axis","Creates a customizable grid object")}
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Grid"))
FreeCADGui.addModule("Arch")
@@ -165,24 +185,44 @@ class CommandArchGrid:
FreeCAD.ActiveDocument.commitTransaction()
def IsActive(self):
return not FreeCAD.ActiveDocument is None
class _Axis:
"The Axis object"
def __init__(self,obj):
obj.addProperty("App::PropertyFloatList","Distances","Arch", QT_TRANSLATE_NOOP("App::Property","The intervals between axes"))
obj.addProperty("App::PropertyFloatList","Angles","Arch", QT_TRANSLATE_NOOP("App::Property","The angles of each axis"))
obj.addProperty("App::PropertyStringList","Labels","Arch", QT_TRANSLATE_NOOP("App::Property","The label of each axis"))
obj.addProperty("App::PropertyLength","Length","Arch", QT_TRANSLATE_NOOP("App::Property","The length of the axes"))
obj.addProperty("App::PropertyPlacement","Placement","Base","")
obj.addProperty("Part::PropertyPartShape","Shape","Base","")
self.Type = "Axis"
obj.Length=3000
obj.Proxy = self
self.setProperties(obj)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Distances" in pl:
obj.addProperty("App::PropertyFloatList","Distances","Axis", QT_TRANSLATE_NOOP("App::Property","The intervals between axes"))
if not "Angles" in pl:
obj.addProperty("App::PropertyFloatList","Angles","Axis", QT_TRANSLATE_NOOP("App::Property","The angles of each axis"))
if not "Labels" in pl:
obj.addProperty("App::PropertyStringList","Labels","Axis", QT_TRANSLATE_NOOP("App::Property","The label of each axis"))
if not "Length" in pl:
obj.addProperty("App::PropertyLength","Length","Axis", QT_TRANSLATE_NOOP("App::Property","The length of the axes"))
obj.Length=3000
if not "Placement" in pl:
obj.addProperty("App::PropertyPlacement","Placement","Base","")
if not "Shape" in pl:
obj.addProperty("Part::PropertyPartShape","Shape","Base","")
self.Type = "Axis"
def onDocumentRestored(self,obj):
self.setProperties(obj)
def execute(self,obj):
import Part
geoms = []
dist = 0
@@ -204,18 +244,22 @@ class _Axis:
obj.Shape = sh
def onChanged(self,obj,prop):
if prop in ["Angles","Distances","Placement"]:
self.execute(obj)
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
def getPoints(self,obj):
"returns the gridpoints of linked axes"
pts = []
for e in obj.Shape.Edges:
pts.append(e.Vertexes[0].Point)
@@ -223,42 +267,66 @@ class _Axis:
class _ViewProviderAxis:
"A View Provider for the Axis object"
def __init__(self,vobj):
vobj.addProperty("App::PropertyLength","BubbleSize","Arch", QT_TRANSLATE_NOOP("App::Property","The size of the axis bubbles"))
vobj.addProperty("App::PropertyEnumeration","NumberingStyle","Arch", QT_TRANSLATE_NOOP("App::Property","The numbering style"))
vobj.addProperty("App::PropertyEnumeration","DrawStyle","Base","")
vobj.addProperty("App::PropertyEnumeration","BubblePosition","Base","")
vobj.addProperty("App::PropertyFloat","LineWidth","Base","")
vobj.addProperty("App::PropertyColor","LineColor","Base","")
vobj.addProperty("App::PropertyInteger","StartNumber","Base","")
vobj.addProperty("App::PropertyFont","FontName","Base","")
vobj.addProperty("App::PropertyLength","FontSize","Base","")
vobj.addProperty("App::PropertyBool","ShowLabel","Base",QT_TRANSLATE_NOOP("App::Property","If true, show the labels"))
vobj.addProperty("App::PropertyPlacement","LabelOffset","Base",QT_TRANSLATE_NOOP("App::Property","A transformation to apply to each label"))
vobj.NumberingStyle = ["1,2,3","01,02,03","001,002,003","A,B,C","a,b,c","I,II,III","L0,L1,L2"]
vobj.DrawStyle = ["Solid","Dashed","Dotted","Dashdot"]
vobj.BubblePosition = ["Start","End","Both","None"]
vobj.Proxy = self
vobj.BubbleSize = 500
vobj.LineWidth = 1
vobj.LineColor = (0.13,0.15,0.37)
vobj.DrawStyle = "Dashdot"
vobj.NumberingStyle = "1,2,3"
vobj.StartNumber = 1
vobj.FontName = Draft.getParam("textfont","Arial,Sans")
vobj.FontSize = 350
vobj.ShowLabel = False
self.setProperties(vobj)
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "BubbleSize" in pl:
vobj.addProperty("App::PropertyLength","BubbleSize","Axis", QT_TRANSLATE_NOOP("App::Property","The size of the axis bubbles"))
vobj.BubbleSize = 500
if not "NumberingStyle" in pl:
vobj.addProperty("App::PropertyEnumeration","NumberingStyle","Axis", QT_TRANSLATE_NOOP("App::Property","The numbering style"))
vobj.NumberingStyle = ["1,2,3","01,02,03","001,002,003","A,B,C","a,b,c","I,II,III","L0,L1,L2"]
vobj.NumberingStyle = "1,2,3"
if not "DrawStyle" in pl:
vobj.addProperty("App::PropertyEnumeration","DrawStyle","Axis",QT_TRANSLATE_NOOP("App::Property","The type of line to draw this axis"))
vobj.DrawStyle = ["Solid","Dashed","Dotted","Dashdot"]
vobj.DrawStyle = "Dashdot"
if not "BubblePosition" in pl:
vobj.addProperty("App::PropertyEnumeration","BubblePosition","Axis",QT_TRANSLATE_NOOP("App::Property","Where to add bubbles to this axis: Start, end, both or none"))
vobj.BubblePosition = ["Start","End","Both","None"]
if not "LineWidth" in pl:
vobj.addProperty("App::PropertyFloat","LineWidth","Axis",QT_TRANSLATE_NOOP("App::Property","The line width to draw this axis"))
vobj.LineWidth = 1
if not "LineColor" in pl:
vobj.addProperty("App::PropertyColor","LineColor","Axis",QT_TRANSLATE_NOOP("App::Property","The color of this axis"))
vobj.LineColor = (0.13,0.15,0.37)
if not "StartNumber" in pl:
vobj.addProperty("App::PropertyInteger","StartNumber","Axis",QT_TRANSLATE_NOOP("App::Property","The number of the first axis"))
vobj.StartNumber = 1
if not "FontName" in pl:
vobj.addProperty("App::PropertyFont","FontName","Axis",QT_TRANSLATE_NOOP("App::Property","The font to use for texts"))
vobj.FontName = Draft.getParam("textfont","Arial,Sans")
if not "FontSize" in pl:
vobj.addProperty("App::PropertyLength","FontSize","Axis",QT_TRANSLATE_NOOP("App::Property","The font size"))
vobj.FontSize = 350
if not "ShowLabel" in pl:
vobj.addProperty("App::PropertyBool","ShowLabel","Axis",QT_TRANSLATE_NOOP("App::Property","If true, show the labels"))
if not "LabelOffset" in pl:
vobj.addProperty("App::PropertyPlacement","LabelOffset","Axis",QT_TRANSLATE_NOOP("App::Property","A transformation to apply to each label"))
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Axis_Tree.svg"
def claimChildren(self):
return []
def attach(self, vobj):
self.bubbles = None
self.bubbletexts = []
sep = coin.SoSeparator()
@@ -282,15 +350,19 @@ class _ViewProviderAxis:
self.onChanged(vobj,"DrawStyle")
def getDisplayModes(self,vobj):
return ["Default"]
def getDefaultDisplayMode(self):
return "Default"
def setDisplayMode(self,mode):
return mode
def updateData(self,obj,prop):
if prop == "Shape":
if obj.Shape:
if obj.Shape.Edges:
@@ -310,19 +382,23 @@ class _ViewProviderAxis:
self.onChanged(obj.ViewObject,"ShowLabel")
def onChanged(self, vobj, prop):
if prop == "LineColor":
l = vobj.LineColor
self.mat.diffuseColor.setValue([l[0],l[1],l[2]])
if hasattr(vobj,"LineColor"):
l = vobj.LineColor
self.mat.diffuseColor.setValue([l[0],l[1],l[2]])
elif prop == "DrawStyle":
if vobj.DrawStyle == "Solid":
self.linestyle.linePattern = 0xffff
elif vobj.DrawStyle == "Dashed":
self.linestyle.linePattern = 0xf00f
elif vobj.DrawStyle == "Dotted":
self.linestyle.linePattern = 0x0f0f
else:
self.linestyle.linePattern = 0xff88
if hasattr(vobj,"DrawStyle"):
if vobj.DrawStyle == "Solid":
self.linestyle.linePattern = 0xffff
elif vobj.DrawStyle == "Dashed":
self.linestyle.linePattern = 0xf00f
elif vobj.DrawStyle == "Dotted":
self.linestyle.linePattern = 0x0f0f
else:
self.linestyle.linePattern = 0xff88
elif prop == "LineWidth":
if hasattr(vobj,"LineWidth"):
self.linestyle.lineWidth = vobj.LineWidth
elif prop in ["BubbleSize","BubblePosition","FontName","FontSize"]:
if hasattr(self,"bubbleset"):
@@ -516,6 +592,7 @@ class _ViewProviderAxis:
def setEdit(self,vobj,mode=0):
taskd = _AxisTaskPanel()
taskd.obj = vobj.Object
taskd.update()
@@ -523,22 +600,29 @@ class _ViewProviderAxis:
return True
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return
def doubleClicked(self,vobj):
self.setEdit(vobj)
def __getstate__(self):
return None
def __setstate__(self,state):
return None
class _AxisTaskPanel:
'''The editmode TaskPanel for Axis objects'''
def __init__(self):
# the panel has a tree widget that contains categories
# for the subcomponents, such as additions, subtractions.
# the categories are shown only if they are not empty.
@@ -580,15 +664,19 @@ class _AxisTaskPanel:
self.update()
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Close)
def update(self):
'fills the treewidget'
self.updating = True
self.tree.clear()
@@ -609,6 +697,7 @@ class _AxisTaskPanel:
self.updating = False
def addElement(self):
item = QtGui.QTreeWidgetItem(self.tree)
item.setText(0,str(self.tree.topLevelItemCount()))
item.setText(1,"1.0")
@@ -617,6 +706,7 @@ class _AxisTaskPanel:
self.resetObject()
def removeElement(self):
it = self.tree.currentItem()
if it:
nr = int(it.text(0))-1
@@ -624,11 +714,14 @@ class _AxisTaskPanel:
self.update()
def edit(self,item,column):
if not self.updating:
self.resetObject()
def resetObject(self,remove=None):
"transfers the values from the widget to the object"
d = []
a = []
l = []
@@ -651,11 +744,13 @@ class _AxisTaskPanel:
FreeCAD.ActiveDocument.recompute()
def reject(self):
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
return True
def retranslateUi(self, TaskPanel):
TaskPanel.setWindowTitle(QtGui.QApplication.translate("Arch", "Axes", None))
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None))
self.addButton.setText(QtGui.QApplication.translate("Arch", "Add", None))
@@ -667,21 +762,38 @@ class _AxisTaskPanel:
class _AxisSystem:
"The Axis System object"
def __init__(self,obj):
obj.addProperty("App::PropertyLinkList","Axes","Arch", QT_TRANSLATE_NOOP("App::Property","The axes this system is made of"))
obj.addProperty("App::PropertyPlacement","Placement","Base","")
self.Type = "AxisSystem"
obj.Proxy = self
self.setProperties(obj)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Axes" in pl:
obj.addProperty("App::PropertyLinkList","Axes","AxisSystem", QT_TRANSLATE_NOOP("App::Property","The axes this system is made of"))
if not "Placement" in pl:
obj.addProperty("App::PropertyPlacement","Placement","AxisSystem",QT_TRANSLATE_NOOP("App::Property","The placement of this axis system"))
self.Type = "AxisSystem"
def onDocumentRestored(self,obj):
self.setProperties(obj)
def execute(self,obj):
pass
def onBeforeChange(self,obj,prop):
if prop == "Placement":
self.Placement = obj.Placement
def onChanged(self,obj,prop):
if prop == "Placement":
if hasattr(self,"Placement"):
delta = obj.Placement.multiply(self.Placement.inverse())
@@ -689,14 +801,17 @@ class _AxisSystem:
o.Placement = delta.multiply(o.Placement)
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
def getPoints(self,obj):
"returns the gridpoints of linked axes"
import DraftGeomUtils
pts = []
if len(obj.Axes) == 1:
@@ -728,61 +843,78 @@ class _AxisSystem:
class _ViewProviderAxisSystem:
"A View Provider for the Axis object"
def __init__(self,vobj):
vobj.Proxy = self
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Axis_System_Tree.svg"
def claimChildren(self):
if hasattr(self,"axes"):
return self.axes
return []
def attach(self, vobj):
self.axes = vobj.Object.Axes
def getDisplayModes(self,vobj):
return ["Default"]
def getDefaultDisplayMode(self):
return "Default"
def setDisplayMode(self,mode):
return mode
def updateData(self,obj,prop):
self.axes = obj.Axes
def onChanged(self, vobj, prop):
if prop == "Visibility":
for o in vobj.Object.Axes:
o.ViewObject.Visibility = vobj.Visibility
def setEdit(self,vobj,mode=0):
taskd = AxisSystemTaskPanel(vobj.Object)
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return
def doubleClicked(self,vobj):
self.setEdit(vobj)
def __getstate__(self):
return None
def __setstate__(self,state):
return None
class AxisSystemTaskPanel:
'''A TaskPanel for all the section plane object'''
def __init__(self,obj):
self.obj = obj
@@ -815,15 +947,19 @@ class AxisSystemTaskPanel:
self.update()
def isAllowedAlterSelection(self):
return True
def isAllowedAlterView(self):
return True
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
def getIcon(self,obj):
if hasattr(obj.ViewObject,"Proxy"):
return QtGui.QIcon(obj.ViewObject.Proxy.getIcon())
elif obj.isDerivedFrom("Sketcher::SketchObject"):
@@ -834,6 +970,7 @@ class AxisSystemTaskPanel:
return QtGui.QIcon(":/icons/Tree_Part.svg")
def update(self):
self.tree.clear()
if self.obj:
for o in self.obj.Axes:
@@ -844,6 +981,7 @@ class AxisSystemTaskPanel:
self.retranslateUi(self.form)
def addElement(self):
if self.obj:
for o in FreeCADGui.Selection.getSelection():
if (not(o in self.obj.Axes)) and (o != self.obj):
@@ -853,6 +991,7 @@ class AxisSystemTaskPanel:
self.update()
def removeElement(self):
if self.obj:
it = self.tree.currentItem()
if it:
@@ -864,11 +1003,13 @@ class AxisSystemTaskPanel:
self.update()
def accept(self):
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
return True
def retranslateUi(self, TaskPanel):
TaskPanel.setWindowTitle(QtGui.QApplication.translate("Arch", "Axes", None))
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None))
self.addButton.setText(QtGui.QApplication.translate("Arch", "Add", None))
@@ -880,24 +1021,48 @@ class ArchGrid:
"The Grid object"
def __init__(self,obj):
obj.addProperty("App::PropertyInteger","Rows","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The number of rows'))
obj.addProperty("App::PropertyInteger","Columns","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The number of columns'))
obj.addProperty("App::PropertyFloatList","RowSize","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The sizes for rows'))
obj.addProperty("App::PropertyFloatList","ColumnSize","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The sizes of columns'))
obj.addProperty("App::PropertyStringList","Spans","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The span ranges of cells that are merged together'))
obj.addProperty("App::PropertyEnumeration","PointsOutput","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The type of 3D points produced by this grid object'))
obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The total width of this grid'))
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The total height of this grid'))
obj.addProperty("App::PropertyLength","AutoWidth","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'Creates automatic column divisions (set to 0 to disable)'))
obj.addProperty("App::PropertyLength","AutoHeight","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'Creates automatic row divisions (set to 0 to disable)'))
obj.addProperty("App::PropertyBool","Reorient","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'When in edge midpoint mode, if this grid must reorient its children along edge normals or not'))
obj.addProperty("App::PropertyIntegerList","HiddenFaces","Arch",QT_TRANSLATE_NOOP("Arch_Grid",'The indices of faces to hide'))
obj.PointsOutput = ["Vertices","Edges","Vertical Edges","Horizontal Edges","Faces"]
self.Type = "Grid"
obj.Proxy = self
self.setProperties(obj)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Rows" in pl:
obj.addProperty("App::PropertyInteger","Rows","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The number of rows'))
if not "Columns" in pl:
obj.addProperty("App::PropertyInteger","Columns","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The number of columns'))
if not "RowSize" in pl:
obj.addProperty("App::PropertyFloatList","RowSize","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The sizes for rows'))
if not "ColumnSize" in pl:
obj.addProperty("App::PropertyFloatList","ColumnSize","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The sizes of columns'))
if not "Spans" in pl:
obj.addProperty("App::PropertyStringList","Spans","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The span ranges of cells that are merged together'))
if not "PointsOutput" in pl:
obj.addProperty("App::PropertyEnumeration","PointsOutput","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The type of 3D points produced by this grid object'))
obj.PointsOutput = ["Vertices","Edges","Vertical Edges","Horizontal Edges","Faces"]
if not "Width" in pl:
obj.addProperty("App::PropertyLength","Width","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The total width of this grid'))
if not "Height" in pl:
obj.addProperty("App::PropertyLength","Height","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The total height of this grid'))
if not "AutoWidth" in pl:
obj.addProperty("App::PropertyLength","AutoWidth","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'Creates automatic column divisions (set to 0 to disable)'))
if not "AutoHeight" in pl:
obj.addProperty("App::PropertyLength","AutoHeight","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'Creates automatic row divisions (set to 0 to disable)'))
if not "Reorient" in pl:
obj.addProperty("App::PropertyBool","Reorient","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'When in edge midpoint mode, if this grid must reorient its children along edge normals or not'))
if not "HiddenFaces" in pl:
obj.addProperty("App::PropertyIntegerList","HiddenFaces","Grid",QT_TRANSLATE_NOOP("Arch_Grid",'The indices of faces to hide'))
self.Type = "Grid"
def onDocumentRestored(self,obj):
self.setProperties(obj)
def getSizes(self,obj):
"returns rowsizes,columnsizes,spangroups"
if not obj.Height.Value:
return [],[],[]
if not obj.Width.Value:
@@ -980,6 +1145,7 @@ class ArchGrid:
return rowsizes,columnsizes,spangroups
def execute(self,obj):
pl = obj.Placement
import Part
rowsizes,columnsizes,spangroups = self.getSizes(obj)
@@ -1020,7 +1186,9 @@ class ArchGrid:
obj.Placement = pl
def getPoints(self,obj):
"returns the gridpoints"
def remdupes(pts):
# eliminate possible duplicates
ret = []
@@ -1044,11 +1212,12 @@ class ArchGrid:
return [f.CenterOfMass for f in obj.Shape.Faces]
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
class ViewProviderArchGrid:
@@ -1056,28 +1225,35 @@ class ViewProviderArchGrid:
"A View Provider for the Arch Grid"
def __init__(self,vobj):
vobj.Proxy = self
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Grid.svg"
def setEdit(self,vobj,mode=0):
taskd = ArchGridTaskPanel(vobj.Object)
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return
def doubleClicked(self,vobj):
self.setEdit(vobj)
def __getstate__(self):
return None
def __setstate__(self,state):
return None
@@ -1086,6 +1262,7 @@ class ArchGridTaskPanel:
'''A TaskPanel for the Arch Grid'''
def __init__(self,obj):
# length, width, label
self.width = 0
self.height = 0
@@ -1161,6 +1338,7 @@ class ArchGridTaskPanel:
self.retranslateUi()
def retranslateUi(self,widget=None):
self.form.setWindowTitle(QtGui.QApplication.translate("Arch", "Grid", None))
self.wLabel.setText(QtGui.QApplication.translate("Arch", "Total width", None))
self.hLabel.setText(QtGui.QApplication.translate("Arch", "Total height", None))
@@ -1173,6 +1351,7 @@ class ArchGridTaskPanel:
self.title.setText(QtGui.QApplication.translate("Arch", "Rows", None)+": "+str(self.table.rowCount())+" / "+QtGui.QApplication.translate("Arch", "Columns", None)+": "+str(self.table.columnCount()))
def update(self):
self.table.clear()
if self.obj.Rows:
self.table.setRowCount(self.obj.Rows)
@@ -1198,6 +1377,7 @@ class ArchGridTaskPanel:
self.spans.append(span)
def checkSpan(self):
if self.table.selectedRanges():
self.spanButton.setEnabled(False)
self.delSpanButton.setEnabled(False)
@@ -1215,28 +1395,33 @@ class ArchGridTaskPanel:
self.delSpanButton.setEnabled(False)
def addRow(self):
c = self.table.currentRow()
self.table.insertRow(c+1)
self.table.setVerticalHeaderItem(c+1,QtGui.QTableWidgetItem("0"))
self.retranslateUi()
def delRow(self):
if self.table.selectedRanges():
self.table.removeRow(self.table.currentRow())
self.retranslateUi()
def addColumn(self):
c = self.table.currentColumn()
self.table.insertColumn(c+1)
self.table.setHorizontalHeaderItem(c+1,QtGui.QTableWidgetItem("0"))
self.retranslateUi()
def delColumn(self):
if self.table.selectedRanges():
self.table.removeColumn(self.table.currentColumn())
self.retranslateUi()
def addSpan(self):
for r in self.table.selectedRanges():
if r.rowCount() * r.columnCount() > 1:
self.table.setSpan(r.topRow(),r.leftColumn(),r.rowCount(),r.columnCount())
@@ -1261,6 +1446,7 @@ class ArchGridTaskPanel:
self.spans.append([tr,lc,(br-tr)+1,(rc-lc)+1])
def removeSpan(self):
for r in self.table.selectedRanges():
if r.rowCount() * r.columnCount() == 1:
if self.table.rowSpan(r.topRow(),r.leftColumn()) > 1 \
@@ -1275,22 +1461,27 @@ class ArchGridTaskPanel:
self.spans.pop(f)
def editHorizontalHeader(self, index):
val,ok = QtGui.QInputDialog.getText(None,'Edit size','New size')
if ok:
self.table.setHorizontalHeaderItem(index,QtGui.QTableWidgetItem(val))
def editVerticalHeader(self, index):
val,ok = QtGui.QInputDialog.getText(None,'Edit size','New size')
if ok:
self.table.setVerticalHeaderItem(index,QtGui.QTableWidgetItem(val))
def setWidth(self,d):
self.width = d
def setHeight(self,d):
self.height = d
def accept(self):
self.obj.Width = self.width
self.obj.Height = self.height
self.obj.Rows = self.table.rowCount()
@@ -1303,6 +1494,7 @@ class ArchGridTaskPanel:
return True
def reject(self):
FreeCADGui.ActiveDocument.resetEdit()
return True

View File

@@ -191,8 +191,10 @@ BuildingTypes = ['Undefined',
def makeBuilding(objectslist=None,baseobj=None,name="Building"):
'''makeBuilding(objectslist): creates a building including the
objects from the given list.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -205,18 +207,24 @@ def makeBuilding(objectslist=None,baseobj=None,name="Building"):
obj.Label = translate("Arch",name)
return obj
class _CommandBuilding:
"the Arch Building command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Building',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Building","Building"),
'Accel': "B, U",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Building","Creates a building object including selected objects.")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
link = p.GetBool("FreeLinking",False)
@@ -234,7 +242,7 @@ class _CommandBuilding:
message = translate( "Arch" , "You can put anything but Site and Building object in a Building object.\n\
Building object is not allowed to accept Site and Building object.\n\
Site and Building objects will be removed from the selection.\n\
You can change that in the preferences.") + "\n"
You can change that in the preferences.") + "\n"
ArchCommands.printMessage( message )
if sel and len(buildingobj) == 0:
message = translate( "Arch" , "There is no valid object in the selection.\n\
@@ -253,23 +261,46 @@ Building creation aborted.") + "\n"
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
class _Building(ArchFloor._Floor):
"The Building object"
def __init__(self,obj):
ArchFloor._Floor.__init__(self,obj)
obj.addProperty("App::PropertyEnumeration","BuildingType","Arch",QT_TRANSLATE_NOOP("App::Property","The type of this building"))
self.Type = "Building"
self.setProperties(obj)
obj.IfcRole = "Building"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "BuildingType" in pl:
obj.addProperty("App::PropertyEnumeration","BuildingType","Arch",QT_TRANSLATE_NOOP("App::Property","The type of this building"))
obj.BuildingType = BuildingTypes
obj.setEditorMode('Height',2)
obj.BuildingType = BuildingTypes
self.Type = "Building"
def onDocumentRestored(self,obj):
ArchFloor._Floor.onDocumentRestored(self,obj)
self.setProperties(obj)
class _ViewProviderBuilding(ArchFloor._ViewProviderFloor):
"A View Provider for the Building object"
def __init__(self,vobj):
ArchFloor._ViewProviderFloor.__init__(self,vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Building_Tree.svg"
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Building',_CommandBuilding())

View File

@@ -93,9 +93,13 @@ else:
# This module provides the base Arch component class, that
# is shared by all of the Arch BIM objects
def convertOldComponents(objs=[]):
"""converts Arch Objects with a Role property to the new IfcRole.
if no object is given, all objects of the active document are converted"""
if not objs:
objs = FreeCAD.ActiveDocument.Objects
if not isinstance(objs,list):
@@ -109,13 +113,15 @@ def convertOldComponents(objs=[]):
else:
FreeCAD.Console.PrintMessage("Role "+obj.Role+" cannot be mapped for object "+obj.Label+"\n")
obj.removeProperty("Role")
def addToComponent(compobject,addobject,mod=None):
'''addToComponent(compobject,addobject,mod): adds addobject
to the given component. Default is in "Additions", "Objects" or
"Components", the first one that exists in the component. Mod
can be set to one of those attributes ("Objects", Base", etc...)
to override the default.'''
import Draft
if compobject == addobject: return
@@ -160,10 +166,12 @@ def addToComponent(compobject,addobject,mod=None):
def removeFromComponent(compobject,subobject):
'''removeFromComponent(compobject,subobject): subtracts subobject
from the given component. If the subobject is already part of the
component (as addition, subtraction, etc... it is removed. Otherwise,
it is added as a subtraction.'''
if compobject == subobject: return
found = False
attribs = ["Additions","Subtractions","Objects","Components","Base","Axes","Fixtures","Group","Hosts"]
@@ -193,7 +201,9 @@ def removeFromComponent(compobject,subobject):
class SelectionTaskPanel:
"""A temporary TaskPanel to wait for a selection"""
def __init__(self):
self.baseform = QtGui.QLabel()
self.baseform.setText(QtGui.QApplication.translate("Arch", "Please select a base object", None))
@@ -209,8 +219,11 @@ class SelectionTaskPanel:
class ComponentTaskPanel:
'''The default TaskPanel for all Arch components'''
def __init__(self):
# the panel has a tree widget that contains categories
# for the subcomponents, such as additions, subtractions.
# the categories are shown only if they are not empty.
@@ -251,15 +264,19 @@ class ComponentTaskPanel:
self.update()
def isAllowedAlterSelection(self):
return True
def isAllowedAlterView(self):
return True
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
def check(self,wid,col):
if not wid.parent():
self.delButton.setEnabled(False)
if self.obj:
@@ -272,6 +289,7 @@ class ComponentTaskPanel:
self.addButton.setEnabled(False)
def getIcon(self,obj):
if hasattr(obj.ViewObject,"Proxy"):
if hasattr(obj.ViewObject.Proxy,"getIcon"):
return QtGui.QIcon(obj.ViewObject.Proxy.getIcon())
@@ -282,6 +300,7 @@ class ComponentTaskPanel:
return QtGui.QIcon(":/icons/Tree_Part.svg")
def update(self):
'fills the treewidget'
self.tree.clear()
dirIcon = QtGui.QApplication.style().standardIcon(QtGui.QStyle.SP_DirIcon)
@@ -313,6 +332,7 @@ class ComponentTaskPanel:
self.retranslateUi(self.baseform)
def addElement(self):
it = self.tree.currentItem()
if it:
mod = None
@@ -324,6 +344,7 @@ class ComponentTaskPanel:
self.update()
def removeElement(self):
it = self.tree.currentItem()
if it:
comp = FreeCAD.ActiveDocument.getObject(str(it.toolTip(0)))
@@ -331,11 +352,13 @@ class ComponentTaskPanel:
self.update()
def accept(self):
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
return True
def editObject(self,wid,col):
if wid.parent():
obj = FreeCAD.ActiveDocument.getObject(str(wid.toolTip(0)))
if obj:
@@ -350,6 +373,7 @@ class ComponentTaskPanel:
FreeCADGui.ActiveDocument.setEdit(obj.Name,0)
def retranslateUi(self, TaskPanel):
self.baseform.setWindowTitle(QtGui.QApplication.translate("Arch", "Components", None))
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None))
self.addButton.setText(QtGui.QApplication.translate("Arch", "Add", None))
@@ -364,35 +388,72 @@ class ComponentTaskPanel:
self.treeGroup.setText(0,QtGui.QApplication.translate("Arch", "Group", None))
self.treeHosts.setText(0,QtGui.QApplication.translate("Arch", "Hosts", None))
class Component:
"The default Arch Component object"
def __init__(self,obj):
obj.addProperty("App::PropertyLink","Base","Component",QT_TRANSLATE_NOOP("App::Property","The base object this component is built upon"))
obj.addProperty("App::PropertyLink","CloneOf","Component",QT_TRANSLATE_NOOP("App::Property","The object this component is cloning"))
obj.addProperty("App::PropertyLinkList","Additions","Component",QT_TRANSLATE_NOOP("App::Property","Other shapes that are appended to this object"))
obj.addProperty("App::PropertyLinkList","Subtractions","Component",QT_TRANSLATE_NOOP("App::Property","Other shapes that are subtracted from this object"))
obj.addProperty("App::PropertyString","Description","Component",QT_TRANSLATE_NOOP("App::Property","An optional description for this component"))
obj.addProperty("App::PropertyString","Tag","Component",QT_TRANSLATE_NOOP("App::Property","An optional tag for this component"))
obj.addProperty("App::PropertyMap","IfcAttributes","Component",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes"))
obj.addProperty("App::PropertyLink","Material","Component",QT_TRANSLATE_NOOP("App::Property","A material for this object"))
obj.addProperty("App::PropertyEnumeration","IfcRole","Component",QT_TRANSLATE_NOOP("App::Property","The role of this object"))
obj.addProperty("App::PropertyBool","MoveWithHost","Component",QT_TRANSLATE_NOOP("App::Property","Specifies if this object must move together when its host is moved"))
obj.addProperty("App::PropertyLink","IfcProperties","Component",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes"))
obj.addProperty("App::PropertyArea","VerticalArea","Component",QT_TRANSLATE_NOOP("App::Property","The area of all vertical faces of this object"))
obj.addProperty("App::PropertyArea","HorizontalArea","Component",QT_TRANSLATE_NOOP("App::Property","The area of the projection of this object onto the XY plane"))
obj.addProperty("App::PropertyLength","PerimeterLength","Component",QT_TRANSLATE_NOOP("App::Property","The perimeter length of the horizontal area"))
obj.addProperty("App::PropertyLink","HiRes","Component",QT_TRANSLATE_NOOP("App::Property","An optional higher-resolution mesh or shape for this object"))
obj.addProperty("App::PropertyLink","Axis","Component",QT_TRANSLATE_NOOP("App::Property","An optional axis or axis system on which this object should be duplicated"))
obj.Proxy = self
Component.setProperties(self,obj)
self.Type = "Component"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Base" in pl:
obj.addProperty("App::PropertyLink","Base","Component",QT_TRANSLATE_NOOP("App::Property","The base object this component is built upon"))
if not "CloneOf" in pl:
obj.addProperty("App::PropertyLink","CloneOf","Component",QT_TRANSLATE_NOOP("App::Property","The object this component is cloning"))
if not "Additions" in pl:
obj.addProperty("App::PropertyLinkList","Additions","Component",QT_TRANSLATE_NOOP("App::Property","Other shapes that are appended to this object"))
if not "Subtractions" in pl:
obj.addProperty("App::PropertyLinkList","Subtractions","Component",QT_TRANSLATE_NOOP("App::Property","Other shapes that are subtracted from this object"))
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 "Material" in pl:
obj.addProperty("App::PropertyLink","Material","Component",QT_TRANSLATE_NOOP("App::Property","A material for this object"))
if not "IfcRole" in pl:
obj.addProperty("App::PropertyEnumeration","IfcRole","Component",QT_TRANSLATE_NOOP("App::Property","The role of this object"))
obj.IfcRole = IfcRoles
if "Role" in pl:
r = obj.Role
obj.removeProperty("Role")
if r in IfcRoles:
obj.IfcRole = r
FreeCAD.Console.PrintMessage("Upgrading "+obj.Label+" Role property to IfcRole\n")
if not "MoveWithHost" in pl:
obj.addProperty("App::PropertyBool","MoveWithHost","Component",QT_TRANSLATE_NOOP("App::Property","Specifies if this object must move together when its host is moved"))
if not "IfcProperties" in pl:
obj.addProperty("App::PropertyLink","IfcProperties","Component",QT_TRANSLATE_NOOP("App::Property","Custom IFC properties and attributes"))
if not "VerticalArea" in pl:
obj.addProperty("App::PropertyArea","VerticalArea","Component",QT_TRANSLATE_NOOP("App::Property","The area of all vertical faces of this object"))
obj.setEditorMode("VerticalArea",1)
if not "HorizontalArea" in pl:
obj.addProperty("App::PropertyArea","HorizontalArea","Component",QT_TRANSLATE_NOOP("App::Property","The area of the projection of this object onto the XY plane"))
obj.setEditorMode("HorizontalArea",1)
if not "PerimeterLength" in pl:
obj.addProperty("App::PropertyLength","PerimeterLength","Component",QT_TRANSLATE_NOOP("App::Property","The perimeter length of the horizontal area"))
obj.setEditorMode("PerimeterLength",1)
if not "HiRes" in pl:
obj.addProperty("App::PropertyLink","HiRes","Component",QT_TRANSLATE_NOOP("App::Property","An optional higher-resolution mesh or shape for this object"))
if not "Axis" in pl:
obj.addProperty("App::PropertyLink","Axis","Component",QT_TRANSLATE_NOOP("App::Property","An optional axis or axis system on which this object should be duplicated"))
self.Subvolume = None
self.MoveWithHost = False
obj.IfcRole = IfcRoles
obj.setEditorMode("VerticalArea",1)
obj.setEditorMode("HorizontalArea",1)
obj.setEditorMode("PerimeterLength",1)
#self.MoveWithHost = False
self.Type = "Component"
def onDocumentRestored(self,obj):
Component.setProperties(self,obj)
def execute(self,obj):
if self.clone(obj):
return
if obj.Base:
@@ -402,13 +463,15 @@ class Component:
obj.Shape = shape
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
def onDocumentRestored(self,obj):
if hasattr(obj,"BaseMaterial"):
if not hasattr(obj,"Material"):
obj.addProperty("App::PropertyLink","Material","Arch",QT_TRANSLATE_NOOP("App::Property","A material for this object"))
@@ -417,10 +480,12 @@ class Component:
print("Migrated old BaseMaterial property -> Material in ",obj.Label)
def onBeforeChange(self,obj,prop):
if prop == "Placement":
self.placementBefore = FreeCAD.Placement(obj.Placement)
def onChanged(self,obj,prop):
if prop == "Placement":
if hasattr(self,"placementBefore"):
delta = FreeCAD.Placement()
@@ -430,6 +495,7 @@ class Component:
o.Placement = o.Placement.multiply(delta)
def getIncluded(self,obj,movable=False):
ilist = []
for o in obj.InList:
if hasattr(o,"Hosts"):
@@ -437,12 +503,13 @@ class Component:
if movable:
if hasattr(o,"MoveWithHost"):
if o.MoveWithHost:
ilist.append(o)
ilist.append(o)
else:
ilist.append(o)
return ilist
def clone(self,obj):
"if this object is a clone, sets the shape. Returns True if this is the case"
if hasattr(obj,"CloneOf"):
if obj.CloneOf:
@@ -457,6 +524,7 @@ class Component:
return False
def getSiblings(self,obj):
"returns a list of objects with the same type and same base as this object"
if not hasattr(obj,"Base"):
return []
@@ -473,6 +541,7 @@ class Component:
return siblings
def getExtrusionData(self,obj):
"returns (shape,extrusion vector,placement) or None"
if hasattr(obj,"CloneOf"):
if obj.CloneOf:
@@ -480,7 +549,7 @@ class Component:
if hasattr(obj.CloneOf.Proxy,"getExtrusionData"):
data = obj.CloneOf.Proxy.getExtrusionData(obj.CloneOf)
if data:
return data
return data
if obj.Base:
if obj.Base.isDerivedFrom("Part::Extrusion"):
if obj.Base.Base:
@@ -526,8 +595,9 @@ class Component:
if rshapes and revs and rpls:
return (rshapes,revs,rpls)
return None
def rebase(self,shape):
"""returns a shape that is a copy of the original shape
but centered on the (0,0) origin, and a placement that is needed to
reposition that shape to its original location/orientation"""
@@ -557,6 +627,7 @@ class Component:
return(shapes,p)
def hideSubobjects(self,obj,prop):
"Hides subobjects when a subobject lists change"
if prop in ["Additions","Subtractions"]:
if hasattr(obj,prop):
@@ -570,9 +641,10 @@ class Component:
if hasattr(obj,prop):
o = getattr(obj,prop)
if o:
o.ViewObject.hide()
o.ViewObject.hide()
def processSubShapes(self,obj,base,placement=None):
"Adds additions and subtractions to a base shape"
import Draft,Part
#print("Processing subshapes of ",obj.Label, " : ",obj.Additions)
@@ -673,6 +745,7 @@ class Component:
return base
def spread(self,obj,shape,placement=None):
"spreads this shape along axis positions"
points = None
if hasattr(obj,"Axis"):
@@ -694,6 +767,7 @@ class Component:
return shape
def applyShape(self,obj,shape,placement,allowinvalid=False,allownosolid=False):
"checks and cleans the given shape, and apply it to the object"
if shape:
if not shape.isNull():
@@ -733,6 +807,7 @@ class Component:
self.computeAreas(obj)
def computeAreas(self,obj):
"computes the area properties"
if not obj.Shape:
return
@@ -794,12 +869,16 @@ class Component:
class ViewProviderComponent:
"A default View Provider for Component objects"
def __init__(self,vobj):
vobj.Proxy = self
self.Object = vobj.Object
def updateData(self,obj,prop):
#print(obj.Name," : updating ",prop)
if prop == "Material":
if obj.Material:
@@ -824,7 +903,7 @@ class ViewProviderComponent:
if hasattr(obj,"Material"):
if obj.Material:
mat = obj.Material
if not mat:
if not mat:
if obj.ViewObject.DiffuseColor != obj.CloneOf.ViewObject.DiffuseColor:
if len(obj.CloneOf.ViewObject.DiffuseColor) > 1:
obj.ViewObject.DiffuseColor = obj.CloneOf.ViewObject.DiffuseColor
@@ -833,6 +912,7 @@ class ViewProviderComponent:
return
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
if hasattr(self.Object,"CloneOf"):
@@ -841,6 +921,7 @@ class ViewProviderComponent:
return ":/icons/Arch_Component.svg"
def onChanged(self,vobj,prop):
#print(vobj.Object.Name, " : changing ",prop)
if prop == "Visibility":
#for obj in vobj.Object.Additions+vobj.Object.Subtractions:
@@ -864,6 +945,7 @@ class ViewProviderComponent:
return
def attach(self,vobj):
from pivy import coin
self.Object = vobj.Object
self.hiresgroup = coin.SoSeparator()
@@ -874,10 +956,12 @@ class ViewProviderComponent:
return
def getDisplayModes(self,vobj):
modes=["HiRes"]
return modes
def setDisplayMode(self,mode):
if hasattr(self,"meshnode"):
if self.meshnode:
self.hiresgroup.removeChild(self.meshnode)
@@ -919,12 +1003,15 @@ class ViewProviderComponent:
return mode
def __getstate__(self):
return None
def __setstate__(self,state):
return None
def claimChildren(self):
if hasattr(self,"Object"):
c = []
if hasattr(self.Object,"Base"):
@@ -964,6 +1051,7 @@ class ViewProviderComponent:
return []
def setEdit(self,vobj,mode):
if mode == 0:
taskd = ComponentTaskPanel()
taskd.obj = self.Object
@@ -973,11 +1061,13 @@ class ViewProviderComponent:
return False
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return False
class ArchSelectionObserver:
"""ArchSelectionObserver([origin,watched,hide,nextCommand]): The ArchSelectionObserver
object can be added as a selection observer to the FreeCAD Gui. If watched is given (a
document object), the observer will be triggered only when that object is selected/unselected.
@@ -986,12 +1076,14 @@ class ArchSelectionObserver:
is given (a FreeCAD command), it will be executed on leave."""
def __init__(self,origin=None,watched=None,hide=True,nextCommand=None):
self.origin = origin
self.watched = watched
self.hide = hide
self.nextCommand = nextCommand
def addSelection(self,document, object, element, position):
if not self.watched:
FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
if self.nextCommand:

View File

@@ -53,6 +53,7 @@ else:
def makeEquipment(baseobj=None,placement=None,name="Equipment"):
"makeEquipment([baseobj,placement,name]): creates an equipment object from the given base object."
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
@@ -74,6 +75,7 @@ def makeEquipment(baseobj=None,placement=None,name="Equipment"):
return obj
def createMeshView(obj,direction=FreeCAD.Vector(0,0,-1),outeronly=False,largestonly=False):
"""createMeshView(obj,[direction,outeronly,largestonly]): creates a flat shape that is the
projection of the given mesh object in the given direction (default = on the XY plane). If
outeronly is True, only the outer contour is taken into consideration, discarding the inner
@@ -162,17 +164,22 @@ def createMeshView(obj,direction=FreeCAD.Vector(0,0,-1),outeronly=False,largesto
class _CommandEquipment:
"the Arch Equipment command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Equipment',
'MenuText': QT_TRANSLATE_NOOP("Arch_Equipment","Equipment"),
'Accel': "E, Q",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Equipment","Creates an equipment object from a selected object (Part or Mesh)")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
s = FreeCADGui.Selection.getSelection()
if not s:
FreeCAD.Console.PrintError(translate("Arch","You must select a base shape object and optionally a mesh object"))
@@ -213,16 +220,21 @@ class _CommandEquipment:
class _Command3Views:
"the Arch 3Views command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_3Views',
'MenuText': QT_TRANSLATE_NOOP("Arch_3Views","3 views from mesh"),
'ToolTip': QT_TRANSLATE_NOOP("Arch_3Views","Creates 3 views (top, front, side) from a mesh-based object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
s = FreeCADGui.Selection.getSelection()
if len(s) != 1:
FreeCAD.Console.PrintError(translate("Arch","You must select exactly one base object"))
@@ -257,22 +269,41 @@ class _Command3Views:
class _Equipment(ArchComponent.Component):
"The Equipment object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyString","Model","Arch",QT_TRANSLATE_NOOP("App::Property","The model description of this equipment"))
obj.addProperty("App::PropertyString","ProductURL","Arch",QT_TRANSLATE_NOOP("App::Property","The URL of the product page of this equipment"))
obj.addProperty("App::PropertyString","StandardCode","Arch",QT_TRANSLATE_NOOP("App::Property","A standard code (MasterFormat, OmniClass,...)"))
obj.addProperty("App::PropertyVectorList","SnapPoints","Arch",QT_TRANSLATE_NOOP("App::Property","Additional snap points for this equipment"))
obj.addProperty("App::PropertyFloat","EquipmentPower","Arch",QT_TRANSLATE_NOOP("App::Property","The electric power needed by this equipment in Watts"))
self.Type = "Equipment"
obj.IfcRole = "Furniture"
obj.Proxy = self
self.setProperties(obj)
obj.IfcRole = "Furniture"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Model" in pl:
obj.addProperty("App::PropertyString","Model","Equipment",QT_TRANSLATE_NOOP("App::Property","The model description of this equipment"))
if not "ProductURL" in pl:
obj.addProperty("App::PropertyString","ProductURL","Equipment",QT_TRANSLATE_NOOP("App::Property","The URL of the product page of this equipment"))
if not "StandardCode" in pl:
obj.addProperty("App::PropertyString","StandardCode","Equipment",QT_TRANSLATE_NOOP("App::Property","A standard code (MasterFormat, OmniClass,...)"))
if not "SnapPoints" in pl:
obj.addProperty("App::PropertyVectorList","SnapPoints","Equipment",QT_TRANSLATE_NOOP("App::Property","Additional snap points for this equipment"))
if not "EquipmentPower" in pl:
obj.addProperty("App::PropertyFloat","EquipmentPower","Equipment",QT_TRANSLATE_NOOP("App::Property","The electric power needed by this equipment in Watts"))
obj.setEditorMode("VerticalArea",2)
obj.setEditorMode("HorizontalArea",2)
obj.setEditorMode("PerimeterLength",2)
self.Type = "Equipment"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def onChanged(self,obj,prop):
self.hideSubobjects(obj,prop)
ArchComponent.Component.onChanged(self,obj,prop)
@@ -294,12 +325,15 @@ class _Equipment(ArchComponent.Component):
class _ViewProviderEquipment(ArchComponent.ViewProviderComponent):
"A View Provider for the Equipment object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
if hasattr(self.Object,"CloneOf"):
@@ -308,6 +342,7 @@ class _ViewProviderEquipment(ArchComponent.ViewProviderComponent):
return ":/icons/Arch_Equipment_Tree.svg"
def attach(self, vobj):
self.Object = vobj.Object
from pivy import coin
sep = coin.SoSeparator()
@@ -320,8 +355,9 @@ class _ViewProviderEquipment(ArchComponent.ViewProviderComponent):
rn = vobj.RootNode
rn.addChild(sep)
ArchComponent.ViewProviderComponent.attach(self,vobj)
def updateData(self, obj, prop):
if prop == "SnapPoints":
if obj.SnapPoints:
self.coords.point.setNum(len(obj.SnapPoints))

View File

@@ -36,7 +36,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchFloor
# \ingroup ARCH
# \brief The Floor object and tools
@@ -49,9 +49,12 @@ __title__="FreeCAD Arch Floor"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"
def makeFloor(objectslist=None,baseobj=None,name="Floor"):
'''makeFloor(objectslist): creates a floor including the
objects from the given list.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -64,18 +67,24 @@ def makeFloor(objectslist=None,baseobj=None,name="Floor"):
obj.Group = objectslist
return obj
class _CommandFloor:
"the Arch Cell command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Floor',
'MenuText': QT_TRANSLATE_NOOP("Arch_Floor","Floor"),
'Accel': "F, L",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Floor","Creates a floor object including selected objects")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
link = p.GetBool("FreeLinking",False)
@@ -112,26 +121,48 @@ Floor creation aborted.") + "\n"
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
class _Floor:
"The Floor object"
def __init__(self,obj):
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height of this object"))
obj.addProperty("App::PropertyArea","Area", "Arch",QT_TRANSLATE_NOOP("App::Property","The computed floor area of this floor"))
if not hasattr(obj,"Placement"):
# obj can be a Part Feature and already has a placement
obj.addProperty("App::PropertyPlacement","Placement","Arch",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
self.Type = "Floor"
obj.Proxy = self
self.Object = obj
_Floor.setProperties(self,obj)
self.IfcRole = "Building Storey"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Height" in pl:
obj.addProperty("App::PropertyLength","Height","Floor",QT_TRANSLATE_NOOP("App::Property","The height of this object"))
if not "Area" in pl:
obj.addProperty("App::PropertyArea","Area", "Floor",QT_TRANSLATE_NOOP("App::Property","The computed floor area of this floor"))
if not hasattr(obj,"Placement"):
# obj can be a Part Feature and already has a placement
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
if not "IfcRole" in pl:
obj.addProperty("App::PropertyEnumeration","IfcRole","Component",QT_TRANSLATE_NOOP("App::Property","The role of this object"))
import ArchComponent
obj.IfcRole = ArchComponent.IfcRoles
self.Type = "Floor"
def onDocumentRestored(self,obj):
_Floor.setProperties(self,obj)
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
def onChanged(self,obj,prop):
if not hasattr(self,"Object"):
# on restore, self.Object is not there anymore
self.Object = obj
@@ -145,6 +176,7 @@ class _Floor:
obj.Area = a
def execute(self,obj):
# move children with this floor
if hasattr(obj,"Placement"):
if not hasattr(self,"OldPlacement"):
@@ -166,6 +198,7 @@ class _Floor:
o.Proxy.execute(o)
def addObject(self,child):
if hasattr(self,"Object"):
g = self.Object.Group
if not child in g:
@@ -173,36 +206,47 @@ class _Floor:
self.Object.Group = g
def removeObject(self,child):
if hasattr(self,"Object"):
g = self.Object.Group
if child in g:
g.remove(child)
self.Object.Group = g
class _ViewProviderFloor:
"A View Provider for the Floor object"
def __init__(self,vobj):
vobj.Proxy = self
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Floor_Tree.svg"
def attach(self,vobj):
self.Object = vobj.Object
return
def claimChildren(self):
if hasattr(self,"Object"):
if self.Object:
return self.Object.Group
return []
def __getstate__(self):
return None
def __setstate__(self,state):
return None
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Floor',_CommandFloor())

View File

@@ -35,7 +35,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchFrame
# \ingroup ARCH
# \brief The Frame object and tools
@@ -48,9 +48,12 @@ __title__="FreeCAD Arch Frame"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"
def makeFrame(baseobj,profile,name=translate("Arch","Frame")):
"""makeFrame(baseobj,profile,[name]): creates a frame object from a base sketch (or any other object
containing wires) and a profile object (an extrudable 2D object containing faces or closed wires)"""
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -67,19 +70,24 @@ def makeFrame(baseobj,profile,name=translate("Arch","Frame")):
profile.ViewObject.hide()
return obj
class _CommandFrame:
"the Arch Frame command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Frame',
'MenuText': QT_TRANSLATE_NOOP("Arch_Frame","Frame"),
'Accel': "F, R",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Frame","Creates a frame object from a planar 2D object (the extrusion path(s)) and a profile. Make sure objects are selected in that order.")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
s = FreeCADGui.Selection.getSelection()
if len(s) == 2:
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Frame"))
@@ -92,28 +100,47 @@ class _CommandFrame:
class _Frame(ArchComponent.Component):
"A parametric frame object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLink","Profile","Arch",QT_TRANSLATE_NOOP("App::Property","The profile used to build this frame"))
obj.addProperty("App::PropertyBool","Align","Arch",QT_TRANSLATE_NOOP("App::Property","Specifies if the profile must be aligned with the extrusion wires"))
obj.addProperty("App::PropertyVectorDistance","Offset","Arch",QT_TRANSLATE_NOOP("App::Property","An offset vector between the base sketch and the frame"))
obj.addProperty("App::PropertyInteger","BasePoint","Arch",QT_TRANSLATE_NOOP("App::Property","Crossing point of the path on the profile."))
obj.addProperty("App::PropertyPlacement","ProfilePlacement","Arch",QT_TRANSLATE_NOOP("App::Property","An optional additional placement to add to the profile before extruding it"))
obj.addProperty("App::PropertyAngle","Rotation","Arch",QT_TRANSLATE_NOOP("App::Property","The rotation of the profile around its extrusion axis"))
obj.addProperty("App::PropertyEnumeration","Edges","Arch",QT_TRANSLATE_NOOP("App::Property","The type of edges to consider"))
obj.addProperty("App::PropertyBool","Fuse","Arch",QT_TRANSLATE_NOOP("App::Property","If true, geometry is fused, otherwise a compound"))
self.Type = "Frame"
obj.Align = True
self.setProperties(obj)
obj.IfcRole = "Railing"
obj.Edges = ["All edges","Vertical edges","Horizontal edges","Bottom horizontal edges","Top horizontal edges"]
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Profile" in pl:
obj.addProperty("App::PropertyLink","Profile","Frame",QT_TRANSLATE_NOOP("App::Property","The profile used to build this frame"))
if not "Align" in pl:
obj.addProperty("App::PropertyBool","Align","Frame",QT_TRANSLATE_NOOP("App::Property","Specifies if the profile must be aligned with the extrusion wires"))
obj.Align = True
if not "Offset" in pl:
obj.addProperty("App::PropertyVectorDistance","Offset","Frame",QT_TRANSLATE_NOOP("App::Property","An offset vector between the base sketch and the frame"))
if not "BasePoint" in pl:
obj.addProperty("App::PropertyInteger","BasePoint","Frame",QT_TRANSLATE_NOOP("App::Property","Crossing point of the path on the profile."))
if not "ProfilePlacement" in pl:
obj.addProperty("App::PropertyPlacement","ProfilePlacement","Frame",QT_TRANSLATE_NOOP("App::Property","An optional additional placement to add to the profile before extruding it"))
if not "Rotation" in pl:
obj.addProperty("App::PropertyAngle","Rotation","Frame",QT_TRANSLATE_NOOP("App::Property","The rotation of the profile around its extrusion axis"))
if not "Edges" in pl:
obj.addProperty("App::PropertyEnumeration","Edges","Frame",QT_TRANSLATE_NOOP("App::Property","The type of edges to consider"))
obj.Edges = ["All edges","Vertical edges","Horizontal edges","Bottom horizontal edges","Top horizontal edges"]
if not "Fuse" in pl:
obj.addProperty("App::PropertyBool","Fuse","Frame",QT_TRANSLATE_NOOP("App::Property","If true, geometry is fused, otherwise a compound"))
self.Type = "Frame"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
if self.clone(obj):
return
if not obj.Base:
return
if not obj.Base.Shape:
@@ -224,21 +251,26 @@ class _Frame(ArchComponent.Component):
class _ViewProviderFrame(ArchComponent.ViewProviderComponent):
"A View Provider for the Frame object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Frame_Tree.svg"
def claimChildren(self):
p = []
if hasattr(self,"Object"):
if self.Object.Profile:
p = [self.Object.Profile]
return ArchComponent.ViewProviderComponent.claimChildren(self)+p
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Frame',_CommandFrame())

View File

@@ -61,11 +61,15 @@ Presets = [None,
["OSB 18mm, 1220 x 2440", 1220,2440,18],
]
def makePanel(baseobj=None,length=0,width=0,thickness=0,placement=None,name="Panel"):
'''makePanel([obj],[length],[width],[thickness],[placement]): creates a
panel element based on the given profile object and the given
extrusion thickness. If no base object is given, you can also specify
length and width for a simple cubic object.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -88,8 +92,10 @@ def makePanel(baseobj=None,length=0,width=0,thickness=0,placement=None,name="Pan
def makePanelView(panel,page=None,name="PanelView"):
"""makePanelView(panel,[page]) : Creates a Drawing view of the given panel
in the given or active Page object (a new page will be created if none exists)."""
if not page:
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom("Drawing::FeaturePage"):
@@ -107,8 +113,10 @@ def makePanelView(panel,page=None,name="PanelView"):
def makePanelCut(panel,name="PanelView"):
"""makePanelCut(panel) : Creates a 2D view of the given panel
in the 3D space, positioned at the origin."""
view = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
PanelCut(view)
view.Source = panel
@@ -119,8 +127,10 @@ def makePanelCut(panel,name="PanelView"):
def makePanelSheet(panels=[],name="PanelSheet"):
"""makePanelSheet([panels]) : Creates a sheet with the given panel cuts
in the 3D space, positioned at the origin."""
sheet = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
PanelSheet(sheet)
if panels:
@@ -131,17 +141,22 @@ def makePanelSheet(panels=[],name="PanelSheet"):
class CommandPanel:
"the Arch Panel command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Panel',
'MenuText': QT_TRANSLATE_NOOP("Arch_Panel","Panel"),
'Accel': "P, A",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Panel","Creates a panel object from scratch or from a selected object (sketch, wire, face or solid)")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
self.Length = p.GetFloat("PanelLength",1000)
self.Width = p.GetFloat("PanelWidth",1000)
@@ -177,7 +192,9 @@ class CommandPanel:
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
def getPoint(self,point=None,obj=None):
"this function is called by the snapper when it has a 3D point"
self.tracker.finalize()
if point == None:
return
@@ -199,7 +216,9 @@ class CommandPanel:
self.Activated()
def taskbox(self):
"sets up a taskbox widget"
w = QtGui.QWidget()
ui = FreeCADGui.UiLoader()
w.setWindowTitle(translate("Arch","Panel options", utf8_decode=True))
@@ -261,7 +280,9 @@ class CommandPanel:
return w
def update(self,point,info):
"this function is called by the Snapper when the mouse is moved"
if FreeCADGui.Control.activeDialog():
self.tracker.pos(point)
if self.rotated:
@@ -274,41 +295,52 @@ class CommandPanel:
self.tracker.length(self.Length)
def setWidth(self,d):
self.Width = d
def setThickness(self,d):
self.Thickness = d
def setLength(self,d):
self.Length = d
def setContinue(self,i):
self.continueCmd = bool(i)
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.continueMode = bool(i)
def setPreset(self,i):
if i > 0:
self.vLength.setText(FreeCAD.Units.Quantity(float(Presets[i][1]),FreeCAD.Units.Length).UserString)
self.vWidth.setText(FreeCAD.Units.Quantity(float(Presets[i][2]),FreeCAD.Units.Length).UserString)
self.vHeight.setText(FreeCAD.Units.Quantity(float(Presets[i][3]),FreeCAD.Units.Length).UserString)
def rotate(self):
self.rotated = not self.rotated
class CommandPanelCut:
"the Arch Panel Cut command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Panel_Cut',
'MenuText': QT_TRANSLATE_NOOP("Arch_Panel_Cut","Panel Cut"),
'Accel': "P, C",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Panel_Sheet","Creates 2D views of selected panels")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
if FreeCADGui.Selection.getSelection():
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Panel Cut")))
FreeCADGui.addModule("Arch")
@@ -320,17 +352,22 @@ class CommandPanelCut:
class CommandPanelSheet:
"the Arch Panel Sheet command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Panel_Sheet',
'MenuText': QT_TRANSLATE_NOOP("Arch_Panel_Sheet","Panel Sheet"),
'Accel': "P, S",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Panel_Sheet","Creates a 2D sheet which can contain panel cuts")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Panel Sheet")))
FreeCADGui.addModule("Arch")
if FreeCADGui.Selection.getSelection():
@@ -350,32 +387,60 @@ class CommandPanelSheet:
class _Panel(ArchComponent.Component):
"The Panel object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLength","Length","Arch", QT_TRANSLATE_NOOP("App::Property","The length of this element, if not based on a profile"))
obj.addProperty("App::PropertyLength","Width","Arch", QT_TRANSLATE_NOOP("App::Property","The width of this element, if not based on a profile"))
obj.addProperty("App::PropertyLength","Thickness","Arch",QT_TRANSLATE_NOOP("App::Property","The thickness or extrusion depth of this element"))
obj.addProperty("App::PropertyInteger","Sheets","Arch", QT_TRANSLATE_NOOP("App::Property","The number of sheets to use"))
obj.addProperty("App::PropertyDistance","Offset","Arch", QT_TRANSLATE_NOOP("App::Property","The offset between this panel and its baseline"))
obj.addProperty("App::PropertyLength","WaveLength","Arch", QT_TRANSLATE_NOOP("App::Property","The length of waves for corrugated elements"))
obj.addProperty("App::PropertyLength","WaveHeight","Arch", QT_TRANSLATE_NOOP("App::Property","The height of waves for corrugated elements"))
obj.addProperty("App::PropertyDistance","WaveOffset","Arch", QT_TRANSLATE_NOOP("App::Property","The horizontal offset of waves for corrugated elements"))
obj.addProperty("App::PropertyAngle","WaveDirection","Arch", QT_TRANSLATE_NOOP("App::Property","The direction of waves for corrugated elements"))
obj.addProperty("App::PropertyEnumeration","WaveType","Arch", QT_TRANSLATE_NOOP("App::Property","The type of waves for corrugated elements"))
obj.addProperty("App::PropertyBool","WaveBottom","Arch", QT_TRANSLATE_NOOP("App::Property","If the wave also affects the bottom side or not"))
obj.addProperty("App::PropertyArea","Area","Arch", QT_TRANSLATE_NOOP("App::Property","The area of this panel"))
obj.addProperty("App::PropertyEnumeration","FaceMaker","Arch",QT_TRANSLATE_NOOP("App::Property","The facemaker type to use to build the profile of this object"))
obj.addProperty("App::PropertyVector","Normal","Arch",QT_TRANSLATE_NOOP("App::Property","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))
obj.Sheets = 1
self.Type = "Panel"
self.setProperties(obj)
obj.IfcRole = "Plate"
obj.WaveType = ["Curved","Trapezoidal","Spikes"]
obj.FaceMaker = ["None","Simple","Cheese","Bullseye"]
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Length" in pl:
obj.addProperty("App::PropertyLength","Length","Panel", QT_TRANSLATE_NOOP("App::Property","The length of this element, if not based on a profile"))
if not "Width" in pl:
obj.addProperty("App::PropertyLength","Width","Panel", QT_TRANSLATE_NOOP("App::Property","The width of this element, if not based on a profile"))
if not "Thickness" in pl:
obj.addProperty("App::PropertyLength","Thickness","Panel",QT_TRANSLATE_NOOP("App::Property","The thickness or extrusion depth of this element"))
if not "Sheets" in pl:
obj.addProperty("App::PropertyInteger","Sheets","Panel", QT_TRANSLATE_NOOP("App::Property","The number of sheets to use"))
obj.Sheets = 1
if not "Offset" in pl:
obj.addProperty("App::PropertyDistance","Offset","Panel", QT_TRANSLATE_NOOP("App::Property","The offset between this panel and its baseline"))
if not "WaveLength" in pl:
obj.addProperty("App::PropertyLength","WaveLength","Panel", QT_TRANSLATE_NOOP("App::Property","The length of waves for corrugated elements"))
if not "WaveHeight" in pl:
obj.addProperty("App::PropertyLength","WaveHeight","Panel", QT_TRANSLATE_NOOP("App::Property","The height of waves for corrugated elements"))
if not "WaveOffset" in pl:
obj.addProperty("App::PropertyDistance","WaveOffset","Panel", QT_TRANSLATE_NOOP("App::Property","The horizontal offset of waves for corrugated elements"))
if not "WaveDirection" in pl:
obj.addProperty("App::PropertyAngle","WaveDirection","Panel", QT_TRANSLATE_NOOP("App::Property","The direction of waves for corrugated elements"))
if not "WaveType" in pl:
obj.addProperty("App::PropertyEnumeration","WaveType","Panel", QT_TRANSLATE_NOOP("App::Property","The type of waves for corrugated elements"))
obj.WaveType = ["Curved","Trapezoidal","Spikes"]
if not "WaveBottom" in pl:
obj.addProperty("App::PropertyBool","WaveBottom","Panel", QT_TRANSLATE_NOOP("App::Property","If the wave also affects the bottom side or not"))
if not "Area" in pl:
obj.addProperty("App::PropertyArea","Area","Panel", QT_TRANSLATE_NOOP("App::Property","The area of this panel"))
if not "FaceMaker" in pl:
obj.addProperty("App::PropertyEnumeration","FaceMaker","Panel",QT_TRANSLATE_NOOP("App::Property","The facemaker type to use to build the profile of this object"))
obj.FaceMaker = ["None","Simple","Cheese","Bullseye"]
if not "Normal" in pl:
obj.addProperty("App::PropertyVector","Normal","Panel",QT_TRANSLATE_NOOP("App::Property","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))
self.Type = "Panel"
obj.setEditorMode("VerticalArea",2)
obj.setEditorMode("HorizontalArea",2)
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
"creates the panel shape"
if self.clone(obj):
@@ -608,7 +673,7 @@ class _Panel(ArchComponent.Component):
upsegment = Part.makePolygon([p1,p2,p3,p5])
if not downsegment:
downsegment = obj.Thickness.Value
upsegment.translate(Vector(bb.getPoint(0).x,bb.getPoint(0).y,bb.Center.z))
if isinstance(downsegment,Part.Shape):
downsegment.translate(Vector(bb.getPoint(0).x,bb.getPoint(0).y,bb.Center.z))
@@ -704,13 +769,16 @@ class _Panel(ArchComponent.Component):
class _ViewProviderPanel(ArchComponent.ViewProviderComponent):
"A View Provider for the Panel object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
vobj.ShapeColor = ArchCommands.getDefaultColor("Panel")
def getIcon(self):
#import Arch_rc
if hasattr(self,"Object"):
if hasattr(self.Object,"CloneOf"):
@@ -719,6 +787,7 @@ class _ViewProviderPanel(ArchComponent.ViewProviderComponent):
return ":/icons/Arch_Panel_Tree.svg"
def updateData(self,obj,prop):
if prop in ["Placement","Shape"]:
if hasattr(obj,"Material"):
if obj.Material:
@@ -740,29 +809,49 @@ class _ViewProviderPanel(ArchComponent.ViewProviderComponent):
class PanelView:
"A Drawing view for Arch Panels"
def __init__(self, obj):
obj.addProperty("App::PropertyLink","Source","Base",QT_TRANSLATE_NOOP("App::Property","The linked object"))
obj.addProperty("App::PropertyFloat","LineWidth","Drawing view",QT_TRANSLATE_NOOP("App::Property","The line width of the rendered objects"))
obj.addProperty("App::PropertyColor","LineColor","Drawing view",QT_TRANSLATE_NOOP("App::Property","The color of the panel outline"))
obj.addProperty("App::PropertyLength","FontSize","Tag view",QT_TRANSLATE_NOOP("App::Property","The size of the tag text"))
obj.addProperty("App::PropertyColor","TextColor","Tag view",QT_TRANSLATE_NOOP("App::Property","The color of the tag text"))
obj.addProperty("App::PropertyFloat","TextX","Tag view",QT_TRANSLATE_NOOP("App::Property","The X offset of the tag text"))
obj.addProperty("App::PropertyFloat","TextY","Tag view",QT_TRANSLATE_NOOP("App::Property","The Y offset of the tag text"))
obj.addProperty("App::PropertyString","FontName","Tag view",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.Proxy = self
self.Type = "PanelView"
obj.LineWidth = 0.35
obj.LineColor = (0.0,0.0,0.0)
obj.TextColor = (0.0,0.0,1.0)
self.setProperties(obj)
obj.X = 10
obj.Y = 10
obj.TextX = 10
obj.TextY = 10
obj.FontName = "sans"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Source" in pl:
obj.addProperty("App::PropertyLink","Source","PanelView",QT_TRANSLATE_NOOP("App::Property","The linked object"))
if not "LineWidth" in pl:
obj.addProperty("App::PropertyFloat","LineWidth","PanelView",QT_TRANSLATE_NOOP("App::Property","The line width of the rendered objects"))
obj.LineWidth = 0.35
if not "LineColor" in pl:
obj.addProperty("App::PropertyColor","LineColor","PanelView",QT_TRANSLATE_NOOP("App::Property","The color of the panel outline"))
obj.LineColor = (0.0,0.0,0.0)
if not "FontSize" in pl:
obj.addProperty("App::PropertyLength","FontSize","PanelView",QT_TRANSLATE_NOOP("App::Property","The size of the tag text"))
if not "TextColor" in pl:
obj.addProperty("App::PropertyColor","TextColor","PanelView",QT_TRANSLATE_NOOP("App::Property","The color of the tag text"))
obj.TextColor = (0.0,0.0,1.0)
if not "TextX" in pl:
obj.addProperty("App::PropertyFloat","TextX","PanelView",QT_TRANSLATE_NOOP("App::Property","The X offset of the tag text"))
obj.TextX = 10
if not "TextY" in pl:
obj.addProperty("App::PropertyFloat","TextY","PanelView",QT_TRANSLATE_NOOP("App::Property","The Y offset of the tag text"))
obj.TextY = 10
if not "FontName" in pl:
obj.addProperty("App::PropertyString","FontName","PanelView",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.FontName = "sans"
self.Type = "PanelView"
def onDocumentRestored(self,obj):
self.setProperties(obj)
def execute(self, obj):
if obj.Source:
if hasattr(obj.Source.Proxy,"BaseProfile"):
p = obj.Source.Proxy.BaseProfile
@@ -797,44 +886,66 @@ class PanelView:
obj.ViewResult = result
def onChanged(self, obj, prop):
pass
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
def getDisplayModes(self,vobj):
modes=["Default"]
return modes
def setDisplayMode(self,mode):
return mode
class PanelCut(Draft._DraftObject):
"A flat, 2D view of an Arch Panel"
def __init__(self, obj):
Draft._DraftObject.__init__(self,obj)
obj.addProperty("App::PropertyLink","Source","Arch",QT_TRANSLATE_NOOP("App::Property","The linked object"))
obj.addProperty("App::PropertyString","TagText","Arch",QT_TRANSLATE_NOOP("App::Property","The text to display. Can be %tag%, %label% or %description% to display the panel tag or label"))
obj.addProperty("App::PropertyLength","TagSize","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the tag text"))
obj.addProperty("App::PropertyVector","TagPosition","Arch",QT_TRANSLATE_NOOP("App::Property","The position of the tag text. Keep (0,0,0) for automatic center position"))
obj.addProperty("App::PropertyAngle","TagRotation","Arch",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text"))
obj.addProperty("App::PropertyFile","FontFile","Arch",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.addProperty("App::PropertyBool","MakeFace","Arch",QT_TRANSLATE_NOOP("App::Property","If True, the object is rendered as a face, if possible."))
obj.addProperty("App::PropertyFloatList","AllowedAngles","Arch",QT_TRANSLATE_NOOP("App::Property","The allowed angles this object can be rotated to when placed on sheets"))
obj.Proxy = self
self.setProperties(obj)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Source" in pl:
obj.addProperty("App::PropertyLink","Source","PanelCut",QT_TRANSLATE_NOOP("App::Property","The linked object"))
if not "TagText" in pl:
obj.addProperty("App::PropertyString","TagText","PanelCut",QT_TRANSLATE_NOOP("App::Property","The text to display. Can be %tag%, %label% or %description% to display the panel tag or label"))
obj.TagText = "%tag%"
if not "TagSize" in pl:
obj.addProperty("App::PropertyLength","TagSize","PanelCut",QT_TRANSLATE_NOOP("App::Property","The size of the tag text"))
obj.TagSize = 10
if not "TagPosition" in pl:
obj.addProperty("App::PropertyVector","TagPosition","PanelCut",QT_TRANSLATE_NOOP("App::Property","The position of the tag text. Keep (0,0,0) for automatic center position"))
if not "TagRotation" in pl:
obj.addProperty("App::PropertyAngle","TagRotation","PanelCut",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text"))
if not "FontFile" in pl:
obj.addProperty("App::PropertyFile","FontFile","PanelCut",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile",QT_TRANSLATE_NOOP("App::Property","The font file"))
if not "MakeFace" in pl:
obj.addProperty("App::PropertyBool","MakeFace","PanelCut",QT_TRANSLATE_NOOP("App::Property","If True, the object is rendered as a face, if possible."))
if not "AllowedAngles" in pl:
obj.addProperty("App::PropertyFloatList","AllowedAngles","PanelCut",QT_TRANSLATE_NOOP("App::Property","The allowed angles this object can be rotated to when placed on sheets"))
self.Type = "PanelCut"
obj.TagText = "%tag%"
obj.MakeFace = False
obj.TagSize = 10
obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile","")
def onDocumentRestored(self,obj):
self.setProperties(obj)
def execute(self, obj):
pl = obj.Placement
if obj.Source:
base = None
@@ -918,6 +1029,7 @@ class PanelCut(Draft._DraftObject):
def buildCut(self,obj,wires):
"""buildCut(obj,wires): builds the object shape"""
import Part
if hasattr(obj,"MakeFace"):
if obj.MakeFace:
@@ -947,6 +1059,7 @@ class PanelCut(Draft._DraftObject):
that define the panel outline, the panel holes, and
tags (engravings): (outline,holes,tags). Any of these can
be None if nonexistent"""
tag = None
outl = None
inl = None
@@ -978,15 +1091,30 @@ class PanelCut(Draft._DraftObject):
outl = Part.Compound([outl.Wires[0]])
return (outl, inl, tag)
class ViewProviderPanelCut(Draft._ViewProviderDraft):
"a view provider for the panel cut object"
def __init__(self,vobj):
Draft._ViewProviderDraft.__init__(self,vobj)
vobj.addProperty("App::PropertyLength","Margin","Arch",QT_TRANSLATE_NOOP("App::Property","A margin inside the boundary"))
vobj.addProperty("App::PropertyBool","ShowMargin","Arch",QT_TRANSLATE_NOOP("App::Property","Turns the display of the margin on/off"))
self.setProperties(self,vobj)
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "Margin" in pl:
vobj.addProperty("App::PropertyLength","Margin","Arch",QT_TRANSLATE_NOOP("App::Property","A margin inside the boundary"))
if not "ShowMargin" in pl:
vobj.addProperty("App::PropertyBool","ShowMargin","Arch",QT_TRANSLATE_NOOP("App::Property","Turns the display of the margin on/off"))
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def attach(self,vobj):
Draft._ViewProviderDraft.attach(self,vobj)
from pivy import coin
self.coords = coin.SoCoordinate3()
@@ -1008,6 +1136,7 @@ class ViewProviderPanelCut(Draft._ViewProviderDraft):
self.onChanged(vobj,"LineColor")
def onChanged(self,vobj,prop):
if prop in ["Margin","ShowMargin"]:
if hasattr(vobj,"Margin") and hasattr(vobj,"ShowMargin"):
if (vobj.Margin.Value > 0) and vobj.Object.Shape and vobj.ShowMargin:
@@ -1039,46 +1168,66 @@ class ViewProviderPanelCut(Draft._ViewProviderDraft):
Draft._ViewProviderDraft.onChanged(self,vobj,prop)
def updateData(self,obj,prop):
if prop in ["Shape"]:
self.onChanged(obj.ViewObject,"Margin")
Draft._ViewProviderDraft.updateData(self,obj,prop)
class PanelSheet(Draft._DraftObject):
"A collection of Panel cuts under a sheet"
def __init__(self, obj):
Draft._DraftObject.__init__(self,obj)
obj.addProperty("App::PropertyLinkList","Group","Arch",QT_TRANSLATE_NOOP("App::Property","The linked Panel cuts"))
obj.addProperty("App::PropertyString","TagText","Arch",QT_TRANSLATE_NOOP("App::Property","The tag text to display"))
obj.addProperty("App::PropertyLength","TagSize","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the tag text"))
obj.addProperty("App::PropertyVector","TagPosition","Arch",QT_TRANSLATE_NOOP("App::Property","The position of the tag text. Keep (0,0,0) for automatic center position"))
obj.addProperty("App::PropertyAngle","TagRotation","Arch",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text"))
obj.addProperty("App::PropertyFile","FontFile","Arch",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of the sheet"))
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height of the sheet"))
obj.addProperty("App::PropertyPercent","FillRatio","Arch",QT_TRANSLATE_NOOP("App::Property","The fill ratio of this sheet"))
obj.addProperty("App::PropertyBool","MakeFace","Arch",QT_TRANSLATE_NOOP("App::Property","If True, the object is rendered as a face, if possible."))
obj.addProperty("App::PropertyAngle","GrainDirection","Arch",QT_TRANSLATE_NOOP("App::Property","Specifies an angle for the wood grain (Clockwise, 0 is North)"))
obj.addProperty("App::PropertyFloat","Scale","Arch", QT_TRANSLATE_NOOP("App::Property","Specifies the scale applied to each panel view."))
obj.addProperty("App::PropertyFloatList","Rotations","Arch", QT_TRANSLATE_NOOP("App::Property","A list of possible rotations for the nester"))
obj.Proxy = self
self.Type = "PanelSheet"
obj.TagSize = 10
self.setProperties(obj)
def setProperties(self,obj):
pl = obj.PropertiesList
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
obj.Width = p.GetFloat("PanelLength",1000)
obj.Height = p.GetFloat("PanelWidth",1000)
obj.MakeFace = False
obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile","")
obj.setEditorMode("FillRatio",2)
obj.Scale = 1.0
if not "Group" in pl:
obj.addProperty("App::PropertyLinkList","Group","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The linked Panel cuts"))
if not "TagText" in pl:
obj.addProperty("App::PropertyString","TagText","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The tag text to display"))
if not "TagSize" in pl:
obj.addProperty("App::PropertyLength","TagSize","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The size of the tag text"))
obj.TagSize = 10
if not "TagPosition" in pl:
obj.addProperty("App::PropertyVector","TagPosition","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The position of the tag text. Keep (0,0,0) for automatic center position"))
if not "TagRotation" in pl:
obj.addProperty("App::PropertyAngle","TagRotation","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text"))
if not "FontFile" in pl:
obj.addProperty("App::PropertyFile","FontFile","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile",QT_TRANSLATE_NOOP("App::Property","The font file"))
if not "Width" in pl:
obj.addProperty("App::PropertyLength","Width","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The width of the sheet"))
obj.Width = p.GetFloat("PanelLength",1000)
if not "Height" in pl:
obj.addProperty("App::PropertyLength","Height","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The height of the sheet"))
obj.Height = p.GetFloat("PanelWidth",1000)
if not "FillRatio" in pl:
obj.addProperty("App::PropertyPercent","FillRatio","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The fill ratio of this sheet"))
obj.setEditorMode("FillRatio",2)
if not "MakeFace" in pl:
obj.addProperty("App::PropertyBool","MakeFace","PanelSheet",QT_TRANSLATE_NOOP("App::Property","If True, the object is rendered as a face, if possible."))
if not "GrainDirection" in pl:
obj.addProperty("App::PropertyAngle","GrainDirection","PanelSheet",QT_TRANSLATE_NOOP("App::Property","Specifies an angle for the wood grain (Clockwise, 0 is North)"))
if not "Scale" in pl:
obj.addProperty("App::PropertyFloat","Scale","PanelSheet", QT_TRANSLATE_NOOP("App::Property","Specifies the scale applied to each panel view."))
obj.Scale = 1.0
if not "Rotations" in pl:
obj.addProperty("App::PropertyFloatList","Rotations","PanelSheet", QT_TRANSLATE_NOOP("App::Property","A list of possible rotations for the nester"))
self.Type = "PanelSheet"
def onDocumentRestored(self, obj):
if not hasattr(obj, 'Scale'):
obj.addProperty("App::PropertyFloat","Scale","Arch", QT_TRANSLATE_NOOP("App::Property","Specifies the scale applied to each panel view."))
obj.Scale = 1.0
self.setProperties(obj)
def execute(self, obj):
import Part
self.sheettag = None
self.sheetborder = None
@@ -1126,6 +1275,7 @@ class PanelSheet(Draft._DraftObject):
obj.FillRatio = int((subarea/area)*100)
def getOutlines(self,obj,transform=False):
"""getOutlines(obj,transform=False): returns a list of compounds whose wires define the
outlines of the panels in this sheet. If transform is True, the placement of
the sheet will be added to each wire"""
@@ -1153,6 +1303,7 @@ class PanelSheet(Draft._DraftObject):
return outp
def getHoles(self,obj,transform=False):
"""getHoles(obj,transform=False): returns a list of compound whose wires define the
holes contained in the panels in this sheet. If transform is True, the placement of
the sheet will be added to each wire"""
@@ -1171,6 +1322,7 @@ class PanelSheet(Draft._DraftObject):
return outp
def getTags(self,obj,transform=False):
"""getTags(obj,transform=False): returns a list of compounds whose wires define the
tags (engravings) contained in the panels in this sheet and the sheet intself.
If transform is True, the placement of the sheet will be added to each wire.
@@ -1199,19 +1351,35 @@ class PanelSheet(Draft._DraftObject):
class ViewProviderPanelSheet(Draft._ViewProviderDraft):
"a view provider for the panel sheet object"
def __init__(self,vobj):
Draft._ViewProviderDraft.__init__(self,vobj)
vobj.addProperty("App::PropertyLength","Margin","Arch",QT_TRANSLATE_NOOP("App::Property","A margin inside the boundary"))
vobj.addProperty("App::PropertyBool","ShowMargin","Arch",QT_TRANSLATE_NOOP("App::Property","Turns the display of the margin on/off"))
vobj.addProperty("App::PropertyBool","ShowGrain","Arch",QT_TRANSLATE_NOOP("App::Property","Turns the display of the wood grain texture on/off"))
self.setProperties(self,vobj)
vobj.PatternSize = 0.0035
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "Margin" in pl:
vobj.addProperty("App::PropertyLength","Margin","PanelSheet",QT_TRANSLATE_NOOP("App::Property","A margin inside the boundary"))
if not "ShowMargin" in pl:
vobj.addProperty("App::PropertyBool","ShowMargin","PanelSheet",QT_TRANSLATE_NOOP("App::Property","Turns the display of the margin on/off"))
if not "ShowGrain" in pl:
vobj.addProperty("App::PropertyBool","ShowGrain","PanelSheet",QT_TRANSLATE_NOOP("App::Property","Turns the display of the wood grain texture on/off"))
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getIcon(self):
return ":/icons/Draft_Drawing.svg"
def setEdit(self,vobj,mode):
if mode == 0:
taskd = SheetTaskPanel(vobj.Object)
taskd.update()
@@ -1220,10 +1388,12 @@ class ViewProviderPanelSheet(Draft._ViewProviderDraft):
return False
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return False
def attach(self,vobj):
Draft._ViewProviderDraft.attach(self,vobj)
from pivy import coin
self.coords = coin.SoCoordinate3()
@@ -1245,6 +1415,7 @@ class ViewProviderPanelSheet(Draft._ViewProviderDraft):
self.onChanged(vobj,"LineColor")
def onChanged(self,vobj,prop):
if prop in ["Margin","ShowMargin"]:
if hasattr(vobj,"Margin") and hasattr(vobj,"ShowMargin"):
if (vobj.Margin.Value > 0) and (vobj.Margin.Value < vobj.Object.Width.Value/2) and (vobj.Margin.Value < vobj.Object.Height.Value/2):
@@ -1275,6 +1446,7 @@ class ViewProviderPanelSheet(Draft._ViewProviderDraft):
def updateData(self,obj,prop):
if prop in ["Width","Height"]:
self.onChanged(obj.ViewObject,"Margin")
elif prop == "GrainDirection":
@@ -1291,6 +1463,7 @@ class ViewProviderPanelSheet(Draft._ViewProviderDraft):
class SheetTaskPanel(ArchComponent.ComponentTaskPanel):
def __init__(self,obj):
ArchComponent.ComponentTaskPanel.__init__(self)
self.obj = obj
self.optwid = QtGui.QWidget()
@@ -1304,6 +1477,7 @@ class SheetTaskPanel(ArchComponent.ComponentTaskPanel):
self.form = [self.form,self.optwid]
def editNodes(self):
FreeCADGui.Control.closeDialog()
FreeCADGui.runCommand("Draft_Edit")
@@ -1312,16 +1486,20 @@ class CommandNest:
"the Arch Panel command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Nest',
'MenuText': QT_TRANSLATE_NOOP("Arch_Nest","Nest"),
'Accel': "N, E",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Nest","Nests a series of selected shapes in a container")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
FreeCADGui.Control.closeDialog()
FreeCADGui.Control.showDialog(NestTaskPanel())
@@ -1332,6 +1510,7 @@ class NestTaskPanel:
'''The TaskPanel for Arch Nest command'''
def __init__(self,obj=None):
import ArchNesting
self.form = FreeCADGui.PySideUic.loadUi(":/ui/ArchNest.ui")
self.form.progressBar.hide()
@@ -1349,11 +1528,13 @@ class NestTaskPanel:
self.temps = []
def reject(self):
self.stop()
self.clearTemps()
return True
def accept(self):
self.stop()
self.clearTemps()
if self.nester:
@@ -1363,12 +1544,14 @@ class NestTaskPanel:
return True
def clearTemps(self):
for t in self.temps:
if FreeCAD.ActiveDocument.getObject(t.Name):
FreeCAD.ActiveDocument.removeObject(t.Name)
self.temps = []
def getContainer(self):
s = FreeCADGui.Selection.getSelection()
if len(s) == 1:
if s[0].isDerivedFrom("Part::Feature"):
@@ -1385,6 +1568,7 @@ class NestTaskPanel:
self.form.Rotations.setText(str(s[0].Rotations))
def getShapes(self):
s = FreeCADGui.Selection.getSelection()
for o in s:
if o.isDerivedFrom("Part::Feature"):
@@ -1394,6 +1578,7 @@ class NestTaskPanel:
self.shapes.append(o)
def addObject(self,obj,form):
i = QtGui.QListWidgetItem()
i.setText(obj.Label)
i.setToolTip(obj.Name)
@@ -1405,6 +1590,7 @@ class NestTaskPanel:
form.addItem(i)
def removeShapes(self):
for i in self.form.Shapes.selectedItems():
o = FreeCAD.ActiveDocument.getObject(i.toolTip())
if o:
@@ -1413,9 +1599,11 @@ class NestTaskPanel:
self.form.Shapes.takeItem(self.form.Shapes.row(i))
def setCounter(self,value):
self.form.progressBar.setValue(value)
def start(self):
self.clearTemps()
self.form.progressBar.setFormat("pass 1: %p%")
self.form.progressBar.setValue(0)
@@ -1443,6 +1631,7 @@ class NestTaskPanel:
self.form.ButtonPreview.setEnabled(True)
def stop(self):
if self.nester:
self.nester.stop()
self.form.ButtonStart.setEnabled(True)
@@ -1451,12 +1640,15 @@ class NestTaskPanel:
self.form.progressBar.hide()
def preview(self):
self.clearTemps()
if self.nester:
t = self.nester.show()
if t:
self.temps.extend(t)
if FreeCAD.GuiUp:
class CommandPanelGroup:

View File

@@ -35,7 +35,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchPipe
# \ingroup ARCH
# \brief The Pipe object and tools
@@ -184,13 +184,28 @@ class _ArchPipe(ArchComponent.Component):
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
self.Type = "Pipe"
self.setProperties(obj)
obj.IfcRole = "Pipe Segment"
obj.addProperty("App::PropertyLength", "Diameter", "Arch", QT_TRANSLATE_NOOP("App::Property","The diameter of this pipe, if not based on a profile"))
obj.addProperty("App::PropertyLength", "Length", "Arch", QT_TRANSLATE_NOOP("App::Property","The length of this pipe, if not based on an edge"))
obj.addProperty("App::PropertyLink", "Profile", "Arch", QT_TRANSLATE_NOOP("App::Property","An optional closed profile to base this pipe on"))
obj.addProperty("App::PropertyLength", "OffsetStart", "Arch", QT_TRANSLATE_NOOP("App::Property","Offset from the start point"))
obj.addProperty("App::PropertyLength", "OffsetEnd", "Arch", QT_TRANSLATE_NOOP("App::Property","Offset from the end point"))
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Diameter" in pl:
obj.addProperty("App::PropertyLength", "Diameter", "Pipe", QT_TRANSLATE_NOOP("App::Property","The diameter of this pipe, if not based on a profile"))
if not "Length" in pl:
obj.addProperty("App::PropertyLength", "Length", "Pipe", QT_TRANSLATE_NOOP("App::Property","The length of this pipe, if not based on an edge"))
if not "Profile" in pl:
obj.addProperty("App::PropertyLink", "Profile", "Pipe", QT_TRANSLATE_NOOP("App::Property","An optional closed profile to base this pipe on"))
if not "OffsetStart" in pl:
obj.addProperty("App::PropertyLength", "OffsetStart", "Pipe", QT_TRANSLATE_NOOP("App::Property","Offset from the start point"))
if not "OffsetEnd" in pl:
obj.addProperty("App::PropertyLength", "OffsetEnd", "Pipe", QT_TRANSLATE_NOOP("App::Property","Offset from the end point"))
self.Type = "Pipe"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
@@ -298,16 +313,29 @@ class _ArchPipeConnector(ArchComponent.Component):
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
self.Type = "PipeConnector"
self.setProperties(obj)
obj.IfcRole = "Pipe Fitting"
obj.addProperty("App::PropertyLength", "Radius", "Arch", QT_TRANSLATE_NOOP("App::Property","The curvature radius of this connector"))
obj.addProperty("App::PropertyLinkList", "Pipes", "Arch", QT_TRANSLATE_NOOP("App::Property","The pipes linked by this connector"))
obj.addProperty("App::PropertyEnumeration", "ConnectorType", "Arch", QT_TRANSLATE_NOOP("App::Property","The type of this connector"))
obj.ConnectorType = ["Corner","Tee"]
obj.setEditorMode("ConnectorType",1)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Radius" in pl:
obj.addProperty("App::PropertyLength", "Radius", "PipeConnector", QT_TRANSLATE_NOOP("App::Property","The curvature radius of this connector"))
if not "Pipes" in pl:
obj.addProperty("App::PropertyLinkList", "Pipes", "PipeConnector", QT_TRANSLATE_NOOP("App::Property","The pipes linked by this connector"))
if not "ConnectorType" in pl:
obj.addProperty("App::PropertyEnumeration", "ConnectorType", "PipeConnector", QT_TRANSLATE_NOOP("App::Property","The type of this connector"))
obj.ConnectorType = ["Corner","Tee"]
obj.setEditorMode("ConnectorType",1)
self.Type = "PipeConnector"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
tol = 1 # tolerance for alignment. This is only visual, we can keep it low...
ptol = 0.001 # tolerance for coincident points

View File

@@ -41,7 +41,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchPrecast
# \ingroup ARCH
# \brief Precast options for ArchStructure
@@ -56,12 +56,26 @@ class _Precast(ArchComponent.Component):
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyDistance","Length","Arch",QT_TRANSLATE_NOOP("App::Property","The length of this element"))
obj.addProperty("App::PropertyDistance","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of this element"))
obj.addProperty("App::PropertyDistance","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height of this element"))
obj.addProperty("App::PropertyVectorList","Nodes","Arch",QT_TRANSLATE_NOOP("App::Property","The structural nodes of this element"))
_Precast.setProperties(self,obj)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Length" in pl:
obj.addProperty("App::PropertyDistance","Length","Structure",QT_TRANSLATE_NOOP("App::Property","The length of this element"))
if not "Width" in pl:
obj.addProperty("App::PropertyDistance","Width","Structure",QT_TRANSLATE_NOOP("App::Property","The width of this element"))
if not "Height" in pl:
obj.addProperty("App::PropertyDistance","Height","Structure",QT_TRANSLATE_NOOP("App::Property","The height of this element"))
if not "Nodes" in pl:
obj.addProperty("App::PropertyVectorList","Nodes","Structure",QT_TRANSLATE_NOOP("App::Property","The structural nodes of this element"))
self.Type = "Precast"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
_Precast.onDocumentRestored(self,obj)
def execute(self,obj):
if self.clone(obj):
@@ -75,12 +89,26 @@ class _PrecastBeam(_Precast):
def __init__(self,obj):
_Precast.__init__(self,obj)
obj.addProperty("App::PropertyDistance","Chamfer","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the chamfer of this element"))
obj.addProperty("App::PropertyDistance","DentLength","Arch",QT_TRANSLATE_NOOP("App::Property","The dent length of this element"))
obj.addProperty("App::PropertyDistance","DentHeight","Arch",QT_TRANSLATE_NOOP("App::Property","The dent height of this element"))
obj.addProperty("App::PropertyStringList","Dents","Arch",QT_TRANSLATE_NOOP("App::Property","The dents of this element"))
self.setProperties(obj)
obj.IfcRole = "Beam"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Chamfer" in pl:
obj.addProperty("App::PropertyDistance","Chamfer","Beam",QT_TRANSLATE_NOOP("App::Property","The size of the chamfer of this element"))
if not "DentLength" in pl:
obj.addProperty("App::PropertyDistance","DentLength","Beam",QT_TRANSLATE_NOOP("App::Property","The dent length of this element"))
if not "DentHeight" in pl:
obj.addProperty("App::PropertyDistance","DentHeight","Beam",QT_TRANSLATE_NOOP("App::Property","The dent height of this element"))
if not "Dents" in pl:
obj.addProperty("App::PropertyStringList","Dents","Beam",QT_TRANSLATE_NOOP("App::Property","The dents of this element"))
def onDocumentRestored(self,obj):
_Precast.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
if self.clone(obj):
@@ -180,10 +208,22 @@ class _PrecastIbeam(_Precast):
def __init__(self,obj):
_Precast.__init__(self,obj)
obj.addProperty("App::PropertyDistance","Chamfer","Arch",QT_TRANSLATE_NOOP("App::Property","The chamfer length of this element"))
obj.addProperty("App::PropertyDistance","BeamBase","Arch",QT_TRANSLATE_NOOP("App::Property","The base length of this element"))
self.setProperties(obj)
obj.IfcRole = "Beam"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Chamfer" in pl:
obj.addProperty("App::PropertyDistance","Chamfer","Beam",QT_TRANSLATE_NOOP("App::Property","The chamfer length of this element"))
if not "BeamBase" in pl:
obj.addProperty("App::PropertyDistance","BeamBase","Beam",QT_TRANSLATE_NOOP("App::Property","The base length of this element"))
def onDocumentRestored(self,obj):
_Precast.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
if self.clone(obj):
@@ -231,14 +271,30 @@ class _PrecastPillar(_Precast):
def __init__(self,obj):
_Precast.__init__(self,obj)
obj.addProperty("App::PropertyDistance","Chamfer","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the chamfer of this element"))
obj.addProperty("App::PropertyDistance","GrooveDepth","Arch",QT_TRANSLATE_NOOP("App::Property","The groove depth of this element"))
obj.addProperty("App::PropertyDistance","GrooveHeight","Arch",QT_TRANSLATE_NOOP("App::Property","The groove height of this element"))
obj.addProperty("App::PropertyDistance","GrooveSpacing","Arch",QT_TRANSLATE_NOOP("App::Property","The spacing between the grooves of this element"))
obj.addProperty("App::PropertyInteger","GrooveNumber","Arch",QT_TRANSLATE_NOOP("App::Property","The number of grooves of this element"))
obj.addProperty("App::PropertyStringList","Dents","Arch",QT_TRANSLATE_NOOP("App::Property","The dents of this element"))
self.setProperties(obj)
obj.IfcRole = "Column"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Chamfer" in pl:
obj.addProperty("App::PropertyDistance","Chamfer","Column",QT_TRANSLATE_NOOP("App::Property","The size of the chamfer of this element"))
if not "GrooveDepth" in pl:
obj.addProperty("App::PropertyDistance","GrooveDepth","Column",QT_TRANSLATE_NOOP("App::Property","The groove depth of this element"))
if not "GrooveHeight" in pl:
obj.addProperty("App::PropertyDistance","GrooveHeight","Column",QT_TRANSLATE_NOOP("App::Property","The groove height of this element"))
if not "GrooveSpacing" in pl:
obj.addProperty("App::PropertyDistance","GrooveSpacing","Column",QT_TRANSLATE_NOOP("App::Property","The spacing between the grooves of this element"))
if not "GrooveNumber" in pl:
obj.addProperty("App::PropertyInteger","GrooveNumber","Column",QT_TRANSLATE_NOOP("App::Property","The number of grooves of this element"))
if not "Dents" in pl:
obj.addProperty("App::PropertyStringList","Dents","Column",QT_TRANSLATE_NOOP("App::Property","The dents of this element"))
def onDocumentRestored(self,obj):
_Precast.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
if self.clone(obj):
@@ -353,11 +409,24 @@ class _PrecastPanel(_Precast):
def __init__(self,obj):
_Precast.__init__(self,obj)
obj.addProperty("App::PropertyDistance","Chamfer","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the chamfer of this element"))
obj.addProperty("App::PropertyDistance","DentWidth","Arch",QT_TRANSLATE_NOOP("App::Property","The dent width of this element"))
obj.addProperty("App::PropertyDistance","DentHeight","Arch",QT_TRANSLATE_NOOP("App::Property","The dent height of this element"))
self.setProperties(obj)
obj.IfcRole = "Plate"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Chamfer" in pl:
obj.addProperty("App::PropertyDistance","Chamfer","Panel",QT_TRANSLATE_NOOP("App::Property","The size of the chamfer of this element"))
if not "DentWidth" in pl:
obj.addProperty("App::PropertyDistance","DentWidth","Panel",QT_TRANSLATE_NOOP("App::Property","The dent width of this element"))
if not "DentHeight" in pl:
obj.addProperty("App::PropertyDistance","DentHeight","Panel",QT_TRANSLATE_NOOP("App::Property","The dent height of this element"))
def onDocumentRestored(self,obj):
_Precast.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
if self.clone(obj):
@@ -448,14 +517,30 @@ class _PrecastSlab(_Precast):
def __init__(self,obj):
_Precast.__init__(self,obj)
obj.addProperty("App::PropertyEnumeration","SlabType","Arch",QT_TRANSLATE_NOOP("App::Property","The type of this slab"))
obj.addProperty("App::PropertyDistance","SlabBase","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the base of this element"))
obj.addProperty("App::PropertyInteger","HoleNumber","Arch",QT_TRANSLATE_NOOP("App::Property","The number of holes in this element"))
obj.addProperty("App::PropertyDistance","HoleMajor","Arch",QT_TRANSLATE_NOOP("App::Property","The major radius of the holes of this element"))
obj.addProperty("App::PropertyDistance","HoleMinor","Arch",QT_TRANSLATE_NOOP("App::Property","The minor radius of the holes of this element"))
obj.addProperty("App::PropertyDistance","HoleSpacing","Arch",QT_TRANSLATE_NOOP("App::Property","The spacing between the holes of this element"))
self.setProperties(obj)
obj.IfcRole = "Slab"
obj.SlabType = ["Champagne","Hat"]
def setProperties(self,obj):
pl = obj.PropertiesList
if not "SlabType" in pl:
obj.addProperty("App::PropertyEnumeration","SlabType","Slab",QT_TRANSLATE_NOOP("App::Property","The type of this slab"))
obj.SlabType = ["Champagne","Hat"]
if not "SlabBase" in pl:
obj.addProperty("App::PropertyDistance","SlabBase","Slab",QT_TRANSLATE_NOOP("App::Property","The size of the base of this element"))
if not "HoleNumber" in pl:
obj.addProperty("App::PropertyInteger","HoleNumber","Slab",QT_TRANSLATE_NOOP("App::Property","The number of holes in this element"))
if not "HoleMajor" in pl:
obj.addProperty("App::PropertyDistance","HoleMajor","Slab",QT_TRANSLATE_NOOP("App::Property","The major radius of the holes of this element"))
if not "HoleMinor" in pl:
obj.addProperty("App::PropertyDistance","HoleMinor","Slab",QT_TRANSLATE_NOOP("App::Property","The minor radius of the holes of this element"))
if not "HoleSpacing" in pl:
obj.addProperty("App::PropertyDistance","HoleSpacing","Slab",QT_TRANSLATE_NOOP("App::Property","The spacing between the holes of this element"))
def onDocumentRestored(self,obj):
_Precast.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
@@ -541,11 +626,25 @@ class _PrecastStairs(_Precast):
def __init__(self,obj):
_Precast.__init__(self,obj)
obj.addProperty("App::PropertyDistance","DownLength","Arch",QT_TRANSLATE_NOOP("App::Property","The length of the down floor of this element"))
obj.addProperty("App::PropertyInteger","RiserNumber","Arch",QT_TRANSLATE_NOOP("App::Property","The number of risers in this element"))
obj.addProperty("App::PropertyDistance","Riser","Arch",QT_TRANSLATE_NOOP("App::Property","The riser height of this element"))
obj.addProperty("App::PropertyDistance","Tread","Arch",QT_TRANSLATE_NOOP("App::Property","The tread depth of this element"))
obj.IfcRole = "Stairs"
self.setProperties(obj)
obj.IfcRole = "Stair"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "DownLength" in pl:
obj.addProperty("App::PropertyDistance","DownLength","Stairs",QT_TRANSLATE_NOOP("App::Property","The length of the down floor of this element"))
if not "RiserNumber" in pl:
obj.addProperty("App::PropertyInteger","RiserNumber","Stairs",QT_TRANSLATE_NOOP("App::Property","The number of risers in this element"))
if not "Riser" in pl:
obj.addProperty("App::PropertyDistance","Riser","Stairs",QT_TRANSLATE_NOOP("App::Property","The riser height of this element"))
if not "Tread" in pl:
obj.addProperty("App::PropertyDistance","Tread","Stairs",QT_TRANSLATE_NOOP("App::Property","The tread depth of this element"))
def onDocumentRestored(self,obj):
_Precast.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
@@ -616,13 +715,16 @@ class _PrecastStairs(_Precast):
class _ViewProviderPrecast(ArchComponent.ViewProviderComponent):
"The View Provider of the Precast object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
vobj.ShapeColor = ArchCommands.getDefaultColor("Structure")
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
if self.Object.CloneOf:
@@ -630,6 +732,7 @@ class _ViewProviderPrecast(ArchComponent.ViewProviderComponent):
return ":/icons/Arch_Structure_Tree.svg"
def setEdit(self,vobj,mode):
if mode == 0:
import FreeCADGui
taskd = ArchComponent.ComponentTaskPanel()
@@ -645,6 +748,7 @@ class _ViewProviderPrecast(ArchComponent.ViewProviderComponent):
return False
def unsetEdit(self,vobj,mode):
import FreeCADGui
if hasattr(self,"dentd"):
self.Object.Dents = self.dentd.getValues()

View File

@@ -51,8 +51,10 @@ __url__ = "http://www.freecadweb.org"
def makeRebar(baseobj=None,sketch=None,diameter=None,amount=1,offset=None,name="Rebar"):
"""makeRebar([baseobj,sketch,diameter,amount,offset,name]): adds a Reinforcement Bar object
to the given structural object, using the given sketch as profile."""
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -90,18 +92,22 @@ def makeRebar(baseobj=None,sketch=None,diameter=None,amount=1,offset=None,name="
class _CommandRebar:
"the Arch Rebar command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Rebar',
'MenuText': QT_TRANSLATE_NOOP("Arch_Rebar","Custom Rebar"),
'Accel': "R, B",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Rebar","Creates a Reinforcement bar from the selected face of a structural object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelectionEx()
if sel:
obj = sel[0].Object
@@ -152,31 +158,56 @@ class _CommandRebar:
class _Rebar(ArchComponent.Component):
"A parametric reinforcement bar (rebar) object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLength","Diameter","Arch",QT_TRANSLATE_NOOP("App::Property","The diameter of the bar"))
obj.addProperty("App::PropertyLength","OffsetStart","Arch",QT_TRANSLATE_NOOP("App::Property","The distance between the border of the beam and the first bar (concrete cover)."))
obj.addProperty("App::PropertyLength","OffsetEnd","Arch",QT_TRANSLATE_NOOP("App::Property","The distance between the border of the beam and the last bar (concrete cover)."))
obj.addProperty("App::PropertyInteger","Amount","Arch",QT_TRANSLATE_NOOP("App::Property","The amount of bars"))
obj.addProperty("App::PropertyLength","Spacing","Arch",QT_TRANSLATE_NOOP("App::Property","The spacing between the bars"))
obj.addProperty("App::PropertyLength","Distance","Arch",QT_TRANSLATE_NOOP("App::Property","The total distance to span the rebars over. Keep 0 to automatically use the host shape size."))
obj.addProperty("App::PropertyVector","Direction","Arch",QT_TRANSLATE_NOOP("App::Property","The direction to use to spread the bars. Keep (0,0,0) for automatic direction."))
obj.addProperty("App::PropertyFloat","Rounding","Arch",QT_TRANSLATE_NOOP("App::Property","The fillet to apply to the angle of the base profile. This value is multiplied by the bar diameter."))
obj.addProperty("App::PropertyPlacementList","PlacementList","Arch",QT_TRANSLATE_NOOP("App::Property","List of placement of all the bars"))
obj.addProperty("App::PropertyLink","Host","Arch",QT_TRANSLATE_NOOP("App::Property","The structure object that hosts this rebar"))
obj.addProperty("App::PropertyString", "CustomSpacing", "Arch", QT_TRANSLATE_NOOP("App::Property","The custom spacing of rebar"))
obj.addProperty("App::PropertyDistance", "Length", "Arch", QT_TRANSLATE_NOOP("App::Property","Length of a single rebar"))
obj.addProperty("App::PropertyDistance", "TotalLength", "Arch", QT_TRANSLATE_NOOP("App::Property","Total length of all rebars"))
self.Type = "Rebar"
obj.IfcRole = "Reinforcing Bar"
obj.setEditorMode("Spacing", 1)
obj.setEditorMode("Length", 1)
obj.setEditorMode("TotalLength", 1)
ArchComponent.Component.__init__(self,obj)
self.setProperties(obj)
obj.IfcRole = "Reinforcing Bar"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Diameter" in pl:
obj.addProperty("App::PropertyLength","Diameter","Rebar",QT_TRANSLATE_NOOP("App::Property","The diameter of the bar"))
if not "OffsetStart" in pl:
obj.addProperty("App::PropertyLength","OffsetStart","Rebar",QT_TRANSLATE_NOOP("App::Property","The distance between the border of the beam and the first bar (concrete cover)."))
if not "OffsetEnd" in pl:
obj.addProperty("App::PropertyLength","OffsetEnd","Rebar",QT_TRANSLATE_NOOP("App::Property","The distance between the border of the beam and the last bar (concrete cover)."))
if not "Amount" in pl:
obj.addProperty("App::PropertyInteger","Amount","Rebar",QT_TRANSLATE_NOOP("App::Property","The amount of bars"))
if not "Spacing" in pl:
obj.addProperty("App::PropertyLength","Spacing","Rebar",QT_TRANSLATE_NOOP("App::Property","The spacing between the bars"))
obj.setEditorMode("Spacing", 1)
if not "Distance" in pl:
obj.addProperty("App::PropertyLength","Distance","Rebar",QT_TRANSLATE_NOOP("App::Property","The total distance to span the rebars over. Keep 0 to automatically use the host shape size."))
if not "Direction" in pl:
obj.addProperty("App::PropertyVector","Direction","Rebar",QT_TRANSLATE_NOOP("App::Property","The direction to use to spread the bars. Keep (0,0,0) for automatic direction."))
if not "Rounding" in pl:
obj.addProperty("App::PropertyFloat","Rounding","Rebar",QT_TRANSLATE_NOOP("App::Property","The fillet to apply to the angle of the base profile. This value is multiplied by the bar diameter."))
if not "PlacementList" in pl:
obj.addProperty("App::PropertyPlacementList","PlacementList","Rebar",QT_TRANSLATE_NOOP("App::Property","List of placement of all the bars"))
if not "Host" in pl:
obj.addProperty("App::PropertyLink","Host","Rebar",QT_TRANSLATE_NOOP("App::Property","The structure object that hosts this rebar"))
if not "CustomSpacing" in pl:
obj.addProperty("App::PropertyString", "CustomSpacing", "Rebar", QT_TRANSLATE_NOOP("App::Property","The custom spacing of rebar"))
if not "Length" in pl:
obj.addProperty("App::PropertyDistance", "Length", "Rebar", QT_TRANSLATE_NOOP("App::Property","Length of a single rebar"))
obj.setEditorMode("Length", 1)
if not "TotalLength" in pl:
obj.addProperty("App::PropertyDistance", "TotalLength", "Rebar", QT_TRANSLATE_NOOP("App::Property","Total length of all rebars"))
obj.setEditorMode("TotalLength", 1)
self.Type = "Rebar"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def getBaseAndAxis(self,wire):
"returns a base point and orientation axis from the base wire"
import DraftGeomUtils
if wire:
@@ -194,6 +225,7 @@ class _Rebar(ArchComponent.Component):
return None,None
def getRebarData(self,obj):
if len(obj.InList) != 1:
return
if Draft.getType(obj.InList[0]) != "Structure":
@@ -251,6 +283,7 @@ class _Rebar(ArchComponent.Component):
return [wires,obj.Diameter.Value/2]
def onChanged(self,obj,prop):
if prop == "Host":
if hasattr(obj,"Host"):
if obj.Host:
@@ -397,19 +430,33 @@ class _Rebar(ArchComponent.Component):
obj.TotalLength = obj.Length * len(obj.PlacementList)
class _ViewProviderRebar(ArchComponent.ViewProviderComponent):
"A View Provider for the Rebar object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
vobj.addProperty("App::PropertyString","RebarShape","Arch",QT_TRANSLATE_NOOP("App::Property","Shape of rebar")).RebarShape
self.setProperties(vobj)
vobj.ShapeColor = ArchCommands.getDefaultColor("Rebar")
vobj.setEditorMode("RebarShape",2)
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "RebarShape" in pl:
vobj.addProperty("App::PropertyString","RebarShape","Rebar",QT_TRANSLATE_NOOP("App::Property","Shape of rebar")).RebarShape
vobj.setEditorMode("RebarShape",2)
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Rebar_Tree.svg"
def setEdit(self, vobj, mode):
if mode == 0:
if vobj.RebarShape:
try:
@@ -421,6 +468,7 @@ class _ViewProviderRebar(ArchComponent.ViewProviderComponent):
module.editDialog(vobj)
def updateData(self,obj,prop):
if prop == "Shape":
if hasattr(self,"centerline"):
if self.centerline:
@@ -453,6 +501,7 @@ class _ViewProviderRebar(ArchComponent.ViewProviderComponent):
ArchComponent.ViewProviderComponent.updateData(self,obj,prop)
def attach(self,vobj):
from pivy import coin
self.centerlinegroup = coin.SoSeparator()
self.centerlinegroup.setName("Centerline")
@@ -464,6 +513,7 @@ class _ViewProviderRebar(ArchComponent.ViewProviderComponent):
ArchComponent.ViewProviderComponent.attach(self,vobj)
def onChanged(self,vobj,prop):
if (prop == "LineColor") and hasattr(vobj,"LineColor"):
if hasattr(self,"centerlinecolor"):
c = vobj.LineColor
@@ -474,10 +524,12 @@ class _ViewProviderRebar(ArchComponent.ViewProviderComponent):
ArchComponent.ViewProviderComponent.onChanged(self,vobj,prop)
def getDisplayModes(self,vobj):
modes=["Centerline"]
return modes+ArchComponent.ViewProviderComponent.getDisplayModes(self,vobj)
def CalculatePlacement(baramount, barnumber, size, axis, rotation, offsetstart, offsetend):
""" CalculatePlacement([baramount, barnumber, size, axis, rotation, offsetstart, offsetend]):
Calculate the placement of the bar from given values."""
if baramount == 1:
@@ -491,6 +543,7 @@ def CalculatePlacement(baramount, barnumber, size, axis, rotation, offsetstart,
return placement
def CustomSpacingPlacement(spacinglist, barnumber, axis, rotation, offsetstart, offsetend):
""" CustomSpacingPlacement(spacinglist, barnumber, axis, rotation, offsetstart, offsetend):
Calculate placement of the bar from custom spacing list."""
if barnumber == 1:
@@ -505,6 +558,7 @@ def CustomSpacingPlacement(spacinglist, barnumber, axis, rotation, offsetstart,
return placement
def strprocessOfCustomSpacing(span_string):
""" strprocessOfCustomSpacing(span_string): This function take input
in specific syntax and return output in the form of list. For eg.
Input: "3@100+2@200+3@100"
@@ -529,6 +583,7 @@ def strprocessOfCustomSpacing(span_string):
return spacinglist
def getLengthOfRebar(rebar):
""" getLengthOfRebar(RebarObject): Calculates the length of the rebar."""
base = rebar.Base
# When rebar is derived from DWire

View File

@@ -35,7 +35,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchRoof
# \ingroup ARCH
# \brief The Roof object and tools
@@ -48,13 +48,16 @@ __title__="FreeCAD Roof"
__author__ = "Yorik van Havre", "Jonathan Wiedemann"
__url__ = "http://www.freecadweb.org"
def makeRoof(baseobj=None,facenr=0, angles=[45.,], run = [], idrel = [0,],thickness = [50.,], overhang=[100.,], name="Roof"):
'''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on
a closed wire or an object. You can provide a list of angles, run,
idrel, thickness, overhang for each edges in the wire to define the
roof shape. The default for angle is 45 and the list is
automatically complete to match with number of edges in the wire.
If the base object is a solid the roof take the shape.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -121,17 +124,22 @@ def makeRoof(baseobj=None,facenr=0, angles=[45.,], run = [], idrel = [0,],thickn
return obj
class _CommandRoof:
"the Arch Roof command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Roof',
'MenuText': QT_TRANSLATE_NOOP("Arch_Roof","Roof"),
'Accel': "R, F",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Roof","Creates a roof object from the selected wire.")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelectionEx()
if sel:
sel = sel[0]
@@ -166,43 +174,74 @@ class _CommandRoof:
FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(nextCommand="Arch_Roof")
FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
class _Roof(ArchComponent.Component):
"The Roof object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyFloatList","Angles","Arch", QT_TRANSLATE_NOOP("App::Property","A list of angles for each roof pane"))
obj.addProperty("App::PropertyFloatList","Runs","Arch", QT_TRANSLATE_NOOP("App::Property","A list of horizontal length projections for each roof pane"))
obj.addProperty("App::PropertyIntegerList","IdRel","Arch", QT_TRANSLATE_NOOP("App::Property","A list of IDs of relative profiles for each roof pane"))
obj.addProperty("App::PropertyFloatList","Thickness","Arch", QT_TRANSLATE_NOOP("App::Property","A list of thicknesses for each roof pane"))
obj.addProperty("App::PropertyFloatList","Overhang","Arch", QT_TRANSLATE_NOOP("App::Property","A list of overhangs for each roof pane"))
obj.addProperty("App::PropertyFloatList","Heights","Arch", QT_TRANSLATE_NOOP("App::Property","A list of calculated heights for each roof pane"))
obj.addProperty("App::PropertyInteger","Face","Base", QT_TRANSLATE_NOOP("App::Property","The face number of the base object used to build this roof"))
obj.addProperty("App::PropertyLength","RidgeLength","Arch", QT_TRANSLATE_NOOP("App::Property","The total length of ridges and hips of this roof"))
obj.addProperty("App::PropertyLength","BorderLength","Arch", QT_TRANSLATE_NOOP("App::Property","The total length of borders of this roof"))
obj.addProperty("App::PropertyBool","Flip","Arch",QT_TRANSLATE_NOOP("App::Property","Flip the roof direction if going the wrong way"))
self.Type = "Roof"
self.setProperties(obj)
obj.IfcRole = "Roof"
obj.Proxy = self
obj.setEditorMode("RidgeLength",1)
obj.setEditorMode("BorderLength",1)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Angles" in pl:
obj.addProperty("App::PropertyFloatList","Angles","Roof", QT_TRANSLATE_NOOP("App::Property","A list of angles for each roof pane"))
if not "Runs" in pl:
obj.addProperty("App::PropertyFloatList","Runs","Roof", QT_TRANSLATE_NOOP("App::Property","A list of horizontal length projections for each roof pane"))
if not "IdRel" in pl:
obj.addProperty("App::PropertyIntegerList","IdRel","Roof", QT_TRANSLATE_NOOP("App::Property","A list of IDs of relative profiles for each roof pane"))
if not "Thickness" in pl:
obj.addProperty("App::PropertyFloatList","Thickness","Roof", QT_TRANSLATE_NOOP("App::Property","A list of thicknesses for each roof pane"))
if not "Overhang" in pl:
obj.addProperty("App::PropertyFloatList","Overhang","Roof", QT_TRANSLATE_NOOP("App::Property","A list of overhangs for each roof pane"))
if not "Heights" in pl:
obj.addProperty("App::PropertyFloatList","Heights","Roof", QT_TRANSLATE_NOOP("App::Property","A list of calculated heights for each roof pane"))
if not "Face" in pl:
obj.addProperty("App::PropertyInteger","Face","Roof", QT_TRANSLATE_NOOP("App::Property","The face number of the base object used to build this roof"))
if not "RidgeLength" in pl:
obj.addProperty("App::PropertyLength","RidgeLength","Roof", QT_TRANSLATE_NOOP("App::Property","The total length of ridges and hips of this roof"))
obj.setEditorMode("RidgeLength",1)
if not "BorderLength" in pl:
obj.addProperty("App::PropertyLength","BorderLength","Roof", QT_TRANSLATE_NOOP("App::Property","The total length of borders of this roof"))
obj.setEditorMode("BorderLength",1)
if not "Flip" in pl:
obj.addProperty("App::PropertyBool","Flip","Roof",QT_TRANSLATE_NOOP("App::Property","Flip the roof direction if going the wrong way"))
self.Type = "Roof"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def calcHeight(self, id):
" Get the height from run and angle of the given roof profil "
" Get the height from run and angle of the given roof profile "
htRel = self.profilsDico[id]["run"]*(math.tan(math.radians(self.profilsDico[id]["angle"])))
return htRel
def calcRun(self, id):
" Get the run from height and angle of the given roof profil "
" Get the run from height and angle of the given roof profile "
runRel = self.profilsDico[id]["height"]/(math.tan(math.radians(self.profilsDico[id]["angle"])))
return runRel
def calcAngle(self, id):
" Get the angle from height and run of the given roof profil "
" Get the angle from height and run of the given roof profile "
a = math.degrees(math.atan(self.profilsDico[id]["height"]/self.profilsDico[id]["run"]))
return a
def getPerpendicular(self, vec, rotEdge, l):
" Get the perpendicular vec of given edge on xy plane "
norm = FreeCAD.Vector(0,0,1)
if hasattr(self,"normal"):
@@ -232,6 +271,7 @@ class _Roof(ArchComponent.Component):
return perpendicular
def makeRoofProfilsDic(self, id, angle, run, idrel, overhang, thickness,):
profilDico = {}
profilDico["id"] = id
if angle == 90.:
@@ -249,6 +289,7 @@ class _Roof(ArchComponent.Component):
self.profilsDico.append(profilDico)
def calcMissingData(self, i):
a = self.profilsDico[i]["angle"]
run = self.profilsDico[i]["run"]
rel = self.profilsDico[i]["idrel"]
@@ -275,6 +316,7 @@ class _Roof(ArchComponent.Component):
self.profilsDico[i]["height"] = ht
def calcEdgeGeometry(self, edges, i):
self.profilsDico[i]["edge"] = edges[i]
vec = edges[i].Vertexes[-1].Point.sub(edges[i].Vertexes[0].Point)
self.profilsDico[i]["vec"] = vec
@@ -282,6 +324,7 @@ class _Roof(ArchComponent.Component):
self.profilsDico[i]["rot"] = rot
def calcDraftEdges(self, i):
import DraftGeomUtils
edge = self.profilsDico[i]["edge"]
vec = self.profilsDico[i]["vec"]
@@ -296,6 +339,7 @@ class _Roof(ArchComponent.Component):
self.profilsDico[i]["ridge"] = ridge
def calcEave(self, i):
import DraftGeomUtils
pt0Eave1 = DraftGeomUtils.findIntersection(self.findProfil(i-1)["eaveD"],self.findProfil(i)["eaveD"],infinite1=True,infinite2=True,)
pt1Eave1 = DraftGeomUtils.findIntersection(self.findProfil(i)["eaveD"],self.findProfil(i+1)["eaveD"],infinite1=True,infinite2=True,)
@@ -303,6 +347,7 @@ class _Roof(ArchComponent.Component):
self.profilsDico[i]["eave"] = eave
def findProfil(self, idx):
if 0<=idx<len(self.profilsDico):
profil = self.profilsDico[idx]
else:
@@ -311,6 +356,7 @@ class _Roof(ArchComponent.Component):
return profil
def nextPignon(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilNext1 = self.findProfil(i+1)
@@ -335,6 +381,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(point[0]))
def backPignon(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilBack1 = self.findProfil(i-1)
@@ -359,6 +406,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(point[0]))
def nextSameHeight(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilNext1 = self.findProfil(i+1)
@@ -374,6 +422,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0]))
def backSameHeight(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilBack1 = self.findProfil(i-1)
@@ -389,6 +438,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(profilCurrent["eave"].Vertexes[0].Point))
def nextHigher(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilNext1 = self.findProfil(i+1)
@@ -408,6 +458,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0]))
def backHigher(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilBack1 = self.findProfil(i-1)
@@ -425,6 +476,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(profilCurrent["eave"].Vertexes[0].Point[0]))
def nextSmaller(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilNext1 = self.findProfil(i+1)
@@ -446,6 +498,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges))
def backSmaller(self, i):
import DraftGeomUtils
profilCurrent = self.findProfil(i)
profilBack1 = self.findProfil(i-1)
@@ -467,6 +520,7 @@ class _Roof(ArchComponent.Component):
self.ptsPaneProject.append(FreeCAD.Vector(profilCurrent["eave"].Vertexes[0].Point[0]))
def getRoofPaneProject(self, i):
self.ptsPaneProject=[]
profilCurrent = self.findProfil(i)
profilBack1 = self.findProfil(i-1)
@@ -499,6 +553,7 @@ class _Roof(ArchComponent.Component):
profilCurrent["points"] = self.ptsPaneProject
def createProfilShape (self, points, midpoint, rot, vec, run, d, f):
import Part
lp = len(points)
points.append(points[0])
@@ -612,6 +667,7 @@ class _Roof(ArchComponent.Component):
FreeCAD.Console.PrintMessage(translate("Arch","Unable to create a roof"))
def getSubVolume(self,obj):
"returns a volume to be subtracted"
if obj.Base:
if obj.Base.isDerivedFrom("Part::Feature"):
@@ -673,24 +729,30 @@ class _Roof(ArchComponent.Component):
class _ViewProviderRoof(ArchComponent.ViewProviderComponent):
"A View Provider for the Roof object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Roof_Tree.svg"
def attach(self,vobj):
self.Object = vobj.Object
return
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return
def setEdit(self,vobj,mode=0):
if vobj.Object.Base.Shape.Solids :
taskd = ArchComponent.ComponentTaskPanel()
taskd.obj = self.Object
@@ -703,8 +765,11 @@ class _ViewProviderRoof(ArchComponent.ViewProviderComponent):
FreeCADGui.Control.showDialog(taskd)
return True
class _RoofTaskPanel:
'''The editmode TaskPanel for Roof objects'''
def __init__(self):
self.updating = False

View File

@@ -36,7 +36,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchSectionPlane
# \ingroup ARCH
# \brief The Section plane object and tools
@@ -45,9 +45,12 @@ else:
# It also contains functionality to produce SVG rendering of
# section planes, to be used in TechDraw and Drawing modules
def makeSectionPlane(objectslist=None,name="Section"):
"""makeSectionPlane([objectslist]) : Creates a Section plane objects including the
given objects. If no object is given, the whole document will be considered."""
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -68,8 +71,10 @@ def makeSectionPlane(objectslist=None,name="Section"):
def makeSectionView(section,name="View"):
"""makeSectionView(section) : Creates a Drawing view of the given Section Plane
in the active Page object (a new page will be created if none exists"""
page = None
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom("Drawing::FeaturePage"):
@@ -88,6 +93,7 @@ def makeSectionView(section,name="View"):
def getCutShapes(objs,section,showHidden):
import Part,DraftGeomUtils
shapes = []
hshapes = []
@@ -132,6 +138,7 @@ def getCutShapes(objs,section,showHidden):
def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale=1, rotation=0, linewidth=1, lineColor=(0.0,0.0,0.0), fontsize=1, showFill=False, fillColor=(0.8,0.8,0.8), techdraw=False):
"""getSVG(section, [renderMode, allOn, showHidden, scale, rotation,
linewidth, lineColor, fontsize, showFill, fillColor, techdraw]):
@@ -300,7 +307,7 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
if not techdraw:
svg += '<g transform="scale(1,-1)">'
for s in sh:
svg += Draft.getSVG(s, scale=scale,
svg += Draft.getSVG(s, scale=scale,
linewidth=svgSymbolLineWidth,
fontsize=fontsize, fillstyle="none",
direction=direction, color=lineColor,
@@ -312,6 +319,7 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
def getDXF(obj):
"returns a DXF representation from a TechDraw/Drawing view"
allOn = True
if hasattr(obj,"AllOn"):
@@ -351,17 +359,22 @@ def getDXF(obj):
class _CommandSectionPlane:
"the Arch SectionPlane command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_SectionPlane',
'Accel': "S, E",
'MenuText': QT_TRANSLATE_NOOP("Arch_SectionPlane","Section Plane"),
'ToolTip': QT_TRANSLATE_NOOP("Arch_SectionPlane","Creates a section plane object, including the selected objects")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
ss = "["
for o in sel:
@@ -379,19 +392,33 @@ class _CommandSectionPlane:
class _SectionPlane:
"A section plane object"
def __init__(self,obj):
obj.Proxy = self
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
obj.addProperty("Part::PropertyPartShape","Shape","Base","")
obj.addProperty("App::PropertyLinkList","Objects","Arch",QT_TRANSLATE_NOOP("App::Property","The objects that must be considered by this section plane. Empty means all document"))
obj.addProperty("App::PropertyBool","OnlySolids","Arch",QT_TRANSLATE_NOOP("App::Property","If false, non-solids will be cut too, with possible wrong results."))
obj.OnlySolids = True
self.setProperties(obj)
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Placement" in pl:
obj.addProperty("App::PropertyPlacement","Placement","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
if not "Shape" in pl:
obj.addProperty("Part::PropertyPartShape","Shape","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The shape of this object"))
if not "Objects" in pl:
obj.addProperty("App::PropertyLinkList","Objects","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The objects that must be considered by this section plane. Empty means all document"))
if not "OnlySolids" in pl:
obj.addProperty("App::PropertyBool","OnlySolids","SectionPlane",QT_TRANSLATE_NOOP("App::Property","If false, non-solids will be cut too, with possible wrong results."))
obj.OnlySolids = True
self.Type = "SectionPlane"
def onDocumentRestored(self,obj):
self.setProperties(obj)
def execute(self,obj):
import Part
if hasattr(obj.ViewObject,"DisplayLength"):
l = obj.ViewObject.DisplayLength.Value
@@ -411,50 +438,86 @@ class _SectionPlane:
obj.Shape = p
def onChanged(self,obj,prop):
pass
def getNormal(self,obj):
return obj.Shape.Faces[0].normalAt(0,0)
def __getstate__(self):
return self.Type
return None
def __setstate__(self,state):
if state:
self.Type = state
return None
class _ViewProviderSectionPlane:
"A View Provider for Section Planes"
def __init__(self,vobj):
vobj.addProperty("App::PropertyLength","DisplayLength","Arch",QT_TRANSLATE_NOOP("App::Property","The display length of this section plane"))
vobj.addProperty("App::PropertyLength","DisplayHeight","Arch",QT_TRANSLATE_NOOP("App::Property","The display height of this section plane"))
vobj.addProperty("App::PropertyLength","ArrowSize","Arch",QT_TRANSLATE_NOOP("App::Property","The size of the arrows of this section plane"))
vobj.addProperty("App::PropertyPercent","Transparency","Base","")
vobj.addProperty("App::PropertyFloat","LineWidth","Base","")
vobj.addProperty("App::PropertyLength","CutDistance","Arch",QT_TRANSLATE_NOOP("App::Property","Show the cut in the 3D view"))
vobj.addProperty("App::PropertyColor","LineColor","Base","")
vobj.addProperty("App::PropertyBool","CutView","Arch",QT_TRANSLATE_NOOP("App::Property","Show the cut in the 3D view"))
vobj.addProperty("App::PropertyLength","CutMargin","Arch",QT_TRANSLATE_NOOP("App::Property","The distance between the cut plane and the actual view cut (keep this a very small value but not zero)"))
vobj.DisplayLength = 1000
vobj.DisplayHeight = 1000
vobj.ArrowSize = 50
vobj.Transparency = 85
vobj.LineWidth = 1
vobj.LineColor = (0.0,0.0,0.4,1.0)
vobj.CutView = False
vobj.CutMargin = 1
vobj.Proxy = self
self.setProperties(vobj)
def setProperties(self,vobj):
pl = vobj.PropertiesList
d = 0
if "DisplaySize" in pl:
d = vobj.DisplaySize.Value
vobj.removeProperty("DisplaySize")
if not "DisplayLength" in pl:
vobj.addProperty("App::PropertyLength","DisplayLength","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The display length of this section plane"))
if d:
vobj.DisplayLength = d
else:
vobj.DisplayLength = 1000
if not "DisplayHeight" in pl:
vobj.addProperty("App::PropertyLength","DisplayHeight","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The display height of this section plane"))
if d:
vobj.DisplayHeight = d
else:
vobj.DisplayHeight = 1000
if not "ArrowSize" in pl:
vobj.addProperty("App::PropertyLength","ArrowSize","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The size of the arrows of this section plane"))
vobj.ArrowSize = 50
if not "Transparency" in pl:
vobj.addProperty("App::PropertyPercent","Transparency","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The transparency of this object"))
vobj.Transparency = 85
if not "LineWidth" in pl:
vobj.addProperty("App::PropertyFloat","LineWidth","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The line width of this object"))
vobj.LineWidth = 1
if not "CutDistance" in pl:
vobj.addProperty("App::PropertyLength","CutDistance","SectionPlane",QT_TRANSLATE_NOOP("App::Property","Show the cut in the 3D view"))
if not "LineColor" in pl:
vobj.addProperty("App::PropertyColor","LineColor","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The color of this object"))
vobj.LineColor = (0.0,0.0,0.4,1.0)
if not "CutView" in pl:
vobj.addProperty("App::PropertyBool","CutView","SectionPlane",QT_TRANSLATE_NOOP("App::Property","Show the cut in the 3D view"))
if not "CutMargin" in pl:
vobj.addProperty("App::PropertyLength","CutMargin","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The distance between the cut plane and the actual view cut (keep this a very small value but not zero)"))
vobj.CutMargin = 1
self.Object = vobj.Object
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_SectionPlane_Tree.svg"
def claimChildren(self):
return []
def attach(self,vobj):
self.clip = None
self.mat1 = coin.SoMaterial()
self.mat2 = coin.SoMaterial()
@@ -486,30 +549,36 @@ class _ViewProviderSectionPlane:
self.onChanged(vobj,"CutView")
def getDisplayModes(self,vobj):
return ["Default"]
def getDefaultDisplayMode(self):
return "Default"
def setDisplayMode(self,mode):
return mode
def updateData(self,obj,prop):
if prop in ["Placement"]:
self.onChanged(obj.ViewObject,"DisplayLength")
self.onChanged(obj.ViewObject,"CutView")
return
def onChanged(self,vobj,prop):
if prop == "LineColor":
l = vobj.LineColor
self.mat1.diffuseColor.setValue([l[0],l[1],l[2]])
self.mat2.diffuseColor.setValue([l[0],l[1],l[2]])
if hasattr(vobj,"LineColor"):
l = vobj.LineColor
self.mat1.diffuseColor.setValue([l[0],l[1],l[2]])
self.mat2.diffuseColor.setValue([l[0],l[1],l[2]])
elif prop == "Transparency":
if hasattr(vobj,"Transparency"):
self.mat2.transparency.setValue(vobj.Transparency/100.0)
elif prop in ["DisplayLength","DisplayHeight","ArrowSize"]:
if hasattr(vobj,"DisplayLength"):
if hasattr(vobj,"DisplayLength") and hasattr(vobj,"DisplayHeight"):
ld = vobj.DisplayLength.Value/2
hd = vobj.DisplayHeight.Value/2
elif hasattr(vobj,"DisplaySize"):
@@ -578,12 +647,15 @@ class _ViewProviderSectionPlane:
return
def __getstate__(self):
return None
def __setstate__(self,state):
return None
def setEdit(self,vobj,mode):
taskd = SectionPlaneTaskPanel()
taskd.obj = vobj.Object
taskd.update()
@@ -591,56 +663,59 @@ class _ViewProviderSectionPlane:
return True
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return False
def doubleClicked(self,vobj):
self.setEdit(vobj,None)
class _ArchDrawingView:
def __init__(self, obj):
obj.addProperty("App::PropertyLink", "Source", "Base",
QT_TRANSLATE_NOOP("App::Property","The linked object"))
obj.addProperty("App::PropertyEnumeration", "RenderingMode", "Drawing view",
QT_TRANSLATE_NOOP("App::Property","The rendering mode to use"))
obj.addProperty("App::PropertyBool", "ShowCut", "Drawing view",
QT_TRANSLATE_NOOP("App::Property","If cut geometry is shown or not"))
obj.addProperty("App::PropertyBool", "ShowFill", "Drawing view",
QT_TRANSLATE_NOOP("App::Property","If cut geometry is filled or not"))
obj.addProperty("App::PropertyFloat", "LineWidth", "Drawing view",
QT_TRANSLATE_NOOP("App::Property","The line width of the rendered objects"))
obj.addProperty("App::PropertyLength", "FontSize", "Drawing view",
QT_TRANSLATE_NOOP("App::Property","The size of the texts inside this object"))
obj.addProperty("App::PropertyBool", "AlwaysOn", "Drawing view",
QT_TRANSLATE_NOOP("App::Property","If checked, source objects are displayed regardless of being visible in the 3D model"))
self.initProperties(obj)
obj.RenderingMode = ["Solid","Wireframe"]
obj.RenderingMode = "Wireframe"
obj.LineWidth = 0.35
obj.ShowCut = False
obj.Proxy = self
self.Type = "ArchSectionView"
obj.FontSize = 12
self.setProperties(obj)
def initProperties(self, obj):
'''Creates and initializes the feature's properties if they do not yet exist.'''
def setProperties(self,obj):
if not hasattr(obj, "LineColor"):
obj.addProperty("App::PropertyColor", "LineColor", "Drawing view",
QT_TRANSLATE_NOOP("App::Property",
"The line color of the projected objects"))
if not hasattr(obj, "FillColor"):
obj.addProperty("App::PropertyColor", "FillColor", "Drawing view",
QT_TRANSLATE_NOOP("App::Property",
"The color of the cut faces (if turned on)"))
pl = obj.PropertiesList
if not "Source" in pl:
obj.addProperty("App::PropertyLink", "Source", "Base", QT_TRANSLATE_NOOP("App::Property","The linked object"))
if not "RenderingMode" in pl:
obj.addProperty("App::PropertyEnumeration", "RenderingMode", "Drawing view", QT_TRANSLATE_NOOP("App::Property","The rendering mode to use"))
obj.RenderingMode = ["Solid","Wireframe"]
obj.RenderingMode = "Wireframe"
if not "ShowCut" in pl:
obj.addProperty("App::PropertyBool", "ShowCut", "Drawing view", QT_TRANSLATE_NOOP("App::Property","If cut geometry is shown or not"))
if not "ShowFill" in pl:
obj.addProperty("App::PropertyBool", "ShowFill", "Drawing view", QT_TRANSLATE_NOOP("App::Property","If cut geometry is filled or not"))
if not "LineWidth" in pl:
obj.addProperty("App::PropertyFloat", "LineWidth", "Drawing view", QT_TRANSLATE_NOOP("App::Property","The line width of the rendered objects"))
obj.LineWidth = 0.35
if not "FontSize" in pl:
obj.addProperty("App::PropertyLength", "FontSize", "Drawing view", QT_TRANSLATE_NOOP("App::Property","The size of the texts inside this object"))
obj.FontSize = 12
if not "AlwaysOn" in pl:
obj.addProperty("App::PropertyBool", "AlwaysOn", "Drawing view", QT_TRANSLATE_NOOP("App::Property","If checked, source objects are displayed regardless of being visible in the 3D model"))
if not "LineColor" in pl:
obj.addProperty("App::PropertyColor", "LineColor", "Drawing view",QT_TRANSLATE_NOOP("App::Property","The line color of the projected objects"))
if not "FillColor" in pl:
obj.addProperty("App::PropertyColor", "FillColor", "Drawing view",QT_TRANSLATE_NOOP("App::Property","The color of the cut faces (if turned on)"))
obj.FillColor = (0.8, 0.8, 0.8)
self.Type = "ArchSectionView"
def onDocumentRestored(self, obj):
self.setProperties(obj)
def execute(self, obj):
if hasattr(obj,"Source"):
if obj.Source:
svgbody = getSVG(section=obj.Source,
svgbody = getSVG(section=obj.Source,
renderMode=obj.RenderingMode,
allOn=getattr(obj, 'AlwaysOn', False),
showHidden=obj.ShowCut,
@@ -661,25 +736,26 @@ class _ArchDrawingView:
result += '</g>\n'
obj.ViewResult = result
def onDocumentRestored(self, obj):
# Fixes properties of old files to match them with the current set of properties.
self.initProperties(obj)
def __getstate__(self):
return self.Type
def __setstate__(self,state):
if state:
self.Type = state
def getDisplayModes(self,vobj):
modes=["Default"]
return modes
def setDisplayMode(self,mode):
return mode
def getDXF(self,obj):
"returns a DXF representation of the view"
if obj.RenderingMode == "Solid":
print("Unable to get DXF from Solid mode: ",obj.Label)
@@ -701,8 +777,11 @@ class _ArchDrawingView:
class SectionPlaneTaskPanel:
'''A TaskPanel for all the section plane object'''
def __init__(self):
# the panel has a tree widget that contains categories
# for the subcomponents, such as additions, subtractions.
# the categories are shown only if they are not empty.

View File

@@ -36,7 +36,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchSite
# \ingroup ARCH
# \brief The Site object and tools
@@ -52,8 +52,10 @@ __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.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -75,6 +77,7 @@ def makeSite(objectslist=None,baseobj=None,name="Site"):
def makeSolarDiagram(longitude,latitude,scale=1,complete=False):
"""makeSolarDiagram(longitude,latitude,[scale,complete]):
returns a solar diagram as a pivy node. If complete is
True, the 12 months are drawn"""
@@ -256,17 +259,22 @@ def makeSolarDiagram(longitude,latitude,scale=1,complete=False):
class _CommandSite:
"the Arch Site command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Site',
'MenuText': QT_TRANSLATE_NOOP("Arch_Site","Site"),
'Accel': "S, I",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Site","Creates a site object including selected objects.")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
link = p.GetBool("FreeLinking",False)
@@ -312,29 +320,63 @@ class _Site(ArchFloor._Floor):
def __init__(self,obj):
ArchFloor._Floor.__init__(self,obj)
obj.addProperty("App::PropertyLink","Terrain","Arch",QT_TRANSLATE_NOOP("App::Property","The base terrain of this site"))
obj.addProperty("App::PropertyString","Address","Arch",QT_TRANSLATE_NOOP("App::Property","The street and house number of this site"))
obj.addProperty("App::PropertyString","PostalCode","Arch",QT_TRANSLATE_NOOP("App::Property","The postal or zip code of this site"))
obj.addProperty("App::PropertyString","City","Arch",QT_TRANSLATE_NOOP("App::Property","The city of this site"))
obj.addProperty("App::PropertyString","Country","Arch",QT_TRANSLATE_NOOP("App::Property","The country of this site"))
obj.addProperty("App::PropertyFloat","Latitude","Arch",QT_TRANSLATE_NOOP("App::Property","The latitude of this site"))
obj.addProperty("App::PropertyFloat","Longitude","Arch",QT_TRANSLATE_NOOP("App::Property","The latitude of this site"))
obj.addProperty("App::PropertyAngle","Declination","Arch",QT_TRANSLATE_NOOP("App::Property","Angle between the true North and the North direction in this document"))
obj.addProperty("App::PropertyLength","Elevation","Arch",QT_TRANSLATE_NOOP("App::Property","The elevation of level 0 of this site"))
obj.addProperty("App::PropertyString","Url","Arch",QT_TRANSLATE_NOOP("App::Property","A url that shows this site in a mapping website"))
obj.addProperty("App::PropertyLinkList","Additions","Arch",QT_TRANSLATE_NOOP("App::Property","Other shapes that are appended to this object"))
obj.addProperty("App::PropertyLinkList","Subtractions","Arch",QT_TRANSLATE_NOOP("App::Property","Other shapes that are subtracted from this object"))
obj.addProperty("App::PropertyArea","ProjectedArea","Arch",QT_TRANSLATE_NOOP("App::Property","The area of the projection of this object onto the XY plane"))
obj.addProperty("App::PropertyLength","Perimeter","Arch",QT_TRANSLATE_NOOP("App::Property","The perimeter length of this terrain"))
obj.addProperty("App::PropertyVolume","AdditionVolume","Arch",QT_TRANSLATE_NOOP("App::Property","The volume of earth to be added to this terrain"))
obj.addProperty("App::PropertyVolume","SubtractionVolume","Arch",QT_TRANSLATE_NOOP("App::Property","The volume of earth to be removed from this terrain"))
obj.addProperty("App::PropertyVector","ExtrusionVector","Arch",QT_TRANSLATE_NOOP("App::Property","An extrusion vector to use when performing boolean operations"))
obj.addProperty("App::PropertyBool","RemoveSplitter","Arch",QT_TRANSLATE_NOOP("App::Property","Remove splitters from the resulting shape"))
obj.addProperty("App::PropertyVector","OriginOffset","Arch",QT_TRANSLATE_NOOP("App::Property","An optional offset between the model (0,0,0) origin and the point indicated by the geocoordinates"))
obj.addExtension("App::GroupExtensionPython", self)
self.setProperties(obj)
obj.IfcRole = "Site"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Terrain" in pl:
obj.addProperty("App::PropertyLink","Terrain","Site",QT_TRANSLATE_NOOP("App::Property","The base terrain of this site"))
if not "Address" in pl:
obj.addProperty("App::PropertyString","Address","Site",QT_TRANSLATE_NOOP("App::Property","The street and house number of this site"))
if not "PostalCode" in pl:
obj.addProperty("App::PropertyString","PostalCode","Site",QT_TRANSLATE_NOOP("App::Property","The postal or zip code of this site"))
if not "City" in pl:
obj.addProperty("App::PropertyString","City","Site",QT_TRANSLATE_NOOP("App::Property","The city of this site"))
if not "Country" in pl:
obj.addProperty("App::PropertyString","Country","Site",QT_TRANSLATE_NOOP("App::Property","The country of this site"))
if not "Latitude" in pl:
obj.addProperty("App::PropertyFloat","Latitude","Site",QT_TRANSLATE_NOOP("App::Property","The latitude of this site"))
if not "Longitude" in pl:
obj.addProperty("App::PropertyFloat","Longitude","Site",QT_TRANSLATE_NOOP("App::Property","The latitude of this site"))
if not "Declination" in pl:
obj.addProperty("App::PropertyAngle","Declination","Site",QT_TRANSLATE_NOOP("App::Property","Angle between the true North and the North direction in this document"))
if "NorthDeviation"in pl:
obj.Declination = obj.NorthDeviation.Value
obj.removeProperty("NorthDeviation")
if not "Elevation" in pl:
obj.addProperty("App::PropertyLength","Elevation","Site",QT_TRANSLATE_NOOP("App::Property","The elevation of level 0 of this site"))
if not "Url" in pl:
obj.addProperty("App::PropertyString","Url","Site",QT_TRANSLATE_NOOP("App::Property","A url that shows this site in a mapping website"))
if not "Additions" in pl:
obj.addProperty("App::PropertyLinkList","Additions","Site",QT_TRANSLATE_NOOP("App::Property","Other shapes that are appended to this object"))
if not "Subtractions" in pl:
obj.addProperty("App::PropertyLinkList","Subtractions","Site",QT_TRANSLATE_NOOP("App::Property","Other shapes that are subtracted from this object"))
if not "ProjectedArea" in pl:
obj.addProperty("App::PropertyArea","ProjectedArea","Site",QT_TRANSLATE_NOOP("App::Property","The area of the projection of this object onto the XY plane"))
if not "Perimeter" in pl:
obj.addProperty("App::PropertyLength","Perimeter","Site",QT_TRANSLATE_NOOP("App::Property","The perimeter length of this terrain"))
if not "AdditionVolume" in pl:
obj.addProperty("App::PropertyVolume","AdditionVolume","Site",QT_TRANSLATE_NOOP("App::Property","The volume of earth to be added to this terrain"))
if not "SubtractionVolume" in pl:
obj.addProperty("App::PropertyVolume","SubtractionVolume","Site",QT_TRANSLATE_NOOP("App::Property","The volume of earth to be removed from this terrain"))
if not "ExtrusionVector" in pl:
obj.addProperty("App::PropertyVector","ExtrusionVector","Site",QT_TRANSLATE_NOOP("App::Property","An extrusion vector to use when performing boolean operations"))
obj.ExtrusionVector = FreeCAD.Vector(0,0,-100000)
if not "RemoveSplitter" in pl:
obj.addProperty("App::PropertyBool","RemoveSplitter","Site",QT_TRANSLATE_NOOP("App::Property","Remove splitters from the resulting shape"))
if not "OriginOffset" in pl:
obj.addProperty("App::PropertyVector","OriginOffset","Site",QT_TRANSLATE_NOOP("App::Property","An optional offset between the model (0,0,0) origin and the point indicated by the geocoordinates"))
if not hasattr(obj,"Group"):
obj.addExtension("App::GroupExtensionPython", self)
self.Type = "Site"
obj.setEditorMode('Height',2)
obj.ExtrusionVector = FreeCAD.Vector(0,0,-100000)
def onDocumentRestored(self,obj):
ArchFloor._Floor.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
@@ -462,19 +504,35 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
"A View Provider for the Site object"
def __init__(self,vobj):
ArchFloor._ViewProviderFloor.__init__(self,vobj)
vobj.addProperty("App::PropertyBool","SolarDiagram","Arch",QT_TRANSLATE_NOOP("App::Property","Show solar diagram or not"))
vobj.addProperty("App::PropertyFloat","SolarDiagramScale","Arch",QT_TRANSLATE_NOOP("App::Property","The scale of the solar diagram"))
vobj.addProperty("App::PropertyVector","SolarDiagramPosition","Arch",QT_TRANSLATE_NOOP("App::Property","The position of the solar diagram"))
vobj.addProperty("App::PropertyColor","SolarDiagramColor","Arch",QT_TRANSLATE_NOOP("App::Property","The color of the solar diagram"))
vobj.SolarDiagramScale = 1
vobj.SolarDiagramColor = (0.16,0.16,0.25)
self.setProperties(vobj)
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "SolarDiagram" in pl:
vobj.addProperty("App::PropertyBool","SolarDiagram","Site",QT_TRANSLATE_NOOP("App::Property","Show solar diagram or not"))
if not "SolarDiagramScale" in pl:
vobj.addProperty("App::PropertyFloat","SolarDiagramScale","Site",QT_TRANSLATE_NOOP("App::Property","The scale of the solar diagram"))
vobj.SolarDiagramScale = 1
if not "SolarDiagramPosition" in pl:
vobj.addProperty("App::PropertyVector","SolarDiagramPosition","Site",QT_TRANSLATE_NOOP("App::Property","The position of the solar diagram"))
if not "SolarDiagramColor" in pl:
vobj.addProperty("App::PropertyColor","SolarDiagramColor","Site",QT_TRANSLATE_NOOP("App::Property","The color of the solar diagram"))
vobj.SolarDiagramColor = (0.16,0.16,0.25)
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Site_Tree.svg"
def claimChildren(self):
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):
@@ -484,6 +542,7 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
return objs
def setEdit(self,vobj,mode):
if mode == 0:
import ArchComponent
taskd = ArchComponent.ComponentTaskPanel()
@@ -494,10 +553,12 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
return False
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return False
def attach(self,vobj):
ArchFloor._ViewProviderFloor.attach(self,vobj)
from pivy import coin
self.diagramsep = coin.SoSeparator()
@@ -509,21 +570,23 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
self.diagramsep.addChild(self.coords)
self.diagramsep.addChild(self.color)
vobj.Annotation.addChild(self.diagramswitch)
def updateData(self,obj,prop):
if prop in ["Longitude","Latitude"]:
self.onChanged(obj.ViewObject,"SolarDiagram")
elif prop == "NorthDeviation":
elif prop == "Declination":
self.onChanged(obj.ViewObject,"SolarDiagramPosition")
def onChanged(self,vobj,prop):
if prop == "SolarDiagramPosition":
if hasattr(vobj,"SolarDiagramPosition"):
p = vobj.SolarDiagramPosition
self.coords.translation.setValue([p.x,p.y,p.z])
if hasattr(vobj.Object,"NorthDeviation"):
if hasattr(vobj.Object,"Declination"):
from pivy import coin
self.coords.rotation.setValue(coin.SbVec3f((0,0,1)),math.radians(vobj.Object.NorthDeviation.Value))
self.coords.rotation.setValue(coin.SbVec3f((0,0,1)),math.radians(vobj.Object.Declination.Value))
elif prop == "SolarDiagramColor":
if hasattr(vobj,"SolarDiagramColor"):
l = vobj.SolarDiagramColor

View File

@@ -161,7 +161,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchSpace
# \ingroup ARCH
# \brief The Space object and tools
@@ -171,9 +171,11 @@ else:
# building, ie. a room.
def makeSpace(objects=None,baseobj=None,name="Space"):
"""makeSpace([objects]): Creates a space object from the given objects. Objects can be one
document object, in which case it becomes the base shape of the space object, or a list of
selection objects as got from getSelectionEx(), or a list of tuples (object, subobjectname)"""
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -196,13 +198,17 @@ def makeSpace(objects=None,baseobj=None,name="Space"):
return obj
def addSpaceBoundaries(space,subobjects):
"""addSpaceBoundaries(space,subobjects): adds the given subobjects to the given space"""
import Draft
if Draft.getType(space) == "Space":
space.Proxy.addSubobjects(space,subobjects)
def removeSpaceBoundaries(space,objects):
"""removeSpaceBoundaries(space,objects): removes the given objects from the given spaces boundaries"""
import Draft
if Draft.getType(space) == "Space":
bounds = space.Boundaries
@@ -214,17 +220,22 @@ def removeSpaceBoundaries(space,objects):
space.Boundaries = bounds
class _CommandSpace:
"the Arch Space command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Space',
'MenuText': QT_TRANSLATE_NOOP("Arch_Space","Space"),
'Accel': "S, P",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Space","Creates a space object from selected boundary objects")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Space"))
FreeCADGui.addModule("Arch")
sel = FreeCADGui.Selection.getSelection()
@@ -246,36 +257,64 @@ class _CommandSpace:
class _Space(ArchComponent.Component):
"A space object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLinkSubList","Boundaries", "Arch",QT_TRANSLATE_NOOP("App::Property","The objects that make the boundaries of this space object"))
obj.addProperty("App::PropertyArea", "Area", "Arch",QT_TRANSLATE_NOOP("App::Property","The computed floor area of this space"))
obj.addProperty("App::PropertyString", "FinishFloor", "Arch",QT_TRANSLATE_NOOP("App::Property","The finishing of the floor of this space"))
obj.addProperty("App::PropertyString", "FinishWalls", "Arch",QT_TRANSLATE_NOOP("App::Property","The finishing of the walls of this space"))
obj.addProperty("App::PropertyString", "FinishCeiling", "Arch",QT_TRANSLATE_NOOP("App::Property","The finishing of the ceiling of this space"))
obj.addProperty("App::PropertyLinkList", "Group", "Arch",QT_TRANSLATE_NOOP("App::Property","Objects that are included inside this space, such as furniture"))
obj.addProperty("App::PropertyEnumeration","SpaceType", "Arch",QT_TRANSLATE_NOOP("App::Property","The type of this space"))
obj.addProperty("App::PropertyLength", "FloorThickness","Arch",QT_TRANSLATE_NOOP("App::Property","The thickness of the floor finish"))
obj.addProperty("App::PropertyLink", "Zone", "Arch",QT_TRANSLATE_NOOP("App::Property","A zone this space is part of"))
obj.addProperty("App::PropertyInteger", "NumberOfPeople","Arch",QT_TRANSLATE_NOOP("App::Property","The number of people who typically occupy this space"))
obj.addProperty("App::PropertyFloat", "LightingPower", "Arch",QT_TRANSLATE_NOOP("App::Property","The electric power needed to light this space in Watts"))
obj.addProperty("App::PropertyFloat", "EquipmentPower","Arch",QT_TRANSLATE_NOOP("App::Property","The electric power needed by the equipment of this space in Watts"))
obj.addProperty("App::PropertyBool", "AutoPower", "Arch",QT_TRANSLATE_NOOP("App::Property","If True, Equipment Power will be automatically filled by the equipment included in this space"))
obj.addProperty("App::PropertyEnumeration","Conditioning", "Arch",QT_TRANSLATE_NOOP("App::Property","The type of air conditioning of this space"))
self.Type = "Space"
obj.SpaceType = SpaceTypes
obj.Conditioning = ConditioningTypes
self.setProperties(obj)
obj.IfcRole = "Space"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Boundaries" in pl:
obj.addProperty("App::PropertyLinkSubList","Boundaries", "Space",QT_TRANSLATE_NOOP("App::Property","The objects that make the boundaries of this space object"))
if not "Area" in pl:
obj.addProperty("App::PropertyArea", "Area", "Space",QT_TRANSLATE_NOOP("App::Property","The computed floor area of this space"))
if not "FinishFloor" in pl:
obj.addProperty("App::PropertyString", "FinishFloor", "Space",QT_TRANSLATE_NOOP("App::Property","The finishing of the floor of this space"))
if not "FinishWalls" in pl:
obj.addProperty("App::PropertyString", "FinishWalls", "Space",QT_TRANSLATE_NOOP("App::Property","The finishing of the walls of this space"))
if not "FinishCeiling" in pl:
obj.addProperty("App::PropertyString", "FinishCeiling", "Space",QT_TRANSLATE_NOOP("App::Property","The finishing of the ceiling of this space"))
if not "Group" in pl:
obj.addProperty("App::PropertyLinkList", "Group", "Space",QT_TRANSLATE_NOOP("App::Property","Objects that are included inside this space, such as furniture"))
if not "SpaceType" in pl:
obj.addProperty("App::PropertyEnumeration","SpaceType", "Space",QT_TRANSLATE_NOOP("App::Property","The type of this space"))
obj.SpaceType = SpaceTypes
if not "FloorThickness" in pl:
obj.addProperty("App::PropertyLength", "FloorThickness","Space",QT_TRANSLATE_NOOP("App::Property","The thickness of the floor finish"))
if not "Zone" in pl:
obj.addProperty("App::PropertyLink", "Zone", "Space",QT_TRANSLATE_NOOP("App::Property","A zone this space is part of"))
if not "NumberOfPeople" in pl:
obj.addProperty("App::PropertyInteger", "NumberOfPeople","Space",QT_TRANSLATE_NOOP("App::Property","The number of people who typically occupy this space"))
if not "LightingPower" in pl:
obj.addProperty("App::PropertyFloat", "LightingPower", "Space",QT_TRANSLATE_NOOP("App::Property","The electric power needed to light this space in Watts"))
if not "EquipmentPower" in pl:
obj.addProperty("App::PropertyFloat", "EquipmentPower","Space",QT_TRANSLATE_NOOP("App::Property","The electric power needed by the equipment of this space in Watts"))
if not "AutoPower" in pl:
obj.addProperty("App::PropertyBool", "AutoPower", "Space",QT_TRANSLATE_NOOP("App::Property","If True, Equipment Power will be automatically filled by the equipment included in this space"))
if not "Conditioning" in pl:
obj.addProperty("App::PropertyEnumeration","Conditioning", "Space",QT_TRANSLATE_NOOP("App::Property","The type of air conditioning of this space"))
obj.Conditioning = ConditioningTypes
self.Type = "Space"
obj.setEditorMode("HorizontalArea",2)
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
if self.clone(obj):
return
self.getShape(obj)
def onChanged(self,obj,prop):
if prop == "Group":
if hasattr(obj,"EquipmentPower"):
if obj.AutoPower:
@@ -290,6 +329,7 @@ class _Space(ArchComponent.Component):
ArchComponent.Component.onChanged(self,obj,prop)
def addSubobjects(self,obj,subobjects):
"adds subobjects to this space"
objs = obj.Boundaries
for o in subobjects:
@@ -304,11 +344,12 @@ class _Space(ArchComponent.Component):
obj.Boundaries = objs
def getShape(self,obj):
"computes a shape from a base shape and/or bounday faces"
import Part
shape = None
faces = []
pl = obj.Placement
#print("starting compute")
@@ -380,7 +421,9 @@ class _Space(ArchComponent.Component):
print("Arch: error computing space boundary")
def getArea(self,obj):
"returns the horizontal area at the center of the space"
import Part,DraftGeomUtils
if not hasattr(obj.Shape,"CenterOfMass"):
return 0
@@ -412,41 +455,65 @@ class _Space(ArchComponent.Component):
class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
"A View Provider for Section Planes"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
self.setProperties(vobj)
vobj.Transparency = 85
vobj.LineWidth = 1
vobj.LineColor = (1.0,0.0,0.0,1.0)
vobj.DrawStyle = "Dotted"
vobj.addProperty("App::PropertyStringList", "Text", "Arch",QT_TRANSLATE_NOOP("App::Property","The text to show. Use $area, $label, $tag, $floor, $walls, $ceiling to insert the respective data"))
vobj.addProperty("App::PropertyFont", "FontName", "Arch",QT_TRANSLATE_NOOP("App::Property","The name of the font"))
vobj.addProperty("App::PropertyColor", "TextColor", "Arch",QT_TRANSLATE_NOOP("App::Property","The color of the area text"))
vobj.addProperty("App::PropertyLength", "FontSize", "Arch",QT_TRANSLATE_NOOP("App::Property","The size of the text font"))
vobj.addProperty("App::PropertyLength", "FirstLine", "Arch",QT_TRANSLATE_NOOP("App::Property","The size of the first line of text"))
vobj.addProperty("App::PropertyFloat", "LineSpacing", "Arch",QT_TRANSLATE_NOOP("App::Property","The space between the lines of text"))
vobj.addProperty("App::PropertyVectorDistance","TextPosition","Arch",QT_TRANSLATE_NOOP("App::Property","The position of the text. Leave (0,0,0) for automatic position"))
vobj.addProperty("App::PropertyEnumeration", "TextAlign", "Arch",QT_TRANSLATE_NOOP("App::Property","The justification of the text"))
vobj.addProperty("App::PropertyInteger", "Decimals", "Arch",QT_TRANSLATE_NOOP("App::Property","The number of decimals to use for calculated texts"))
vobj.addProperty("App::PropertyBool", "ShowUnit", "Arch",QT_TRANSLATE_NOOP("App::Property","Show the unit suffix"))
vobj.TextColor = (0.0,0.0,0.0,1.0)
vobj.Text = ["$label","$area"]
vobj.TextAlign = ["Left","Center","Right"]
vobj.FontSize = Draft.getParam("textheight",10)
vobj.FirstLine = Draft.getParam("textheight",10)
vobj.FontName = Draft.getParam("textfont","")
vobj.Decimals = Draft.getParam("dimPrecision",2)
vobj.ShowUnit = Draft.getParam("showUnit",True)
vobj.LineSpacing = 1.0
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "Text" in pl:
vobj.addProperty("App::PropertyStringList", "Text", "Space",QT_TRANSLATE_NOOP("App::Property","The text to show. Use $area, $label, $tag, $floor, $walls, $ceiling to insert the respective data"))
vobj.Text = ["$label","$area"]
if not "FontName" in pl:
vobj.addProperty("App::PropertyFont", "FontName", "Space",QT_TRANSLATE_NOOP("App::Property","The name of the font"))
vobj.FontName = Draft.getParam("textfont","")
if not "TextColor" in pl:
vobj.addProperty("App::PropertyColor", "TextColor", "Space",QT_TRANSLATE_NOOP("App::Property","The color of the area text"))
vobj.TextColor = (0.0,0.0,0.0,1.0)
if not "FontSize" in pl:
vobj.addProperty("App::PropertyLength", "FontSize", "Space",QT_TRANSLATE_NOOP("App::Property","The size of the text font"))
vobj.FontSize = Draft.getParam("textheight",10)
if not "FirstLine" in pl:
vobj.addProperty("App::PropertyLength", "FirstLine", "Space",QT_TRANSLATE_NOOP("App::Property","The size of the first line of text"))
vobj.FirstLine = Draft.getParam("textheight",10)
if not "LineSpacing" in pl:
vobj.addProperty("App::PropertyFloat", "LineSpacing", "Space",QT_TRANSLATE_NOOP("App::Property","The space between the lines of text"))
vobj.LineSpacing = 1.0
if not "TextPosition" in pl:
vobj.addProperty("App::PropertyVectorDistance","TextPosition","Space",QT_TRANSLATE_NOOP("App::Property","The position of the text. Leave (0,0,0) for automatic position"))
if not "TextAlign" in pl:
vobj.addProperty("App::PropertyEnumeration", "TextAlign", "Space",QT_TRANSLATE_NOOP("App::Property","The justification of the text"))
vobj.TextAlign = ["Left","Center","Right"]
if not "Decimals" in pl:
vobj.addProperty("App::PropertyInteger", "Decimals", "Space",QT_TRANSLATE_NOOP("App::Property","The number of decimals to use for calculated texts"))
vobj.Decimals = Draft.getParam("dimPrecision",2)
if not "ShowUnit" in pl:
vobj.addProperty("App::PropertyBool", "ShowUnit", "Space",QT_TRANSLATE_NOOP("App::Property","Show the unit suffix"))
vobj.ShowUnit = Draft.getParam("showUnit",True)
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getDefaultDisplayMode(self):
return "Wireframe"
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Space_Tree.svg"
def attach(self,vobj):
ArchComponent.ViewProviderComponent.attach(self,vobj)
from pivy import coin
self.color = coin.SoBaseColor()
@@ -477,11 +544,13 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
self.onChanged(vobj,"FontName")
def updateData(self,obj,prop):
if prop in ["Shape","Label","Tag","Area"]:
self.onChanged(obj.ViewObject,"Text")
self.onChanged(obj.ViewObject,"TextPosition")
def getTextPosition(self,vobj):
pos = FreeCAD.Vector()
if hasattr(vobj,"TextPosition"):
import DraftVecUtils
@@ -497,6 +566,7 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
return pos
def onChanged(self,vobj,prop):
if prop in ["Text","Decimals","ShowUnit"]:
if hasattr(self,"text1") and hasattr(self,"text2") and hasattr(vobj,"Text"):
self.text1.string.deleteValues(0)
@@ -584,7 +654,7 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
else:
self.text1.justification = coin.SoAsciiText.LEFT
self.text2.justification = coin.SoAsciiText.LEFT
elif prop == "Visibility":
if vobj.Visibility:
self.label.whichChild = 0
@@ -601,9 +671,11 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
class SpaceTaskPanel(ArchComponent.ComponentTaskPanel):
"A modified version of the Arch component task panel"
def __init__(self):
ArchComponent.ComponentTaskPanel.__init__(self)
self.editButton = QtGui.QPushButton(self.form)
self.editButton.setObjectName("editButton")
@@ -628,8 +700,9 @@ class SpaceTaskPanel(ArchComponent.ComponentTaskPanel):
self.grid.addWidget(self.delCompButton, 7, 1, 1, 1)
self.delCompButton.setText(QtGui.QApplication.translate("Arch", "Remove", None))
QtCore.QObject.connect(self.delCompButton, QtCore.SIGNAL("clicked()"), self.delBoundary)
def updateBoundaries(self):
self.boundList.clear()
if self.obj:
for b in self.obj.Boundaries:
@@ -639,17 +712,20 @@ class SpaceTaskPanel(ArchComponent.ComponentTaskPanel):
it = QtGui.QListWidgetItem(s)
it.setToolTip(b[0].Name)
self.boundList.addItem(it)
def setTextPos(self):
FreeCADGui.runCommand("Draft_Edit")
def addBoundary(self):
if self.obj:
if FreeCADGui.Selection.getSelectionEx():
self.obj.Proxy.addSubobjects(self.obj,FreeCADGui.Selection.getSelectionEx())
self.updateBoundaries()
def delBoundary(self):
if self.boundList.currentRow() >= 0:
it = self.boundList.item(self.boundList.currentRow())
if it and self.obj:
@@ -662,5 +738,6 @@ class SpaceTaskPanel(ArchComponent.ComponentTaskPanel):
self.obj.Boundaries = bounds
self.updateBoundaries()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Space',_CommandSpace())

View File

@@ -39,16 +39,19 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchStairs
# \ingroup ARCH
# \brief The Stairs object and tools
#
# This module provides tools to build Stairs objects.
def makeStairs(baseobj=None,length=None,width=None,height=None,steps=None,name="Stairs"):
"""makeStairs([baseobj,length,width,height,steps]): creates a Stairs
objects with given attributes."""
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -78,17 +81,22 @@ def makeStairs(baseobj=None,length=None,width=None,height=None,steps=None,name="
class _CommandStairs:
"the Arch Stairs command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Stairs',
'MenuText': QT_TRANSLATE_NOOP("Arch_Stairs","Stairs"),
'Accel': "S, R",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Space","Creates a stairs object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Stairs"))
FreeCADGui.addModule("Arch")
@@ -104,53 +112,82 @@ class _CommandStairs:
class _Stairs(ArchComponent.Component):
"A stairs object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
self.setProperties(obj)
obj.IfcRole = "Stair"
def setProperties(self,obj):
# http://en.wikipedia.org/wiki/Stairs
pl = obj.PropertiesList
# base properties
obj.addProperty("App::PropertyLength","Length","Arch",QT_TRANSLATE_NOOP("App::Property","The length of these stairs, if no baseline is defined"))
obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of these stairs"))
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The total height of these stairs"))
obj.addProperty("App::PropertyEnumeration","Align","Arch",QT_TRANSLATE_NOOP("App::Property","The alignment of these stairs on their baseline, if applicable"))
if not "Length" in pl:
obj.addProperty("App::PropertyLength","Length","Stairs",QT_TRANSLATE_NOOP("App::Property","The length of these stairs, if no baseline is defined"))
if not "Width" in pl:
obj.addProperty("App::PropertyLength","Width","Stairs",QT_TRANSLATE_NOOP("App::Property","The width of these stairs"))
if not "Height" in pl:
obj.addProperty("App::PropertyLength","Height","Stairs",QT_TRANSLATE_NOOP("App::Property","The total height of these stairs"))
if not "Align" in pl:
obj.addProperty("App::PropertyEnumeration","Align","Stairs",QT_TRANSLATE_NOOP("App::Property","The alignment of these stairs on their baseline, if applicable"))
obj.Align = ['Left','Right','Center']
# steps properties
obj.addProperty("App::PropertyInteger","NumberOfSteps","Steps",QT_TRANSLATE_NOOP("App::Property","The number of risers in these stairs"))
obj.addProperty("App::PropertyLength","TreadDepth","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the treads of these stairs"))
obj.addProperty("App::PropertyLength","RiserHeight","Steps",QT_TRANSLATE_NOOP("App::Property","The height of the risers of these stairs"))
obj.addProperty("App::PropertyLength","Nosing","Steps",QT_TRANSLATE_NOOP("App::Property","The size of the nosing"))
obj.addProperty("App::PropertyLength","TreadThickness","Steps",QT_TRANSLATE_NOOP("App::Property","The thickness of the treads"))
obj.addProperty("App::PropertyFloat","BlondelRatio","Steps",QT_TRANSLATE_NOOP("App::Property","The Blondel ratio, must be between 62 and 64cm or 24.5 and 25.5in"))
if not "NumberOfSteps" in pl:
obj.addProperty("App::PropertyInteger","NumberOfSteps","Steps",QT_TRANSLATE_NOOP("App::Property","The number of risers in these stairs"))
if not "TreadDepth" in pl:
obj.addProperty("App::PropertyLength","TreadDepth","Steps",QT_TRANSLATE_NOOP("App::Property","The depth of the treads of these stairs"))
obj.setEditorMode("TreadDepth",1)
if not "RiserHeight" in pl:
obj.addProperty("App::PropertyLength","RiserHeight","Steps",QT_TRANSLATE_NOOP("App::Property","The height of the risers of these stairs"))
obj.setEditorMode("RiserHeight",1)
if not "Nosing" in pl:
obj.addProperty("App::PropertyLength","Nosing","Steps",QT_TRANSLATE_NOOP("App::Property","The size of the nosing"))
if not "TreadThickness" in pl:
obj.addProperty("App::PropertyLength","TreadThickness","Steps",QT_TRANSLATE_NOOP("App::Property","The thickness of the treads"))
if not "BlondelRatio" in pl:
obj.addProperty("App::PropertyFloat","BlondelRatio","Steps",QT_TRANSLATE_NOOP("App::Property","The Blondel ratio indicates comfortable stairs and should be between 62 and 64cm or 24.5 and 25.5in"))
obj.setEditorMode("BlondelRatio",1)
# structural properties
obj.addProperty("App::PropertyEnumeration","Landings","Structure",QT_TRANSLATE_NOOP("App::Property","The type of landings of these stairs"))
obj.addProperty("App::PropertyEnumeration","Winders","Structure",QT_TRANSLATE_NOOP("App::Property","The type of winders in these stairs"))
obj.addProperty("App::PropertyEnumeration","Structure","Structure",QT_TRANSLATE_NOOP("App::Property","The type of structure of these stairs"))
obj.addProperty("App::PropertyLength","StructureThickness","Structure",QT_TRANSLATE_NOOP("App::Property","The thickness of the massive structure or of the stringers"))
obj.addProperty("App::PropertyLength","StringerWidth","Structure",QT_TRANSLATE_NOOP("App::Property","The width of the stringers"))
obj.addProperty("App::PropertyLength","StructureOffset","Structure",QT_TRANSLATE_NOOP("App::Property","The offset between the border of the stairs and the structure"))
obj.addProperty("App::PropertyLength","StringerOverlap","Structure",QT_TRANSLATE_NOOP("App::Property","The overlap of the stringers above the bottom of the treads"))
if not "Landings" in pl:
obj.addProperty("App::PropertyEnumeration","Landings","Structure",QT_TRANSLATE_NOOP("App::Property","The type of landings of these stairs"))
obj.Landings = ["None","At center","At each corner"]
if not "Winders" in pl:
obj.addProperty("App::PropertyEnumeration","Winders","Structure",QT_TRANSLATE_NOOP("App::Property","The type of winders in these stairs"))
obj.Winders = ["None","All","Corners strict","Corners relaxed"]
if not "Structure" in pl:
obj.addProperty("App::PropertyEnumeration","Structure","Structure",QT_TRANSLATE_NOOP("App::Property","The type of structure of these stairs"))
obj.Structure = ["None","Massive","One stringer","Two stringers"]
if not "StructureThickness" in pl:
obj.addProperty("App::PropertyLength","StructureThickness","Structure",QT_TRANSLATE_NOOP("App::Property","The thickness of the massive structure or of the stringers"))
if not "StringerWidth" in pl:
obj.addProperty("App::PropertyLength","StringerWidth","Structure",QT_TRANSLATE_NOOP("App::Property","The width of the stringers"))
if not "StructureOffset" in pl:
obj.addProperty("App::PropertyLength","StructureOffset","Structure",QT_TRANSLATE_NOOP("App::Property","The offset between the border of the stairs and the structure"))
if not "StringerOverlap" in pl:
obj.addProperty("App::PropertyLength","StringerOverlap","Structure",QT_TRANSLATE_NOOP("App::Property","The overlap of the stringers above the bottom of the treads"))
obj.Align = ['Left','Right','Center']
obj.Landings = ["None","At center","At each corner"]
obj.Winders = ["None","All","Corners strict","Corners relaxed"]
obj.Structure = ["None","Massive","One stringer","Two stringers"]
obj.setEditorMode("TreadDepth",1)
obj.setEditorMode("RiserHeight",1)
obj.setEditorMode("BlondelRatio",1)
self.Type = "Stairs"
obj.IfcRole = "Stair"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
"constructs the shape of the stairs"
if self.clone(obj):
return
import Part
self.steps = []
self.pseudosteps = []
@@ -233,6 +270,7 @@ class _Stairs(ArchComponent.Component):
def align(self,basepoint,align,widthvec):
"moves a given basepoint according to the alignment"
if align == "Center":
basepoint = basepoint.add(DraftVecUtils.scale(widthvec,-0.5))
@@ -499,20 +537,27 @@ class _Stairs(ArchComponent.Component):
def makeCurvedStairs(self,obj,edge):
print("Not yet implemented!")
def makeCurvedStairsWithLanding(self,obj,edge):
print("Not yet implemented!")
class _ViewProviderStairs(ArchComponent.ViewProviderComponent):
"A View Provider for Stairs"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
def getIcon(self):
import Arch_rc
return ":/icons/Arch_Stairs_Tree.svg"
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Stairs',_CommandStairs())

View File

@@ -38,7 +38,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchStructure
# \ingroup ARCH
# \brief The Structure object and tools
@@ -62,10 +62,12 @@ for pre in Presets:
def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structure"):
'''makeStructure([obj],[length],[width],[height],[swap]): creates a
structure element based on the given profile object and the given
extrusion height. If no base object is given, you can also specify
length and width for a cubic object.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -99,8 +101,10 @@ def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structur
return obj
def makeStructuralSystem(objects=[],axes=[],name="StructuralSystem"):
'''makeStructuralSystem(objects,axes): makes a structural system
based on the given objects and axes'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -133,17 +137,22 @@ def makeStructuralSystem(objects=[],axes=[],name="StructuralSystem"):
return result
class _CommandStructure:
"the Arch Structure command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Structure',
'MenuText': QT_TRANSLATE_NOOP("Arch_Structure","Structure"),
'Accel': "S, T",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Structure","Creates a structure object from scratch or from a selected object (sketch, wire, face or solid)")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
self.Length = p.GetFloat("StructureLength",100)
self.Width = p.GetFloat("StructureWidth",100)
@@ -195,7 +204,9 @@ class _CommandStructure:
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=[self.taskbox(),self.precast.form,self.dents.form])
def getPoint(self,point=None,obj=None):
"this function is called by the snapper when it has a 3D point"
if self.modeb.isChecked() and (self.bpoint == None):
self.bpoint = point
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=[self.taskbox(),self.precast.form,self.dents.form])
@@ -254,19 +265,22 @@ class _CommandStructure:
if self.continueCmd:
self.Activated()
def _createItemlist(self, baselist) :
def _createItemlist(self, baselist):
ilist=[]
for p in baselist:
ilist.append(p[2]+" ("+str(p[4])+"x"+str(p[5])+"mm)")
return ilist
def taskbox(self):
"sets up a taskbox widget"
w = QtGui.QWidget()
ui = FreeCADGui.UiLoader()
w.setWindowTitle(translate("Arch","Structure options", utf8_decode=True))
grid = QtGui.QGridLayout(w)
# mode box
labelmode = QtGui.QLabel(translate("Arch","Drawing mode:", utf8_decode=True))
self.modeb = QtGui.QRadioButton(translate("Arch","Beam", utf8_decode=True))
@@ -346,7 +360,9 @@ class _CommandStructure:
return w
def update(self,point,info):
"this function is called by the Snapper when the mouse is moved"
if FreeCADGui.Control.activeDialog():
if self.Height >= self.Length:
delta = Vector(0,0,self.Height/2)
@@ -366,23 +382,28 @@ class _CommandStructure:
self.tracker.off()
def setWidth(self,d):
self.Width = d
self.tracker.width(d)
def setHeight(self,d):
self.Height = d
self.tracker.height(d)
def setLength(self,d):
self.Length = d
self.tracker.length(d)
def setContinue(self,i):
self.continueCmd = bool(i)
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.continueMode = bool(i)
def setCategory(self,i):
self.vPresets.clear()
if i > 1:
self.precast.form.hide()
@@ -403,6 +424,7 @@ class _CommandStructure:
self.vPresets.addItems(fpresets)
def setPreset(self,i):
self.Profile = None
elt = self.pSelect[i]
if elt:
@@ -420,6 +442,7 @@ class _CommandStructure:
self.Profile = Presets[p]
def switchLH(self,bmode):
if bmode:
self.bmode = True
if self.Height > self.Length:
@@ -431,12 +454,14 @@ class _CommandStructure:
self.tracker.setRotation(FreeCAD.Rotation())
def rotateLH(self):
h = self.Height
l = self.Length
self.vLength.setText(FreeCAD.Units.Quantity(h,FreeCAD.Units.Length).UserString)
self.vHeight.setText(FreeCAD.Units.Quantity(l,FreeCAD.Units.Length).UserString)
def rotateLW(self):
w = self.Width
l = self.Length
self.vLength.setText(FreeCAD.Units.Quantity(w,FreeCAD.Units.Length).UserString)
@@ -448,21 +473,42 @@ class _Structure(ArchComponent.Component):
"The Structure object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLink","Tool","Arch",QT_TRANSLATE_NOOP("App::Property","An optional extrusion path for this element"))
obj.addProperty("App::PropertyLength","Length","Arch",QT_TRANSLATE_NOOP("App::Property","The length of this element, if not based on a profile"))
obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of this element, if not based on a profile"))
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height or extrusion depth of this element. Keep 0 for automatic"))
obj.addProperty("App::PropertyVector","Normal","Arch",QT_TRANSLATE_NOOP("App::Property","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))
obj.addProperty("App::PropertyVectorList","Nodes","Arch",QT_TRANSLATE_NOOP("App::Property","The structural nodes of this element"))
obj.addProperty("App::PropertyString","Profile","Arch",QT_TRANSLATE_NOOP("App::Property","A description of the standard profile this element is based upon"))
obj.addProperty("App::PropertyDistance","NodesOffset","Arch",QT_TRANSLATE_NOOP("App::Property","Offset distance between the centerline and the nodes line"))
obj.addProperty("App::PropertyEnumeration","FaceMaker","Arch",QT_TRANSLATE_NOOP("App::Property","The facemaker type to use to build the profile of this object"))
self.Type = "Structure"
obj.FaceMaker = ["None","Simple","Cheese","Bullseye"]
self.setProperties(obj)
obj.IfcRole = "Beam"
def setProperties(self,obj):
pl = obj.PropertiesList
if not "Tool" in pl:
obj.addProperty("App::PropertyLink","Tool","Structure",QT_TRANSLATE_NOOP("App::Property","An optional extrusion path for this element"))
if not "Length" in pl:
obj.addProperty("App::PropertyLength","Length","Structure",QT_TRANSLATE_NOOP("App::Property","The length of this element, if not based on a profile"))
if not "Width" in pl:
obj.addProperty("App::PropertyLength","Width","Structure",QT_TRANSLATE_NOOP("App::Property","The width of this element, if not based on a profile"))
if not "Height" in pl:
obj.addProperty("App::PropertyLength","Height","Structure",QT_TRANSLATE_NOOP("App::Property","The height or extrusion depth of this element. Keep 0 for automatic"))
if not "Normal" in pl:
obj.addProperty("App::PropertyVector","Normal","Structure",QT_TRANSLATE_NOOP("App::Property","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))
if not "Nodes" in pl:
obj.addProperty("App::PropertyVectorList","Nodes","Structure",QT_TRANSLATE_NOOP("App::Property","The structural nodes of this element"))
if not "Profile" in pl:
obj.addProperty("App::PropertyString","Profile","Structure",QT_TRANSLATE_NOOP("App::Property","A description of the standard profile this element is based upon"))
if not "NodesOffset" in pl:
obj.addProperty("App::PropertyDistance","NodesOffset","Structure",QT_TRANSLATE_NOOP("App::Property","Offset distance between the centerline and the nodes line"))
if not "FaceMaker" in pl:
obj.addProperty("App::PropertyEnumeration","FaceMaker","Structure",QT_TRANSLATE_NOOP("App::Property","The facemaker type to use to build the profile of this object"))
obj.FaceMaker = ["None","Simple","Cheese","Bullseye"]
self.Type = "Structure"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
"creates the structure shape"
import Part, DraftGeomUtils
@@ -511,9 +557,11 @@ class _Structure(ArchComponent.Component):
base = self.processSubShapes(obj,base,pl)
self.applyShape(obj,base,pl)
def getExtrusionData(self,obj):
"""returns (shape,extrusion vector,placement) or None"""
if hasattr(obj,"IfcRole"):
role = obj.IfcRole
else:
@@ -612,6 +660,7 @@ class _Structure(ArchComponent.Component):
return None
def onChanged(self,obj,prop):
if hasattr(obj,"IfcRole"):
role = obj.IfcRole
elif hasattr(obj,"Role"):
@@ -655,7 +704,9 @@ class _Structure(ArchComponent.Component):
ArchComponent.Component.onChanged(self,obj,prop)
def getNodeEdges(self,obj):
"returns a list of edges from stuctural nodes"
edges = []
if obj.Nodes:
import Part
@@ -668,21 +719,38 @@ class _Structure(ArchComponent.Component):
class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
"A View Provider for the Structure object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
vobj.addProperty("App::PropertyBool","ShowNodes","Arch",QT_TRANSLATE_NOOP("App::Property","If the nodes are visible or not")).ShowNodes = False
vobj.addProperty("App::PropertyFloat","NodeLine","Base",QT_TRANSLATE_NOOP("App::Property","The width of the nodes line"))
vobj.addProperty("App::PropertyFloat","NodeSize","Base",QT_TRANSLATE_NOOP("App::Property","The size of the node points"))
vobj.addProperty("App::PropertyColor","NodeColor","Base",QT_TRANSLATE_NOOP("App::Property","The color of the nodes line"))
vobj.addProperty("App::PropertyEnumeration","NodeType","Arch",QT_TRANSLATE_NOOP("App::Property","The type of structural node"))
vobj.NodeColor = (1.0,1.0,1.0,1.0)
vobj.NodeSize = 6
vobj.NodeType = ["Linear","Area"]
self.setProperties(vobj)
vobj.ShapeColor = ArchCommands.getDefaultColor("Structure")
def setProperties(self,vobj):
pl = vobj.PropertiesList
if not "ShowNodes" in pl:
vobj.addProperty("App::PropertyBool","ShowNodes","Nodes",QT_TRANSLATE_NOOP("App::Property","If the nodes are visible or not")).ShowNodes = False
if not "NodeLine" in pl:
vobj.addProperty("App::PropertyFloat","NodeLine","Nodes",QT_TRANSLATE_NOOP("App::Property","The width of the nodes line"))
if not "NodeSize" in pl:
vobj.addProperty("App::PropertyFloat","NodeSize","Nodes",QT_TRANSLATE_NOOP("App::Property","The size of the node points"))
vobj.NodeSize = 6
if not "NodeColor" in pl:
vobj.addProperty("App::PropertyColor","NodeColor","Nodes",QT_TRANSLATE_NOOP("App::Property","The color of the nodes line"))
vobj.NodeColor = (1.0,1.0,1.0,1.0)
if not "NodeType" in pl:
vobj.addProperty("App::PropertyEnumeration","NodeType","Nodes",QT_TRANSLATE_NOOP("App::Property","The type of structural node"))
vobj.NodeType = ["Linear","Area"]
def onDocumentRestored(self,vobj):
self.setProperties(vobj)
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
if hasattr(self.Object,"CloneOf"):
@@ -691,6 +759,7 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
return ":/icons/Arch_Structure_Tree.svg"
def updateData(self,obj,prop):
if prop == "Nodes":
if obj.Nodes:
if hasattr(self,"nodes"):
@@ -708,6 +777,7 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
self.coords.point.set1Value(len(p),p[0][0],p[0][1],p[0][2])
self.lineset.coordIndex.setValues(0,len(p)+2,range(len(p)+1)+[-1])
self.faceset.coordIndex.setValues(0,len(p)+1,range(len(p))+[-1])
elif prop in ["Role","IfcRole"]:
if hasattr(obj.ViewObject,"NodeType"):
if hasattr(obj,"IfcRole"):
@@ -722,6 +792,7 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
ArchComponent.ViewProviderComponent.updateData(self,obj,prop)
def onChanged(self,vobj,prop):
if prop == "ShowNodes":
if hasattr(self,"nodes"):
vobj.Annotation.removeChild(self.nodes)
@@ -759,23 +830,29 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
self.onChanged(vobj,"NodeColor")
self.onChanged(vobj,"NodeLine")
self.onChanged(vobj,"NodeSize")
elif prop == "NodeColor":
if hasattr(self,"mat"):
l = vobj.NodeColor
self.mat.diffuseColor.setValue([l[0],l[1],l[2]])
self.fmat.diffuseColor.setValue([l[0],l[1],l[2]])
elif prop == "NodeLine":
if hasattr(self,"linestyle"):
self.linestyle.lineWidth = vobj.NodeLine
elif prop == "NodeSize":
if hasattr(self,"pointstyle"):
self.pointstyle.pointSize = vobj.NodeSize
elif prop == "NodeType":
self.updateData(vobj.Object,"Nodes")
else:
ArchComponent.ViewProviderComponent.onChanged(self,vobj,prop)
def setEdit(self,vobj,mode):
if mode == 0:
taskd = StructureTaskPanel(vobj.Object)
taskd.obj = self.Object
@@ -788,6 +865,7 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
class StructureTaskPanel(ArchComponent.ComponentTaskPanel):
def __init__(self,obj):
ArchComponent.ComponentTaskPanel.__init__(self)
self.optwid = QtGui.QWidget()
self.optwid.setWindowTitle(QtGui.QApplication.translate("Arch", "Node Tools", None))
@@ -833,13 +911,16 @@ class StructureTaskPanel(ArchComponent.ComponentTaskPanel):
self.nodevis = None
def editNodes(self):
FreeCADGui.Control.closeDialog()
FreeCADGui.runCommand("Draft_Edit")
def resetNodes(self):
self.Object.Proxy.onChanged(self.Object,"ResetNodes")
def extendNodes(self,other=None):
if not other:
self.observer = StructSelectionObserver(self.extendNodes)
FreeCADGui.Selection.addObserver(self.observer)
@@ -871,6 +952,7 @@ class StructureTaskPanel(ArchComponent.ComponentTaskPanel):
self.Object.Nodes = [self.Object.Nodes[0],self.Object.Placement.inverse().multVec(intersect)]
def connectNodes(self,other=None):
if not other:
self.observer = StructSelectionObserver(self.connectNodes)
FreeCADGui.Selection.addObserver(self.observer)
@@ -906,6 +988,7 @@ class StructureTaskPanel(ArchComponent.ComponentTaskPanel):
other.Nodes = [other.Nodes[0],other.Placement.inverse().multVec(intersect)]
def toggleNodes(self):
if self.nodevis:
for obj in self.nodevis:
obj[0].ViewObject.ShowNodes = obj[1]
@@ -918,6 +1001,7 @@ class StructureTaskPanel(ArchComponent.ComponentTaskPanel):
obj.ViewObject.ShowNodes = True
def accept(self):
if self.observer:
FreeCADGui.Selection.removeObserver(self.observer)
if self.nodevis:
@@ -938,9 +1022,12 @@ class StructSelectionObserver:
self.callback(obj)
class _StructuralSystem(ArchComponent.Component):
class _StructuralSystem(ArchComponent.Component): # OBSOLETE - All Arch objects can now be based on axes
"The Structural System object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLinkList","Axes","Arch",QT_TRANSLATE_NOOP("App::Property","Axes systems this structure is built on"))
obj.addProperty("App::PropertyIntegerList","Exclude","Arch",QT_TRANSLATE_NOOP("App::Property","The element numbers to exclude when this structure is based on axes"))
@@ -1036,9 +1123,11 @@ class _StructuralSystem(ArchComponent.Component):
class _ViewProviderStructuralSystem(ArchComponent.ViewProviderComponent):
"A View Provider for the Structural System object"
def getIcon(self):
import Arch_rc
return ":/icons/Arch_StructuralSystem_Tree.svg"

View File

@@ -35,7 +35,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
## @package ArchWall
# \ingroup ARCH
# \brief The Wall object and tools
@@ -49,11 +49,15 @@ __title__="FreeCAD Wall"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"
def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",face=None,name="Wall"):
'''makeWall([obj],[length],[width],[height],[align],[face],[name]): creates a wall based on the
given object, which can be a sketch, a draft object, a face or a solid, or no object at
all, then you must provide length, width and height. Align can be "Center","Left" or "Right",
face can be an index number of a face in the base object to base the wall on.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
return
@@ -87,8 +91,10 @@ def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",face
return obj
def joinWalls(walls,delete=False):
"""joins the given list of walls into one sketch-based wall. If delete
is True, merged wall objects are deleted"""
if not walls:
return None
if not isinstance(walls,list):
@@ -120,7 +126,9 @@ def joinWalls(walls,delete=False):
return base
def mergeShapes(w1,w2):
"returns a Shape built on two walls that share same properties and have a coincident endpoint"
if not areSameWallTypes([w1,w2]):
return None
if (not hasattr(w1.Base,"Shape")) or (not hasattr(w2.Base,"Shape")):
@@ -144,7 +152,9 @@ def mergeShapes(w1,w2):
return None
def areSameWallTypes(walls):
"returns True is all the walls in the given list have same height, width, and alignment"
for att in ["Width","Height","Align"]:
value = None
for w in walls:
@@ -161,18 +171,25 @@ def areSameWallTypes(walls):
return False
return True
class _CommandWall:
"the Arch Wall command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Wall',
'MenuText': QT_TRANSLATE_NOOP("Arch_Wall","Wall"),
'Accel': "W, A",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Wall","Creates a wall object from scratch or from a selected object (wire, face or solid)")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
self.Align = "Center"
self.MultiMat = None
self.Length = None
@@ -221,7 +238,9 @@ class _CommandWall:
FreeCADGui.Snapper.getPoint(callback=self.getPoint,extradlg=self.taskbox())
def getPoint(self,point=None,obj=None):
"this function is called by the snapper when it has a 3D point"
if obj:
if Draft.getType(obj) == "Wall":
if not obj in self.existing:
@@ -271,6 +290,7 @@ class _CommandWall:
self.Activated()
def addDefault(self,l):
FreeCADGui.doCommand('base=FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")')
FreeCADGui.doCommand('base.Placement = FreeCAD.DraftWorkingPlane.getPlacement()')
FreeCADGui.doCommand('base.addGeometry(trace)')
@@ -282,7 +302,9 @@ class _CommandWall:
FreeCADGui.doCommand("Draft.autogroup(wall)")
def update(self,point,info):
"this function is called by the Snapper when the mouse is moved"
if FreeCADGui.Control.activeDialog():
b = self.points[0]
n = FreeCAD.DraftWorkingPlane.axis
@@ -300,7 +322,9 @@ class _CommandWall:
self.Length.setText(FreeCAD.Units.Quantity(bv.Length,FreeCAD.Units.Length).UserString)
def taskbox(self):
"sets up a taskbox widget"
w = QtGui.QWidget()
ui = FreeCADGui.UiLoader()
w.setWindowTitle(translate("Arch","Wall options", utf8_decode=True))
@@ -370,35 +394,42 @@ class _CommandWall:
QtCore.QObject.connect(value2,QtCore.SIGNAL("returnPressed()"),self.createFromGUI)
QtCore.QObject.connect(matCombo,QtCore.SIGNAL("currentIndexChanged(int)"),self.setMat)
return w
def setMat(self,d):
if d == 0:
self.MultiMat = None
del FreeCAD.LastArchMultiMaterial
elif d <= len(self.multimats):
self.MultiMat = self.multimats[d-1]
FreeCAD.LastArchMultiMaterial = self.MultiMat.Name
def setLength(self,d):
self.lengthValue = d
def setWidth(self,d):
self.Width = d
self.tracker.width(d)
def setHeight(self,d):
self.Height = d
self.tracker.height(d)
def setAlign(self,i):
self.Align = ["Center","Left","Right"][i]
def setContinue(self,i):
self.continueCmd = bool(i)
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.continueMode = bool(i)
def createFromGUI(self):
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Wall"))
FreeCADGui.addModule("Arch")
FreeCADGui.doCommand('wall = Arch.makeWall(length='+str(self.lengthValue)+',width='+str(self.Width)+',height='+str(self.Height)+',align="'+str(self.Align)+'")')
@@ -409,17 +440,24 @@ class _CommandWall:
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.escape()
class _CommandMergeWalls:
"the Arch Merge Walls command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_MergeWalls',
'MenuText': QT_TRANSLATE_NOOP("Arch_MergeWalls","Merge Walls"),
'ToolTip': QT_TRANSLATE_NOOP("Arch_MergeWalls","Merges the selected walls, if possible")}
def IsActive(self):
return bool(FreeCADGui.Selection.getSelection())
def Activated(self):
walls = FreeCADGui.Selection.getSelection()
if len(walls) == 1:
if Draft.getType(walls[0]) == "Wall":
@@ -451,36 +489,65 @@ class _CommandMergeWalls:
FreeCAD.ActiveDocument.commitTransaction()
class _Wall(ArchComponent.Component):
"The Wall object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLength","Length","Arch",QT_TRANSLATE_NOOP("App::Property","The length of this wall. Not used if this wall is based on an underlying object"))
obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of this wall. Not used if this wall is based on a face"))
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid"))
obj.addProperty("App::PropertyEnumeration","Align","Arch",QT_TRANSLATE_NOOP("App::Property","The alignment of this wall on its base object, if applicable"))
obj.addProperty("App::PropertyVector","Normal","Arch",QT_TRANSLATE_NOOP("App::Property","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))
obj.addProperty("App::PropertyInteger","Face","Arch",QT_TRANSLATE_NOOP("App::Property","The face number of the base object used to build this wall"))
obj.addProperty("App::PropertyDistance","Offset","Arch",QT_TRANSLATE_NOOP("App::Property","The offset between this wall and its baseline (only for left and right alignments)"))
obj.addProperty("App::PropertyBool","MakeBlocks","Wall",QT_TRANSLATE_NOOP("App::Property","Enable this to make the wall generate blocks"))
obj.addProperty("App::PropertyLength","BlockLength","Wall",QT_TRANSLATE_NOOP("App::Property","The length of each block"))
obj.addProperty("App::PropertyLength","BlockHeight","Wall",QT_TRANSLATE_NOOP("App::Property","The height of each block"))
obj.addProperty("App::PropertyLength","OffsetFirst","Wall",QT_TRANSLATE_NOOP("App::Property","The horizontal offset of the first line of blocks"))
obj.addProperty("App::PropertyLength","OffsetSecond","Wall",QT_TRANSLATE_NOOP("App::Property","The horizontal offset of the second line of blocks"))
obj.addProperty("App::PropertyLength","Joint","Wall",QT_TRANSLATE_NOOP("App::Property","The size of the joints between each block"))
obj.addProperty("App::PropertyInteger","CountEntire","Wall",QT_TRANSLATE_NOOP("App::Property","The number of entire blocks"))
obj.addProperty("App::PropertyInteger","CountBroken","Wall",QT_TRANSLATE_NOOP("App::Property","The number of broken blocks"))
obj.setEditorMode("CountEntire",1)
obj.setEditorMode("CountBroken",1)
obj.Align = ['Left','Right','Center']
self.Type = "Wall"
class _Wall(ArchComponent.Component):
"The Wall object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
self.setProperties(obj)
obj.IfcRole = "Wall"
def setProperties(self,obj):
lp = obj.PropertiesList
if not "Length" in lp:
obj.addProperty("App::PropertyLength","Length","Wall",QT_TRANSLATE_NOOP("App::Property","The length of this wall. Not used if this wall is based on an underlying object"))
if not "Width" in lp:
obj.addProperty("App::PropertyLength","Width","Wall",QT_TRANSLATE_NOOP("App::Property","The width of this wall. Not used if this wall is based on a face"))
if not "Height" in lp:
obj.addProperty("App::PropertyLength","Height","Wall",QT_TRANSLATE_NOOP("App::Property","The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid"))
if not "Align" in lp:
obj.addProperty("App::PropertyEnumeration","Align","Wall",QT_TRANSLATE_NOOP("App::Property","The alignment of this wall on its base object, if applicable"))
obj.Align = ['Left','Right','Center']
if not "Normal" in lp:
obj.addProperty("App::PropertyVector","Normal","Wall",QT_TRANSLATE_NOOP("App::Property","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))
if not "Face" in lp:
obj.addProperty("App::PropertyInteger","Face","Wall",QT_TRANSLATE_NOOP("App::Property","The face number of the base object used to build this wall"))
if not "Offset" in lp:
obj.addProperty("App::PropertyDistance","Offset","Wall",QT_TRANSLATE_NOOP("App::Property","The offset between this wall and its baseline (only for left and right alignments)"))
if not "MakeBlocks" in lp:
obj.addProperty("App::PropertyBool","MakeBlocks","Blocks",QT_TRANSLATE_NOOP("App::Property","Enable this to make the wall generate blocks"))
if not "BlockLength" in lp:
obj.addProperty("App::PropertyLength","BlockLength","Blocks",QT_TRANSLATE_NOOP("App::Property","The length of each block"))
if not "BlockHeight" in lp:
obj.addProperty("App::PropertyLength","BlockHeight","Blocks",QT_TRANSLATE_NOOP("App::Property","The height of each block"))
if not "OffsetFirst" in lp:
obj.addProperty("App::PropertyLength","OffsetFirst","Blocks",QT_TRANSLATE_NOOP("App::Property","The horizontal offset of the first line of blocks"))
if not "OffsetSecond" in lp:
obj.addProperty("App::PropertyLength","OffsetSecond","Blocks",QT_TRANSLATE_NOOP("App::Property","The horizontal offset of the second line of blocks"))
if not "Joint" in lp:
obj.addProperty("App::PropertyLength","Joint","Blocks",QT_TRANSLATE_NOOP("App::Property","The size of the joints between each block"))
if not "CountEntire" in lp:
obj.addProperty("App::PropertyInteger","CountEntire","Blocks",QT_TRANSLATE_NOOP("App::Property","The number of entire blocks"))
obj.setEditorMode("CountEntire",1)
if not "CountBroken" in lp:
obj.addProperty("App::PropertyInteger","CountBroken","Blocks",QT_TRANSLATE_NOOP("App::Property","The number of broken blocks"))
obj.setEditorMode("CountBroken",1)
self.Type = "Wall"
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def execute(self,obj):
"builds the wall shape"
if self.clone(obj):
return
@@ -606,7 +673,7 @@ class _Wall(ArchComponent.Component):
base = self.processSubShapes(obj,base,pl)
self.applyShape(obj,base,pl)
# count blocks
if hasattr(obj,"MakeBlocks"):
if obj.MakeBlocks:
@@ -633,6 +700,7 @@ class _Wall(ArchComponent.Component):
obj.Length = l
def onChanged(self,obj,prop):
if prop == "Length":
if obj.Base and obj.Length.Value:
if obj.Base.isDerivedFrom("Part::Feature"):
@@ -653,8 +721,9 @@ class _Wall(ArchComponent.Component):
FreeCAD.Console.PrintError(translate("Arch","Error: Unable to modify the base object of this wall")+"\n")
self.hideSubobjects(obj,prop)
ArchComponent.Component.onChanged(self,obj,prop)
def getFootprint(self,obj):
faces = []
if obj.Shape:
for f in obj.Shape.Faces:
@@ -662,8 +731,9 @@ class _Wall(ArchComponent.Component):
if abs(abs(f.CenterOfMass.z) - abs(obj.Shape.BoundBox.ZMin)) < 0.001:
faces.append(f)
return faces
def getExtrusionData(self,obj):
"""returns (shape,extrusion vector,placement) or None"""
import Part,DraftGeomUtils
data = ArchComponent.Component.getExtrusionData(self,obj)
@@ -739,7 +809,7 @@ class _Wall(ArchComponent.Component):
for cluster in Part.getSortedClusters(obj.Base.Shape.Edges):
for c in Part.sortEdges(cluster):
self.basewires.append(Part.Wire(c))
if self.basewires and width:
if (len(self.basewires) == 1) and layers:
self.basewires = [self.basewires[0] for l in layers]
@@ -777,7 +847,7 @@ class _Wall(ArchComponent.Component):
layeroffset += layers[i]
else:
dvec.multiply(width)
if off:
if off:
dvec2 = DraftVecUtils.scaleTo(dvec,off)
wire = DraftGeomUtils.offsetWire(wire,dvec2)
w2 = DraftGeomUtils.offsetWire(wire,dvec)
@@ -847,13 +917,16 @@ class _Wall(ArchComponent.Component):
return None
class _ViewProviderWall(ArchComponent.ViewProviderComponent):
"A View Provider for the Wall object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
vobj.ShapeColor = ArchCommands.getDefaultColor("Wall")
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
if self.Object.CloneOf:
@@ -864,6 +937,7 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
return ":/icons/Arch_Wall_Tree.svg"
def attach(self,vobj):
self.Object = vobj.Object
from pivy import coin
tex = coin.SoTexture2()
@@ -883,6 +957,7 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
ArchComponent.ViewProviderComponent.attach(self,vobj)
def updateData(self,obj,prop):
if prop in ["Placement","Shape","Material"]:
if obj.ViewObject.DisplayMode == "Footprint":
obj.ViewObject.Proxy.setDisplayMode("Footprint")
@@ -907,10 +982,12 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
obj.ViewObject.DiffuseColor = obj.ViewObject.DiffuseColor
def getDisplayModes(self,vobj):
modes = ArchComponent.ViewProviderComponent.getDisplayModes(self,vobj)+["Footprint"]
return modes
def setDisplayMode(self,mode):
self.fset.coordIndex.deleteValues(0)
self.fcoords.point.deleteValues(0)
if mode == "Footprint":

View File

@@ -59,7 +59,9 @@ WindowOpeningModes = ["None","Arc 90","Arc 90 inv","Arc 45","Arc 45 inv","Arc 18
"Arc 180 inv","Triangle","Triangle inv","Sliding","Sliding inv"]
def makeWindow(baseobj=None,width=None,height=None,parts=None,name="Window"):
'''makeWindow(baseobj,[width,height,parts,name]): creates a window based on the
given base 2D object (sketch or draft).'''
@@ -106,11 +108,13 @@ def makeWindow(baseobj=None,width=None,height=None,parts=None,name="Window"):
return obj
def recolorize(obj):
if obj.ViewObject:
if obj.ViewObject.Proxy:
obj.ViewObject.Proxy.colorize(obj,force=True)
def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None):
"""makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,[placement]): makes a
window object based on the given data. windowtype must be one of the names
defined in Arch.WindowPresets"""
@@ -138,7 +142,9 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
s = FreeCAD.ActiveDocument.addObject('Sketcher::SketchObject','Sketch')
def addFrame(s,p1,p2,p3,p4,p5,p6,p7,p8):
"adds two rectangles to the given sketch"
idx = s.GeometryCount
s.addGeometry(Part.LineSegment(p1,p2))
s.addGeometry(Part.LineSegment(p2,p3))
@@ -166,6 +172,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
s.addConstraint(Sketcher.Constraint('Vertical',idx+7))
def outerFrame(s,width,height,h1,w1,o1):
p1 = Vector(0,0,0)
p2 = Vector(width,0,0)
p3 = Vector(width,height,0)
@@ -187,6 +194,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
return ["OuterFrame","Frame","Wire0,Wire1",str(w1),str(o1)]
def doorFrame(s,width,height,h1,w1,o1):
p1 = Vector(0,0,0)
p2 = Vector(width,0,0)
p3 = Vector(width,height,0)
@@ -208,10 +216,12 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
return ["OuterFrame","Frame","Wire0,Wire1",str(w1),str(o1)]
if windowtype == "Fixed":
wp = outerFrame(s,width,height,h1,w1,o1)
wp.extend(["Glass","Glass panel","Wire1",str(w1/gla),str(w1+w1/2)])
elif windowtype == "Open 1-pane":
wp = outerFrame(s,width,height,h1,w1,o1)
p1 = Vector(h1+tol,h1+tol,0)
p2 = Vector(width-(h1+tol),h1+tol,0)
@@ -234,6 +244,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
wp.extend(["InnerGlass","Glass panel","Wire3",str(w2/gla),str(o1+o2+w2/2)])
elif windowtype == "Open 2-pane":
wp = outerFrame(s,width,height,h1,w1,o1)
p1 = Vector(h1+tol,h1+tol,0)
p2 = Vector((width/2)-tol,h1+tol,0)
@@ -275,6 +286,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
wp.extend(["RightGlass","Glass panel","Wire5",str(w2/gla),str(o1+o2+w2/2)])
elif windowtype == "Sash 2-pane":
wp = outerFrame(s,width,height,h1,w1,o1)
p1 = Vector(h1+tol,h1+tol,0)
p2 = Vector(width-(h1+tol),h1+tol,0)
@@ -316,6 +328,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
wp.extend(["UpperGlass","Glass panel","Wire5",str(w2/gla),str(o1+o2+w2/2)])
elif windowtype == "Sliding 2-pane":
wp = outerFrame(s,width,height,h1,w1,o1)
p1 = Vector(h1+tol,h1+tol,0)
p2 = Vector((width/2)-tol,h1+tol,0)
@@ -357,6 +370,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
wp.extend(["RightGlass","Glass panel","Wire5",str(w2/gla),str(o1+o2+w2+w2/2)])
elif windowtype == "Sliding 4-pane":
wp = outerFrame(s,width,height,h1,w1,o1)
p1 = Vector(h1+tol,h1+tol,0)
p2 = Vector(width/4-tol,h1+tol,0)
@@ -436,10 +450,12 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
wp.extend(["RightMostGlass","Glass panel","Wire9",str(w2/gla),str(o1+o2+w2/2)])
elif windowtype == "Simple door":
wp = doorFrame(s,width,height,h1,w1,o1)
wp.extend(["Door","Solid panel","Wire1",str(w2),str(o1+o2)])
elif windowtype == "Glass door":
wp = doorFrame(s,width,height,h1,w1,o1)
p1 = Vector(h1+tol,h1+tol,0)
p2 = Vector(width-(h1+tol),h1+tol,0)
@@ -482,19 +498,24 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
print("Arch: Unknown window type")
class _CommandWindow:
"the Arch Window command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_Window',
'MenuText': QT_TRANSLATE_NOOP("Arch_Window","Window"),
'Accel': "W, N",
'ToolTip': QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from a selected object (wire, rectangle or sketch)")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
self.sel = FreeCADGui.Selection.getSelection()
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
self.Thickness = p.GetFloat("WindowThickness",50)
@@ -556,7 +577,9 @@ class _CommandWindow:
#FreeCADGui.Snapper.setSelectMode(True)
def getPoint(self,point=None,obj=None):
"this function is called by the snapper when it has a 3D point"
self.tracker.finalize()
if point == None:
return
@@ -606,7 +629,9 @@ class _CommandWindow:
return
def update(self,point,info):
"this function is called by the Snapper when the mouse is moved"
delta = FreeCAD.Vector(self.Width/2,self.Thickness/2,self.Height/2)
delta = delta.add(FreeCAD.Vector(0,0,self.Sill))
rot = FreeCAD.Rotation()
@@ -626,7 +651,9 @@ class _CommandWindow:
#self.tracker.setRotation(rot)
def taskbox(self):
"sets up a taskbox widget"
w = QtGui.QWidget()
ui = FreeCADGui.UiLoader()
w.setWindowTitle(translate("Arch","Window options", utf8_decode=True))
@@ -708,21 +735,26 @@ class _CommandWindow:
return w
def getValueChanged(self,p):
return lambda d : self.setParams(p, d)
def setSill(self,d):
self.Sill = d
def setInclude(self,i):
self.Include = bool(i)
def setParams(self,param,d):
setattr(self,param,d)
self.tracker.length(self.Width)
self.tracker.height(self.Height)
self.tracker.width(self.W1)
def setPreset(self,i):
self.Preset = i
if i >= 0:
FreeCADGui.Snapper.setSelectMode(False)
@@ -780,36 +812,63 @@ class _CommandWindow:
class _Window(ArchComponent.Component):
"The Window object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
obj.addProperty("App::PropertyLinkList","Hosts","Arch",QT_TRANSLATE_NOOP("App::Property","The objects that host this window"))
obj.addProperty("App::PropertyStringList","WindowParts","Arch",QT_TRANSLATE_NOOP("App::Property","The components of this window"))
obj.addProperty("App::PropertyLength","WindowParts","Arch",QT_TRANSLATE_NOOP("App::Property","The components of this window"))
obj.addProperty("App::PropertyLength","HoleDepth","Arch",QT_TRANSLATE_NOOP("App::Property","The depth of the hole that this window makes in its host object. If 0, the value will be calculated automatically."))
obj.addProperty("App::PropertyLink","Subvolume","Arch",QT_TRANSLATE_NOOP("App::Property","An optional object that defines a volume to be subtracted from hosts of this window"))
obj.addProperty("App::PropertyLength","Width","Arch",QT_TRANSLATE_NOOP("App::Property","The width of this window (for preset windows only)"))
obj.addProperty("App::PropertyLength","Height","Arch",QT_TRANSLATE_NOOP("App::Property","The height of this window (for preset windows only)"))
obj.addProperty("App::PropertyVector","Normal","Arch",QT_TRANSLATE_NOOP("App::Property","The normal direction of this window"))
obj.addProperty("App::PropertyInteger","Preset","Arch","")
obj.addProperty("App::PropertyArea","Area","Arch",QT_TRANSLATE_NOOP("App::Property","The area of this window"))
obj.addProperty("App::PropertyLength","LouvreWidth","Louvres",QT_TRANSLATE_NOOP("App::Property","The width of louvre elements"))
obj.addProperty("App::PropertyLength","LouvreSpacing","Louvres",QT_TRANSLATE_NOOP("App::Property","The space between louvre elements"))
obj.addProperty("App::PropertyPercent","Opening","Arch",QT_TRANSLATE_NOOP("App::Property","Opens the subcomponents that have a hinge defined"))
obj.addProperty("App::PropertyInteger","HoleWire","Arch",QT_TRANSLATE_NOOP("App::Property","The number of the wire that defines the hole. If 0, the value will be calculated automatically"))
obj.addProperty("App::PropertyBool","SymbolPlan","Arch",QT_TRANSLATE_NOOP("App::Property","Shows plan opening symbols if available"))
obj.addProperty("App::PropertyBool","SymbolElevation","Arch",QT_TRANSLATE_NOOP("App::Property","Show elevation opening symbols if available"))
obj.setEditorMode("Preset",2)
obj.setEditorMode("WindowParts",2)
self.setProperties(obj)
obj.IfcRole = "Window"
obj.MoveWithHost = True
def setProperties(self,obj):
lp = obj.PropertiesList
if not "Hosts" in lp:
obj.addProperty("App::PropertyLinkList","Hosts","Window",QT_TRANSLATE_NOOP("App::Property","The objects that host this window"))
if not "WindowParts" in lp:
obj.addProperty("App::PropertyStringList","WindowParts","Window",QT_TRANSLATE_NOOP("App::Property","The components of this window"))
obj.setEditorMode("WindowParts",2)
if not "HoleDepth" in lp:
obj.addProperty("App::PropertyLength","HoleDepth","Window",QT_TRANSLATE_NOOP("App::Property","The depth of the hole that this window makes in its host object. If 0, the value will be calculated automatically."))
if not "Subvolume" in lp:
obj.addProperty("App::PropertyLink","Subvolume","Window",QT_TRANSLATE_NOOP("App::Property","An optional object that defines a volume to be subtracted from hosts of this window"))
if not "Width" in lp:
obj.addProperty("App::PropertyLength","Width","Window",QT_TRANSLATE_NOOP("App::Property","The width of this window (for preset windows only)"))
if not "Height" in lp:
obj.addProperty("App::PropertyLength","Height","Window",QT_TRANSLATE_NOOP("App::Property","The height of this window (for preset windows only)"))
if not "Normal" in lp:
obj.addProperty("App::PropertyVector","Normal","Window",QT_TRANSLATE_NOOP("App::Property","The normal direction of this window"))
if not "Preset" in lp:
obj.addProperty("App::PropertyInteger","Preset","Window",QT_TRANSLATE_NOOP("App::Property","The preset number this window is based on"))
obj.setEditorMode("Preset",2)
if not "Area" in lp:
obj.addProperty("App::PropertyArea","Area","Window",QT_TRANSLATE_NOOP("App::Property","The area of this window"))
if not "LouvreWidth" in lp:
obj.addProperty("App::PropertyLength","LouvreWidth","Window",QT_TRANSLATE_NOOP("App::Property","The width of louvre elements"))
if not "LouvreSpacing" in lp:
obj.addProperty("App::PropertyLength","LouvreSpacing","Window",QT_TRANSLATE_NOOP("App::Property","The space between louvre elements"))
if not "Opening" in lp:
obj.addProperty("App::PropertyPercent","Opening","Window",QT_TRANSLATE_NOOP("App::Property","Opens the subcomponents that have a hinge defined"))
if not "HoleWire" in lp:
obj.addProperty("App::PropertyInteger","HoleWire","Window",QT_TRANSLATE_NOOP("App::Property","The number of the wire that defines the hole. If 0, the value will be calculated automatically"))
if not "SymbolPlan" in lp:
obj.addProperty("App::PropertyBool","SymbolPlan","Window",QT_TRANSLATE_NOOP("App::Property","Shows plan opening symbols if available"))
if not "SymbolElevation" in lp:
obj.addProperty("App::PropertyBool","SymbolElevation","Window",QT_TRANSLATE_NOOP("App::Property","Show elevation opening symbols if available"))
obj.setEditorMode("VerticalArea",2)
obj.setEditorMode("HorizontalArea",2)
obj.setEditorMode("PerimeterLength",2)
self.Type = "Window"
obj.IfcRole = "Window"
obj.Proxy = self
obj.MoveWithHost = True
def onDocumentRestored(self,obj):
ArchComponent.Component.onDocumentRestored(self,obj)
self.setProperties(obj)
def onChanged(self,obj,prop):
self.hideSubobjects(obj,prop)
if not "Restore" in obj.State:
if prop in ["Base","WindowParts","Placement","HoleDepth","Height","Width","Hosts"]:
@@ -1087,6 +1146,7 @@ class _Window(ArchComponent.Component):
obj.Area = obj.Width.Value * obj.Height.Value
def getSubVolume(self,obj,plac=None):
"returns a subvolume for cutting in a base object"
# check if we have a custom subvolume
@@ -1168,13 +1228,18 @@ class _Window(ArchComponent.Component):
def computeAreas(self,obj):
return
class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
"A View Provider for the Window object"
def __init__(self,vobj):
ArchComponent.ViewProviderComponent.__init__(self,vobj)
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
if hasattr(self.Object,"CloneOf"):
@@ -1183,6 +1248,7 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
return ":/icons/Arch_Window_Tree.svg"
def updateData(self,obj,prop):
if prop == "Shape":
if obj.Base:
if obj.Base.isDerivedFrom("Part::Compound"):
@@ -1204,11 +1270,13 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
obj.ViewObject.update()
def onDelete(self,vobj,subelements):
for o in vobj.Object.Hosts:
o.touch()
return True
def onChanged(self,vobj,prop):
if (prop in ["DiffuseColor","Transparency"]) and vobj.Object:
self.colorize(vobj.Object)
elif prop == "ShapeColor":
@@ -1216,6 +1284,7 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
ArchComponent.ViewProviderComponent.onChanged(self,vobj,prop)
def setEdit(self,vobj,mode):
taskd = _ArchWindowTaskPanel()
taskd.obj = self.Object
self.sets = [vobj.DisplayMode,vobj.Transparency]
@@ -1228,6 +1297,7 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
return True
def unsetEdit(self,vobj,mode):
vobj.DisplayMode = self.sets[0]
vobj.Transparency = self.sets[1]
vobj.DiffuseColor = vobj.DiffuseColor # reset face colors
@@ -1237,6 +1307,7 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
return
def colorize(self,obj,force=False):
"setting different part colors"
if obj.CloneOf:
if self.areDifferentColors(obj.ViewObject.DiffuseColor,obj.CloneOf.ViewObject.DiffuseColor) or force:
@@ -1286,6 +1357,7 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
obj.ViewObject.DiffuseColor = colors
def areDifferentColors(self,a,b):
if len(a) != len(b):
return True
for i in range(len(a)):
@@ -1293,8 +1365,11 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
return True
return False
class _ArchWindowTaskPanel:
'''The TaskPanel for Arch Windows'''
def __init__(self):
self.obj = None
@@ -1429,19 +1504,24 @@ class _ArchWindowTaskPanel:
FreeCADGui.Selection.clearSelection()
def isAllowedAlterSelection(self):
return True
def isAllowedAlterView(self):
return True
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Close)
def check(self,wid,col):
self.editButton.setEnabled(True)
self.delButton.setEnabled(True)
def select(self,wid,col):
FreeCADGui.Selection.clearSelection()
ws = ''
for it in self.wiretree.selectedItems():
@@ -1458,7 +1538,9 @@ class _ArchWindowTaskPanel:
self.field3.setText(ws)
def selectHole(self):
"takes a selected edge to determine current Hole Wire"
s = FreeCADGui.Selection.getSelectionEx()
if s and self.obj:
if s[0].SubElementNames:
@@ -1471,7 +1553,9 @@ class _ArchWindowTaskPanel:
break
def setHoleNumber(self,val):
"sets the HoleWire obj property"
if val.isdigit():
val = int(val)
if self.obj:
@@ -1480,6 +1564,7 @@ class _ArchWindowTaskPanel:
self.obj.HoleWire = val
def getIcon(self,obj):
if hasattr(obj.ViewObject,"Proxy"):
return QtGui.QIcon(obj.ViewObject.Proxy.getIcon())
elif obj.isDerivedFrom("Sketcher::SketchObject"):
@@ -1488,7 +1573,9 @@ class _ArchWindowTaskPanel:
return QtGui.QIcon(":/icons/Tree_Part.svg")
def update(self):
'fills the tree widgets'
self.tree.clear()
self.wiretree.clear()
self.comptree.clear()
@@ -1520,7 +1607,9 @@ class _ArchWindowTaskPanel:
self.basepanel.update()
def addElement(self):
'opens the component creation dialog'
self.field1.setText('')
self.field3.setText('')
self.field4.setText('')
@@ -1546,6 +1635,7 @@ class _ArchWindowTaskPanel:
self.delButton.setEnabled(False)
def removeElement(self):
for it in self.comptree.selectedItems():
comp = str(it.text(0))
if self.obj:
@@ -1560,6 +1650,7 @@ class _ArchWindowTaskPanel:
self.delButton.setEnabled(False)
def editElement(self):
for it in self.comptree.selectedItems():
self.addElement()
comp = str(it.text(0))
@@ -1593,7 +1684,9 @@ class _ArchWindowTaskPanel:
f.setText(t)
def create(self):
'adds a new component'
# testing if fields are ok
ok = True
ar = []
@@ -1660,6 +1753,7 @@ class _ArchWindowTaskPanel:
self.addButton.setEnabled(True)
def addEdge(self):
for sel in FreeCADGui.Selection.getSelectionEx():
for sub in sel.SubElementNames:
if "Edge" in sub:
@@ -1667,11 +1761,13 @@ class _ArchWindowTaskPanel:
return
def reject(self):
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
return True
def retranslateUi(self, TaskPanel):
TaskPanel.setWindowTitle(QtGui.QApplication.translate("Arch", "Window elements", None))
self.holeLabel.setText(QtGui.QApplication.translate("Arch", "Hole wire", None))
self.holeNumber.setToolTip(QtGui.QApplication.translate("Arch", "The number of the wire that defines a hole in the host object. A value of zero will automatically adopt the largest wire", None))
@@ -1698,5 +1794,7 @@ class _ArchWindowTaskPanel:
for i in range(len(WindowOpeningModes)):
self.field7.setItemText(i, QtGui.QApplication.translate("Arch", WindowOpeningModes[i], None))
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Window',_CommandWindow())