More improvements to the Arch module
+ Draft snap can now pass the object being snapped to + Handle when wall is based on a closed wire + Handle when wall is based on a self-intersecting wire
This commit is contained in:
parent
28a989463d
commit
8d01d70038
|
@ -98,17 +98,14 @@ class _CommandWall:
|
||||||
import DraftTrackers
|
import DraftTrackers
|
||||||
self.points = []
|
self.points = []
|
||||||
self.tracker = DraftTrackers.boxTracker()
|
self.tracker = DraftTrackers.boxTracker()
|
||||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint)
|
FreeCADGui.Snapper.getPoint(callback=self.getPoint,extradlg=TaskArchWall())
|
||||||
|
|
||||||
def getPoint(self,point):
|
def getPoint(self,point,obj):
|
||||||
"this function is called by the snapper when it has a 3D point"
|
"this function is called by the snapper when it has a 3D point"
|
||||||
pos = FreeCADGui.ActiveDocument.ActiveView.getCursorPos()
|
if obj:
|
||||||
exi = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo(pos)
|
if Draft.getType(obj) == "Wall":
|
||||||
if exi:
|
if not obj in self.existing:
|
||||||
exi = FreeCAD.ActiveDocument.getObject(exi['Object'])
|
self.existing.append(obj)
|
||||||
if Draft.getType(exi) == "Wall":
|
|
||||||
if not exi in self.existing:
|
|
||||||
self.existing.append(exi)
|
|
||||||
if point == None:
|
if point == None:
|
||||||
self.tracker.finalize()
|
self.tracker.finalize()
|
||||||
return
|
return
|
||||||
|
@ -119,6 +116,8 @@ class _CommandWall:
|
||||||
elif len(self.points) == 2:
|
elif len(self.points) == 2:
|
||||||
import Part
|
import Part
|
||||||
l = Part.Line(self.points[0],self.points[1])
|
l = Part.Line(self.points[0],self.points[1])
|
||||||
|
self.tracker.finalize()
|
||||||
|
FreeCAD.ActiveDocument.openTransaction("Wall")
|
||||||
if not self.existing:
|
if not self.existing:
|
||||||
s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")
|
s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")
|
||||||
s.addGeometry(l)
|
s.addGeometry(l)
|
||||||
|
@ -126,7 +125,7 @@ class _CommandWall:
|
||||||
else:
|
else:
|
||||||
w = joinWalls(self.existing)
|
w = joinWalls(self.existing)
|
||||||
w.Base.addGeometry(l)
|
w.Base.addGeometry(l)
|
||||||
self.tracker.finalize()
|
FreeCAD.ActiveDocument.commitTransaction()
|
||||||
FreeCAD.ActiveDocument.recompute()
|
FreeCAD.ActiveDocument.recompute()
|
||||||
|
|
||||||
def update(self,point):
|
def update(self,point):
|
||||||
|
@ -182,6 +181,8 @@ class _Wall(ArchComponent.Component):
|
||||||
dvec = fcvec.neg(dvec)
|
dvec = fcvec.neg(dvec)
|
||||||
w2 = fcgeo.offsetWire(wire,dvec)
|
w2 = fcgeo.offsetWire(wire,dvec)
|
||||||
sh = fcgeo.bind(w1,w2)
|
sh = fcgeo.bind(w1,w2)
|
||||||
|
# fixing self-intersections
|
||||||
|
sh.fix(0.1,0,1)
|
||||||
if height:
|
if height:
|
||||||
norm = Vector(normal).multiply(height)
|
norm = Vector(normal).multiply(height)
|
||||||
sh = sh.extrude(norm)
|
sh = sh.extrude(norm)
|
||||||
|
@ -258,4 +259,9 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
|
||||||
def getIcon(self):
|
def getIcon(self):
|
||||||
return ":/icons/Arch_Wall_Tree.svg"
|
return ":/icons/Arch_Wall_Tree.svg"
|
||||||
|
|
||||||
|
class TaskArchWall:
|
||||||
|
def __init__(self):
|
||||||
|
from PyQt4 import QtGui
|
||||||
|
self.form = QtGui.QWidget()
|
||||||
|
|
||||||
FreeCADGui.addCommand('Arch_Wall',_CommandWall())
|
FreeCADGui.addCommand('Arch_Wall',_CommandWall())
|
||||||
|
|
|
@ -136,7 +136,7 @@ class DraftLineEdit(QtGui.QLineEdit):
|
||||||
QtGui.QLineEdit.keyPressEvent(self, event)
|
QtGui.QLineEdit.keyPressEvent(self, event)
|
||||||
|
|
||||||
class DraftTaskPanel:
|
class DraftTaskPanel:
|
||||||
def __init__(self,widget):
|
def __init__(self,widget,extradlg=None):
|
||||||
self.form = widget
|
self.form = widget
|
||||||
def getStandardButtons(self):
|
def getStandardButtons(self):
|
||||||
return int(QtGui.QDialogButtonBox.Cancel)
|
return int(QtGui.QDialogButtonBox.Cancel)
|
||||||
|
@ -463,7 +463,7 @@ class DraftToolBar:
|
||||||
# Interface modes
|
# Interface modes
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
def taskUi(self,title):
|
def taskUi(self,title,extradlg=None):
|
||||||
if self.taskmode:
|
if self.taskmode:
|
||||||
self.isTaskOn = True
|
self.isTaskOn = True
|
||||||
todo.delay(FreeCADGui.Control.closeDialog,None)
|
todo.delay(FreeCADGui.Control.closeDialog,None)
|
||||||
|
@ -472,7 +472,7 @@ class DraftToolBar:
|
||||||
self.layout = QtGui.QVBoxLayout(self.baseWidget)
|
self.layout = QtGui.QVBoxLayout(self.baseWidget)
|
||||||
self.setupToolBar(task=True)
|
self.setupToolBar(task=True)
|
||||||
self.retranslateUi(self.baseWidget)
|
self.retranslateUi(self.baseWidget)
|
||||||
self.panel = DraftTaskPanel(self.baseWidget)
|
self.panel = DraftTaskPanel(self.baseWidget,extradlg)
|
||||||
todo.delay(FreeCADGui.Control.showDialog,self.panel)
|
todo.delay(FreeCADGui.Control.showDialog,self.panel)
|
||||||
else:
|
else:
|
||||||
self.setTitle(title)
|
self.setTitle(title)
|
||||||
|
@ -510,9 +510,9 @@ class DraftToolBar:
|
||||||
self.labelx.setText(translate("draft", "Center X"))
|
self.labelx.setText(translate("draft", "Center X"))
|
||||||
self.continueCmd.show()
|
self.continueCmd.show()
|
||||||
|
|
||||||
def pointUi(self,title=translate("draft","Point"),cancel=None):
|
def pointUi(self,title=translate("draft","Point"),cancel=None,extradlg=None):
|
||||||
if cancel: self.cancel = cancel
|
if cancel: self.cancel = cancel
|
||||||
self.taskUi(title)
|
self.taskUi(title,extradlg)
|
||||||
self.xValue.setEnabled(True)
|
self.xValue.setEnabled(True)
|
||||||
self.yValue.setEnabled(True)
|
self.yValue.setEnabled(True)
|
||||||
self.labelx.setText(translate("draft", "X"))
|
self.labelx.setText(translate("draft", "X"))
|
||||||
|
@ -536,6 +536,7 @@ class DraftToolBar:
|
||||||
|
|
||||||
def offUi(self):
|
def offUi(self):
|
||||||
todo.delay(FreeCADGui.Control.closeDialog,None)
|
todo.delay(FreeCADGui.Control.closeDialog,None)
|
||||||
|
self.cancel = None
|
||||||
if self.taskmode:
|
if self.taskmode:
|
||||||
self.isTaskOn = False
|
self.isTaskOn = False
|
||||||
self.baseWidget = QtGui.QWidget()
|
self.baseWidget = QtGui.QWidget()
|
||||||
|
|
|
@ -68,6 +68,7 @@ class Snapper:
|
||||||
self.grid = None
|
self.grid = None
|
||||||
self.constrainLine = None
|
self.constrainLine = None
|
||||||
self.trackLine = None
|
self.trackLine = None
|
||||||
|
self.lastSnappedObject = None
|
||||||
|
|
||||||
# the snapmarker has "dot","circle" and "square" available styles
|
# the snapmarker has "dot","circle" and "square" available styles
|
||||||
self.mk = {'passive':'circle',
|
self.mk = {'passive':'circle',
|
||||||
|
@ -175,6 +176,8 @@ class Snapper:
|
||||||
obj = FreeCAD.ActiveDocument.getObject(info['Object'])
|
obj = FreeCAD.ActiveDocument.getObject(info['Object'])
|
||||||
if not obj:
|
if not obj:
|
||||||
return cstr(point)
|
return cstr(point)
|
||||||
|
|
||||||
|
self.lastSnappedObject = obj
|
||||||
|
|
||||||
if hasattr(obj.ViewObject,"Selectable"):
|
if hasattr(obj.ViewObject,"Selectable"):
|
||||||
if not obj.ViewObject.Selectable:
|
if not obj.ViewObject.Selectable:
|
||||||
|
@ -531,6 +534,7 @@ class Snapper:
|
||||||
for v in self.views:
|
for v in self.views:
|
||||||
v.unsetCursor()
|
v.unsetCursor()
|
||||||
self.views = []
|
self.views = []
|
||||||
|
self.cursorMode = None
|
||||||
else:
|
else:
|
||||||
if mode != self.cursorMode:
|
if mode != self.cursorMode:
|
||||||
if not self.views:
|
if not self.views:
|
||||||
|
@ -559,11 +563,9 @@ class Snapper:
|
||||||
self.extLine.off()
|
self.extLine.off()
|
||||||
if self.grid:
|
if self.grid:
|
||||||
self.grid.off()
|
self.grid.off()
|
||||||
if self.constrainLine:
|
self.unconstrain()
|
||||||
self.constrainLine.off()
|
|
||||||
self.radius = 0
|
self.radius = 0
|
||||||
self.setCursor()
|
self.setCursor()
|
||||||
self.cursorMode = None
|
|
||||||
|
|
||||||
def constrain(self,point,basepoint=None,axis=None):
|
def constrain(self,point,basepoint=None,axis=None):
|
||||||
'''constrain(point,basepoint=None,axis=None: Returns a
|
'''constrain(point,basepoint=None,axis=None: Returns a
|
||||||
|
@ -627,11 +629,12 @@ class Snapper:
|
||||||
if self.constrainLine:
|
if self.constrainLine:
|
||||||
self.constrainLine.off()
|
self.constrainLine.off()
|
||||||
|
|
||||||
def getPoint(self,last=None,callback=None,movecallback=None):
|
def getPoint(self,last=None,callback=None,movecallback=None,extradlg=None):
|
||||||
|
|
||||||
"""getPoint([last],[callback],[movecallback]) : gets a 3D point from the screen. You
|
"""getPoint([last],[callback],[movecallback],[extradlg]) : gets a 3D point
|
||||||
can provide an existing point, in that case additional snap options and a tracker
|
from the screen. You can provide an existing point, in that case additional
|
||||||
are available. You can also pass a function as callback, which will get called
|
snap options and a tracker are available.
|
||||||
|
You can also pass a function as callback, which will get called
|
||||||
with the resulting point as argument, when a point is clicked, and optionally
|
with the resulting point as argument, when a point is clicked, and optionally
|
||||||
another callback which gets called when the mouse is moved.
|
another callback which gets called when the mouse is moved.
|
||||||
|
|
||||||
|
@ -642,7 +645,12 @@ class Snapper:
|
||||||
def cb(point):
|
def cb(point):
|
||||||
if point:
|
if point:
|
||||||
print "got a 3D point: ",point
|
print "got a 3D point: ",point
|
||||||
FreeCADGui.Snapper.getPoint(callback=cb)"""
|
FreeCADGui.Snapper.getPoint(callback=cb)
|
||||||
|
|
||||||
|
If the callback function accepts more than one argument, it will also receive
|
||||||
|
the last snapped object.Finally, a task dialog can be passed as extradlg."""
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
|
||||||
self.pt = None
|
self.pt = None
|
||||||
self.ui = FreeCADGui.draftToolBar
|
self.ui = FreeCADGui.draftToolBar
|
||||||
|
@ -673,12 +681,16 @@ class Snapper:
|
||||||
if event.getState() == coin.SoMouseButtonEvent.DOWN:
|
if event.getState() == coin.SoMouseButtonEvent.DOWN:
|
||||||
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
|
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
|
||||||
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove)
|
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove)
|
||||||
|
obj = FreeCADGui.Snapper.lastSnappedObject
|
||||||
FreeCADGui.Snapper.off()
|
FreeCADGui.Snapper.off()
|
||||||
self.ui.offUi()
|
self.ui.offUi()
|
||||||
if self.trackLine:
|
if self.trackLine:
|
||||||
self.trackLine.off()
|
self.trackLine.off()
|
||||||
if callback:
|
if callback:
|
||||||
callback(self.pt)
|
if len(inspect.getargspec(callback).args) > 2:
|
||||||
|
callback(self.pt,obj)
|
||||||
|
else:
|
||||||
|
callback(self.pt)
|
||||||
self.pt = None
|
self.pt = None
|
||||||
|
|
||||||
def cancel():
|
def cancel():
|
||||||
|
@ -692,7 +704,7 @@ class Snapper:
|
||||||
callback(None)
|
callback(None)
|
||||||
|
|
||||||
# adding 2 callback functions
|
# adding 2 callback functions
|
||||||
self.ui.pointUi(cancel=cancel)
|
self.ui.pointUi(cancel=cancel,extradlg=extradlg)
|
||||||
self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click)
|
self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click)
|
||||||
self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move)
|
self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move)
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,7 @@ class Line(Creator):
|
||||||
if self.isWire:
|
if self.isWire:
|
||||||
msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n"))
|
msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n"))
|
||||||
else:
|
else:
|
||||||
currentshape = self.obj.Shape
|
currentshape = self.obj.Shape.copy()
|
||||||
last = self.node[len(self.node)-2]
|
last = self.node[len(self.node)-2]
|
||||||
newseg = Part.Line(last,point).toShape()
|
newseg = Part.Line(last,point).toShape()
|
||||||
newshape=currentshape.fuse(newseg)
|
newshape=currentshape.fuse(newseg)
|
||||||
|
|
|
@ -959,9 +959,19 @@ def getTangent(edge,frompoint=None):
|
||||||
def bind(w1,w2):
|
def bind(w1,w2):
|
||||||
'''bind(wire1,wire2): binds 2 wires by their endpoints and
|
'''bind(wire1,wire2): binds 2 wires by their endpoints and
|
||||||
returns a face'''
|
returns a face'''
|
||||||
w3 = Part.Line(w1.Vertexes[0].Point,w2.Vertexes[0].Point).toShape()
|
if w1.isClosed() and w2.isClosed():
|
||||||
w4 = Part.Line(w1.Vertexes[-1].Point,w2.Vertexes[-1].Point).toShape()
|
d1 = w1.BoundBox.DiagonalLength
|
||||||
return Part.Face(Part.Wire(w1.Edges+[w3]+w2.Edges+[w4]))
|
d2 = w2.BoundBox.DiagonalLength
|
||||||
|
if d1 > d2:
|
||||||
|
#w2.reverse()
|
||||||
|
return Part.Face([w1,w2])
|
||||||
|
else:
|
||||||
|
#w1.reverse()
|
||||||
|
return Part.Face([w2,w1])
|
||||||
|
else:
|
||||||
|
w3 = Part.Line(w1.Vertexes[0].Point,w2.Vertexes[0].Point).toShape()
|
||||||
|
w4 = Part.Line(w1.Vertexes[-1].Point,w2.Vertexes[-1].Point).toShape()
|
||||||
|
return Part.Face(Part.Wire(w1.Edges+[w3]+w2.Edges+[w4]))
|
||||||
|
|
||||||
def cleanFaces(shape):
|
def cleanFaces(shape):
|
||||||
"removes inner edges from coplanar faces"
|
"removes inner edges from coplanar faces"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user