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:
Yorik van Havre 2012-02-02 09:37:47 -02:00
parent 28a989463d
commit 8d01d70038
5 changed files with 58 additions and 29 deletions

View File

@ -98,17 +98,14 @@ class _CommandWall:
import DraftTrackers
self.points = []
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"
pos = FreeCADGui.ActiveDocument.ActiveView.getCursorPos()
exi = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo(pos)
if exi:
exi = FreeCAD.ActiveDocument.getObject(exi['Object'])
if Draft.getType(exi) == "Wall":
if not exi in self.existing:
self.existing.append(exi)
if obj:
if Draft.getType(obj) == "Wall":
if not obj in self.existing:
self.existing.append(obj)
if point == None:
self.tracker.finalize()
return
@ -119,6 +116,8 @@ class _CommandWall:
elif len(self.points) == 2:
import Part
l = Part.Line(self.points[0],self.points[1])
self.tracker.finalize()
FreeCAD.ActiveDocument.openTransaction("Wall")
if not self.existing:
s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace")
s.addGeometry(l)
@ -126,7 +125,7 @@ class _CommandWall:
else:
w = joinWalls(self.existing)
w.Base.addGeometry(l)
self.tracker.finalize()
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
def update(self,point):
@ -182,6 +181,8 @@ class _Wall(ArchComponent.Component):
dvec = fcvec.neg(dvec)
w2 = fcgeo.offsetWire(wire,dvec)
sh = fcgeo.bind(w1,w2)
# fixing self-intersections
sh.fix(0.1,0,1)
if height:
norm = Vector(normal).multiply(height)
sh = sh.extrude(norm)
@ -258,4 +259,9 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
def getIcon(self):
return ":/icons/Arch_Wall_Tree.svg"
class TaskArchWall:
def __init__(self):
from PyQt4 import QtGui
self.form = QtGui.QWidget()
FreeCADGui.addCommand('Arch_Wall',_CommandWall())

View File

@ -136,7 +136,7 @@ class DraftLineEdit(QtGui.QLineEdit):
QtGui.QLineEdit.keyPressEvent(self, event)
class DraftTaskPanel:
def __init__(self,widget):
def __init__(self,widget,extradlg=None):
self.form = widget
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Cancel)
@ -463,7 +463,7 @@ class DraftToolBar:
# Interface modes
#---------------------------------------------------------------------------
def taskUi(self,title):
def taskUi(self,title,extradlg=None):
if self.taskmode:
self.isTaskOn = True
todo.delay(FreeCADGui.Control.closeDialog,None)
@ -472,7 +472,7 @@ class DraftToolBar:
self.layout = QtGui.QVBoxLayout(self.baseWidget)
self.setupToolBar(task=True)
self.retranslateUi(self.baseWidget)
self.panel = DraftTaskPanel(self.baseWidget)
self.panel = DraftTaskPanel(self.baseWidget,extradlg)
todo.delay(FreeCADGui.Control.showDialog,self.panel)
else:
self.setTitle(title)
@ -510,9 +510,9 @@ class DraftToolBar:
self.labelx.setText(translate("draft", "Center X"))
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
self.taskUi(title)
self.taskUi(title,extradlg)
self.xValue.setEnabled(True)
self.yValue.setEnabled(True)
self.labelx.setText(translate("draft", "X"))
@ -536,6 +536,7 @@ class DraftToolBar:
def offUi(self):
todo.delay(FreeCADGui.Control.closeDialog,None)
self.cancel = None
if self.taskmode:
self.isTaskOn = False
self.baseWidget = QtGui.QWidget()

View File

@ -68,6 +68,7 @@ class Snapper:
self.grid = None
self.constrainLine = None
self.trackLine = None
self.lastSnappedObject = None
# the snapmarker has "dot","circle" and "square" available styles
self.mk = {'passive':'circle',
@ -175,6 +176,8 @@ class Snapper:
obj = FreeCAD.ActiveDocument.getObject(info['Object'])
if not obj:
return cstr(point)
self.lastSnappedObject = obj
if hasattr(obj.ViewObject,"Selectable"):
if not obj.ViewObject.Selectable:
@ -531,6 +534,7 @@ class Snapper:
for v in self.views:
v.unsetCursor()
self.views = []
self.cursorMode = None
else:
if mode != self.cursorMode:
if not self.views:
@ -559,11 +563,9 @@ class Snapper:
self.extLine.off()
if self.grid:
self.grid.off()
if self.constrainLine:
self.constrainLine.off()
self.unconstrain()
self.radius = 0
self.setCursor()
self.cursorMode = None
def constrain(self,point,basepoint=None,axis=None):
'''constrain(point,basepoint=None,axis=None: Returns a
@ -627,11 +629,12 @@ class Snapper:
if self.constrainLine:
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
can provide an existing point, in that case additional snap options and a tracker
are available. You can also pass a function as callback, which will get called
"""getPoint([last],[callback],[movecallback],[extradlg]) : gets a 3D point
from the screen. You can provide an existing point, in that case additional
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
another callback which gets called when the mouse is moved.
@ -642,7 +645,12 @@ class Snapper:
def cb(point):
if 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.ui = FreeCADGui.draftToolBar
@ -673,12 +681,16 @@ class Snapper:
if event.getState() == coin.SoMouseButtonEvent.DOWN:
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove)
obj = FreeCADGui.Snapper.lastSnappedObject
FreeCADGui.Snapper.off()
self.ui.offUi()
if self.trackLine:
self.trackLine.off()
if callback:
callback(self.pt)
if len(inspect.getargspec(callback).args) > 2:
callback(self.pt,obj)
else:
callback(self.pt)
self.pt = None
def cancel():
@ -692,7 +704,7 @@ class Snapper:
callback(None)
# 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.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move)

View File

@ -476,7 +476,7 @@ class Line(Creator):
if self.isWire:
msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n"))
else:
currentshape = self.obj.Shape
currentshape = self.obj.Shape.copy()
last = self.node[len(self.node)-2]
newseg = Part.Line(last,point).toShape()
newshape=currentshape.fuse(newseg)

View File

@ -959,9 +959,19 @@ def getTangent(edge,frompoint=None):
def bind(w1,w2):
'''bind(wire1,wire2): binds 2 wires by their endpoints and
returns a face'''
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]))
if w1.isClosed() and w2.isClosed():
d1 = w1.BoundBox.DiagonalLength
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):
"removes inner edges from coplanar faces"