Draft: Split Draft Edit into 4 modules
One for interaction handling and 3 for object editing functions, divided between Draft, Part, Arch
This commit is contained in:
committed by
Yorik van Havre
parent
83b708127d
commit
4e8124e415
@@ -230,6 +230,9 @@ SET(Draft_GUI_tools
|
||||
draftguitools/gui_snaps.py
|
||||
draftguitools/gui_snapper.py
|
||||
draftguitools/gui_trackers.py
|
||||
draftguitools/gui_edit_draft_objects.py
|
||||
draftguitools/gui_edit_arch_objects.py
|
||||
draftguitools/gui_edit_part_objects.py
|
||||
draftguitools/gui_edit.py
|
||||
draftguitools/gui_lineops.py
|
||||
draftguitools/gui_togglemodes.py
|
||||
|
||||
@@ -50,6 +50,10 @@ import DraftGeomUtils
|
||||
from draftutils.translate import translate
|
||||
import draftguitools.gui_trackers as trackers
|
||||
|
||||
import draftguitools.gui_edit_draft_objects as edit_draft
|
||||
import draftguitools.gui_edit_arch_objects as edit_arch
|
||||
import draftguitools.gui_edit_part_objects as edit_part
|
||||
|
||||
|
||||
COLORS = {
|
||||
"default": Gui.draftToolBar.getDefaultColor("snap"),
|
||||
@@ -431,10 +435,10 @@ class Edit(gui_base_original.Modifier):
|
||||
self.display_tracker_menu(event)
|
||||
if key == 105: # "i"
|
||||
if utils.get_type(self.obj) == "Circle":
|
||||
self.arcInvert(self.obj)
|
||||
#if key == 65535: # BUG: delete key activate Std::Delete command at the same time!
|
||||
# print("DELETE PRESSED\n")
|
||||
# self.delPoint(event)
|
||||
edit_draft.arcInvert(self.obj)
|
||||
if key == 65535 and Gui.Selection.GetSelection() is None: # BUG: delete key activate Std::Delete command at the same time!
|
||||
print("DELETE PRESSED\n")
|
||||
self.delPoint(event)
|
||||
|
||||
def mousePressed(self, event_callback):
|
||||
"""
|
||||
@@ -673,7 +677,7 @@ class Edit(gui_base_original.Modifier):
|
||||
return
|
||||
self.trackers[obj.Name] = []
|
||||
if utils.get_type(obj) == "BezCurve":
|
||||
self.resetTrackersBezier(obj)
|
||||
edit_draft.resetTrackersBezier(obj)
|
||||
else:
|
||||
if obj.Name in self.trackers:
|
||||
self.removeTrackers(obj)
|
||||
@@ -766,7 +770,7 @@ class Edit(gui_base_original.Modifier):
|
||||
elif utils.get_type(obj) == "BezCurve":
|
||||
self.ghost.on()
|
||||
plist = self.applyPlacement(obj.Points)
|
||||
pointList = self.recomputePointsBezier(obj,plist,idx,pt,obj.Degree,moveTrackers=True)
|
||||
pointList = edit_draft.recomputePointsBezier(obj,plist,idx,pt,obj.Degree,moveTrackers=True)
|
||||
self.ghost.update(pointList,obj.Degree)
|
||||
elif utils.get_type(obj) == "Circle":
|
||||
self.ghost.on()
|
||||
@@ -785,10 +789,9 @@ class Edit(gui_base_original.Modifier):
|
||||
# edit by 3 points
|
||||
if self.editing == 0:
|
||||
# center point
|
||||
import DraftVecUtils
|
||||
p1 = self.invpl.multVec(self.obj.Shape.Vertexes[0].Point)
|
||||
p2 = self.invpl.multVec(self.obj.Shape.Vertexes[1].Point)
|
||||
p0 = DraftVecUtils.project(self.invpl.multVec(pt),self.invpl.multVec(self.getArcMid(obj, global_placement=True)))
|
||||
p0 = DraftVecUtils.project(self.invpl.multVec(pt),self.invpl.multVec(edit_draft.getArcMid(obj, global_placement=True)))
|
||||
self.ghost.autoinvert=False
|
||||
self.ghost.setRadius(p1.sub(p0).Length)
|
||||
self.ghost.setStartPoint(self.obj.Shape.Vertexes[1].Point)
|
||||
@@ -796,9 +799,9 @@ class Edit(gui_base_original.Modifier):
|
||||
self.ghost.setCenter(self.pl.multVec(p0))
|
||||
return
|
||||
else:
|
||||
p1 = self.getArcStart(obj, global_placement=True)
|
||||
p2 = self.getArcMid(obj, global_placement=True)
|
||||
p3 = self.getArcEnd(obj, global_placement=True)
|
||||
p1 = edit_draft.getArcStart(obj, global_placement=True)
|
||||
p2 = edit_draft.getArcMid(obj, global_placement=True)
|
||||
p3 = edit_draft.getArcEnd(obj, global_placement=True)
|
||||
if self.editing == 1:
|
||||
p1=pt
|
||||
elif self.editing == 3:
|
||||
@@ -980,7 +983,8 @@ class Edit(gui_base_original.Modifier):
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def setEditPoints(self, obj):
|
||||
"""append given object's editpoints to self.edipoints and set EditTrackers"""
|
||||
"""Append given object's editpoints to self.edipoints and set EditTrackers
|
||||
"""
|
||||
self.setPlacement(obj)
|
||||
self.editpoints = self.getEditPoints(obj)
|
||||
if self.editpoints: # set trackers and align plane
|
||||
@@ -988,44 +992,44 @@ class Edit(gui_base_original.Modifier):
|
||||
self.editpoints = []
|
||||
|
||||
def getEditPoints(self, obj):
|
||||
"""Return a list of App.Vectors relative to object edit nodes.
|
||||
"""Return a list of App.Vectors according to the given object edit nodes.
|
||||
"""
|
||||
objectType = utils.get_type(obj)
|
||||
|
||||
if objectType in ["Wire", "BSpline"]:
|
||||
self.ui.editUi("Wire")
|
||||
return self.getWirePts(obj)
|
||||
return edit_draft.getWirePts(obj)
|
||||
elif objectType == "BezCurve":
|
||||
self.ui.editUi("BezCurve")
|
||||
self.resetTrackersBezier(obj)
|
||||
edit_draft.resetTrackersBezier(obj)
|
||||
self.editpoints = []
|
||||
return
|
||||
elif objectType == "Circle":
|
||||
return self.getCirclePts(obj)
|
||||
return edit_draft.getCirclePts(obj)
|
||||
elif objectType == "Rectangle":
|
||||
return self.getRectanglePts(obj)
|
||||
return edit_draft.getRectanglePts(obj)
|
||||
elif objectType == "Polygon":
|
||||
return self.getPolygonPts(obj)
|
||||
return edit_draft.getPolygonPts(obj)
|
||||
elif objectType in ("Dimension","LinearDimension"):
|
||||
return self.getDimensionPts(obj)
|
||||
return edit_draft.getDimensionPts(obj)
|
||||
elif objectType == "Wall":
|
||||
return self.getWallPts(obj)
|
||||
return edit_arch.getWallPts(obj)
|
||||
elif objectType == "Window":
|
||||
return self.getWindowPts(obj)
|
||||
return edit_arch.getWindowPts(obj)
|
||||
elif objectType == "Space":
|
||||
return self.getSpacePts(obj)
|
||||
return edit_arch.getSpacePts(obj)
|
||||
elif objectType == "Structure":
|
||||
return self.getStructurePts(obj)
|
||||
return edit_arch.getStructurePts(obj)
|
||||
elif objectType == "PanelCut":
|
||||
return self.getPanelCutPts(obj)
|
||||
return edit_arch.getPanelCutPts(obj)
|
||||
elif objectType == "PanelSheet":
|
||||
return self.getPanelSheetPts(obj)
|
||||
return edit_arch.getPanelSheetPts(obj)
|
||||
elif objectType == "Part" and obj.TypeId == "Part::Box":
|
||||
return self.getPartBoxPts(obj)
|
||||
return edit_part.getPartBoxPts(obj)
|
||||
elif objectType == "Part::Line" and obj.TypeId == "Part::Line":
|
||||
return self.getPartLinePts(obj)
|
||||
return edit_part.getPartLinePts(obj)
|
||||
elif objectType == "Sketch":
|
||||
return self.getSketchPts(obj)
|
||||
return edit_arch.getSketchPts(obj)
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -1036,35 +1040,35 @@ class Edit(gui_base_original.Modifier):
|
||||
App.ActiveDocument.openTransaction("Edit")
|
||||
|
||||
if objectType in ["Wire", "BSpline"]:
|
||||
self.updateWire(obj, nodeIndex, v)
|
||||
edit_draft.updateWire(obj, nodeIndex, v)
|
||||
elif objectType == "BezCurve":
|
||||
self.updateWire(obj, nodeIndex, v)
|
||||
edit_draft.updateWire(obj, nodeIndex, v)
|
||||
elif objectType == "Circle":
|
||||
self.updateCircle(obj, nodeIndex, v)
|
||||
edit_draft.updateCircle(obj, nodeIndex, v, self.alt_edit_mode)
|
||||
elif objectType == "Rectangle":
|
||||
self.updateRectangle(obj, nodeIndex, v)
|
||||
edit_draft.updateRectangle(obj, nodeIndex, v)
|
||||
elif objectType == "Polygon":
|
||||
self.updatePolygon(obj, nodeIndex, v)
|
||||
edit_draft.updatePolygon(obj, nodeIndex, v)
|
||||
elif objectType in ("Dimension","LinearDimension"):
|
||||
self.updateDimension(obj, nodeIndex, v)
|
||||
edit_draft.updateDimension(obj, nodeIndex, v)
|
||||
elif objectType == "Sketch":
|
||||
self.updateSketch(obj, nodeIndex, v)
|
||||
edit_arch.updateSketch(obj, nodeIndex, v)
|
||||
elif objectType == "Wall":
|
||||
self.updateWall(obj, nodeIndex, v)
|
||||
edit_arch.updateWall(obj, nodeIndex, v)
|
||||
elif objectType == "Window":
|
||||
self.updateWindow(obj, nodeIndex, v)
|
||||
edit_arch.updateWindow(obj, nodeIndex, v)
|
||||
elif objectType == "Space":
|
||||
self.updateSpace(obj, nodeIndex, v)
|
||||
edit_arch.updateSpace(obj, nodeIndex, v)
|
||||
elif objectType == "Structure":
|
||||
self.updateStructure(obj, nodeIndex, v)
|
||||
edit_arch.updateStructure(obj, nodeIndex, v)
|
||||
elif objectType == "PanelCut":
|
||||
self.updatePanelCut(obj, nodeIndex, v)
|
||||
edit_arch.updatePanelCut(obj, nodeIndex, v)
|
||||
elif objectType == "PanelSheet":
|
||||
self.updatePanelSheet(obj, nodeIndex, v)
|
||||
edit_arch.updatePanelSheet(obj, nodeIndex, v)
|
||||
elif objectType == "Part::Line" and self.obj.TypeId == "Part::Line":
|
||||
self.updatePartLine(obj, nodeIndex, v)
|
||||
edit_arch.updatePartLine(obj, nodeIndex, v)
|
||||
elif objectType == "Part" and self.obj.TypeId == "Part::Box":
|
||||
self.updatePartBox(obj, nodeIndex, v)
|
||||
edit_arch.updatePartBox(obj, nodeIndex, v)
|
||||
obj.recompute()
|
||||
|
||||
App.ActiveDocument.commitTransaction()
|
||||
@@ -1074,683 +1078,6 @@ class Edit(gui_base_original.Modifier):
|
||||
except AttributeError as err:
|
||||
pass
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Line/Wire/Bspline/Bezcurve
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getWirePts(self, obj):
|
||||
editpoints = []
|
||||
for p in obj.Points:
|
||||
p = obj.getGlobalPlacement().multVec(p)
|
||||
editpoints.append(p)
|
||||
return editpoints
|
||||
|
||||
def updateWire(self, obj, nodeIndex, v):
|
||||
pts = obj.Points
|
||||
editPnt = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
# DNC: allows to close the curve by placing ends close to each other
|
||||
tol = 0.001
|
||||
if ( ( nodeIndex == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or (
|
||||
nodeIndex == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol):
|
||||
obj.Closed = True
|
||||
# DNC: fix error message if edited point coincides with one of the existing points
|
||||
if ( editPnt in pts ) == True: # checks if point enter is equal to other, this could cause a OCC problem
|
||||
App.Console.PrintMessage(translate("draft",
|
||||
"This object does not support possible "
|
||||
"coincident points, please try again.")
|
||||
+ "\n")
|
||||
if utils.get_type(obj) in ["BezCurve"]:
|
||||
self.resetTrackers(obj)
|
||||
else:
|
||||
self.trackers[obj.Name][nodeIndex].set(obj.getGlobalPlacement().
|
||||
multVec(obj.Points[nodeIndex]))
|
||||
return
|
||||
if utils.get_type(obj) in ["BezCurve"]:
|
||||
pts = self.recomputePointsBezier(obj,pts,nodeIndex,v,obj.Degree,moveTrackers=False)
|
||||
|
||||
if obj.Closed:
|
||||
# check that the new point lies on the plane of the wire
|
||||
if hasattr(obj.Shape,"normalAt"):
|
||||
normal = obj.Shape.normalAt(0,0)
|
||||
point_on_plane = obj.Shape.Vertexes[0].Point
|
||||
print(v)
|
||||
v.projectToPlane(point_on_plane, normal)
|
||||
print(v)
|
||||
editPnt = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
pts[nodeIndex] = editPnt
|
||||
obj.Points = pts
|
||||
self.trackers[obj.Name][nodeIndex].set(v)
|
||||
|
||||
def recomputePointsBezier(self, obj, pts, idx, v,
|
||||
degree, moveTrackers=True):
|
||||
"""
|
||||
(object, Points as list, nodeIndex as Int, App.Vector of new point, moveTrackers as Bool)
|
||||
return the new point list, applying the App.Vector to the given index point
|
||||
"""
|
||||
editPnt = v
|
||||
# DNC: allows to close the curve by placing ends close to each other
|
||||
tol = 0.001
|
||||
if ( ( idx == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or (
|
||||
idx == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol):
|
||||
obj.Closed = True
|
||||
# DNC: fix error message if edited point coincides with one of the existing points
|
||||
#if ( editPnt in pts ) == False:
|
||||
knot = None
|
||||
ispole = idx % degree
|
||||
|
||||
if ispole == 0: #knot
|
||||
if degree >= 3:
|
||||
if idx >= 1: #move left pole
|
||||
knotidx = idx if idx < len(pts) else 0
|
||||
pts[idx-1] = pts[idx-1] + editPnt - pts[knotidx]
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][idx-1].set(pts[idx-1])
|
||||
if idx < len(pts)-1: #move right pole
|
||||
pts[idx+1] = pts[idx+1] + editPnt - pts[idx]
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][idx+1].set(pts[idx+1])
|
||||
if idx == 0 and obj.Closed: # move last pole
|
||||
pts[-1] = pts [-1] + editPnt -pts[idx]
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][-1].set(pts[-1])
|
||||
|
||||
elif ispole == 1 and (idx >=2 or obj.Closed): #right pole
|
||||
knot = idx -1
|
||||
changep = idx - 2 # -1 in case of closed curve
|
||||
|
||||
elif ispole == degree-1 and idx <= len(pts)-3: # left pole
|
||||
knot = idx + 1
|
||||
changep = idx + 2
|
||||
|
||||
elif ispole == degree-1 and obj.Closed and idx == len(pts)-1: #last pole
|
||||
knot = 0
|
||||
changep = 1
|
||||
|
||||
if knot is not None: # we need to modify the opposite pole
|
||||
segment = int(knot / degree) - 1
|
||||
cont = obj.Continuity[segment] if len(obj.Continuity) > segment else 0
|
||||
if cont == 1: #tangent
|
||||
pts[changep] = obj.Proxy.modifytangentpole(pts[knot],
|
||||
editPnt,pts[changep])
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][changep].set(pts[changep])
|
||||
elif cont == 2: #symmetric
|
||||
pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot],editPnt)
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][changep].set(pts[changep])
|
||||
pts[idx] = v
|
||||
|
||||
return pts # returns the list of new points, taking into account knot continuity
|
||||
|
||||
def resetTrackersBezier(self, obj):
|
||||
# in future move tracker definition to DraftTrackers
|
||||
from pivy import coin
|
||||
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[obj.Name] = []
|
||||
cont = obj.Continuity
|
||||
firstknotcont = cont[-1] if (obj.Closed and cont) else 0
|
||||
pointswithmarkers = [(obj.Shape.Edges[0].Curve.
|
||||
getPole(1),knotmarkers[firstknotcont])]
|
||||
for edgeindex, edge in enumerate(obj.Shape.Edges):
|
||||
poles = edge.Curve.getPoles()
|
||||
pointswithmarkers.extend([(point,polemarker) for point in poles[1:-1]])
|
||||
if not obj.Closed or len(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[obj.Name].append(trackers.editTracker(p,obj.Name,
|
||||
index,obj.ViewObject.LineColor,marker=marker))
|
||||
|
||||
def smoothBezPoint(self, obj, point, style='Symmetric'):
|
||||
"called when changing the continuity of a knot"
|
||||
style2cont = {'Sharp':0,'Tangent':1,'Symmetric':2}
|
||||
if point is None:
|
||||
return
|
||||
if not (utils.get_type(obj) == "BezCurve"):
|
||||
return
|
||||
pts = obj.Points
|
||||
deg = 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 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 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:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Can't change Knot belonging to pole %d"%point)
|
||||
+ "\n")
|
||||
return
|
||||
if knot:
|
||||
if style == 'Tangent':
|
||||
pts[changep] = obj.Proxy.modifytangentpole(pts[knot],
|
||||
pts[keepp],pts[changep])
|
||||
elif style == 'Symmetric':
|
||||
pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot],
|
||||
pts[keepp])
|
||||
else: #sharp
|
||||
pass #
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Selection is not a Knot")
|
||||
+ "\n")
|
||||
return
|
||||
else: #point is a knot
|
||||
if style == 'Sharp':
|
||||
if 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 = 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 = 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 obj.Closed and (style == 'Symmetric' or style == 'Tangent'):
|
||||
if style == 'Tangent':
|
||||
pts[1], pts[-1] = obj.Proxy.tangentpoles(pts[0], pts[1], pts[-1])
|
||||
elif style == 'Symmetric':
|
||||
pts[1], pts[-1] = obj.Proxy.symmetricpoles(pts[0], pts[1], pts[-1])
|
||||
knot = 0
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Endpoint of BezCurve can't be smoothed")
|
||||
+ "\n")
|
||||
return
|
||||
segment = knot // deg # segment index
|
||||
newcont = obj.Continuity[:] # don't edit a property inplace !!!
|
||||
if not obj.Closed and (len(obj.Continuity) == segment -1 or
|
||||
segment == 0) :
|
||||
pass # open curve
|
||||
elif (len(obj.Continuity) >= segment or obj.Closed and segment == 0 and
|
||||
len(obj.Continuity) >1):
|
||||
newcont[segment-1] = style2cont.get(style)
|
||||
else: #should not happen
|
||||
App.Console.PrintWarning('Continuity indexing error:'
|
||||
+ 'point:%d deg:%d len(cont):%d' % (knot,deg,
|
||||
len(obj.Continuity)))
|
||||
obj.Points = pts
|
||||
obj.Continuity = newcont
|
||||
self.resetTrackers(obj)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Rectangle
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getRectanglePts(self, obj):
|
||||
"""Return the list of edipoints for the given Draft Rectangle.
|
||||
|
||||
0 : Placement.Base
|
||||
1 : Length
|
||||
2 : Height
|
||||
"""
|
||||
editpoints = []
|
||||
editpoints.append(obj.getGlobalPlacement().Base)
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(obj.Length,0,0)))
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(0,obj.Height,0)))
|
||||
return editpoints
|
||||
|
||||
def updateRectangleTrackers(self, obj):
|
||||
self.trackers[obj.Name][0].set(obj.getGlobalPlacement().Base)
|
||||
self.trackers[obj.Name][1].set(obj.getGlobalPlacement().multVec(App.Vector(obj.Length,0,0)))
|
||||
self.trackers[obj.Name][2].set(obj.getGlobalPlacement().multVec(App.Vector(0,obj.Height,0)))
|
||||
|
||||
def updateRectangle(self, obj, nodeIndex, v):
|
||||
import DraftVecUtils
|
||||
delta = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
if nodeIndex == 0:
|
||||
# p = obj.getGlobalPlacement()
|
||||
# p.move(delta)
|
||||
obj.Placement.move(delta)
|
||||
elif self.editing == 1:
|
||||
obj.Length = DraftVecUtils.project(delta,App.Vector(1,0,0)).Length
|
||||
elif self.editing == 2:
|
||||
obj.Height = DraftVecUtils.project(delta,App.Vector(0,1,0)).Length
|
||||
self.updateRectangleTrackers(obj)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Ellipse (# TODO: yet to be implemented)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def setEllipsePts(self):
|
||||
return
|
||||
|
||||
def updateEllipse(self,v):
|
||||
return
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Circle/Arc
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getCirclePts(self, obj):
|
||||
"""Return the list of edipoints for the given Draft Arc or Circle.
|
||||
|
||||
circle:
|
||||
0 : Placement.Base or center
|
||||
1 : radius
|
||||
|
||||
arc:
|
||||
0 : Placement.Base or center
|
||||
1 : first endpoint
|
||||
2 : second endpoint
|
||||
3 : midpoint
|
||||
"""
|
||||
editpoints = []
|
||||
editpoints.append(obj.getGlobalPlacement().Base)
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
# obj is a circle
|
||||
self.ui.editUi("Circle")
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(obj.Radius,0,0)))
|
||||
else:
|
||||
# obj is an arc
|
||||
self.ui.editUi("Arc")
|
||||
editpoints.append(self.getArcStart(obj, global_placement=True))#First endpoint
|
||||
editpoints.append(self.getArcEnd(obj, global_placement=True))#Second endpoint
|
||||
editpoints.append(self.getArcMid(obj, global_placement=True))#Midpoint
|
||||
return editpoints
|
||||
|
||||
def updateCircleTrackers(self, obj):
|
||||
self.trackers[obj.Name][0].set(obj.getGlobalPlacement().Base)
|
||||
self.trackers[obj.Name][1].set(self.getArcStart(obj, global_placement=True))
|
||||
if len(self.trackers[obj.Name]) > 2:
|
||||
# object is an arc
|
||||
self.trackers[obj.Name][2].set(self.getArcEnd(obj, global_placement=True))
|
||||
self.trackers[obj.Name][3].set(self.getArcMid(obj, global_placement=True))
|
||||
|
||||
def updateCircle(self, obj, nodeIndex, v):
|
||||
delta = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
local_v = obj.Placement.multVec(delta)
|
||||
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
# object is a circle
|
||||
if nodeIndex == 0:
|
||||
obj.Placement.Base = local_v
|
||||
elif nodeIndex == 1:
|
||||
obj.Radius = delta.Length
|
||||
|
||||
else:
|
||||
# obj is an arc
|
||||
if self.alt_edit_mode == 0:
|
||||
# edit arc by 3 points
|
||||
import Part
|
||||
if nodeIndex == 0:
|
||||
# center point
|
||||
import DraftVecUtils
|
||||
p1 = self.getArcStart(obj)
|
||||
p2 = self.getArcEnd(obj)
|
||||
p0 = DraftVecUtils.project(delta,self.getArcMid(obj))
|
||||
obj.Radius = p1.sub(p0).Length
|
||||
obj.FirstAngle = -math.degrees(DraftVecUtils.angle(p1.sub(p0)))
|
||||
obj.LastAngle = -math.degrees(DraftVecUtils.angle(p2.sub(p0)))
|
||||
obj.Placement.Base = obj.Placement.multVec(p0)
|
||||
self.setPlacement(obj)
|
||||
|
||||
else:
|
||||
if nodeIndex == 1: # first point
|
||||
p1=v
|
||||
p2=self.getArcMid(obj,global_placement=True)
|
||||
p3=self.getArcEnd(obj,global_placement=True)
|
||||
elif nodeIndex == 3: # midpoint
|
||||
p1=self.getArcStart(obj,global_placement=True)
|
||||
p2=v
|
||||
p3=self.getArcEnd(obj,global_placement=True)
|
||||
elif nodeIndex == 2: # second point
|
||||
p1=self.getArcStart(obj,global_placement=True)
|
||||
p2=self.getArcMid(obj,global_placement=True)
|
||||
p3=v
|
||||
arc=Part.ArcOfCircle(p1,p2,p3)
|
||||
obj.Placement.Base = obj.Placement.multVec(obj.getGlobalPlacement().inverse().multVec(arc.Location))
|
||||
self.setPlacement(obj)
|
||||
obj.Radius = arc.Radius
|
||||
delta = self.invpl.multVec(p1)
|
||||
obj.FirstAngle = math.degrees(math.atan2(delta[1],delta[0]))
|
||||
delta = self.invpl.multVec(p3)
|
||||
obj.LastAngle = math.degrees(math.atan2(delta[1],delta[0]))
|
||||
|
||||
elif self.alt_edit_mode == 1:
|
||||
# edit arc by center radius FirstAngle LastAngle
|
||||
if nodeIndex == 0:
|
||||
obj.Placement.Base = local_v
|
||||
self.setPlacement(obj)
|
||||
else:
|
||||
dangle = math.degrees(math.atan2(delta[1],delta[0]))
|
||||
if nodeIndex == 1:
|
||||
obj.FirstAngle = dangle
|
||||
elif nodeIndex == 2:
|
||||
obj.LastAngle = dangle
|
||||
elif nodeIndex == 3:
|
||||
obj.Radius = delta.Length
|
||||
|
||||
obj.recompute()
|
||||
self.updateCircleTrackers(obj)
|
||||
|
||||
|
||||
def getArcStart(self, obj, global_placement=False):#Returns object midpoint
|
||||
if utils.get_type(obj) == "Circle":
|
||||
return self.pointOnCircle(obj, obj.FirstAngle, global_placement)
|
||||
|
||||
def getArcEnd(self, obj, global_placement=False):#Returns object midpoint
|
||||
if utils.get_type(obj) == "Circle":
|
||||
return self.pointOnCircle(obj, obj.LastAngle, global_placement)
|
||||
|
||||
def getArcMid(self, obj, global_placement=False):#Returns object midpoint
|
||||
if utils.get_type(obj) == "Circle":
|
||||
if obj.LastAngle > obj.FirstAngle:
|
||||
midAngle = obj.FirstAngle + (obj.LastAngle - obj.FirstAngle) / 2.0
|
||||
else:
|
||||
midAngle = obj.FirstAngle + (obj.LastAngle - obj.FirstAngle) / 2.0
|
||||
midAngle += App.Units.Quantity(180,App.Units.Angle)
|
||||
return self.pointOnCircle(obj, midAngle, global_placement)
|
||||
|
||||
def pointOnCircle(self, obj, angle, global_placement=False):
|
||||
if utils.get_type(obj) == "Circle":
|
||||
px = obj.Radius * math.cos(math.radians(angle))
|
||||
py = obj.Radius * math.sin(math.radians(angle))
|
||||
p = App.Vector(px, py, 0.0)
|
||||
if global_placement == True:
|
||||
p = obj.getGlobalPlacement().multVec(p)
|
||||
return p
|
||||
return None
|
||||
|
||||
def arcInvert(self, obj):
|
||||
obj.FirstAngle, obj.LastAngle = obj.LastAngle, obj.FirstAngle
|
||||
obj.recompute()
|
||||
self.updateCircleTrackers(obj)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Polygon (maybe could also rotate the polygon)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getPolygonPts(self, obj):
|
||||
editpoints = []
|
||||
editpoints.append(obj.Placement.Base)
|
||||
editpoints.append(obj.Shape.Vertexes[0].Point)
|
||||
return editpoints
|
||||
|
||||
def updatePolygon(self, obj, nodeIndex, v):
|
||||
delta = v.sub(self.obj.Placement.Base)
|
||||
if self.editing == 0:
|
||||
p = self.obj.Placement
|
||||
p.move(delta)
|
||||
self.obj.Placement = p
|
||||
self.trackers[self.obj.Name][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[self.obj.Name][1].set(self.obj.Shape.Vertexes[0].Point)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Dimension (point on dimension line is not clickable)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getDimensionPts(self, obj):
|
||||
editpoints = []
|
||||
p = obj.ViewObject.Proxy.textpos.translation.getValue()
|
||||
editpoints.append(obj.Start)
|
||||
editpoints.append(obj.End)
|
||||
editpoints.append(obj.Dimline)
|
||||
editpoints.append(App.Vector(p[0], p[1], p[2]))
|
||||
return editpoints
|
||||
|
||||
def updateDimension(self, obj, nodeIndex, v):
|
||||
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
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : ARCH Wall, Windows, Structure, Panel, etc.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# SKETCH: just if it's composed by a single segment-----------------------
|
||||
|
||||
def getSketchPts(self, obj):
|
||||
"""Return the list of edipoints for the given single line sketch.
|
||||
|
||||
(WallTrace)
|
||||
0 : startpoint
|
||||
1 : endpoint
|
||||
"""
|
||||
editpoints = []
|
||||
if obj.GeometryCount == 1:
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,1)))
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,2)))
|
||||
return editpoints
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Sketch is too complex to edit: "
|
||||
"it is suggested to use sketcher default editor")
|
||||
+ "\n")
|
||||
return None
|
||||
|
||||
def updateSketch(self, obj, nodeIndex, v):
|
||||
"""Move a single line sketch vertex a certain displacement.
|
||||
|
||||
(single segment sketch object, node index as Int, App.Vector)
|
||||
move a single line sketch (WallTrace) vertex according to a given App.Vector
|
||||
0 : startpoint
|
||||
1 : endpoint
|
||||
"""
|
||||
if nodeIndex == 0:
|
||||
obj.movePoint(0,1,obj.getGlobalPlacement().inverse().multVec(v))
|
||||
elif nodeIndex == 1:
|
||||
obj.movePoint(0,2,obj.getGlobalPlacement().inverse().multVec(v))
|
||||
obj.recompute()
|
||||
|
||||
# WALL---------------------------------------------------------------------
|
||||
|
||||
def getWallPts(self, obj):
|
||||
"""Return the list of edipoints for the given Arch Wall object.
|
||||
|
||||
0 : height of the wall
|
||||
1-to end : base object editpoints, in place with the wall
|
||||
"""
|
||||
editpoints = []
|
||||
# height of the wall
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(0,0,obj.Height)))
|
||||
# try to add here an editpoint based on wall height (maybe should be good to associate it with a circular tracker)
|
||||
if obj.Base:
|
||||
# base points are added to self.trackers under wall-name key
|
||||
basepoints = []
|
||||
if utils.get_type(obj.Base) in ["Wire","Circle","Rectangle",
|
||||
"Polygon", "Sketch"]:
|
||||
basepoints = self.getEditPoints(obj.Base)
|
||||
for point in basepoints:
|
||||
editpoints.append(obj.Placement.multVec(point)) #works ok except if App::Part is rotated... why?
|
||||
return editpoints
|
||||
|
||||
def updateWallTrackers(self, obj):
|
||||
"""Update self.trackers[obj.Name][0] to match with given object."""
|
||||
pass
|
||||
|
||||
def updateWall(self, obj, nodeIndex, v):
|
||||
if nodeIndex == 0:
|
||||
delta= obj.getGlobalPlacement().inverse().multVec(v)
|
||||
vz=DraftVecUtils.project(delta,App.Vector(0, 0, 1))
|
||||
if vz.Length > 0:
|
||||
obj.Height = vz.Length
|
||||
elif nodeIndex > 0:
|
||||
if obj.Base:
|
||||
if utils.get_type(obj.Base) in ["Wire", "Circle", "Rectangle",
|
||||
"Polygon", "Sketch"]:
|
||||
self.update(obj.Base, nodeIndex - 1,
|
||||
obj.Placement.inverse().multVec(v))
|
||||
obj.recompute()
|
||||
|
||||
# WINDOW-------------------------------------------------------------------
|
||||
|
||||
def getWindowPts(self, obj):
|
||||
editpoints = []
|
||||
pos = obj.Base.Placement.Base
|
||||
h = float(obj.Height) + pos.z
|
||||
normal = obj.Normal
|
||||
angle = normal.getAngle(App.Vector(1, 0, 0))
|
||||
editpoints.append(pos)
|
||||
editpoints.append(App.Vector(pos.x + float(obj.Width) * math.cos(angle-math.pi / 2.0),
|
||||
pos.y + float(obj.Width) * math.sin(angle-math.pi / 2.0),
|
||||
pos.z))
|
||||
editpoints.append(App.Vector(pos.x, pos.y, h))
|
||||
return editpoints
|
||||
|
||||
def updateWindow(self, obj, nodeIndex, v):
|
||||
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()
|
||||
|
||||
# STRUCTURE----------------------------------------------------------------
|
||||
|
||||
def getStructurePts(self, obj):
|
||||
if obj.Nodes:
|
||||
editpoints = []
|
||||
self.originalDisplayMode = obj.ViewObject.DisplayMode
|
||||
self.originalPoints = obj.ViewObject.NodeSize
|
||||
self.originalNodes = obj.ViewObject.ShowNodes
|
||||
self.obj.ViewObject.DisplayMode = "Wireframe"
|
||||
self.obj.ViewObject.NodeSize = 1
|
||||
# self.obj.ViewObject.ShowNodes = True
|
||||
for p in obj.Nodes:
|
||||
if self.pl:
|
||||
p = self.pl.multVec(p)
|
||||
editpoints.append(p)
|
||||
return editpoints
|
||||
else:
|
||||
return None
|
||||
|
||||
def updateStructure(self, obj, nodeIndex, v):
|
||||
nodes = self.obj.Nodes
|
||||
nodes[self.editing] = self.invpl.multVec(v)
|
||||
self.obj.Nodes = nodes
|
||||
|
||||
# SPACE--------------------------------------------------------------------
|
||||
|
||||
def getSpacePts(self, obj):
|
||||
try:
|
||||
editpoints = []
|
||||
self.editpoints.append(obj.ViewObject.Proxy.getTextPosition(obj.ViewObject))
|
||||
return editpoints
|
||||
except:
|
||||
pass
|
||||
|
||||
def updateSpace(self, obj, nodeIndex, v):
|
||||
if self.editing == 0:
|
||||
self.obj.ViewObject.TextPosition = v
|
||||
|
||||
# PANELS-------------------------------------------------------------------
|
||||
|
||||
def getPanelCutPts(self, obj):
|
||||
editpoints = []
|
||||
if self.obj.TagPosition.Length == 0:
|
||||
pos = obj.Shape.BoundBox.Center
|
||||
else:
|
||||
pos = self.pl.multVec(obj.TagPosition)
|
||||
editpoints.append(pos)
|
||||
return editpoints
|
||||
|
||||
def updatePanelCut(self, obj, nodeIndex, v):
|
||||
if self.editing == 0:
|
||||
self.obj.TagPosition = self.invpl.multVec(v)
|
||||
|
||||
def getPanelSheetPts(self, obj):
|
||||
editpoints = []
|
||||
editpoints.append(self.pl.multVec(obj.TagPosition))
|
||||
for o in obj.Group:
|
||||
editpoints.append(self.pl.multVec(o.Placement.Base))
|
||||
return editpoints
|
||||
|
||||
def updatePanelSheet(self, obj, nodeIndex, v):
|
||||
if self.editing == 0:
|
||||
self.obj.TagPosition = self.invpl.multVec(v)
|
||||
else:
|
||||
self.obj.Group[self.editing-1].Placement.Base = self.invpl.multVec(v)
|
||||
|
||||
# PART::LINE--------------------------------------------------------------
|
||||
|
||||
def getPartLinePts(self, obj):
|
||||
editpoints = []
|
||||
editpoints.append(self.pl.multVec(App.Vector(obj.X1,obj.Y1,obj.Z1)))
|
||||
editpoints.append(self.pl.multVec(App.Vector(obj.X2,obj.Y2,obj.Z2)))
|
||||
return editpoints
|
||||
|
||||
def updatePartLine(self, obj, nodeIndex, v):
|
||||
pt=self.invpl.multVec(v)
|
||||
if self.editing == 0:
|
||||
self.obj.X1 = pt.x
|
||||
self.obj.Y1 = pt.y
|
||||
self.obj.Z1 = pt.z
|
||||
elif self.editing == 1:
|
||||
self.obj.X2 = pt.x
|
||||
self.obj.Y2 = pt.y
|
||||
self.obj.Z2 = pt.z
|
||||
|
||||
# PART::BOX---------------------------------------------------------------
|
||||
|
||||
def getPartBoxPts(self, obj):
|
||||
editpoints = []
|
||||
editpoints.append(obj.Placement.Base)
|
||||
editpoints.append(self.pl.multVec(App.Vector(obj.Length, 0, 0)))
|
||||
editpoints.append(self.pl.multVec(App.Vector(0, obj.Width, 0)))
|
||||
editpoints.append(self.pl.multVec(App.Vector(0, 0, obj.Height)))
|
||||
return editpoints
|
||||
|
||||
def updatePartBox(self, obj, nodeIndex, v):
|
||||
delta = self.invpl.multVec(v)
|
||||
if self.editing == 0:
|
||||
self.obj.Placement.Base = v
|
||||
self.setPlacement(self.obj)
|
||||
elif self.editing == 1:
|
||||
_vector = DraftVecUtils.project(delta, App.Vector(1, 0, 0))
|
||||
self.obj.Length = _vector.Length
|
||||
elif self.editing == 2:
|
||||
_vector = DraftVecUtils.project(delta, App.Vector(0, 1, 0))
|
||||
self.obj.Width = _vector.Length
|
||||
elif self.editing == 3:
|
||||
_vector = DraftVecUtils.project(delta, App.Vector(0, 0, 1))
|
||||
self.obj.Height = _vector.Length
|
||||
self.trackers[self.obj.Name][0].set(self.obj.Placement.Base)
|
||||
self.trackers[self.obj.Name][1].set(self.pl.multVec(App.Vector(self.obj.Length,0,0)))
|
||||
self.trackers[self.obj.Name][2].set(self.pl.multVec(App.Vector(0,self.obj.Width,0)))
|
||||
self.trackers[self.obj.Name][3].set(self.pl.multVec(App.Vector(0,0,self.obj.Height)))
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Context menu
|
||||
@@ -1805,11 +1132,11 @@ class Edit(gui_base_original.Modifier):
|
||||
obj = App.getDocument(doc).getObject(self.overNode.get_obj_name())
|
||||
idx = self.overNode.get_subelement_index()
|
||||
if action_label == "make sharp":
|
||||
self.smoothBezPoint(obj, idx, 'Sharp')
|
||||
edit_draft.smoothBezPoint(obj, idx, 'Sharp')
|
||||
elif action_label == "make tangent":
|
||||
self.smoothBezPoint(obj, idx, 'Tangent')
|
||||
edit_draft.smoothBezPoint(obj, idx, 'Tangent')
|
||||
elif action_label == "make symmetric":
|
||||
self.smoothBezPoint(obj, idx, 'Symmetric')
|
||||
edit_draft.smoothBezPoint(obj, idx, 'Symmetric')
|
||||
# addPoint and deletePoint menu
|
||||
elif action_label == "delete point":
|
||||
self.delPoint(self.event)
|
||||
|
||||
227
src/Mod/Draft/draftguitools/gui_edit_arch_objects.py
Normal file
227
src/Mod/Draft/draftguitools/gui_edit_arch_objects.py
Normal file
@@ -0,0 +1,227 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
|
||||
# * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> *
|
||||
# * Copyright (c) 2019, 2020 Carlo Pavan <carlopav@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""Provide the support functions to Draft_Edit for Arch objects."""
|
||||
## @package gui_edit_arch_objects
|
||||
# \ingroup DRAFT
|
||||
# \brief Provide the support functions to Draft_Edit for Arch objects
|
||||
|
||||
__title__ = "FreeCAD Draft Edit Tool"
|
||||
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
|
||||
"Dmitry Chigrin, Carlo Pavan")
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
import math
|
||||
import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
|
||||
from draftutils.translate import translate
|
||||
import draftutils.utils as utils
|
||||
|
||||
|
||||
# SKETCH: just if it's composed by a single segment-----------------------
|
||||
|
||||
def getSketchPts(obj):
|
||||
"""Return the list of edipoints for the given single line sketch.
|
||||
|
||||
(WallTrace)
|
||||
0 : startpoint
|
||||
1 : endpoint
|
||||
"""
|
||||
editpoints = []
|
||||
if obj.GeometryCount == 1:
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,1)))
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,2)))
|
||||
return editpoints
|
||||
else:
|
||||
_wrn = translate("draft", "Sketch is too complex to edit: "
|
||||
"it is suggested to use sketcher default editor")
|
||||
App.Console.PrintWarning(_wrn + "\n")
|
||||
return None
|
||||
|
||||
|
||||
def updateSketch(obj, nodeIndex, v):
|
||||
"""Move a single line sketch vertex a certain displacement.
|
||||
|
||||
(single segment sketch object, node index as Int, App.Vector)
|
||||
move a single line sketch (WallTrace) vertex according to a given App.Vector
|
||||
0 : startpoint
|
||||
1 : endpoint
|
||||
"""
|
||||
if nodeIndex == 0:
|
||||
obj.movePoint(0,1,obj.getGlobalPlacement().inverse().multVec(v))
|
||||
elif nodeIndex == 1:
|
||||
obj.movePoint(0,2,obj.getGlobalPlacement().inverse().multVec(v))
|
||||
obj.recompute()
|
||||
|
||||
|
||||
# WALL---------------------------------------------------------------------
|
||||
|
||||
def getWallPts(obj):
|
||||
"""Return the list of edipoints for the given Arch Wall object.
|
||||
|
||||
0 : height of the wall
|
||||
1-to end : base object editpoints, in place with the wall
|
||||
"""
|
||||
editpoints = []
|
||||
# height of the wall
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(0,0,obj.Height)))
|
||||
# try to add here an editpoint based on wall height (maybe should be good to associate it with a circular tracker)
|
||||
if obj.Base:
|
||||
# base points are added to self.trackers under wall-name key
|
||||
basepoints = []
|
||||
if utils.get_type(obj.Base) in ["Wire","Circle","Rectangle",
|
||||
"Polygon", "Sketch"]:
|
||||
pass # TODO: make it work again
|
||||
#basepoints = self.getEditPoints(obj.Base)
|
||||
#for point in basepoints:
|
||||
# editpoints.append(obj.Placement.multVec(point)) #works ok except if App::Part is rotated... why?
|
||||
return editpoints
|
||||
|
||||
|
||||
def updateWallTrackers(obj):
|
||||
"""Update self.trackers[obj.Name][0] to match with given object."""
|
||||
pass
|
||||
|
||||
|
||||
def updateWall(obj, nodeIndex, v):
|
||||
if nodeIndex == 0:
|
||||
delta= obj.getGlobalPlacement().inverse().multVec(v)
|
||||
vz = DraftVecUtils.project(delta, App.Vector(0, 0, 1))
|
||||
if vz.Length > 0:
|
||||
obj.Height = vz.Length
|
||||
elif nodeIndex > 0:
|
||||
if obj.Base:
|
||||
if utils.get_type(obj.Base) in ["Wire", "Circle", "Rectangle",
|
||||
"Polygon", "Sketch"]:
|
||||
pass #TODO: make it work again
|
||||
#self.update(obj.Base, nodeIndex - 1,
|
||||
# obj.Placement.inverse().multVec(v))
|
||||
obj.recompute()
|
||||
|
||||
|
||||
# WINDOW-------------------------------------------------------------------
|
||||
|
||||
def getWindowPts(obj):
|
||||
editpoints = []
|
||||
pos = obj.Base.Placement.Base
|
||||
h = float(obj.Height) + pos.z
|
||||
normal = obj.Normal
|
||||
angle = normal.getAngle(App.Vector(1, 0, 0))
|
||||
editpoints.append(pos)
|
||||
editpoints.append(App.Vector(pos.x + float(obj.Width) * math.cos(angle-math.pi / 2.0),
|
||||
pos.y + float(obj.Width) * math.sin(angle-math.pi / 2.0),
|
||||
pos.z))
|
||||
editpoints.append(App.Vector(pos.x, pos.y, h))
|
||||
return editpoints
|
||||
|
||||
|
||||
def updateWindow(obj, nodeIndex, v):
|
||||
pos = obj.Base.Placement.Base
|
||||
if nodeIndex == 0:
|
||||
obj.Base.Placement.Base = v
|
||||
obj.Base.recompute()
|
||||
if nodeIndex == 1:
|
||||
obj.Width = pos.sub(v).Length
|
||||
obj.Base.recompute()
|
||||
if nodeIndex == 2:
|
||||
obj.Height = pos.sub(v).Length
|
||||
obj.Base.recompute()
|
||||
for obj in obj.Hosts:
|
||||
obj.recompute()
|
||||
obj.recompute()
|
||||
|
||||
|
||||
# STRUCTURE----------------------------------------------------------------
|
||||
|
||||
def getStructurePts(obj):
|
||||
if obj.Nodes:
|
||||
editpoints = []
|
||||
# TODO: make it work again
|
||||
#self.originalDisplayMode = obj.ViewObject.DisplayMode
|
||||
#self.originalPoints = obj.ViewObject.NodeSize
|
||||
#self.originalNodes = obj.ViewObject.ShowNodes
|
||||
#self.obj.ViewObject.DisplayMode = "Wireframe"
|
||||
#self.obj.ViewObject.NodeSize = 1
|
||||
## self.obj.ViewObject.ShowNodes = True
|
||||
#for p in obj.Nodes:
|
||||
# if self.pl:
|
||||
# p = self.pl.multVec(p)
|
||||
# editpoints.append(p)
|
||||
#return editpoints
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def updateStructure(obj, nodeIndex, v):
|
||||
nodes = obj.Nodes
|
||||
nodes[nodeIndex] = obj.Placement.inverse().multVec(v)
|
||||
obj.Nodes = nodes
|
||||
|
||||
|
||||
# SPACE--------------------------------------------------------------------
|
||||
|
||||
def getSpacePts(obj):
|
||||
try:
|
||||
editpoints = []
|
||||
editpoints.append(obj.ViewObject.Proxy.getTextPosition(obj.ViewObject))
|
||||
return editpoints
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def updateSpace(obj, nodeIndex, v):
|
||||
if nodeIndex == 0:
|
||||
obj.ViewObject.TextPosition = v
|
||||
|
||||
|
||||
# PANELS-------------------------------------------------------------------
|
||||
|
||||
def getPanelCutPts(obj):
|
||||
editpoints = []
|
||||
if obj.TagPosition.Length == 0:
|
||||
pos = obj.Shape.BoundBox.Center
|
||||
else:
|
||||
pos = obj.Placement.multVec(obj.TagPosition)
|
||||
editpoints.append(pos)
|
||||
return editpoints
|
||||
|
||||
|
||||
def updatePanelCut(obj, nodeIndex, v):
|
||||
if nodeIndex == 0:
|
||||
obj.TagPosition = obj.Placement.inverse().multVec(v)
|
||||
|
||||
|
||||
def getPanelSheetPts(obj):
|
||||
editpoints = []
|
||||
editpoints.append(obj.Placement.multVec(obj.TagPosition))
|
||||
for o in obj.Group:
|
||||
editpoints.append(obj.Placement.multVec(o.Placement.Base))
|
||||
return editpoints
|
||||
|
||||
|
||||
def updatePanelSheet(obj, nodeIndex, v):
|
||||
if nodeIndex == 0:
|
||||
obj.TagPosition = obj.Placement.inverse().multVec(v)
|
||||
else:
|
||||
obj.Group[nodeIndex-1].Placement.Base = obj.Placement.inverse().multVec(v)
|
||||
482
src/Mod/Draft/draftguitools/gui_edit_draft_objects.py
Normal file
482
src/Mod/Draft/draftguitools/gui_edit_draft_objects.py
Normal file
@@ -0,0 +1,482 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2010 Yorik van Havre <yorik@uncreated.net> *
|
||||
# * Copyright (c) 2010 Ken Cline <cline@frii.com> *
|
||||
# * Copyright (c) 2020 Carlo Pavan <carlopav@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""Provide the Draft_Edit command used by the Draft workbench."""
|
||||
## @package gui_edit_draft_objects
|
||||
# \ingroup DRAFT
|
||||
# \brief Provide the Draft_Edit command used by the Draft workbench
|
||||
|
||||
__title__ = "FreeCAD Draft Edit Tool"
|
||||
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
|
||||
"Dmitry Chigrin, Carlo Pavan")
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
import math
|
||||
import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
|
||||
from draftutils.translate import translate
|
||||
import draftutils.utils as utils
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Line/Wire/Bspline/Bezcurve
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getWirePts(obj):
|
||||
editpoints = []
|
||||
for p in obj.Points:
|
||||
p = obj.getGlobalPlacement().multVec(p)
|
||||
editpoints.append(p)
|
||||
return editpoints
|
||||
|
||||
def updateWire(obj, nodeIndex, v): #TODO: Fix it
|
||||
pts = obj.Points
|
||||
editPnt = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
# DNC: allows to close the curve by placing ends close to each other
|
||||
tol = 0.001
|
||||
if ( ( nodeIndex == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or (
|
||||
nodeIndex == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol):
|
||||
obj.Closed = True
|
||||
# DNC: fix error message if edited point coincides with one of the existing points
|
||||
if ( editPnt in pts ) == True: # checks if point enter is equal to other, this could cause a OCC problem
|
||||
App.Console.PrintMessage(translate("draft",
|
||||
"This object does not support possible "
|
||||
"coincident points, please try again.")
|
||||
+ "\n")
|
||||
if utils.get_type(obj) in ["BezCurve"]: # TODO: Remove code to recompute trackers
|
||||
self.resetTrackers(obj)
|
||||
else:
|
||||
self.trackers[obj.Name][nodeIndex].set(obj.getGlobalPlacement().
|
||||
multVec(obj.Points[nodeIndex]))
|
||||
return
|
||||
if utils.get_type(obj) in ["BezCurve"]:
|
||||
pts = recomputePointsBezier(obj,pts,nodeIndex,v,obj.Degree,moveTrackers=False)
|
||||
|
||||
if obj.Closed:
|
||||
# check that the new point lies on the plane of the wire
|
||||
if hasattr(obj.Shape,"normalAt"):
|
||||
normal = obj.Shape.normalAt(0,0)
|
||||
point_on_plane = obj.Shape.Vertexes[0].Point
|
||||
print(v)
|
||||
v.projectToPlane(point_on_plane, normal)
|
||||
print(v)
|
||||
editPnt = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
pts[nodeIndex] = editPnt
|
||||
obj.Points = pts
|
||||
|
||||
|
||||
def recomputePointsBezier(obj, pts, idx, v,
|
||||
degree, moveTrackers=True):
|
||||
"""
|
||||
(object, Points as list, nodeIndex as Int, App.Vector of new point, moveTrackers as Bool)
|
||||
return the new point list, applying the App.Vector to the given index point
|
||||
"""
|
||||
editPnt = v
|
||||
# DNC: allows to close the curve by placing ends close to each other
|
||||
tol = 0.001
|
||||
if ( ( idx == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or (
|
||||
idx == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol):
|
||||
obj.Closed = True
|
||||
# DNC: fix error message if edited point coincides with one of the existing points
|
||||
#if ( editPnt in pts ) == False:
|
||||
knot = None
|
||||
ispole = idx % degree
|
||||
|
||||
if ispole == 0: #knot
|
||||
if degree >= 3:
|
||||
if idx >= 1: #move left pole
|
||||
knotidx = idx if idx < len(pts) else 0
|
||||
pts[idx-1] = pts[idx-1] + editPnt - pts[knotidx]
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][idx-1].set(pts[idx-1]) # TODO: Remove code to recompute trackers
|
||||
if idx < len(pts)-1: #move right pole
|
||||
pts[idx+1] = pts[idx+1] + editPnt - pts[idx]
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][idx+1].set(pts[idx+1])
|
||||
if idx == 0 and obj.Closed: # move last pole
|
||||
pts[-1] = pts [-1] + editPnt -pts[idx]
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][-1].set(pts[-1])
|
||||
|
||||
elif ispole == 1 and (idx >=2 or obj.Closed): #right pole
|
||||
knot = idx -1
|
||||
changep = idx - 2 # -1 in case of closed curve
|
||||
|
||||
elif ispole == degree-1 and idx <= len(pts)-3: # left pole
|
||||
knot = idx + 1
|
||||
changep = idx + 2
|
||||
|
||||
elif ispole == degree-1 and obj.Closed and idx == len(pts)-1: #last pole
|
||||
knot = 0
|
||||
changep = 1
|
||||
|
||||
if knot is not None: # we need to modify the opposite pole
|
||||
segment = int(knot / degree) - 1
|
||||
cont = obj.Continuity[segment] if len(obj.Continuity) > segment else 0
|
||||
if cont == 1: #tangent
|
||||
pts[changep] = obj.Proxy.modifytangentpole(pts[knot],
|
||||
editPnt,pts[changep])
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][changep].set(pts[changep])
|
||||
elif cont == 2: #symmetric
|
||||
pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot],editPnt)
|
||||
if moveTrackers:
|
||||
self.trackers[obj.Name][changep].set(pts[changep])
|
||||
pts[idx] = v
|
||||
|
||||
return pts # returns the list of new points, taking into account knot continuity
|
||||
|
||||
def resetTrackersBezier(obj):
|
||||
# in future move tracker definition to DraftTrackers
|
||||
from pivy import coin
|
||||
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[obj.Name] = []
|
||||
cont = obj.Continuity
|
||||
firstknotcont = cont[-1] if (obj.Closed and cont) else 0
|
||||
pointswithmarkers = [(obj.Shape.Edges[0].Curve.
|
||||
getPole(1),knotmarkers[firstknotcont])]
|
||||
for edgeindex, edge in enumerate(obj.Shape.Edges):
|
||||
poles = edge.Curve.getPoles()
|
||||
pointswithmarkers.extend([(point,polemarker) for point in poles[1:-1]])
|
||||
if not obj.Closed or len(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[obj.Name].append(trackers.editTracker(p,obj.Name,
|
||||
index,obj.ViewObject.LineColor,marker=marker))
|
||||
|
||||
def smoothBezPoint(obj, point, style='Symmetric'):
|
||||
"called when changing the continuity of a knot"
|
||||
style2cont = {'Sharp':0,'Tangent':1,'Symmetric':2}
|
||||
if point is None:
|
||||
return
|
||||
if not (utils.get_type(obj) == "BezCurve"):
|
||||
return
|
||||
pts = obj.Points
|
||||
deg = 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 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 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:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Can't change Knot belonging to pole %d"%point)
|
||||
+ "\n")
|
||||
return
|
||||
if knot:
|
||||
if style == 'Tangent':
|
||||
pts[changep] = obj.Proxy.modifytangentpole(pts[knot],
|
||||
pts[keepp],pts[changep])
|
||||
elif style == 'Symmetric':
|
||||
pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot],
|
||||
pts[keepp])
|
||||
else: #sharp
|
||||
pass #
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Selection is not a Knot")
|
||||
+ "\n")
|
||||
return
|
||||
else: #point is a knot
|
||||
if style == 'Sharp':
|
||||
if 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 = 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 = 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 obj.Closed and (style == 'Symmetric' or style == 'Tangent'):
|
||||
if style == 'Tangent':
|
||||
pts[1], pts[-1] = obj.Proxy.tangentpoles(pts[0], pts[1], pts[-1])
|
||||
elif style == 'Symmetric':
|
||||
pts[1], pts[-1] = obj.Proxy.symmetricpoles(pts[0], pts[1], pts[-1])
|
||||
knot = 0
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft",
|
||||
"Endpoint of BezCurve can't be smoothed")
|
||||
+ "\n")
|
||||
return
|
||||
segment = knot // deg # segment index
|
||||
newcont = obj.Continuity[:] # don't edit a property inplace !!!
|
||||
if not obj.Closed and (len(obj.Continuity) == segment -1 or
|
||||
segment == 0) :
|
||||
pass # open curve
|
||||
elif (len(obj.Continuity) >= segment or obj.Closed and segment == 0 and
|
||||
len(obj.Continuity) >1):
|
||||
newcont[segment-1] = style2cont.get(style)
|
||||
else: #should not happen
|
||||
App.Console.PrintWarning('Continuity indexing error:'
|
||||
+ 'point:%d deg:%d len(cont):%d' % (knot,deg,
|
||||
len(obj.Continuity)))
|
||||
obj.Points = pts
|
||||
obj.Continuity = newcont
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Rectangle
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getRectanglePts(obj):
|
||||
"""Return the list of edipoints for the given Draft Rectangle.
|
||||
|
||||
0 : Placement.Base
|
||||
1 : Length
|
||||
2 : Height
|
||||
"""
|
||||
editpoints = []
|
||||
editpoints.append(obj.getGlobalPlacement().Base)
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(obj.Length,0,0)))
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(0,obj.Height,0)))
|
||||
return editpoints
|
||||
|
||||
|
||||
def updateRectangle(obj, nodeIndex, v):
|
||||
delta = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
if nodeIndex == 0:
|
||||
# p = obj.getGlobalPlacement()
|
||||
# p.move(delta)
|
||||
obj.Placement.move(delta)
|
||||
elif nodeIndex == 1:
|
||||
obj.Length = DraftVecUtils.project(delta,App.Vector(1,0,0)).Length
|
||||
elif nodeIndex == 2:
|
||||
obj.Height = DraftVecUtils.project(delta,App.Vector(0,1,0)).Length
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Ellipse (# TODO: yet to be implemented)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def setEllipsePts(obj):
|
||||
return
|
||||
|
||||
def updateEllipse(obj, nodeIndex, v):
|
||||
return
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Circle/Arc
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getCirclePts(obj):
|
||||
"""Return the list of edipoints for the given Draft Arc or Circle.
|
||||
|
||||
circle:
|
||||
0 : Placement.Base or center
|
||||
1 : radius
|
||||
|
||||
arc:
|
||||
0 : Placement.Base or center
|
||||
1 : first endpoint
|
||||
2 : second endpoint
|
||||
3 : midpoint
|
||||
"""
|
||||
editpoints = []
|
||||
editpoints.append(obj.getGlobalPlacement().Base)
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
# obj is a circle
|
||||
editpoints.append(obj.getGlobalPlacement().multVec(App.Vector(obj.Radius,0,0)))
|
||||
else:
|
||||
# obj is an arc
|
||||
editpoints.append(getArcStart(obj, global_placement=True))#First endpoint
|
||||
editpoints.append(getArcEnd(obj, global_placement=True))#Second endpoint
|
||||
editpoints.append(getArcMid(obj, global_placement=True))#Midpoint
|
||||
return editpoints
|
||||
|
||||
|
||||
def updateCircle(obj, nodeIndex, v, alt_edit_mode=0):
|
||||
delta = obj.getGlobalPlacement().inverse().multVec(v)
|
||||
local_v = obj.Placement.multVec(delta)
|
||||
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
# object is a circle
|
||||
if nodeIndex == 0:
|
||||
obj.Placement.Base = local_v
|
||||
elif nodeIndex == 1:
|
||||
obj.Radius = delta.Length
|
||||
|
||||
else:
|
||||
# obj is an arc
|
||||
if alt_edit_mode == 0:
|
||||
# edit arc by 3 points
|
||||
import Part
|
||||
if nodeIndex == 0:
|
||||
# center point
|
||||
p1 = getArcStart(obj)
|
||||
p2 = getArcEnd(obj)
|
||||
p0 = DraftVecUtils.project(delta, getArcMid(obj))
|
||||
obj.Radius = p1.sub(p0).Length
|
||||
obj.FirstAngle = -math.degrees(DraftVecUtils.angle(p1.sub(p0)))
|
||||
obj.LastAngle = -math.degrees(DraftVecUtils.angle(p2.sub(p0)))
|
||||
obj.Placement.Base = obj.Placement.multVec(p0)
|
||||
|
||||
else:
|
||||
if nodeIndex == 1: # first point
|
||||
p1 = v
|
||||
p2 = getArcMid(obj, global_placement=True)
|
||||
p3 = getArcEnd(obj, global_placement=True)
|
||||
elif nodeIndex == 3: # midpoint
|
||||
p1 = getArcStart(obj, global_placement=True)
|
||||
p2 = v
|
||||
p3 = getArcEnd(obj, global_placement=True)
|
||||
elif nodeIndex == 2: # second point
|
||||
p1 = getArcStart(obj, global_placement=True)
|
||||
p2 = getArcMid(obj, global_placement=True)
|
||||
p3 = v
|
||||
arc=Part.ArcOfCircle(p1,p2,p3)
|
||||
obj.Placement.Base = obj.Placement.multVec(obj.getGlobalPlacement().inverse().multVec(arc.Location))
|
||||
obj.Radius = arc.Radius
|
||||
delta = obj.Placement.inverse().multVec(p1)
|
||||
obj.FirstAngle = math.degrees(math.atan2(delta[1],delta[0]))
|
||||
delta = obj.Placement.inverse().multVec(p3)
|
||||
obj.LastAngle = math.degrees(math.atan2(delta[1],delta[0]))
|
||||
|
||||
elif alt_edit_mode == 1:
|
||||
# edit arc by center radius FirstAngle LastAngle
|
||||
if nodeIndex == 0:
|
||||
obj.Placement.Base = local_v
|
||||
else:
|
||||
dangle = math.degrees(math.atan2(delta[1],delta[0]))
|
||||
if nodeIndex == 1:
|
||||
obj.FirstAngle = dangle
|
||||
elif nodeIndex == 2:
|
||||
obj.LastAngle = dangle
|
||||
elif nodeIndex == 3:
|
||||
obj.Radius = delta.Length
|
||||
|
||||
obj.recompute()
|
||||
|
||||
|
||||
def getArcStart(obj, global_placement=False):#Returns object midpoint
|
||||
if utils.get_type(obj) == "Circle":
|
||||
return pointOnCircle(obj, obj.FirstAngle, global_placement)
|
||||
|
||||
|
||||
def getArcEnd(obj, global_placement=False):#Returns object midpoint
|
||||
if utils.get_type(obj) == "Circle":
|
||||
return pointOnCircle(obj, obj.LastAngle, global_placement)
|
||||
|
||||
|
||||
def getArcMid(obj, global_placement=False):#Returns object midpoint
|
||||
if utils.get_type(obj) == "Circle":
|
||||
if obj.LastAngle > obj.FirstAngle:
|
||||
midAngle = obj.FirstAngle + (obj.LastAngle - obj.FirstAngle) / 2.0
|
||||
else:
|
||||
midAngle = obj.FirstAngle + (obj.LastAngle - obj.FirstAngle) / 2.0
|
||||
midAngle += App.Units.Quantity(180,App.Units.Angle)
|
||||
return pointOnCircle(obj, midAngle, global_placement)
|
||||
|
||||
|
||||
def pointOnCircle(obj, angle, global_placement=False):
|
||||
if utils.get_type(obj) == "Circle":
|
||||
px = obj.Radius * math.cos(math.radians(angle))
|
||||
py = obj.Radius * math.sin(math.radians(angle))
|
||||
p = App.Vector(px, py, 0.0)
|
||||
if global_placement == True:
|
||||
p = obj.getGlobalPlacement().multVec(p)
|
||||
return p
|
||||
return None
|
||||
|
||||
|
||||
def arcInvert(obj):
|
||||
obj.FirstAngle, obj.LastAngle = obj.LastAngle, obj.FirstAngle
|
||||
obj.recompute()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Polygon (maybe could also rotate the polygon)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getPolygonPts(obj):
|
||||
editpoints = []
|
||||
editpoints.append(obj.Placement.Base)
|
||||
editpoints.append(obj.Shape.Vertexes[0].Point)
|
||||
return editpoints
|
||||
|
||||
|
||||
def updatePolygon(obj, nodeIndex, v):
|
||||
delta = v.sub(obj.Placement.Base)
|
||||
if nodeIndex == 0:
|
||||
p = obj.Placement
|
||||
p.move(delta)
|
||||
obj.Placement = p
|
||||
elif nodeIndex == 1:
|
||||
if obj.DrawMode == 'inscribed':
|
||||
obj.Radius = delta.Length
|
||||
else:
|
||||
halfangle = ((math.pi*2)/obj.FacesNumber)/2
|
||||
rad = math.cos(halfangle)*delta.Length
|
||||
obj.Radius = rad
|
||||
obj.recompute()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT OBJECT TOOLS : Dimension (point on dimension line is not clickable)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def getDimensionPts(obj):
|
||||
editpoints = []
|
||||
p = obj.ViewObject.Proxy.textpos.translation.getValue()
|
||||
editpoints.append(obj.Start)
|
||||
editpoints.append(obj.End)
|
||||
editpoints.append(obj.Dimline)
|
||||
editpoints.append(App.Vector(p[0], p[1], p[2]))
|
||||
return editpoints
|
||||
|
||||
def updateDimension(obj, nodeIndex, v):
|
||||
if nodeIndex == 0:
|
||||
obj.Start = v
|
||||
elif nodeIndex == 1:
|
||||
obj.End = v
|
||||
elif nodeIndex == 2:
|
||||
obj.Dimline = v
|
||||
elif nodeIndex == 3:
|
||||
obj.ViewObject.TextPosition = v
|
||||
|
||||
|
||||
79
src/Mod/Draft/draftguitools/gui_edit_part_objects.py
Normal file
79
src/Mod/Draft/draftguitools/gui_edit_part_objects.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2019 Carlo Pavan <carlopav@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""Provide the support functions to Draft_Edit for Part objects."""
|
||||
## @package gui_edit_part_objects
|
||||
# \ingroup DRAFT
|
||||
# \brief Provide the support functions to Draft_Edit for Part objects
|
||||
|
||||
__title__ = "FreeCAD Draft Edit Tool"
|
||||
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
|
||||
"Dmitry Chigrin, Carlo Pavan")
|
||||
__url__ = "https://www.freecadweb.org"
|
||||
|
||||
|
||||
import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
|
||||
|
||||
# PART::LINE--------------------------------------------------------------
|
||||
|
||||
def getPartLinePts(obj):
|
||||
editpoints = []
|
||||
editpoints.append(obj.Placement.multVec(App.Vector(obj.X1,obj.Y1,obj.Z1)))
|
||||
editpoints.append(obj.Placement.pl.multVec(App.Vector(obj.X2,obj.Y2,obj.Z2)))
|
||||
return editpoints
|
||||
|
||||
|
||||
def updatePartLine(obj, nodeIndex, v):
|
||||
pt=obj.Placement.inverse().multVec(v)
|
||||
if nodeIndex == 0:
|
||||
obj.X1 = pt.x
|
||||
obj.Y1 = pt.y
|
||||
obj.Z1 = pt.z
|
||||
elif nodeIndex == 1:
|
||||
obj.X2 = pt.x
|
||||
obj.Y2 = pt.y
|
||||
obj.Z2 = pt.z
|
||||
|
||||
# PART::BOX---------------------------------------------------------------
|
||||
|
||||
def getPartBoxPts(self, obj):
|
||||
editpoints = []
|
||||
editpoints.append(obj.Placement.Base)
|
||||
editpoints.append(obj.Placement.multVec(App.Vector(obj.Length, 0, 0)))
|
||||
editpoints.append(obj.Placement.multVec(App.Vector(0, obj.Width, 0)))
|
||||
editpoints.append(obj.Placement.multVec(App.Vector(0, 0, obj.Height)))
|
||||
return editpoints
|
||||
|
||||
|
||||
def updatePartBox(self, obj, nodeIndex, v):
|
||||
delta = obj.Placement.inverse().multVec(v)
|
||||
if nodeIndex == 0:
|
||||
obj.Placement.Base = v
|
||||
elif nodeIndex == 1:
|
||||
_vector = DraftVecUtils.project(delta, App.Vector(1, 0, 0))
|
||||
obj.Length = _vector.Length
|
||||
elif nodeIndex == 2:
|
||||
_vector = DraftVecUtils.project(delta, App.Vector(0, 1, 0))
|
||||
obj.Width = _vector.Length
|
||||
elif nodeIndex == 3:
|
||||
_vector = DraftVecUtils.project(delta, App.Vector(0, 0, 1))
|
||||
obj.Height = _vector.Length
|
||||
Reference in New Issue
Block a user