diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 316ea0bba6..d03a91241b 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -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()) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index d6e2159144..8b223c2fa0 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -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() diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 87b8f45f6b..7742926a49 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -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) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 65bbd96c48..a74f4d733e 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -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) diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/draftlibs/fcgeo.py index 275f9a0dee..a2844af079 100755 --- a/src/Mod/Draft/draftlibs/fcgeo.py +++ b/src/Mod/Draft/draftlibs/fcgeo.py @@ -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"