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 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())

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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"