Separate Draft Edit

My last attempt to separate draft edit. Everything seems to work fine.
This commit is contained in:
carlopav
2019-06-09 20:42:50 +02:00
committed by Yorik van Havre
parent 7065ce27a6
commit 555d04c221
3 changed files with 1070 additions and 868 deletions

1061
src/Mod/Draft/DraftEdit.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,8 @@ from DraftSnap import *
from DraftTrackers import *
from pivy import coin
import DraftEdit
#---------------------------------------------------------------------------
# Preflight stuff
#---------------------------------------------------------------------------
@@ -4508,873 +4510,6 @@ class EditImproved(Modifier):
# This can occur if objects have had graph changing operations
pass
class Edit(Modifier):
"The Draft_Edit FreeCAD command definition"
def __init__(self):
self.running = False
self.trackers = []
self.obj = None
self.call = None
self.selectstate = None
self.originalDisplayMode = None
self.originalPoints = None
self.originalNodes = None
def GetResources(self):
return {'Pixmap' : 'Draft_Edit',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edit"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edits the active object")}
def Activated(self):
if self.running:
self.finish()
Modifier.Activated(self,"Edit")
if FreeCADGui.Selection.getSelection():
self.selection = FreeCADGui.Selection.getSelection()
if len(self.selection) == 1:
if "Proxy" in self.selection[0].PropertiesList:
if hasattr(self.selection[0].Proxy,"Type"):
if Draft.getType(self.selection[0]) in ["BezCurve","Wire","BSpline","Circle","Rectangle",
"Polygon","Dimension","Space","Structure","PanelCut",
"PanelSheet","Wall", "Window"]:
self.proceed()
return
#ELSE:
FreeCAD.Console.PrintWarning(translate("draft", "This object type is not editable")+"\n")
self.finish()
return
else:
FreeCAD.Console.PrintWarning(translate("draft", "Please select only one object")+"\n")
self.finish()
return
else:
self.ghost = None
self.ui.selectUi()
FreeCAD.Console.PrintMessage(translate("draft", "Select a Draft object to edit")+"\n")
if self.call:
self.view.removeEventCallback("SoEvent",self.call)
self.call = self.view.addEventCallback("SoEvent",selectObject)
def proceed(self):
if self.call:
self.view.removeEventCallback("SoEvent",self.call)
self.call = None
if self.doc:
self.obj = FreeCADGui.Selection.getSelection()
if self.obj:
self.obj = self.obj[0]
if not Draft.getType(self.obj) in ["BezCurve","Wire","BSpline","Circle","Rectangle",
"Polygon","Dimension","Space","Structure","PanelCut",
"PanelSheet","Wall"]:
FreeCAD.Console.PrintWarning(translate("draft", "This object type is not editable")+"\n")
self.finish()
return
if Draft.getType(self.obj) == "Wall":
if Draft.getType(self.obj.Base) in ["Wire","Circle","Rectangle",
"Polygon"]:
self.obj=self.obj.Base
if (Draft.getType(self.obj) == "BezCurve"):
self.ui.editUi("BezCurve")
else:
self.ui.editUi()
# store selectable state of the object
if hasattr(self.obj.ViewObject,"Selectable"):
self.selectstate = self.obj.ViewObject.Selectable
self.obj.ViewObject.Selectable = False
FreeCADGui.Selection.clearSelection()
self.editing = None
self.editpoints = []
self.pl = None
self.arc3Pt = False
FreeCADGui.Snapper.setSelectMode(True)
# Edit Gui setup is moved inside each kind of object
# overwrite self.obj to match the right editing target
if Draft.getType(self.obj) == "Wall":
if Draft.getType(self.obj.Base) in ["Wire","Circle","Rectangle",
"Polygon"]:
self.obj=self.obj.Base
if "Placement" in self.obj.PropertiesList:
self.pl = self.obj.Placement
self.invpl = self.pl.inverse()
# setup of different object type (set editUi, set editTrackers)
if Draft.getType(self.obj) in ["Wire","BSpline"]:
self.ui.editUi("Wire")
for p in self.obj.Points:
if self.pl: p = self.pl.multVec(p)
self.editpoints.append(p)
elif Draft.getType(self.obj) == "BezCurve":
self.ui.editUi("BezCurve")
self.resetTrackersBezier()
self.call = self.view.addEventCallback("SoEvent",self.action)
self.running = True
plane.save()
if "Shape" in self.obj.PropertiesList:
plane.alignToFace(self.obj.Shape)
if self.planetrack:
self.planetrack.set(self.obj.Shape.Edges[0].Curve.\
getPole(1))
elif Draft.getType(self.obj) == "Circle":
self.setCirclePts()
elif Draft.getType(self.obj) == "Rectangle":
self.ui.editUi()
self.editpoints.append(self.obj.Placement.Base)
self.editpoints.append(self.obj.Shape.Vertexes[2].Point)
v = self.obj.Shape.Vertexes
self.bx = v[1].Point.sub(v[0].Point)
if self.obj.Length < 0:
self.bx = self.bx.negative()
self.by = v[2].Point.sub(v[1].Point)
if self.obj.Height < 0:
self.by = self.by.negative()
elif Draft.getType(self.obj) == "Polygon":
self.ui.editUi()
self.editpoints.append(self.obj.Placement.Base)
self.editpoints.append(self.obj.Shape.Vertexes[0].Point)
elif Draft.getType(self.obj) == "Dimension":
self.ui.editUi()
p = self.obj.ViewObject.Proxy.textpos.translation.getValue()
self.editpoints.append(self.obj.Start)
self.editpoints.append(self.obj.End)
self.editpoints.append(self.obj.Dimline)
self.editpoints.append(Vector(p[0],p[1],p[2]))
elif Draft.getType(self.obj) == "Wall":
self.ui.editUi()
if Draft.getType(self.obj.Base) == "Sketch":
if self.obj.Base.GeometryCount == 1:
self.editpoints.append(self.obj.Base.getPoint(0,1))
self.editpoints.append(self.obj.Base.getPoint(0,2))
else:
FreeCAD.Console.PrintWarning(translate("draft","Wall base sketch is too complex to edit. Please edit the sketch directly")+"\n")
elif Draft.getType(self.obj) == "Window":
#print("Window was found")
self.ui.editUi()
import DraftGeomUtils
pos=self.obj.Base.Placement.Base
h=float(self.obj.Height)+pos.z
normal=self.obj.Normal
angle=normal.getAngle(FreeCAD.Vector(1,0,0))
self.editpoints.append(pos)
self.editpoints.append(FreeCAD.Vector(pos.x+float(self.obj.Width)*math.cos(angle-math.pi/2),
pos.y+float(self.obj.Width)*math.sin(angle-math.pi/2),
pos.z))
self.editpoints.append(FreeCAD.Vector(pos.x,pos.y,h))
elif Draft.getType(self.obj) == "Space":
self.ui.editUi()
try:
self.editpoints.append(self.obj.ViewObject.Proxy.getTextPosition(self.obj.ViewObject))
except:
pass
elif Draft.getType(self.obj) == "Structure":
self.ui.editUi()
if self.obj.Nodes:
self.originalDisplayMode = self.obj.ViewObject.DisplayMode
self.originalPoints = self.obj.ViewObject.NodeSize
self.originalNodes = self.obj.ViewObject.ShowNodes
self.obj.ViewObject.DisplayMode = "Wireframe"
self.obj.ViewObject.NodeSize = 1
self.obj.ViewObject.ShowNodes = True
for p in self.obj.Nodes:
if self.pl:
p = self.pl.multVec(p)
self.editpoints.append(p)
elif Draft.getType(self.obj) == "PanelCut":
self.ui.editUi()
if self.obj.TagPosition.Length == 0:
pos = self.obj.Shape.BoundBox.Center
else:
pos = self.pl.multVec(self.obj.TagPosition)
self.editpoints.append(pos)
elif Draft.getType(self.obj) == "PanelSheet":
self.ui.editUi()
self.editpoints.append(self.pl.multVec(self.obj.TagPosition))
for o in self.obj.Group:
self.editpoints.append(self.pl.multVec(o.Placement.Base))
elif Draft.getType(self.obj) == "Wall":
if Draft.getType(self.obj.Base) == "Sketch":
if self.obj.Base.GeometryCount == 1:
self.editpoints.append(self.obj.Base.getPoint(0,1))
self.editpoints.append(self.obj.Base.getPoint(0,2))
else:
FreeCAD.Console.PrintWarning(translate("draft","Wall base sketch is too complex to edit. Please edit the sketch directly")+"\n")
if Draft.getType(self.obj) != "BezCurve":
self.trackers = []
if self.editpoints:
for ep in range(len(self.editpoints)):
self.trackers.append(editTracker(self.editpoints[ep],self.obj.Name,ep))
self.call = self.view.addEventCallback("SoEvent",self.action)
self.running = True
plane.save()
if "Shape" in self.obj.PropertiesList:
if plane.weak:
plane.alignToFace(self.obj.Shape)
if self.planetrack:
self.planetrack.set(self.editpoints[0])
else:
FreeCAD.Console.PrintWarning(translate("draft", "This object type is not editable")+"\n")
self.finish()
else:
self.finish()
def finish(self,closed=False):
"terminates the operation"
FreeCADGui.Snapper.setSelectMode(False)
if self.obj and closed:
if "Closed" in self.obj.PropertiesList:
if not self.obj.Closed:
self.obj.Closed = True
if self.ui:
if self.trackers:
for t in self.trackers:
t.finalize()
if self.obj:
if hasattr(self.obj.ViewObject,"Selectable") and (self.selectstate != None):
self.obj.ViewObject.Selectable = self.selectstate
if Draft.getType(self.obj) == "Structure":
if self.originalDisplayMode != None:
self.obj.ViewObject.DisplayMode = self.originalDisplayMode
if self.originalPoints != None:
self.obj.ViewObject.NodeSize = self.originalPoints
if self.originalNodes != None:
self.obj.ViewObject.ShowNodes = self.originalNodes
self.selectstate = None
self.originalDisplayMode = None
self.originalPoints = None
self.originalNodes = None
Modifier.finish(self)
plane.restore()
if FreeCADGui.Snapper.grid:
FreeCADGui.Snapper.grid.set()
self.running = False
# following line causes crash
# FreeCADGui.ActiveDocument.resetEdit()
def action(self,arg):
"scene event handler"
if arg["Type"] == "SoKeyboardEvent":
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Key"] == "f":
self.finish()
elif arg["Key"] == "c":
self.finish(closed=True)
elif arg["Key"] == "i":
if (arg["State"] == "DOWN") and Draft.getType(self.obj) == "Circle":
self.arcInvert()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
self.point,ctrlPoint,info = getPoint(self,arg)
if self.editing != None:
self.trackers[self.editing].set(self.point)
# commented out the following line to disable updating
# the object during edit, otherwise it confuses the snapper
#self.update(self.trackers[self.editing].get())
if hasattr(self.obj.ViewObject,"Selectable"):
if self.ui.addButton.isChecked():
self.obj.ViewObject.Selectable = True
else:
self.obj.ViewObject.Selectable = False
redraw3DView()
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
self.ui.redraw()
if self.editing == None:
p = FreeCADGui.ActiveDocument.ActiveView.getCursorPos()
done = False
selobjs = FreeCADGui.ActiveDocument.ActiveView.getObjectsInfo(p)
if not selobjs:
selobjs = [FreeCADGui.ActiveDocument.ActiveView.getObjectInfo(p)]
if not selobjs or selobjs == [None]:
return
for info in selobjs:
if info["Object"] == self.obj.Name:
if done:
return
if self.ui.addButton.isChecked() \
and Draft.getType(self.obj) == "Wire" \
and 'Edge' in info["Component"]:
self.addPointOnEdge(FreeCAD.Vector(info["x"],info["y"],info["z"]), int(info["Component"][4:]))
done = True
elif self.ui.addButton.isChecked():
if self.point:
pt = self.point
if "x" in info:
# prefer "real" 3D location over working-plane-driven one if possible
pt = FreeCAD.Vector(info["x"],info["y"],info["z"])
self.addPoint(pt,info)
done = True
ep = None
if ('EditNode' in info["Component"]):#True as a result of getObjectInfo
ep = int(info["Component"][8:])
elif ('Vertex' in info["Component"]):# if vertex is clicked, the edit point is selected only if (distance < tolerance)
p = FreeCAD.Vector(info["x"],info["y"],info["z"])
for i,t in enumerate(self.trackers):
if (t.get().sub(p)).Length <= 0.01:
ep = i
break
elif ('Edge' in info["Component"]) or ('Face' in info["Component"]) : # if edge is clicked, the nearest edit point is selected, then tolerance is verified
p = FreeCAD.Vector(info["x"],info["y"],info["z"])
d = 1000000.0
for i,t in enumerate(self.trackers):
if (t.get().sub(p)).Length < d:
d = (t.get().sub(p)).Length
ep = i
if d > 20:# should find a way to link the tolerance to zoom
return
if ep != None:
if self.ui.delButton.isChecked():
self.delPoint(ep)
# don't do tan/sym on DWire/BSpline!
elif ((Draft.getType(self.obj) == "BezCurve") and
(self.ui.sharpButton.isChecked())):
self.smoothBezPoint(ep, info, 'Sharp')
elif ((Draft.getType(self.obj) == "BezCurve") and
(self.ui.tangentButton.isChecked())):
self.smoothBezPoint(ep, info, 'Tangent')
elif ((Draft.getType(self.obj) == "BezCurve") and
(self.ui.symmetricButton.isChecked())):
self.smoothBezPoint(ep, info, 'Symmetric')
else:
if self.ui.arc3PtButton.isChecked():
self.arc3Pt = True # store arc 3 points edit mode
else:
self.arc3Pt = False # decide if it's deselected after every editing point
self.ui.pointUi()
self.ui.isRelative.show()
self.editing = ep
self.trackers[self.editing].off()
if hasattr(self.obj.ViewObject,"Selectable"):
self.obj.ViewObject.Selectable = False
self.node.append(self.trackers[self.editing].get())
FreeCADGui.Snapper.setSelectMode(False)
done = True
else:
self.trackers[self.editing].on()
#if hasattr(self.obj.ViewObject,"Selectable"):
# self.obj.ViewObject.Selectable = True
FreeCADGui.Snapper.setSelectMode(True)
self.numericInput(self.trackers[self.editing].get())
def update(self,v):
self.doc.openTransaction("Edit")
if Draft.getType(self.obj) in ["Wire","BSpline","BezCurve"]:
pts = self.obj.Points
editPnt = self.invpl.multVec(v)
# DNC: allows to close the curve by placing ends close to each other
tol = 0.001
if ( ( self.editing == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or ( self.editing == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol):
self.obj.Closed = True
# DNC: fix error message if edited point coincides with one of the existing points
if ( editPnt in pts ) == False:
if Draft.getType(self.obj) in ["BezCurve"]:
knot = None
ispole = self.editing % self.obj.Degree #
if ispole == 0: #knot
if self.obj.Degree >=3:
if self.editing >= 1: #move left pole
knotidx = self.editing if self.editing < len(pts) else 0
pts[self.editing-1] = pts[self.editing-1] + \
editPnt - pts[knotidx]
self.trackers[self.editing-1].set(\
pts[self.editing-1])
if self.editing < len(pts)-1: #move right pole
pts[self.editing+1] = pts[self.editing+1] + \
editPnt - pts[self.editing]
self.trackers[self.editing+1].set(\
pts[self.editing+1])
if self.editing == 0 and self.obj.Closed: # move last pole
pts[-1] = pts [-1] + editPnt -pts[self.editing]
self.trackers[-1].set(pts[-1])
elif ispole == 1 and (self.editing >=2 or self.obj.Closed): #right pole
knot = self.editing -1
changep = self.editing -2 # -1 in case of closed curve
elif ispole == self.obj.Degree-1 and \
self.editing <= len(pts)-3: #left pole
knot = self.editing +1
changep = self.editing +2
elif ispole == self.obj.Degree-1 and self.obj.Closed and \
self.editing == len(pts)-1: #last pole
knot = 0
changep = 1
if knot is not None: # we need to modify the opposite pole
segment = int(knot / self.obj.Degree) -1
cont=self.obj.Continuity[segment] if \
len(self.obj.Continuity) > segment else 0
if cont == 1: #tangent
pts[changep] = self.obj.Proxy.modifytangentpole(\
pts[knot],editPnt,pts[changep])
self.trackers[changep].set(pts[changep])
elif cont ==2: #symmetric
pts[changep] = self.obj.Proxy.modifysymmetricpole(\
pts[knot],editPnt)
self.trackers[changep].set(pts[changep])
# check that the new point lies on the plane of the wire
import DraftGeomUtils
if self.obj.Closed:
n = DraftGeomUtils.getNormal(self.obj.Shape)
dv = editPnt.sub(pts[self.editing])
rn = DraftVecUtils.project(dv,n)
if dv.Length:
editPnt = editPnt.add(rn.negative())
pts[self.editing] = editPnt
self.obj.Points = pts
self.trackers[self.editing].set(v)
elif Draft.getType(self.obj) == "Circle":
self.updateCircle(v)
elif Draft.getType(self.obj) == "Rectangle":
delta = v.sub(self.obj.Placement.Base)
if self.editing == 0:
p = self.obj.Placement
p.move(delta)
self.obj.Placement = p
elif self.editing == 1:
diag = v.sub(self.obj.Placement.Base)
nx = DraftVecUtils.project(diag,self.bx)
ny = DraftVecUtils.project(diag,self.by)
ax = nx.Length
ay = ny.Length
if ax and ay:
if abs(nx.getAngle(self.bx)) > 0.1:
ax = -ax
if abs(ny.getAngle(self.by)) > 0.1:
ay = -ay
self.obj.Length = ax
self.obj.Height = ay
self.obj.recompute()
self.trackers[0].set(self.obj.Placement.Base)
self.trackers[1].set(self.obj.Shape.Vertexes[2].Point)
elif Draft.getType(self.obj) == "Polygon":
delta = v.sub(self.obj.Placement.Base)
if self.editing == 0:
p = self.obj.Placement
p.move(delta)
self.obj.Placement = p
self.trackers[0].set(self.obj.Placement.Base)
elif self.editing == 1:
if self.obj.DrawMode == 'inscribed':
self.obj.Radius = delta.Length
else:
halfangle = ((math.pi*2)/self.obj.FacesNumber)/2
rad = math.cos(halfangle)*delta.Length
self.obj.Radius = rad
self.obj.recompute()
self.trackers[1].set(self.obj.Shape.Vertexes[0].Point)
elif Draft.getType(self.obj) == "Dimension":
if self.editing == 0:
self.obj.Start = v
elif self.editing == 1:
self.obj.End = v
elif self.editing == 2:
self.obj.Dimline = v
elif self.editing == 3:
self.obj.ViewObject.TextPosition = v
elif Draft.getType(self.obj) == "Wall":
if self.editing == 0:
self.obj.Base.movePoint(0,1,v)
self.obj.Base.recompute()
if self.editing == 1:
self.obj.Base.movePoint(0,2,v)
self.obj.Base.recompute()
self.obj.recompute()
elif Draft.getType(self.obj) == "Window":
pos=self.obj.Base.Placement.Base
if self.editing == 0:
self.obj.Base.Placement.Base=v
self.obj.Base.recompute()
if self.editing == 1:
self.obj.Width = pos.sub(v).Length
self.obj.Base.recompute()
if self.editing == 2:
self.obj.Height = pos.sub(v).Length
self.obj.Base.recompute()
for obj in self.obj.Hosts:
obj.recompute()
self.obj.recompute()
elif Draft.getType(self.obj) == "Space":
if self.editing == 0:
self.obj.ViewObject.TextPosition = v
elif Draft.getType(self.obj) == "Structure":
nodes = self.obj.Nodes
nodes[self.editing] = self.invpl.multVec(v)
self.obj.Nodes = nodes
elif Draft.getType(self.obj) == "PanelCut":
if self.editing == 0:
self.obj.TagPosition = self.invpl.multVec(v)
elif Draft.getType(self.obj) == "PanelSheet":
if self.editing == 0:
self.obj.TagPosition = self.invpl.multVec(v)
else:
self.obj.Group[self.editing-1].Placement.Base = self.invpl.multVec(v)
self.doc.commitTransaction()
try:
FreeCADGui.ActiveDocument.ActiveView.redraw()
except AttributeError as err:
pass
def setCirclePts(self):
self.editpoints.clear()
self.editpoints.append(self.obj.Placement.Base)
if self.obj.FirstAngle == self.obj.LastAngle:#self.obj is a circle
self.ui.editUi("Circle")
self.editpoints.append(self.obj.Shape.Vertexes[0].Point)
else:#self.obj is an arc
self.ui.editUi("Arc")
self.editpoints.append(self.obj.Shape.Vertexes[0].Point)#First endpoint
self.editpoints.append(self.obj.Shape.Vertexes[1].Point)#Second endpoint
self.editpoints.append(self.getArcMid())#Midpoint
def updateCirclePts(self,ep1=1,ep2=1,ep3=1,ep4=1):
self.obj.recompute()
if ep1 == 1:
self.trackers[0].set(self.obj.Placement.Base)
if ep2 == 1:
self.trackers[1].set(self.obj.Shape.Vertexes[0].Point)
if ep3 == 1:
self.trackers[2].set(self.obj.Shape.Vertexes[1].Point)
if ep4 == 1:
self.trackers[3].set(self.getArcMid())
def updateCircle(self,v):
delta = v.sub(self.obj.Placement.Base)
if self.obj.FirstAngle == self.obj.LastAngle:# object is a circle
if self.editing == 0:
p = self.obj.Placement
p.move(delta)
self.obj.Placement = p
self.updateCirclePts(0,1,0,0)
if self.editing == 1:
self.obj.Radius = delta.Length
self.updateCirclePts(0,0,0,0)
else:#self.obj is an arc
if self.arc3Pt == True:#edit by center radius FirstAngle LastAngle
deltaX = v[0]-self.obj.Placement.Base[0]
deltaY = v[1]-self.obj.Placement.Base[1]
dangle = math.degrees(math.atan2(deltaY,deltaX))
if self.editing == 0:
p = self.obj.Placement
p.move(delta)
self.obj.Placement = p
self.updateCirclePts(0,1,1,1)
elif self.editing == 1:
self.obj.FirstAngle=dangle
self.obj.recompute()
self.updateCirclePts(0,1,0,1)
elif self.editing == 2:
self.obj.LastAngle=dangle
self.obj.recompute()
self.updateCirclePts(0,0,1,1)
elif self.editing == 3:
self.obj.Radius = delta.Length
self.obj.recompute()
self.updateCirclePts(0,1,1,1)
elif self.arc3Pt == False:
if self.editing == 0:#center point
import DraftVecUtils
p1 = self.obj.Shape.Vertexes[0].Point
p2 = self.obj.Shape.Vertexes[1].Point
p0 = DraftVecUtils.project(delta,self.getArcMid().sub(self.obj.Placement.Base))
p0 = p0.add(self.obj.Placement.Base)
self.obj.Placement.Base = p0
self.obj.Radius = p1.sub(p0).Length
self.obj.FirstAngle = -math.degrees(DraftVecUtils.angle(p1.sub(p0)))
self.obj.LastAngle = -math.degrees(DraftVecUtils.angle(p2.sub(p0)))
self.updateCirclePts(1,0,0,1)
return
else:
if self.editing == 1:#first point
p1=v
p2=self.getArcMid()
p3=self.obj.Shape.Vertexes[1].Point
elif self.editing == 3:#midpoint
p1=self.obj.Shape.Vertexes[0].Point
p2=v
p3=self.obj.Shape.Vertexes[1].Point
elif self.editing == 2:#second point
p1=self.obj.Shape.Vertexes[0].Point
p2=self.getArcMid()
p3=v
arc=Part.ArcOfCircle(p1,p2,p3)#object is a support, do i have to delete it someway after?
self.obj.Placement.Base=arc.Center
self.obj.Radius = arc.Radius
deltaX = p1[0]-self.obj.Placement.Base[0]
deltaY = p1[1]-self.obj.Placement.Base[1]
dangleF = math.degrees(math.atan2(deltaY,deltaX))
deltaX = p3[0]-self.obj.Placement.Base[0]
deltaY = p3[1]-self.obj.Placement.Base[1]
dangleL = math.degrees(math.atan2(deltaY,deltaX))
self.obj.FirstAngle = dangleF
self.obj.LastAngle = dangleL
self.updateCirclePts()
def getArcMid(self):#Returns object midpoint
if Draft.getType(self.obj) == "Circle":
if self.obj.LastAngle>self.obj.FirstAngle:
midAngle=math.radians(self.obj.FirstAngle+(self.obj.LastAngle-self.obj.FirstAngle)/2)
else:
midAngle=math.radians(self.obj.FirstAngle+(self.obj.LastAngle-self.obj.FirstAngle)/2)+math.pi
midRadX=self.obj.Radius*math.cos(midAngle)
midRadY=self.obj.Radius*math.sin(midAngle)
deltaMid=FreeCAD.Vector(midRadX,midRadY,0)
midPoint=(self.obj.Placement.Base+deltaMid)
return(midPoint)
elif Draft.getType(self.obj) == "Wall":
if self.obj.Base.GeometryCount == 1:
print("wall edit mode: get midpoint")
else:
print("Failed to get object midpoint during Editing")
def arcInvert(self):
FA=self.obj.FirstAngle
self.obj.FirstAngle=self.obj.LastAngle
self.obj.LastAngle=FA
self.obj.recompute()
self.trackers[1].set(self.obj.Shape.Vertexes[0].Point)
self.trackers[2].set(self.obj.Shape.Vertexes[1].Point)
self.trackers[3].set(self.getArcMid())
def numericInput(self,v,numy=None,numz=None):
'''this function gets called by the toolbar
when valid x, y, and z have been entered there'''
if (numy != None):
v = Vector(v,numy,numz)
self.update(v)
self.doc.recompute()
self.editing = None
self.ui.editUi(self.ui.lastMode)
self.node = []
def addPointOnEdge(self, newPoint, edgeIndex):
newPoints = []
hasAddedPoint = False
for index, point in enumerate(self.obj.Points):
if index == edgeIndex:
hasAddedPoint = True
newPoints.append(self.invpl.multVec(newPoint))
newPoints.append(point)
if not hasAddedPoint:
newPoints.append(point)
self.obj.Points = newPoints
self.doc.recompute()
self.resetTrackers()
def addPoint(self,point,info=None):
if not (Draft.getType(self.obj) in ["BSpline","BezCurve"]): return
pts = self.obj.Points
if Draft.getType(self.obj) == "BezCurve":
if not info['Component'].startswith('Edge'):
return # clicked control point
edgeindex = int(info['Component'].lstrip('Edge'))-1
wire=self.obj.Shape.Wires[0]
bz=wire.Edges[edgeindex].Curve
param=bz.parameter(point)
seg1=wire.Edges[edgeindex].copy().Curve
seg2=wire.Edges[edgeindex].copy().Curve
seg1.segment(seg1.FirstParameter,param)
seg2.segment(param,seg2.LastParameter)
if edgeindex == len(wire.Edges):
#we hit the last segment, we need to fix the degree
degree=wire.Edges[0].Curve.Degree
seg1.increase(degree)
seg2.increase(degree)
edges=wire.Edges[0:edgeindex]+[Part.Edge(seg1),Part.Edge(seg2)]\
+ wire.Edges[edgeindex+1:]
pts = edges[0].Curve.getPoles()[0:1]
for edge in edges:
pts.extend(edge.Curve.getPoles()[1:])
if self.obj.Closed:
pts.pop()
c=self.obj.Continuity
# assume we have a tangent continuity for an arbitrarily split
# segment, unless it's linear
cont = 1 if (self.obj.Degree >= 2) else 0
self.obj.Continuity = c[0:edgeindex]+[cont]+c[edgeindex:]
else:
if ( Draft.getType(self.obj) in ["BSpline"]):
if (self.obj.Closed == True):
curve = self.obj.Shape.Edges[0].Curve
else:
curve = self.obj.Shape.Curve
uNewPoint = curve.parameter(point)
uPoints = []
for p in self.obj.Points:
uPoints.append(curve.parameter(p))
for i in range(len(uPoints)-1):
if ( uNewPoint > uPoints[i] ) and ( uNewPoint < uPoints[i+1] ):
pts.insert(i+1, self.invpl.multVec(point))
break
# DNC: fix: add points to last segment if curve is closed
if ( self.obj.Closed ) and ( uNewPoint > uPoints[-1] ) :
pts.append(self.invpl.multVec(point))
self.obj.Points = pts
self.doc.recompute()
self.resetTrackers()
def delPoint(self,point):
if not (Draft.getType(self.obj) in ["Wire","BSpline","BezCurve"]): return
if len(self.obj.Points) <= 2:
FreeCAD.Console.PrintWarning(translate("draft", "Active object must have more than two points/nodes")+"\n")
else:
pts = self.obj.Points
pts.pop(point)
self.obj.Points = pts
if Draft.getType(self.obj) =="BezCurve":
self.obj.Proxy.resetcontinuity(self.obj)
self.doc.recompute()
self.resetTrackers()
def smoothBezPoint(self,point, info=None, style='Symmetric'):
style2cont = {'Sharp':0,'Tangent':1,'Symmetric':2}
if not (Draft.getType(self.obj) == "BezCurve"):return
if info['Component'].startswith('Edge'):
return # didn't click control point
pts = self.obj.Points
deg = self.obj.Degree
if deg < 2: return
if point % deg != 0: #point is a pole
if deg >=3: #allow to select poles
if (point % deg == 1) and (point > 2 or self.obj.Closed): #right pole
knot = point -1
keepp = point
changep = point -2
elif point < len(pts) -3 and point % deg == deg -1: #left pole
knot = point +1
keepp = point
changep = point +2
elif point == len(pts)-1 and self.obj.Closed: #last pole
# if the curve is closed the last pole has the last
# index in the points lists
knot = 0
keepp = point
changep = 1
else:
FreeCAD.Console.PrintWarning(translate("draft", "Can't change Knot belonging to pole %d"%point)+"\n")
return
if knot:
if style == 'Tangent':
pts[changep] = self.obj.Proxy.modifytangentpole(\
pts[knot],pts[keepp],pts[changep])
elif style == 'Symmetric':
pts[changep] = self.obj.Proxy.modifysymmetricpole(\
pts[knot],pts[keepp])
else: #sharp
pass #
else:
FreeCAD.Console.PrintWarning(translate("draft", "Selection is not a Knot\n"))
return
else: #point is a knot
if style == 'Sharp':
if self.obj.Closed and point == len(pts)-1:
knot = 0
else:
knot = point
elif style == 'Tangent' and point > 0 and point < len(pts)-1:
prev, next = self.obj.Proxy.tangentpoles(pts[point],pts[point-1],pts[point+1])
pts[point-1] = prev
pts[point+1] = next
knot = point #index for continuity
elif style == 'Symmetric' and point > 0 and point < len(pts)-1:
prev, next = self.obj.Proxy.symmetricpoles(pts[point],pts[point-1],pts[point+1])
pts[point-1] = prev
pts[point+1] = next
knot = point #index for continuity
elif self.obj.Closed and (style == 'Symmetric' or style == 'Tangent'):
if style == 'Tangent':
pts[1],pts[-1] = self.obj.Proxy.tangentpoles(pts[0],pts[1],pts[-1])
elif style == 'Symmetric':
pts[1],pts[-1] = self.obj.Proxy.symmetricpoles(pts[0],pts[1],pts[-1])
knot = 0
else:
FreeCAD.Console.PrintWarning(translate("draft", "Endpoint of BezCurve can't be smoothed")+"\n")
return
segment = knot // deg #segment index
newcont=self.obj.Continuity[:] #don't edit a property inplace !!!
if not self.obj.Closed and (len(self.obj.Continuity) == segment -1 or \
segment == 0) : pass # open curve
elif len(self.obj.Continuity) >= segment or \
self.obj.Closed and segment == 0 and \
len(self.obj.Continuity) >1:
newcont[segment-1] = style2cont.get(style)
else: #should not happen
FreeCAD.Console.PrintWarning('Continuity indexing error:'+\
'point:%d deg:%d len(cont):%d' % (knot,deg,\
len(self.obj.Continuity)))
self.obj.Points = pts
self.obj.Continuity=newcont
self.resetTrackers()
def resetTrackersBezier(self):
knotmarkers = (coin.SoMarkerSet.DIAMOND_FILLED_9_9,#sharp
coin.SoMarkerSet.SQUARE_FILLED_9_9, #tangent
coin.SoMarkerSet.HOURGLASS_FILLED_9_9) #symmetric
polemarker = coin.SoMarkerSet.CIRCLE_FILLED_9_9 #pole
self.trackers=[]
cont=self.obj.Continuity
firstknotcont = cont[-1] if (self.obj.Closed and cont) else 0
pointswithmarkers=[(self.obj.Shape.Edges[0].Curve.\
getPole(1),knotmarkers[firstknotcont])]
for edgeindex, edge in enumerate(self.obj.Shape.Edges):
poles=edge.Curve.getPoles()
pointswithmarkers.extend([(point,polemarker) for \
point in poles[1:-1]])
if not self.obj.Closed or len(self.obj.Shape.Edges) > edgeindex +1:
knotmarkeri=cont[edgeindex] if len(cont) > edgeindex else 0
pointswithmarkers.append((poles[-1],knotmarkers[knotmarkeri]))
for index,pwm in enumerate(pointswithmarkers):
p,marker=pwm
if self.pl: p = self.pl.multVec(p)
self.trackers.append(editTracker(p,self.obj.Name,\
index,self.obj.ViewObject.LineColor,\
marker=marker))
def resetTrackers(self):
for t in self.trackers:
t.finalize()
self.trackers = []
if Draft.getType(self.obj) == "BezCurve":
self.resetTrackersBezier()
else:
for ep in range(len(self.obj.Points)):
objPoints = self.obj.Points[ep]
if self.pl: objPoints = self.pl.multVec(objPoints)
self.trackers.append(editTracker(objPoints,self.obj.Name,ep,self.obj.ViewObject.LineColor))
class AddToGroup():
"The AddToGroup FreeCAD command definition"
@@ -6687,7 +5822,7 @@ FreeCADGui.addCommand('Draft_Downgrade',Downgrade())
FreeCADGui.addCommand('Draft_Trimex',Trimex())
FreeCADGui.addCommand('Draft_Scale',Scale())
FreeCADGui.addCommand('Draft_Drawing',Drawing())
FreeCADGui.addCommand('Draft_Edit',Edit())
FreeCADGui.addCommand('Draft_Edit',DraftEdit.Edit())
FreeCADGui.addCommand('Draft_Edit_Improved',EditImproved())
FreeCADGui.addCommand('Draft_AddPoint',AddPoint())
FreeCADGui.addCommand('Draft_DelPoint',DelPoint())

View File

@@ -805,6 +805,12 @@ class wireTracker(Tracker):
p = wire.Vertexes[0].Point
self.coords.point.set1Value(t,[p.x,p.y,p.z])
def updateFromPointlist(self,points,forceclosed=False):
if points:
for i in range(len(points)):
p=points[i]
self.coords.point.set1Value(i,[p.x,p.y,p.z])
class gridTracker(Tracker):
"A grid tracker"
def __init__(self):