diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 2d096138d..9ea142e70 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -56,7 +56,7 @@ class ArchWorkbench(Workbench): "Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array", "Draft_Clone"] self.draftextratools = ["Draft_WireToBSpline","Draft_AddPoint","Draft_DelPoint","Draft_ShapeString", - "Draft_PathArray","Draft_Mirror"] + "Draft_PathArray","Draft_Mirror","Draft_Stretch"] self.draftcontexttools = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", "Draft_SelectGroup","Draft_SelectPlane", "Draft_ShowSnapBar","Draft_ToggleGrid","Draft_UndoLine", diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index 91bba89a9..a50f8fb77 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -96,10 +96,14 @@ def isNull(something): def isPtOnEdge(pt,edge) : '''isPtOnEdge(Vector,edge): Tests if a point is on an edge''' v = Part.Vertex(pt) - d = v.distToShape(edge) - if d: - if round(d[0],precision()) == 0: - return True + try: + d = v.distToShape(edge) + except: + return False + else: + if d: + if round(d[0],precision()) == 0: + return True return False def hasCurves(shape): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 2a7d3a51b..6bd409b16 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -2670,6 +2670,149 @@ class Offset(Modifier): self.finish() +class Stretch(Modifier): + "The Draft_Stretch FreeCAD command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Stretch', + 'Accel' : "S, H", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Stretch", "Stretch"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Stretch", "Stretches the selected objects")} + + def Activated(self): + Modifier.Activated(self,"Stretch") + if self.ui: + if not FreeCADGui.Selection.getSelection(): + self.ui.selectUi() + msg(translate("draft", "Select an object to stretch\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() + + def proceed(self): + if self.call: + self.view.removeEventCallback("SoEvent",self.call) + self.sel = FreeCADGui.Selection.getSelection() + if self.ui and self.sel: + self.step = 1 + self.refpoint = None + self.ui.pointUi("Stretch") + self.ui.extUi() + self.call = self.view.addEventCallback("SoEvent",self.action) + self.rectracker = rectangleTracker() + self.nodetracker = [] + self.displacement = None + msg(translate("draft", "Pick first point of selection rectangle:\n")) + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint,info = getPoint(self,arg) #,mobile=True) #,noTracker=(self.step < 3)) + if self.step == 2: + self.rectracker.update(point) + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + if (arg["Position"] == self.pos): + # clicked twice on the same point + self.finish() + else: + point,ctrlPoint,info = getPoint(self,arg) #,mobile=True) #,noTracker=(self.step < 3)) + self.addPoint(point) + + def addPoint(self,point): + if self.step == 1: + # first rctangle point + msg(translate("draft", "Pick opposite point of selection rectangle:\n")) + self.ui.setRelative() + self.rectracker.setorigin(point) + self.rectracker.on() + if self.planetrack: + self.planetrack.set(point) + self.step = 2 + elif self.step == 2: + # second rectangle point + msg(translate("draft", "Pick start point of displacement:\n")) + self.rectracker.off() + nodes = [] + self.ops = [] + for o in self.sel: + tp = Draft.getType(o) + if tp in ["Wire","BSpline","BezCurve"]: + np = [] + iso = False + for p in o.Points: + p = o.Placement.multVec(p) + isi = self.rectracker.isInside(p) + np.append(isi) + if isi: + iso = True + nodes.append(p) + if iso: + self.ops.append([o,np]) + elif tp == "Circle": + self.ops.append([o]) + nodes.append(o.Placement.Base) + else: + print "Draft Stretch: Skipping unsupported object: ",o.Label + for n in nodes: + nt = editTracker(n) + nt.on() + self.nodetracker.append(nt) + self.step = 3 + elif self.step == 3: + # first point of displacement line + msg(translate("draft", "Pick end point of displacement:\n")) + self.displacement = point + self.node = [point] + self.step = 4 + elif self.step == 4: + self.displacement = point.sub(self.displacement) + self.doStretch() + if self.point: + self.ui.redraw() + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + point = Vector(numx,numy,numz) + self.addPoint(point) + + def finish(self,closed=False): + if self.rectracker: + self.rectracker.finalize() + if self.nodetracker: + for n in self.nodetracker: + n.finalize() + Modifier.finish(self) + + def doStretch(self): + "does the actual stretching" + commitops = [] + if self.displacement: + if self.displacement.Length > 0: + + for ops in self.ops: + tp = Draft.getType(ops[0]) + if tp in ["Wire","BSpline","BezCurve"]: + pts = [] + for i in range(len(ops[1])): + if ops[1][i] == False: + pts.append(ops[0].Points[i]) + else: + pts.append(ops[0].Points[i].add(self.displacement)) + pts = str(pts).replace("Vector","FreeCAD.Vector") + commitops.append("FreeCAD.ActiveDocument."+ops[0].Name+".Points="+pts) + elif tp == "Circle": + commitops.append("FreeCAD.ActiveDocument."+ops[0].Name+".Placement.Base=FreeCAD."+str(ops[0].Placement.Base.add(self.displacement))) + if commitops: + commitops.append("FreeCAD.ActiveDocument.recompute()") + FreeCADGui.addModule("Draft") + self.commit(translate("draft","Stretch"),commitops) + self.finish() + + class Upgrade(Modifier): '''The Draft_Upgrade FreeCAD command definition.''' @@ -4923,6 +5066,7 @@ FreeCADGui.addCommand('Draft_Heal',Heal()) FreeCADGui.addCommand('Draft_VisGroup',VisGroup()) FreeCADGui.addCommand('Draft_Mirror',Mirror()) FreeCADGui.addCommand('Draft_Slope',Draft_Slope()) +FreeCADGui.addCommand('Draft_Stretch',Stretch()) # context commands FreeCADGui.addCommand('Draft_FinishLine',FinishLine()) diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index b0e500b7f..731012db3 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -245,6 +245,20 @@ class rectangleTracker(Tracker): def getNormal(self): "returns the normal of the rectangle" return (self.u.cross(self.v)).normalize() + + def isInside(self,point): + "returns True if the given point is inside the rectangle" + vp = point.sub(self.p1()) + uv = self.p2().sub(self.p1()) + vv = self.p4().sub(self.p1()) + uvp = DraftVecUtils.project(vp,uv) + vvp = DraftVecUtils.project(vp,vv) + if uvp.getAngle(uv) < 1: + if vvp.getAngle(vv) < 1: + if uvp.Length <= uv.Length: + if vvp.Length <= vv.Length: + return True + return False class dimTracker(Tracker): "A Dimension tracker, used by the dimension tool" diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 282b5ebcf..c118df631 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -76,7 +76,7 @@ class DraftWorkbench (Workbench): "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", "Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array", - "Draft_PathArray","Draft_Clone","Draft_Drawing","Draft_Mirror"] + "Draft_PathArray","Draft_Clone","Draft_Drawing","Draft_Mirror","Draft_Stretch"] self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", "Draft_SelectGroup","Draft_SelectPlane", "Draft_ShowSnapBar","Draft_ToggleGrid"] diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index 2ade2035b..0bbac2fdb 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -71,6 +71,7 @@ icons/Draft_Grid.svg icons/Draft_Slope.svg icons/DraftWorkbench.svg + icons/Draft_Stretch.svg patterns/concrete.svg patterns/cross.svg patterns/line.svg diff --git a/src/Mod/Draft/Resources/icons/Draft_Stretch.svg b/src/Mod/Draft/Resources/icons/Draft_Stretch.svg new file mode 100644 index 000000000..cc5a62dc5 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Draft_Stretch.svg @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Mon Oct 10 13:44:52 2011 +0000 + + + [wmayer] + + + + + FreeCAD LGPL2+ + + + + + FreeCAD + + + FreeCAD/src/Mod/Draft/Resources/icons/Draft_Scale.svg + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + [agryson] Alexander Gryson + + + + + square + arrow + dotted line + + + + A small square in the bottom left corner of a large dotted box ith an arrow pointing from the top left corner of the inner box to the top left corner of the outer box + + + +