Arch: Refactor of Structure's Column/Beam modes and fixed rotation issues

This commit is contained in:
Yorik van Havre
2019-05-15 15:08:23 -03:00
parent 2a4012872e
commit ff130d08f4

View File

@@ -73,7 +73,7 @@ def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structur
return
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Structure")
obj.Label = translate("Arch",name)
obj.Label = translate("Arch","Structure")
_Structure(obj)
if FreeCAD.GuiUp:
_ViewProviderStructure(obj.ViewObject)
@@ -88,7 +88,8 @@ def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structur
if height:
obj.Height = height
else:
obj.Height = p.GetFloat("StructureHeight",1000)
if not length:
obj.Height = p.GetFloat("StructureHeight",1000)
if length:
obj.Length = length
else:
@@ -96,10 +97,34 @@ def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structur
# don't set the length if we have a base object, otherwise the length X height calc
# gets wrong
obj.Length = p.GetFloat("StructureLength",100)
if baseobj:
w = 0
h = 0
if hasattr(baseobj,"Width") and hasattr(baseobj,"Height"):
w = baseobj.Width.Value
h = baseobj.Height.Value
elif hasattr(baseobj,"Length") and hasattr(baseobj,"Width"):
w = baseobj.Length.Value
h = baseobj.Width.Value
elif hasattr(baseobj,"Length") and hasattr(baseobj,"Height"):
w = baseobj.Length.Value
h = baseobj.Height.Value
if w and h:
if length and not height:
obj.Width = w
obj.Height = h
elif height and not length:
obj.Width = w
obj.Length = h
if not height and not length:
obj.IfcType = "Undefined"
elif obj.Length > obj.Height:
obj.IfcType = "Beam"
obj.Label = translate("Arch","Beam")
elif obj.Height > obj.Length:
obj.IfcType = "Column"
obj.Label = translate("Arch","Column")
return obj
def makeStructuralSystem(objects=[],axes=[],name="StructuralSystem"):
@@ -138,6 +163,28 @@ def makeStructuralSystem(objects=[],axes=[],name="StructuralSystem"):
else:
return result
def placeAlongEdge(p1,p2,horizontal=False):
"""placeAlongEdge(p1,p2,[horizontal]): returns a Placement positioned at p1, with Z axis oriented towards p2.
If horizontal is True, then the X axis is oriented towards p2, not the Z axis"""
pl = FreeCAD.Placement()
pl.Base = p1
up = FreeCAD.Vector(0,0,1)
if hasattr(FreeCAD,"DraftWorkingPlane"):
up = FreeCAD.DraftWorkingPlane.axis
zaxis = p2.sub(p1)
yaxis = up.cross(zaxis)
if yaxis.Length > 0:
xaxis = zaxis.cross(yaxis)
if horizontal:
pl.Rotation = FreeCAD.Rotation(zaxis,yaxis,xaxis,"ZXY")
else:
pl.Rotation = FreeCAD.Rotation(xaxis,yaxis,zaxis,"ZXY")
pl.Rotation = FreeCAD.Rotation(pl.Rotation.multVec(FreeCAD.Vector(0,0,1)),90).multiply(pl.Rotation)
return pl
class _CommandStructure:
"the Arch Structure command definition"
@@ -160,13 +207,18 @@ class _CommandStructure:
def Activated(self):
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
self.Length = p.GetFloat("StructureLength",100)
self.Width = p.GetFloat("StructureWidth",100)
self.Height = p.GetFloat("StructureHeight",1000)
if self.beammode:
self.Height = p.GetFloat("StructureLength",100)
self.Length = p.GetFloat("StructureHeight",1000)
else:
self.Length = p.GetFloat("StructureLength",100)
self.Height = p.GetFloat("StructureHeight",1000)
self.Profile = None
self.continueCmd = False
self.bpoint = None
self.bmode = False
self.precastvalues = None
sel = FreeCADGui.Selection.getSelection()
if sel:
st = Draft.getObjectsOfType(sel,"Structure")
@@ -203,6 +255,7 @@ class _CommandStructure:
self.tracker.width(self.Width)
self.tracker.height(self.Height)
self.tracker.length(self.Length)
self.tracker.setRotation(FreeCAD.DraftWorkingPlane.getRotation().Rotation)
self.tracker.on()
self.precast = ArchPrecast._PrecastTaskPanel()
self.dents = ArchPrecast._DentsTaskPanel()
@@ -217,27 +270,34 @@ class _CommandStructure:
"this function is called by the snapper when it has a 3D point"
if self.modeb.isChecked() and (self.bpoint == None):
self.bmode = self.modeb.isChecked()
if self.bmode 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],title=translate("Arch","Next point")+":",mode="line")
FreeCADGui.Snapper.getPoint(last=point,callback=self.getPoint,movecallback=self.update,extradlg=[self.taskbox(),self.precast.form,self.dents.form],title=translate("Arch","Next point")+":",mode="line")
return
self.tracker.finalize()
if point == None:
return
horiz = True # determines the type of rotation to apply to the final object
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Structure"))
FreeCADGui.addModule("Arch")
if self.Profile is not None:
if "Precast" in self.Profile:
try: # try to update latest precast values - fails if dialog has been destroyed already
self.precastvalues = self.precast.getValues()
except:
pass
if ("Precast" in self.Profile) and self.precastvalues:
# precast concrete
args = self.precast.getValues()
args["PrecastType"] = self.Profile.split("_")[1]
args["Length"] = self.Length
args["Width"] = self.Width
args["Height"] = self.Height
self.precastvalues["PrecastType"] = self.Profile.split("_")[1]
self.precastvalues["Length"] = self.Length
self.precastvalues["Width"] = self.Width
self.precastvalues["Height"] = self.Height
argstring = ""
# fix for precast placement, since their (0,0) point is the lower left corner
point = FreeCAD.Vector(point.x-self.Length/2,point.y-self.Width/2,point.z)
for pair in args.items():
if not self.bmode:
point = FreeCAD.Vector(point.x-self.Length/2,point.y-self.Width/2,point.z)
for pair in self.precastvalues.items():
argstring += pair[0].lower() + "="
if isinstance(pair[1],str):
argstring += '"' + pair[1] + '",'
@@ -248,29 +308,26 @@ class _CommandStructure:
else:
# metal profile
FreeCADGui.doCommand('p = Arch.makeProfile('+str(self.Profile)+')')
if abs(self.Length - self.Profile[4]) < 0.1: # forgive rounding errors
if (abs(self.Length - self.Profile[4]) >= 0.1) or self.bmode: # forgive rounding errors
# horizontal
FreeCADGui.doCommand('s = Arch.makeStructure(p,length='+str(self.Length)+')')
horiz = False
else:
# vertical
FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Height)+')')
else:
# horizontal
FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Length)+')')
if not self.bmode:
FreeCADGui.doCommand('s.Placement.Rotation = FreeCAD.Rotation(-0.5,0.5,-0.5,0.5)')
#if not self.bmode:
# FreeCADGui.doCommand('s.Placement.Rotation = FreeCAD.Rotation(-0.5,0.5,-0.5,0.5)')
FreeCADGui.doCommand('s.Profile = "'+self.Profile[2]+'"')
else :
FreeCADGui.doCommand('s = Arch.makeStructure(length='+str(self.Length)+',width='+str(self.Width)+',height='+str(self.Height)+')')
# calculate rotation
if self.bmode and self.bpoint:
FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(self.bpoint))
FreeCADGui.doCommand('s.Placement = Arch.placeAlongEdge('+DraftVecUtils.toString(self.bpoint)+","+DraftVecUtils.toString(point)+","+str(horiz)+")")
else:
FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point))
if self.bmode and self.bpoint:
if (self.Profile != None) and (not "Precast" in self.Profile):
rot = FreeCAD.Rotation(Vector(0,0,1),(point.sub(self.bpoint)).normalize())
else:
rot = FreeCAD.Rotation(Vector(1,0,0),(point.sub(self.bpoint)).normalize())
FreeCADGui.doCommand('s.Placement.Rotation=FreeCAD.Rotation'+str(rot.Q))
else:
FreeCADGui.doCommand('s.Placement.Rotation=s.Placement.Rotation.multiply(FreeCAD.DraftWorkingPlane.getRotation().Rotation)')
FreeCADGui.doCommand('s.Placement.Rotation = s.Placement.Rotation.multiply(FreeCAD.DraftWorkingPlane.getRotation().Rotation)')
FreeCADGui.addModule("Draft")
FreeCADGui.doCommand("Draft.autogroup(s)")
FreeCAD.ActiveDocument.commitTransaction()
@@ -313,10 +370,10 @@ class _CommandStructure:
# categories box
labelc = QtGui.QLabel(translate("Arch","Category"))
valuec = QtGui.QComboBox()
valuec.addItems([" ","Precast concrete"]+Categories)
self.valuec = QtGui.QComboBox()
self.valuec.addItems([" ","Precast concrete"]+Categories)
grid.addWidget(labelc,2,0,1,1)
grid.addWidget(valuec,2,1,1,1)
grid.addWidget(self.valuec,2,1,1,1)
# presets box
labelp = QtGui.QLabel(translate("Arch","Preset"))
@@ -330,7 +387,10 @@ class _CommandStructure:
# length
label1 = QtGui.QLabel(translate("Arch","Length"))
self.vLength = ui.createWidget("Gui::InputField")
self.vLength.setText(FreeCAD.Units.Quantity(self.Length,FreeCAD.Units.Length).UserString)
if self.modeb.isChecked():
self.vLength.setText(FreeCAD.Units.Quantity(self.Height,FreeCAD.Units.Length).UserString)
else:
self.vLength.setText(FreeCAD.Units.Quantity(self.Length,FreeCAD.Units.Length).UserString)
grid.addWidget(label1,4,0,1,1)
grid.addWidget(self.vLength,4,1,1,1)
@@ -344,7 +404,10 @@ class _CommandStructure:
# height
label3 = QtGui.QLabel(translate("Arch","Height"))
self.vHeight = ui.createWidget("Gui::InputField")
self.vHeight.setText(FreeCAD.Units.Quantity(self.Height,FreeCAD.Units.Length).UserString)
if self.modeb.isChecked():
self.vHeight.setText(FreeCAD.Units.Quantity(self.Length,FreeCAD.Units.Length).UserString)
else:
self.vHeight.setText(FreeCAD.Units.Quantity(self.Height,FreeCAD.Units.Length).UserString)
grid.addWidget(label3,6,0,1,1)
grid.addWidget(self.vHeight,6,1,1,1)
@@ -366,7 +429,8 @@ class _CommandStructure:
grid.addWidget(label4,8,0,1,1)
grid.addWidget(value4,8,1,1,1)
QtCore.QObject.connect(valuec,QtCore.SIGNAL("currentIndexChanged(int)"),self.setCategory)
# connect slots
QtCore.QObject.connect(self.valuec,QtCore.SIGNAL("currentIndexChanged(int)"),self.setCategory)
QtCore.QObject.connect(self.vPresets,QtCore.SIGNAL("currentIndexChanged(int)"),self.setPreset)
QtCore.QObject.connect(self.vLength,QtCore.SIGNAL("valueChanged(double)"),self.setLength)
QtCore.QObject.connect(self.vWidth,QtCore.SIGNAL("valueChanged(double)"),self.setWidth)
@@ -375,6 +439,23 @@ class _CommandStructure:
QtCore.QObject.connect(value5,QtCore.SIGNAL("pressed()"),self.rotateLH)
QtCore.QObject.connect(value6,QtCore.SIGNAL("pressed()"),self.rotateLW)
QtCore.QObject.connect(self.modeb,QtCore.SIGNAL("toggled(bool)"),self.switchLH)
# restore preset
stored = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetString("StructurePreset","")
if stored:
if stored.lower().startswith("precast_"):
self.valuec.setCurrentIndex(1)
tp = stored.split("_")[1]
if tp and (tp in self.precast.PrecastTypes):
self.vPresets.setCurrentIndex(self.precast.PrecastTypes.index(tp))
elif ";" in stored:
stored = stored.split(";")
if len(stored) >= 3:
if stored[1] in Categories:
self.valuec.setCurrentIndex(2+Categories.index(stored[1]))
ps = [p[2] for p in self.pSelect]
if stored[2] in ps:
self.vPresets.setCurrentIndex(ps.index(stored[2]))
return w
def update(self,point,info):
@@ -382,16 +463,24 @@ class _CommandStructure:
"this function is called by the Snapper when the mouse is moved"
if FreeCADGui.Control.activeDialog():
try: # try to update latest precast values - fails if dialog has been destroyed already
self.precastvalues = self.precast.getValues()
except:
pass
if self.Height >= self.Length:
delta = Vector(0,0,self.Height/2)
else:
delta = Vector(self.Length/2,0,0)
if hasattr(FreeCAD,"DraftWorkingPlane"):
delta = FreeCAD.DraftWorkingPlane.getRotation().multVec(delta)
if self.modec.isChecked():
self.tracker.pos(point.add(delta))
self.tracker.on()
else:
if self.bpoint:
delta = Vector(0,0,-self.Height/2)
if hasattr(FreeCAD,"DraftWorkingPlane"):
delta = FreeCAD.DraftWorkingPlane.getRotation().multVec(delta)
self.tracker.update([self.bpoint.add(delta),point.add(delta)])
self.tracker.on()
l = (point.sub(self.bpoint)).Length
@@ -449,6 +538,7 @@ class _CommandStructure:
self.pSelect = [None]
fpresets = [" "]
self.vPresets.addItems(fpresets)
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetString("StructurePreset","")
def setPreset(self,i):
@@ -462,11 +552,13 @@ class _CommandStructure:
self.dents.form.show()
else:
self.dents.form.hide()
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetString("StructurePreset",self.Profile)
else:
p=elt[0]-1 # Presets indexes are 1-based
self.vLength.setText(FreeCAD.Units.Quantity(float(Presets[p][4]),FreeCAD.Units.Length).UserString)
self.vWidth.setText(FreeCAD.Units.Quantity(float(Presets[p][5]),FreeCAD.Units.Length).UserString)
self.Profile = Presets[p]
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetString("StructurePreset",";".join([str(i) for i in self.Profile]))
def switchLH(self,bmode):