Draft: Improvements to Trimex tool - fixes #1598

* Autotrim 2 intersecting draft lines, wires or arcs
* Don't snap if CTRL is not pressed
* Allow to trim/extend against itself
This commit is contained in:
Yorik van Havre 2015-01-19 13:49:33 -02:00
parent ca0fb1480e
commit a91fcc681c
3 changed files with 107 additions and 8 deletions

View File

@ -2663,17 +2663,24 @@ class Trimex(Modifier):
self.placement = None
self.ghost = None
self.linetrack = None
self.color = None
self.width = None
if self.ui:
if not FreeCADGui.Selection.getSelection():
self.ui.selectUi()
msg(translate("draft", "Select an object to trim/extend\n"))
msg(translate("draft", "Select object(s) to trim/extend\n"))
self.call = self.view.addEventCallback("SoEvent",selectObject)
else:
self.proceed()
def proceed(self):
if self.call: self.view.removeEventCallback("SoEvent",self.call)
self.obj = FreeCADGui.Selection.getSelection()[0]
sel = FreeCADGui.Selection.getSelection()
if len(sel) == 2:
self.trimObjects(sel)
self.finish()
return
self.obj = sel[0]
self.ui.trimUi()
self.linetrack = lineTracker()
@ -2703,7 +2710,11 @@ class Trimex(Modifier):
self.ghost.append(lineTracker())
else:
# normal wire trimex mode
self.obj.ViewObject.Visibility = False
self.color = self.obj.ViewObject.LineColor
self.width = self.obj.ViewObject.LineWidth
#self.obj.ViewObject.Visibility = False
self.obj.ViewObject.LineColor = (.5,.5,.5)
self.obj.ViewObject.LineWidth = 1
self.extrudeMode = False
if self.obj.Shape.Wires:
self.edges = self.obj.Shape.Wires[0].Edges
@ -2711,9 +2722,9 @@ class Trimex(Modifier):
else:
self.edges = self.obj.Shape.Edges
self.ghost = []
lc = self.obj.ViewObject.LineColor
lc = self.color
sc = (lc[0],lc[1],lc[2])
sw = self.obj.ViewObject.LineWidth
sw = self.width
for e in self.edges:
if DraftGeomUtils.geomType(e) == "Line":
self.ghost.append(lineTracker(scolor=sc,swidth=sw))
@ -2738,8 +2749,11 @@ class Trimex(Modifier):
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
self.shift = hasMod(arg,MODCONSTRAIN)
self.alt = hasMod(arg,MODALT)
self.ctrl = hasMod(arg,MODSNAP)
if self.extrudeMode:
arg["ShiftDown"] = False
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.setSelectMode(not self.ctrl)
wp = not(self.extrudeMode and self.shift)
self.point,cp,info = getPoint(self,arg,workingplane=wp)
if hasMod(arg,MODSNAP): self.snapped = None
@ -2954,6 +2968,73 @@ class Trimex(Modifier):
self.doc.recompute()
for g in self.ghost: g.off()
def trimObjects(self,objectslist):
"attempts to trim two objects together"
import Part
wires = []
for obj in objectslist:
if not Draft.getType(obj) in ["Wire","Circle"]:
msg(translate("draft","Unable to trim these objects, only Draft wires and arcs are supported\n"),"error")
return
if len (obj.Shape.Wires) > 1:
msg(translate("draft","Unable to trim these objects, too many wires\n"),"error")
return
if len(obj.Shape.Wires) == 1:
wires.append(obj.Shape.Wires[0])
else:
wires.append(Part.Wire(obj.Shape.Edges))
ints = []
edge1 = None
edge2 = None
for i1,e1 in enumerate(wires[0].Edges):
for i2,e2 in enumerate(wires[1].Edges):
i = DraftGeomUtils.findIntersection(e1,e2,dts=False)
if len(i) == 1:
ints.append(i[0])
edge1 = i1
edge2 = i2
if not ints:
msg(translate("draft","These objects don't intersect\n"),"error")
return
if len(ints) != 1:
msg(translate("draft","Too many intersection points\n"),"error")
return
v11 = wires[0].Vertexes[0].Point
v12 = wires[0].Vertexes[-1].Point
v21 = wires[1].Vertexes[0].Point
v22 = wires[1].Vertexes[-1].Point
if DraftVecUtils.closest(ints[0],[v11,v12]) == 1:
last1 = True
else:
last1 = False
if DraftVecUtils.closest(ints[0],[v21,v22]) == 1:
last2 = True
else:
last2 = False
for i,obj in enumerate(objectslist):
if i == 0:
ed = edge1
la = last1
else:
ed = edge2
la = last2
if Draft.getType(obj) == "Wire":
if la:
pts = obj.Points[:ed+1] + ints
else:
pts = ints + obj.Points[ed+1:]
obj.Points = pts
else:
vec = ints[0].sub(obj.Placement.Base)
vec = obj.Placement.inverse().Rotation.multVec(vec)
ang = math.degrees(-DraftVecUtils.angle(vec,obj.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)),obj.Shape.Edges[0].Curve.Axis))
if la:
obj.LastAngle = ang
else:
obj.FirstAngle = ang
self.doc.recompute()
def finish(self,closed=False):
Modifier.finish(self)
self.force = None
@ -2963,7 +3044,12 @@ class Trimex(Modifier):
if self.ghost:
for g in self.ghost:
g.finalize()
if self.obj:
self.obj.ViewObject.Visibility = True
if self.color:
self.obj.ViewObject.LineColor = self.color
if self.width:
self.obj.ViewObject.LineWidth = self.width
Draft.select(self.obj)
def numericRadius(self,dist):

View File

@ -131,12 +131,12 @@ class snapTracker(Tracker):
class lineTracker(Tracker):
"A Line tracker, used by the tools that need to draw temporary lines"
def __init__(self,dotted=False,scolor=None,swidth=None):
def __init__(self,dotted=False,scolor=None,swidth=None,ontop=False):
line = coin.SoLineSet()
line.numVertices.setValue(2)
self.coords = coin.SoCoordinate3() # this is the coordinate
self.coords.point.setValues(0,2,[[0,0,0],[1,0,0]])
Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line])
Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line],ontop)
def p1(self,point=None):
"sets or gets the first point of the line"

View File

@ -188,6 +188,19 @@ def find(vector,vlist):
return i
return None
def closest(vector,vlist):
'''closest(vector,vlist): finds the closest vector to the given vector
in a list of vectors'''
typecheck ([(vector,Vector), (vlist,list)], "closest")
dist = 9999999999999999
index = None
for i,v in enumerate(vlist):
d = vector.sub(v).Length
if d < dist:
dist = d
index = i
return index
def isColinear(vlist):
'''isColinear(list_of_vectors): checks if vectors in given list are colinear'''
typecheck ([(vlist,list)], "isColinear");