Draft: Added stretch tool - fixes #1163
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<file>icons/Draft_Grid.svg</file>
|
||||
<file>icons/Draft_Slope.svg</file>
|
||||
<file>icons/DraftWorkbench.svg</file>
|
||||
<file>icons/Draft_Stretch.svg</file>
|
||||
<file>patterns/concrete.svg</file>
|
||||
<file>patterns/cross.svg</file>
|
||||
<file>patterns/line.svg</file>
|
||||
|
||||
276
src/Mod/Draft/Resources/icons/Draft_Stretch.svg
Normal file
276
src/Mod/Draft/Resources/icons/Draft_Stretch.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 11 KiB |
Reference in New Issue
Block a user