Arch: Support for opening symbols - fixes #2353

This commit is contained in:
Yorik van Havre
2016-11-02 20:10:20 -02:00
parent 5d866f15e0
commit fe8f0945d7
2 changed files with 193 additions and 7 deletions

View File

@@ -85,7 +85,7 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
if not section.Objects:
return
import DraftGeomUtils
import Part,DraftGeomUtils
p = FreeCAD.Placement(section.Placement)
direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
objs = Draft.getGroupContents(section.Objects,walls=True,addgroups=True)
@@ -95,6 +95,7 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
spaces = []
nonspaces = []
drafts = []
windows = []
cutface = None
for o in objs:
if Draft.getType(o) == "Space":
@@ -105,6 +106,8 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
drafts.append(o)
else:
nonspaces.append(o)
if Draft.getType(o) == "Window":
windows.append(o)
objs = nonspaces
svg = ''
fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"'
@@ -238,6 +241,32 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
svg += Draft.getSVG(s,scale=scale,linewidth=linewidth,fontsize=fontsize,direction=direction,techdraw=techdraw,rotation=rotation)
if not techdraw:
svg += '</g>'
# add additional edge symbols from windows
if cutface and windows:
cutwindows = [w.Name for w in windows if w.Shape.BoundBox.intersect(cutface.BoundBox)]
if windows:
sh = []
for w in windows:
if not hasattr(w.Proxy,"sshapes"):
w.Proxy.execute(w)
if hasattr(w.Proxy,"sshapes"):
if w.Proxy.sshapes and (w.Name in cutwindows):
c = Part.makeCompound(w.Proxy.sshapes)
c.Placement = w.Placement
sh.append(c)
if hasattr(w.Proxy,"vshapes"):
if w.Proxy.vshapes:
c = Part.makeCompound(w.Proxy.vshapes)
c.Placement = w.Placement
sh.append(c)
if sh:
if not techdraw:
svg += '<g transform="scale(1,-1)">'
for s in sh:
svg += Draft.getSVG(s,scale=scale,linewidth=linewidth,fontsize=fontsize,fillstyle="none",direction=direction,techdraw=techdraw,rotation=rotation)
if not techdraw:
svg += '</g>'
#print "complete node:",svg
return svg

View File

@@ -43,6 +43,7 @@ WindowPartTypes = ["Frame","Solid panel","Glass panel","Louvre"]
AllowedHosts = ["Wall","Structure","Roof"]
WindowPresets = ["Fixed", "Open 1-pane", "Open 2-pane", "Sash 2-pane",
"Sliding 2-pane", "Simple door", "Glass door"]
WindowOpeningModes = ["None","Arc 90","Arc 90 inv","Arc 45","Arc 45 inv","Arc 180","Arc 180 inv","Triangle","Triangle inv","Sliding","Sliding inv"]
Roles = ["Window","Door"]
@@ -370,6 +371,7 @@ def makeWindowPreset(windowtype,width,height,h1,h2,h3,w1,w2,o1,o2,placement=None
obj.Placement = FreeCAD.Placement() # unable to find where this bug comes from...
if "door" in windowtype:
obj.Role = "Door"
obj.Label = translate("Arch","Door")
FreeCAD.ActiveDocument.recompute()
return obj
@@ -639,7 +641,7 @@ class _Window(ArchComponent.Component):
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.setEditorMode("Preset",2)
obj.setEditorMode("WindowParts",2)
self.Type = "Window"
obj.Role = Roles
obj.Proxy = self
@@ -685,6 +687,8 @@ class _Window(ArchComponent.Component):
import Part,DraftGeomUtils,math
pl = obj.Placement
base = None
self.sshapes = []
self.vshapes = []
if obj.Base:
if obj.Base.isDerivedFrom("Part::Feature"):
if hasattr(obj,"WindowParts"):
@@ -692,12 +696,21 @@ class _Window(ArchComponent.Component):
shapes = []
for i in range(len(obj.WindowParts)/5):
wires = []
hinge = None
omode = None
ssymbols = []
vsymbols = []
wstr = obj.WindowParts[(i*5)+2].split(',')
for s in wstr:
j = int(s[4:])
if obj.Base.Shape.Wires:
if len(obj.Base.Shape.Wires) >= j:
wires.append(obj.Base.Shape.Wires[j])
if "Wire" in s:
j = int(s[4:])
if obj.Base.Shape.Wires:
if len(obj.Base.Shape.Wires) >= j:
wires.append(obj.Base.Shape.Wires[j])
elif "Edge" in s:
hinge = int(s[4:])-1
elif "Mode" in s:
omode = int(s[-1])
if wires:
max_length = 0
for w in wires:
@@ -711,6 +724,88 @@ class _Window(ArchComponent.Component):
if obj.Normal:
if not DraftVecUtils.isNull(obj.Normal):
norm = obj.Normal
if hinge and omode:
e = obj.Base.Shape.Edges[hinge]
ev1 = e.Vertexes[0].Point
ev2 = e.Vertexes[-1].Point
if ev2.z < ev1.z:
ev1,ev2 = ev2,ev1
p = None
d = 0
for v in shape.Vertexes:
dist = v.Point.distanceToLine(ev1,ev2.sub(ev1))
if dist > d:
d = dist
p = v.Point
if p:
chord = p.sub(ev1)
enorm = ev2.sub(ev1)
proj = DraftVecUtils.project(chord,enorm)
if proj.Length > 0:
v1 = ev1.add(proj)
chord = p.sub(v1)
else:
v1 = e.Vertexes[0].Point
v4 = p.add(DraftVecUtils.scale(enorm,0.5))
if omode == 1: # Arc 90,"Arc 90 inv","Arc 45","Arc 45 inv","Arc 180","Arc 180 inv","Triangle","Triangle inv","Sliding","Sliding inv"
v2 = v1.add(DraftVecUtils.rotate(chord,math.pi/4,enorm))
v3 = v1.add(DraftVecUtils.rotate(chord,math.pi/2,enorm))
ssymbols.append(Part.Arc(p,v2,v3).toShape())
ssymbols.append(Part.Line(v3,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 2: # Arc -90
v2 = v1.add(DraftVecUtils.rotate(chord,-math.pi/4,enorm))
v3 = v1.add(DraftVecUtils.rotate(chord,-math.pi/2,enorm))
ssymbols.append(Part.Arc(p,v2,v3).toShape())
ssymbols.append(Part.Line(v3,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 3: # Arc 45
v2 = v1.add(DraftVecUtils.rotate(chord,math.pi/8,enorm))
v3 = v1.add(DraftVecUtils.rotate(chord,math.pi/4,enorm))
ssymbols.append(Part.Arc(p,v2,v3).toShape())
ssymbols.append(Part.Line(v3,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 4: # Arc -45
v2 = v1.add(DraftVecUtils.rotate(chord,-math.pi/8,enorm))
v3 = v1.add(DraftVecUtils.rotate(chord,-math.pi/4,enorm))
ssymbols.append(Part.Arc(p,v2,v3).toShape())
ssymbols.append(Part.Line(v3,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 5: # Arc 180
v2 = v1.add(DraftVecUtils.rotate(chord,math.pi/2,enorm))
v3 = v1.add(DraftVecUtils.rotate(chord,math.pi,enorm))
ssymbols.append(Part.Arc(p,v2,v3).toShape())
ssymbols.append(Part.Line(v3,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 6: # Arc -180
v2 = v1.add(DraftVecUtils.rotate(chord,-math.pi/2,enorm))
v3 = v1.add(DraftVecUtils.rotate(chord,-math.pi,enorm))
ssymbols.append(Part.Arc(p,v2,v3).toShape())
ssymbols.append(Part.Line(v3,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 7: # tri
v2 = v1.add(DraftVecUtils.rotate(chord,math.pi/2,enorm))
ssymbols.append(Part.Line(p,v2).toShape())
ssymbols.append(Part.Line(v2,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 8: # -tri
v2 = v1.add(DraftVecUtils.rotate(chord,-math.pi/2,enorm))
ssymbols.append(Part.Line(p,v2).toShape())
ssymbols.append(Part.Line(v2,v1).toShape())
vsymbols.append(Part.Line(v1,v4).toShape())
vsymbols.append(Part.Line(v4,ev2).toShape())
elif omode == 9: # sliding
pass
elif omode == 10: # -sliding
pass
thk = float(obj.WindowParts[(i*5)+3])
if thk:
exv = DraftVecUtils.scaleTo(norm,thk)
@@ -724,6 +819,10 @@ class _Window(ArchComponent.Component):
if zof:
zov = DraftVecUtils.scaleTo(norm,zof)
shape.translate(zov)
for symb in ssymbols:
symb.translate(zov)
for symb in vsymbols:
symb.translate(zov)
if obj.WindowParts[(i*5)+1] == "Louvre":
if hasattr(obj,"LouvreWidth"):
if obj.LouvreWidth and obj.LouvreSpacing:
@@ -743,6 +842,8 @@ class _Window(ArchComponent.Component):
self.boxes.translate(shape.BoundBox.Center.sub(self.boxes.BoundBox.Center))
shape = shape.common(self.boxes)
shapes.append(shape)
self.sshapes.extend(ssymbols)
self.vshapes.extend(vsymbols)
if shapes:
base = Part.makeCompound(shapes)
elif not obj.WindowParts:
@@ -756,6 +857,8 @@ class _Window(ArchComponent.Component):
base = self.processSubShapes(obj,base)
if base:
if not base.isNull():
if self.sshapes:
base = Part.makeCompound([base]+self.sshapes+self.vshapes)
self.applyShape(obj,base,pl,allowinvalid=True,allownosolid=True)
if hasattr(obj,"Area"):
obj.Area = obj.Width.Value * obj.Height.Value
@@ -961,11 +1064,15 @@ class _ArchWindowTaskPanel:
self.new3 = QtGui.QLabel(self.form)
self.new4 = QtGui.QLabel(self.form)
self.new5 = QtGui.QLabel(self.form)
self.new6 = QtGui.QLabel(self.form)
self.new7 = QtGui.QLabel(self.form)
self.field1 = QtGui.QLineEdit(self.form)
self.field2 = QtGui.QComboBox(self.form)
self.field3 = QtGui.QLineEdit(self.form)
self.field4 = ui.createWidget("Gui::InputField")
self.field5 = ui.createWidget("Gui::InputField")
self.field6 = QtGui.QPushButton(self.form)
self.field7 = QtGui.QComboBox(self.form)
self.createButton = QtGui.QPushButton(self.form)
self.createButton.setObjectName("createButton")
self.createButton.setIcon(QtGui.QIcon(":/icons/Arch_Add.svg"))
@@ -980,13 +1087,19 @@ class _ArchWindowTaskPanel:
self.grid.addWidget(self.field4, 10, 2, 1, 5)
self.grid.addWidget(self.new5, 11, 0, 1, 1)
self.grid.addWidget(self.field5, 11, 2, 1, 5)
self.grid.addWidget(self.createButton, 12, 0, 1, 7)
self.grid.addWidget(self.new6, 12, 0, 1, 1)
self.grid.addWidget(self.field6, 12, 2, 1, 5)
self.grid.addWidget(self.new7, 13, 0, 1, 1)
self.grid.addWidget(self.field7, 13, 2, 1, 5)
self.grid.addWidget(self.createButton, 14, 0, 1, 7)
self.newtitle.setVisible(False)
self.new1.setVisible(False)
self.new2.setVisible(False)
self.new3.setVisible(False)
self.new4.setVisible(False)
self.new5.setVisible(False)
self.new6.setVisible(False)
self.new7.setVisible(False)
self.field1.setVisible(False)
self.field2.setVisible(False)
for t in WindowPartTypes:
@@ -995,6 +1108,10 @@ class _ArchWindowTaskPanel:
self.field3.setReadOnly(True)
self.field4.setVisible(False)
self.field5.setVisible(False)
self.field6.setVisible(False)
self.field7.setVisible(False)
for t in WindowOpeningModes:
self.field7.addItem("")
self.createButton.setVisible(False)
QtCore.QObject.connect(self.addButton, QtCore.SIGNAL("clicked()"), self.addElement)
@@ -1003,6 +1120,7 @@ class _ArchWindowTaskPanel:
QtCore.QObject.connect(self.createButton, QtCore.SIGNAL("clicked()"), self.create)
QtCore.QObject.connect(self.comptree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.check)
QtCore.QObject.connect(self.wiretree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.select)
QtCore.QObject.connect(self.field6, QtCore.SIGNAL("clicked()"), self.addEdge)
self.update()
FreeCADGui.Selection.clearSelection()
@@ -1081,11 +1199,15 @@ class _ArchWindowTaskPanel:
self.new3.setVisible(True)
self.new4.setVisible(True)
self.new5.setVisible(True)
self.new6.setVisible(True)
self.new7.setVisible(True)
self.field1.setVisible(True)
self.field2.setVisible(True)
self.field3.setVisible(True)
self.field4.setVisible(True)
self.field5.setVisible(True)
self.field6.setVisible(True)
self.field7.setVisible(True)
self.createButton.setVisible(True)
self.addButton.setEnabled(False)
self.editButton.setEnabled(False)
@@ -1121,6 +1243,18 @@ class _ArchWindowTaskPanel:
f.setCurrentIndex(WindowPartTypes.index(t))
else:
f.setCurrentIndex(0)
elif i == 2:
wires = []
for l in t.split(","):
if "Wire" in l:
wires.append(l)
elif "Edge" in l:
self.field6.setText(l)
elif "Mode" in l:
self.field7.setCurrentIndex(int(l[-1]))
if wires:
f.setText(",".join(wires))
elif i in [3,4]:
f.setProperty("text",FreeCAD.Units.Quantity(float(t),FreeCAD.Units.Length).UserString)
else:
@@ -1153,6 +1287,12 @@ class _ArchWindowTaskPanel:
t = str(q.Value)
except (ValueError,TypeError):
ok = False
if i == 2:
# check additional opening parameters
hinge = self.field6.property("text")
n = self.field7.currentIndex()
if (hinge.startswith("Edge")) and (n > 0):
t += "," + hinge + ",Mode" + str(n)
ar.append(t)
if ok:
@@ -1175,13 +1315,24 @@ class _ArchWindowTaskPanel:
self.new3.setVisible(False)
self.new4.setVisible(False)
self.new5.setVisible(False)
self.new6.setVisible(False)
self.new7.setVisible(False)
self.field1.setVisible(False)
self.field2.setVisible(False)
self.field3.setVisible(False)
self.field4.setVisible(False)
self.field5.setVisible(False)
self.field6.setVisible(False)
self.field7.setVisible(False)
self.createButton.setVisible(False)
self.addButton.setEnabled(True)
def addEdge(self):
for sel in FreeCADGui.Selection.getSelectionEx():
for sub in sel.SubElementNames:
if "Edge" in sub:
self.field6.setText(sub)
return
def reject(self):
FreeCAD.ActiveDocument.recompute()
@@ -1203,8 +1354,14 @@ class _ArchWindowTaskPanel:
self.new3.setText(QtGui.QApplication.translate("Arch", "Wires", None, QtGui.QApplication.UnicodeUTF8))
self.new4.setText(QtGui.QApplication.translate("Arch", "Thickness", None, QtGui.QApplication.UnicodeUTF8))
self.new5.setText(QtGui.QApplication.translate("Arch", "Z offset", None, QtGui.QApplication.UnicodeUTF8))
self.new6.setText(QtGui.QApplication.translate("Arch", "Hinge", None, QtGui.QApplication.UnicodeUTF8))
self.new7.setText(QtGui.QApplication.translate("Arch", "Opening mode", None, QtGui.QApplication.UnicodeUTF8))
self.field6.setText(QtGui.QApplication.translate("Arch", "Get selected edge", None, QtGui.QApplication.UnicodeUTF8))
self.field6.setToolTip(QtGui.QApplication.translate("Arch", "Press to retrieve the selected edge", None, QtGui.QApplication.UnicodeUTF8))
for i in range(len(WindowPartTypes)):
self.field2.setItemText(i, QtGui.QApplication.translate("Arch", WindowPartTypes[i], None, QtGui.QApplication.UnicodeUTF8))
for i in range(len(WindowOpeningModes)):
self.field7.setItemText(i, QtGui.QApplication.translate("Arch", WindowOpeningModes[i], None, QtGui.QApplication.UnicodeUTF8))
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Window',_CommandWindow())