Draft: Edit reordering 1

Started a general refactor to handle all the conversion between global and object coordinate system inside the main methods and just use object coordinates inside object functions.
Draft: Edit reordering 2

Fixed Editing of Part objects according to the new refactor
Draft: fix in autogroup function for dimensions


Draft: fixed Polygon editing when inscribed or circumscribed


Draft: Edit support for Ellipse object


.


Draft: Edit docstrings


Draft: Edit reordering 3


Draft: Fixed Edit for structure object

And also refactor Edit methods that control special object display during editing.
Draft: Fixed edit for arch wall object
This commit is contained in:
carlopav
2020-05-24 11:14:50 +02:00
committed by Yorik van Havre
parent 61dd57407e
commit a98e2076db
5 changed files with 436 additions and 390 deletions

View File

@@ -181,10 +181,6 @@ class Edit(gui_base_original.Modifier):
the user is editing corresponding node, so next click
will be processed as an attempt to end editing operation
editpoints: List [FreeCAD::App.Vector]
List of editpoints collected from the edited object,
on whick editTrackers will be placed.
trackers: Dictionary {object.Name : [editTrackers]}
It records the list of DraftTrackers.editTracker.
{object.Name as String : [editTrackers for the object]}
@@ -233,10 +229,7 @@ class Edit(gui_base_original.Modifier):
self._mousePressedCB = None
# this are used to edit structure objects, it's a bit buggy i think
self.selectstate = None
self.originalDisplayMode = None
self.originalPoints = None
self.originalNodes = None
self.objs_formats = {}
# settings
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
@@ -250,7 +243,7 @@ class Edit(gui_base_original.Modifier):
#list of supported Draft and Arch objects
self.supportedObjs = ["BezCurve","Wire","BSpline","Circle","Rectangle",
"Polygon","Dimension","LinearDimension","Space",
"Polygon","Ellipse","Dimension","LinearDimension","Space",
"Structure","PanelCut","PanelSheet","Wall", "Window"]
#list of supported Part objects (they don't have a proxy)
@@ -299,17 +292,15 @@ class Edit(gui_base_original.Modifier):
+ "\n")
self.register_selection_callback()
def proceed(self):
"""this method defines editpoints and set the editTrackers"""
"""this method set the editTrackers"""
self.unregister_selection_callback()
self.edited_objects = self.getObjsFromSelection()
if not self.edited_objects:
return self.finish()
# Save selectstate and turn selectable false.
# Object can remain selectable commenting following lines:
# self.saveSelectState(self.obj)
# self.setSelectState(self.obj, False)
self.format_objects_for_editing(self.edited_objects)
# start object editing
Gui.Selection.clearSelection()
@@ -318,7 +309,7 @@ class Edit(gui_base_original.Modifier):
self.ui.editUi()
for obj in self.edited_objects:
self.setEditPoints(obj)
self.setTrackers(obj, self.getEditPoints(obj))
self.register_editing_callbacks()
@@ -327,6 +318,18 @@ class Edit(gui_base_original.Modifier):
# self.alignWorkingPlane()
def numericInput(self, v, numy=None, numz=None):
"""Execute callback by the toolbar to activate the update function.
This function gets called by the toolbar
or by the mouse click and activate the update function.
"""
if numy:
v = App.Vector(v, numy, numz)
self.endEditing(self.obj, self.editing, v)
App.ActiveDocument.recompute()
def finish(self, closed=False):
"""Terminate Edit Tool."""
self.unregister_selection_callback()
@@ -340,18 +343,9 @@ class Edit(gui_base_original.Modifier):
self.obj.Closed = True
if self.ui:
self.removeTrackers()
self.restoreSelectState(self.obj)
if utils.get_type(self.obj) == "Structure":
if self.originalDisplayMode is not None:
self.obj.ViewObject.DisplayMode = self.originalDisplayMode
if self.originalPoints is not None:
self.obj.ViewObject.NodeSize = self.originalPoints
if self.originalNodes is not None:
self.obj.ViewObject.ShowNodes = self.originalNodes
self.selectstate = None
self.originalDisplayMode = None
self.originalPoints = None
self.originalNodes = None
self.deformat_objects_after_editing(self.edited_objects)
super(Edit, self).finish()
App.DraftWorkingPlane.restore()
if Gui.Snapper.grid:
@@ -361,6 +355,7 @@ class Edit(gui_base_original.Modifier):
from PySide import QtCore
QtCore.QTimer.singleShot(0, Gui.ActiveDocument.resetEdit)
# -------------------------------------------------------------------------
# SCENE EVENTS CALLBACKS
# -------------------------------------------------------------------------
@@ -491,7 +486,6 @@ class Edit(gui_base_original.Modifier):
self.obj = doc.getObject(str(node.objectName.getValue()))
if self.obj is None:
return
self.setPlacement(self.obj)
App.Console.PrintMessage(self.obj.Name
+ ": editing node number "
@@ -539,127 +533,6 @@ class Edit(gui_base_original.Modifier):
self.showTrackers()
gui_tool_utils.redraw_3d_view()
# -------------------------------------------------------------------------
# UTILS
# -------------------------------------------------------------------------
def getObjsFromSelection(self):
"""Evaluate selection and return a valid object to edit."""
selection = Gui.Selection.getSelection()
self.edited_objects = []
if len(selection) > self.maxObjects:
App.Console.PrintMessage(translate("draft",
"Too many objects selected, max number set to: ")
+ str(self.maxObjects) + "\n")
return None
for obj in selection:
if utils.get_type(obj) in self.supportedObjs:
self.edited_objects.append(obj)
continue
elif utils.get_type(obj) in self.supportedPartObjs:
if obj.TypeId in self.supportedPartObjs:
self.edited_objects.append(obj)
continue
App.Console.PrintWarning(obj.Name
+ translate("draft",
": this object is not editable")
+ "\n")
return self.edited_objects
def get_selected_obj_at_position(self, pos):
"""Return object at given position.
If object is one of the edited objects (self.edited_objects).
"""
selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1]))
if not selobjs:
return
for info in selobjs:
if not info:
return
for obj in self.edited_objects:
if obj.Name == info["Object"]:
return obj
def numericInput(self, v, numy=None, numz=None):
"""Execute callback by the toolbar to activate the update function.
This function gets called by the toolbar
or by the mouse click and activate the update function.
"""
if numy:
v = App.Vector(v, numy, numz)
self.endEditing(self.obj, self.editing, v)
App.ActiveDocument.recompute()
def setSelectState(self, obj, selState=False):
if hasattr(obj.ViewObject, "Selectable"):
obj.ViewObject.Selectable = selState
def saveSelectState(self, obj):
if hasattr(obj.ViewObject, "Selectable"):
self.selectstate = obj.ViewObject.Selectable
def restoreSelectState(self,obj):
if obj:
if hasattr(obj.ViewObject,"Selectable") and (self.selectstate is not None):
obj.ViewObject.Selectable = self.selectstate
def setPlacement(self, obj):
"""Set placement of object.
Set self.pl and self.invpl to self.obj placement
and inverse placement.
"""
if not obj:
return
if "Placement" in obj.PropertiesList:
self.pl = obj.getGlobalPlacement()
self.invpl = self.pl.inverse()
def alignWorkingPlane(self):
"""Align working plane to self.obj."""
if "Shape" in self.obj.PropertiesList:
pass
#if DraftTools.plane.weak: TODO Use App.DraftWorkingPlane instead of DraftTools.plane
# DraftTools.plane.alignToFace(self.obj.Shape)
if self.planetrack:
self.planetrack.set(self.editpoints[0])
def getEditNode(self, pos):
"""Get edit node from given screen position."""
node = self.sendRay(pos)
return node
def sendRay(self, mouse_pos):
"""Send a ray through the scene and return the nearest entity."""
ray_pick = coin.SoRayPickAction(self.render_manager.getViewportRegion())
ray_pick.setPoint(coin.SbVec2s(*mouse_pos))
ray_pick.setRadius(self.pick_radius)
ray_pick.setPickAll(True)
ray_pick.apply(self.render_manager.getSceneGraph())
picked_point = ray_pick.getPickedPointList()
return self.searchEditNode(picked_point)
def searchEditNode(self, picked_point):
"""Search edit node inside picked point list and return node number."""
for point in picked_point:
path = point.getPath()
length = path.getLength()
point = path.getNode(length - 2)
#import DraftTrackers
if hasattr(point,"subElementName") and 'EditNode' in str(point.subElementName.getValue()):
return point
return None
def getEditNodeIndex(self, point):
"""Get edit node index from given screen position."""
if point:
subElement = str(point.subElementName.getValue())
ep = int(subElement[8:])
return ep
else:
return None
# -------------------------------------------------------------------------
# EDIT TRACKERS functions
@@ -755,21 +628,21 @@ class Edit(gui_base_original.Modifier):
def updateGhost(self, obj, idx, pt):
if utils.get_type(obj) in ["Wire"]:
self.ghost.on()
pointList = self.applyPlacement(obj.Points)
pointList = self.globalize_vectors(obj, obj.Points)
pointList[idx] = pt
if obj.Closed:
pointList.append(pointList[0])
self.ghost.updateFromPointlist(pointList)
elif utils.get_type(obj) == "BSpline":
self.ghost.on()
pointList = self.applyPlacement(obj.Points)
pointList = self.globalize_vectors(obj, obj.Points)
pointList[idx] = pt
if obj.Closed:
pointList.append(pointList[0])
self.ghost.update(pointList)
elif utils.get_type(obj) == "BezCurve":
self.ghost.on()
plist = self.applyPlacement(obj.Points)
plist = self.globalize_vectors(obj, obj.Points)
pointList = edit_draft.recomputePointsBezier(obj,plist,idx,pt,obj.Degree,moveTrackers=True)
self.ghost.update(pointList,obj.Degree)
elif utils.get_type(obj) == "Circle":
@@ -789,14 +662,15 @@ class Edit(gui_base_original.Modifier):
# edit by 3 points
if self.editing == 0:
# center point
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(edit_draft.getArcMid(obj, global_placement=True)))
p1 = self.relativize_vector(self.obj, self.obj.Shape.Vertexes[0].Point)
p2 = self.relativize_vector(self.obj, self.obj.Shape.Vertexes[1].Point)
p0 = DraftVecUtils.project(self.relativize_vector(self.obj, pt),
self.relativize_vector(self.obj, (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)
self.ghost.setEndPoint(self.obj.Shape.Vertexes[0].Point)
self.ghost.setCenter(self.pl.multVec(p0))
self.ghost.setCenter(self.globalize_vector(self.obj, p0))
return
else:
p1 = edit_draft.getArcStart(obj, global_placement=True)
@@ -820,19 +694,9 @@ class Edit(gui_base_original.Modifier):
elif self.editing == 2:
self.ghost.setEndPoint(pt)
elif self.editing == 3:
self.ghost.setRadius(self.invpl.multVec(pt).Length)
self.ghost.setRadius(self.relativize_vector(self.obj, pt).Length)
gui_tool_utils.redraw_3d_view()
def applyPlacement(self, pointList):
if self.pl:
plist = []
for p in pointList:
point = self.pl.multVec(p)
plist.append(point)
return plist
else:
return pointList
def finalizeGhost(self):
try:
self.ghost.finalize()
@@ -860,7 +724,6 @@ class Edit(gui_base_original.Modifier):
continue
self.obj = o
break
self.setPlacement(self.obj)
if utils.get_type(self.obj) == "Wire" and 'Edge' in info["Component"]:
pt = App.Vector(info["x"], info["y"], info["z"])
self.addPointToWire(self.obj, pt, int(info["Component"][4:]))
@@ -872,9 +735,7 @@ class Edit(gui_base_original.Modifier):
continue
self.addPointToCurve(pt, info)
self.obj.recompute()
self.removeTrackers(self.obj)
self.setEditPoints(self.obj)
# self.setSelectState(self.obj, False)
self.resetTrackers(self.obj)
return
def addPointToWire(self, obj, newPoint, edgeIndex):
@@ -887,11 +748,11 @@ class Edit(gui_base_original.Modifier):
for index, point in enumerate(self.obj.Points):
if index == edgeIndex:
newPoints.append(self.invpl.multVec(newPoint))
newPoints.append(self.relativize_vector(self.obj, newPoint))
newPoints.append(point)
if obj.Closed and edgeIndex == len(obj.Points):
# last segment when object is closed
newPoints.append(self.invpl.multVec(newPoint))
newPoints.append(self.relativize_vector(self.obj, newPoint))
obj.Points = newPoints
def addPointToCurve(self, point, info=None):
@@ -939,11 +800,11 @@ class Edit(gui_base_original.Modifier):
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))
pts.insert(i + 1, self.relativize_vector(self.obj, 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))
pts.append(self.relativize_vector(self.obj, point))
self.obj.Points = pts
def delPoint(self, event):
@@ -975,112 +836,11 @@ class Edit(gui_base_original.Modifier):
self.obj.recompute()
# don't do tan/sym on DWire/BSpline!
self.removeTrackers(self.obj)
self.setEditPoints(self.obj)
# -------------------------------------------------------------------------
# EDIT OBJECT TOOLS : GENERAL
# -------------------------------------------------------------------------
def setEditPoints(self, obj):
"""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
self.setTrackers(obj, self.editpoints)
self.editpoints = []
def getEditPoints(self, obj):
"""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 edit_draft.getWirePts(obj)
elif objectType == "BezCurve":
self.ui.editUi("BezCurve")
edit_draft.resetTrackersBezier(obj)
self.editpoints = []
return
elif objectType == "Circle":
return edit_draft.getCirclePts(obj)
elif objectType == "Rectangle":
return edit_draft.getRectanglePts(obj)
elif objectType == "Polygon":
return edit_draft.getPolygonPts(obj)
elif objectType in ("Dimension","LinearDimension"):
return edit_draft.getDimensionPts(obj)
elif objectType == "Wall":
return edit_arch.getWallPts(obj)
elif objectType == "Window":
return edit_arch.getWindowPts(obj)
elif objectType == "Space":
return edit_arch.getSpacePts(obj)
elif objectType == "Structure":
return edit_arch.getStructurePts(obj)
elif objectType == "PanelCut":
return edit_arch.getPanelCutPts(obj)
elif objectType == "PanelSheet":
return edit_arch.getPanelSheetPts(obj)
elif objectType == "Part" and obj.TypeId == "Part::Box":
return edit_part.getPartBoxPts(obj)
elif objectType == "Part::Line" and obj.TypeId == "Part::Line":
return edit_part.getPartLinePts(obj)
elif objectType == "Sketch":
return edit_arch.getSketchPts(obj)
else:
return None
def update(self, obj, nodeIndex, v):
"""Apply the App.Vector to the modified point and update self.obj."""
objectType = utils.get_type(obj)
App.ActiveDocument.openTransaction("Edit")
if objectType in ["Wire", "BSpline"]:
edit_draft.updateWire(obj, nodeIndex, v)
elif objectType == "BezCurve":
edit_draft.updateWire(obj, nodeIndex, v)
elif objectType == "Circle":
edit_draft.updateCircle(obj, nodeIndex, v, self.alt_edit_mode)
elif objectType == "Rectangle":
edit_draft.updateRectangle(obj, nodeIndex, v)
elif objectType == "Polygon":
edit_draft.updatePolygon(obj, nodeIndex, v)
elif objectType in ("Dimension","LinearDimension"):
edit_draft.updateDimension(obj, nodeIndex, v)
elif objectType == "Sketch":
edit_arch.updateSketch(obj, nodeIndex, v)
elif objectType == "Wall":
edit_arch.updateWall(obj, nodeIndex, v)
elif objectType == "Window":
edit_arch.updateWindow(obj, nodeIndex, v)
elif objectType == "Space":
edit_arch.updateSpace(obj, nodeIndex, v)
elif objectType == "Structure":
edit_arch.updateStructure(obj, nodeIndex, v)
elif objectType == "PanelCut":
edit_arch.updatePanelCut(obj, nodeIndex, v)
elif objectType == "PanelSheet":
edit_arch.updatePanelSheet(obj, nodeIndex, v)
elif objectType == "Part::Line" and self.obj.TypeId == "Part::Line":
edit_arch.updatePartLine(obj, nodeIndex, v)
elif objectType == "Part" and self.obj.TypeId == "Part::Box":
edit_arch.updatePartBox(obj, nodeIndex, v)
obj.recompute()
App.ActiveDocument.commitTransaction()
try:
gui_tool_utils.redraw_3d_view()
except AttributeError as err:
pass
self.resetTrackers(self.obj)
# ------------------------------------------------------------------------
# Context menu
# DRAFT EDIT Context menu
# ------------------------------------------------------------------------
def display_tracker_menu(self, event):
@@ -1124,6 +884,7 @@ class Edit(gui_base_original.Modifier):
self.tracker_menu.popup(Gui.getMainWindow().cursor().pos())
QtCore.QObject.connect(self.tracker_menu,QtCore.SIGNAL("triggered(QAction *)"),self.evaluate_menu_action)
def evaluate_menu_action(self, labelname):
action_label = str(labelname.text())
# Bezier curve menu
@@ -1154,4 +915,293 @@ class Edit(gui_base_original.Modifier):
del self.event
# -------------------------------------------------------------------------
# EDIT OBJECT TOOLS
#
# This section contains the code to retrieve the object points and update them
#
# -------------------------------------------------------------------------
def getEditPoints(self, obj):
"""Return a list of App.Vectors according to the given object edit nodes.
"""
eps = None
objectType = utils.get_type(obj)
if objectType in ["Wire", "BSpline"]:
eps = edit_draft.getWirePts(obj)
elif objectType == "BezCurve":
self.ui.editUi("BezCurve")
edit_draft.resetTrackersBezier(obj)
return
elif objectType == "Circle":
eps = edit_draft.getCirclePts(obj)
elif objectType == "Rectangle":
eps = edit_draft.getRectanglePts(obj)
elif objectType == "Polygon":
eps = edit_draft.getPolygonPts(obj)
elif objectType == "Ellipse":
eps = edit_draft.getEllipsePts(obj)
elif objectType in ("Dimension","LinearDimension"):
eps = edit_draft.getDimensionPts(obj)
elif objectType == "Wall":
eps = self.globalize_vectors(obj, edit_arch.getWallPts(obj))
if obj.Base and utils.get_type(obj.Base) in ["Wire","Circle",
"Rectangle", "Polygon", "Sketch"]:
basepoints = self.getEditPoints(obj.Base)
for point in basepoints:
eps.append(obj.Placement.multVec(point)) #works ok except if App::Part is rotated... why?
return eps
elif objectType == "Window":
eps = edit_arch.getWindowPts(obj)
elif objectType == "Space":
eps = edit_arch.getSpacePts(obj)
elif objectType == "Structure":
eps = edit_arch.getStructurePts(obj)
elif objectType == "PanelCut":
eps = edit_arch.getPanelCutPts(obj)
elif objectType == "PanelSheet":
eps = edit_arch.getPanelSheetPts(obj)
elif objectType == "Part" and obj.TypeId == "Part::Box":
eps = edit_part.getPartBoxPts(obj)
elif objectType == "Part::Line" and obj.TypeId == "Part::Line":
eps = edit_part.getPartLinePts(obj)
elif objectType == "Sketch":
eps = edit_arch.getSketchPts(obj)
if eps:
return self.globalize_vectors(obj, eps)
else:
return None
def update(self, obj, nodeIndex, v):
"""Apply the App.Vector to the modified point and update self.obj."""
v = self.relativize_vector(obj, v)
App.ActiveDocument.openTransaction("Edit")
self.update_object(obj, nodeIndex, v)
App.ActiveDocument.commitTransaction()
if not utils.get_type(obj) in ["Wire", "BSpline"]:
self.resetTrackers(obj)
try:
gui_tool_utils.redraw_3d_view()
except AttributeError as err:
pass
def update_object(self, obj, nodeIndex, v):
objectType = utils.get_type(obj)
if objectType in ["Wire", "BSpline"]:
edit_draft.updateWire(obj, nodeIndex, v)
elif objectType == "BezCurve":
edit_draft.updateWire(obj, nodeIndex, v)
elif objectType == "Circle":
edit_draft.updateCircle(obj, nodeIndex, v, self.alt_edit_mode)
elif objectType == "Rectangle":
edit_draft.updateRectangle(obj, nodeIndex, v)
elif objectType == "Polygon":
edit_draft.updatePolygon(obj, nodeIndex, v)
elif objectType == "Ellipse":
edit_draft.updateEllipse(obj, nodeIndex, v)
elif objectType in ("Dimension","LinearDimension"):
edit_draft.updateDimension(obj, nodeIndex, v)
elif objectType == "Sketch":
edit_arch.updateSketch(obj, nodeIndex, v)
elif objectType == "Wall":
if nodeIndex == 0:
edit_arch.updateWall(obj, nodeIndex, v)
elif nodeIndex > 0:
if obj.Base:
if utils.get_type(obj.Base) in ["Wire", "Circle", "Rectangle",
"Polygon", "Sketch"]:
self.update(obj.Base, nodeIndex - 1, v)
elif objectType == "Window":
edit_arch.updateWindow(obj, nodeIndex, v)
elif objectType == "Space":
edit_arch.updateSpace(obj, nodeIndex, v)
elif objectType == "Structure":
edit_arch.updateStructure(obj, nodeIndex, v)
elif objectType == "PanelCut":
edit_arch.updatePanelCut(obj, nodeIndex, v)
elif objectType == "PanelSheet":
edit_arch.updatePanelSheet(obj, nodeIndex, v)
elif objectType == "Part::Line" and self.obj.TypeId == "Part::Line":
edit_part.updatePartLine(obj, nodeIndex, v)
elif objectType == "Part" and self.obj.TypeId == "Part::Box":
edit_part.updatePartBox(obj, nodeIndex, v)
obj.recompute()
# -------------------------------------------------------------------------
# UTILS
# -------------------------------------------------------------------------
def getObjsFromSelection(self):
"""Evaluate selection and return a valid object to edit.
#to be used for app link support
for selobj in Gui.Selection.getSelectionEx('', 0):
for sub in selobj.SubElementNames:
obj = selobj.Object
obj_matrix = selobj.Object.getSubObject(sub, retType=4)
"""
selection = Gui.Selection.getSelection()
self.edited_objects = []
if len(selection) > self.maxObjects:
App.Console.PrintMessage(translate("draft",
"Too many objects selected, max number set to: ")
+ str(self.maxObjects) + "\n")
return None
for obj in selection:
if utils.get_type(obj) in self.supportedObjs:
self.edited_objects.append(obj)
continue
elif utils.get_type(obj) in self.supportedPartObjs:
if obj.TypeId in self.supportedPartObjs:
self.edited_objects.append(obj)
continue
App.Console.PrintWarning(obj.Name
+ translate("draft",
": this object is not editable")
+ "\n")
return self.edited_objects
def format_objects_for_editing(self, objs):
"""Change objects style during editing mode.
"""
for obj in objs:
# TODO: Placeholder for changing the Selectable property of obj ViewProvide
if utils.get_type(obj) == "Structure":
self.objs_formats[obj.Name] = edit_arch.get_structure_format(obj)
edit_arch.set_structure_editing_format(obj)
def deformat_objects_after_editing(self, objs):
"""Restore objects style during editing mode.
"""
for obj in objs:
# TODO: Placeholder for changing the Selectable property of obj ViewProvide
if utils.get_type(obj) == "Structure":
edit_arch.restore_structure_format(obj, self.objs_formats[obj.Name])
def get_selected_obj_at_position(self, pos):
"""Return object at given position.
If object is one of the edited objects (self.edited_objects).
"""
selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1]))
if not selobjs:
return
for info in selobjs:
if not info:
return
for obj in self.edited_objects:
if obj.Name == info["Object"]:
return obj
def globalize_vectors(self, obj, pointList):
"""Return the given point list in the global coordinate system."""
plist = []
for p in pointList:
point = self.globalize_vector(obj, p)
plist.append(point)
return plist
def globalize_vector(self, obj, point):
"""Return the given point in the global coordinate system."""
if hasattr(obj, "getGlobalPlacement"):
return obj.getGlobalPlacement().multVec(point)
else:
return point
def relativize_vectors(self, obj, pointList):
"""Return the given point list in the given object coordinate system."""
plist = []
for p in pointList:
point = self.relativize_vector(obj, p)
plist.append(point)
return plist
def relativize_vector(self, obj, point):
"""Return the given point in the given object coordinate system."""
if hasattr(obj, "getGlobalPlacement"):
return obj.getGlobalPlacement().inverse().multVec(point)
else:
return point
def getEditNode(self, pos):
"""Get edit node from given screen position."""
node = self.sendRay(pos)
return node
def sendRay(self, mouse_pos):
"""Send a ray through the scene and return the nearest entity."""
ray_pick = coin.SoRayPickAction(self.render_manager.getViewportRegion())
ray_pick.setPoint(coin.SbVec2s(*mouse_pos))
ray_pick.setRadius(self.pick_radius)
ray_pick.setPickAll(True)
ray_pick.apply(self.render_manager.getSceneGraph())
picked_point = ray_pick.getPickedPointList()
return self.searchEditNode(picked_point)
def searchEditNode(self, picked_point):
"""Search edit node inside picked point list and return node number."""
for point in picked_point:
path = point.getPath()
length = path.getLength()
point = path.getNode(length - 2)
#import DraftTrackers
if hasattr(point,"subElementName") and 'EditNode' in str(point.subElementName.getValue()):
return point
return None
def getEditNodeIndex(self, point):
"""Get edit node index from given screen position."""
if point:
subElement = str(point.subElementName.getValue())
ep = int(subElement[8:])
return ep
else:
return None
Gui.addCommand('Draft_Edit', Edit())

View File

@@ -23,7 +23,7 @@
"""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
# \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, "
@@ -50,8 +50,8 @@ def getSketchPts(obj):
"""
editpoints = []
if obj.GeometryCount == 1:
editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,1)))
editpoints.append(obj.getGlobalPlacement().multVec(obj.getPoint(0,2)))
editpoints.append(obj.getPoint(0,1))
editpoints.append(obj.getPoint(0,2))
return editpoints
else:
_wrn = translate("draft", "Sketch is too complex to edit: "
@@ -69,9 +69,9 @@ def updateSketch(obj, nodeIndex, v):
1 : endpoint
"""
if nodeIndex == 0:
obj.movePoint(0,1,obj.getGlobalPlacement().inverse().multVec(v))
obj.movePoint(0, 1, v)
elif nodeIndex == 1:
obj.movePoint(0,2,obj.getGlobalPlacement().inverse().multVec(v))
obj.movePoint(0, 2, v)
obj.recompute()
@@ -85,38 +85,15 @@ def getWallPts(obj):
"""
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?
editpoints.append(App.Vector(0, 0, obj.Height))
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))
vz = DraftVecUtils.project(v, 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()
@@ -153,29 +130,34 @@ def updateWindow(obj, nodeIndex, v):
# STRUCTURE----------------------------------------------------------------
def get_structure_format(obj):
return (obj.ViewObject.DisplayMode,
obj.ViewObject.NodeSize,
obj.ViewObject.ShowNodes)
def set_structure_editing_format(obj):
obj.ViewObject.DisplayMode = "Wireframe"
obj.ViewObject.NodeSize = 1
obj.ViewObject.ShowNodes = True
def restore_structure_format(obj, modes):
obj.ViewObject.DisplayMode = modes[0]
obj.ViewObject.NodeSize = modes[1]
obj.ViewObject.ShowNodes = modes[2]
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
for p in obj.Nodes:
editpoints.append(p)
return editpoints
else:
return None
def updateStructure(obj, nodeIndex, v):
nodes = obj.Nodes
nodes[nodeIndex] = obj.Placement.inverse().multVec(v)
nodes[nodeIndex] = v
obj.Nodes = nodes
@@ -202,26 +184,26 @@ def getPanelCutPts(obj):
if obj.TagPosition.Length == 0:
pos = obj.Shape.BoundBox.Center
else:
pos = obj.Placement.multVec(obj.TagPosition)
pos = obj.TagPosition
editpoints.append(pos)
return editpoints
def updatePanelCut(obj, nodeIndex, v):
if nodeIndex == 0:
obj.TagPosition = obj.Placement.inverse().multVec(v)
obj.TagPosition = v
def getPanelSheetPts(obj):
editpoints = []
editpoints.append(obj.Placement.multVec(obj.TagPosition))
editpoints.append(obj.TagPosition)
for o in obj.Group:
editpoints.append(obj.Placement.multVec(o.Placement.Base))
editpoints.append(o.Placement.Base)
return editpoints
def updatePanelSheet(obj, nodeIndex, v):
if nodeIndex == 0:
obj.TagPosition = obj.Placement.inverse().multVec(v)
obj.TagPosition = v
else:
obj.Group[nodeIndex-1].Placement.Base = obj.Placement.inverse().multVec(v)
obj.Group[nodeIndex-1].Placement.Base = v

View File

@@ -20,10 +20,22 @@
# * USA *
# * *
# ***************************************************************************
"""Provide the Draft_Edit command used by the Draft workbench."""
"""Provide the support functions to Draft_Edit for Draft objects.
All functions in this module work with Object coordinate space.
No conversion to global coordinate system is needed.
To support an new Object Draft_Edit needs at least two functions:
getObjectPts(obj): returns a list of points on which Draft_Edit will display
edit trackers
updateObject(obj, nodeIndex, v): update the give object according to the
index of a moved edit tracker and the vector of the displacement
TODO: Abstract the code that handles the preview and move the object specific
code to this module from main Draft_Edit module
"""
## @package gui_edit_draft_objects
# \ingroup DRAFT
# \brief Provide the Draft_Edit command used by the Draft workbench
# \brief Provide the support functions to Draft_Edit for Draft objects.
__title__ = "FreeCAD Draft Edit Tool"
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
@@ -46,13 +58,12 @@ import draftutils.utils as utils
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)
editPnt = 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 (
@@ -272,34 +283,20 @@ def getRectanglePts(obj):
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)))
editpoints.append(App.Vector(0, 0, 0))
editpoints.append(App.Vector(obj.Length, 0, 0))
editpoints.append(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)
obj.Placement.Base = obj.Placement.multVec(v)
elif nodeIndex == 1:
obj.Length = DraftVecUtils.project(delta,App.Vector(1,0,0)).Length
obj.Length = DraftVecUtils.project(v, App.Vector(1,0,0)).Length
elif nodeIndex == 2:
obj.Height = DraftVecUtils.project(delta,App.Vector(0,1,0)).Length
obj.Height = DraftVecUtils.project(v, 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
# -------------------------------------------------------------------------
@@ -430,30 +427,50 @@ def arcInvert(obj):
# -------------------------------------------------------------------------
# EDIT OBJECT TOOLS : Polygon (maybe could also rotate the polygon)
# EDIT OBJECT TOOLS : Ellipse
# -------------------------------------------------------------------------
def getEllipsePts(obj):
editpoints = []
editpoints.append(App.Vector(0, 0, 0))
editpoints.append(App.Vector(obj.MajorRadius, 0, 0))
editpoints.append(App.Vector(0, obj.MinorRadius, 0))
return editpoints
def updateEllipse(obj, nodeIndex, v):
if nodeIndex == 0:
obj.Placement.Base = obj.Placement.multVec(v)
elif nodeIndex == 1:
obj.MajorRadius = v.Length
elif nodeIndex == 2:
if v.Length <= obj.MajorRadius:
obj.MinorRadius = v.Length
else:
obj.MinorRadius = obj.MajorRadius
obj.recompute()
# -------------------------------------------------------------------------
# EDIT OBJECT TOOLS : Polygon
# -------------------------------------------------------------------------
def getPolygonPts(obj):
editpoints = []
editpoints.append(obj.Placement.Base)
editpoints.append(obj.Shape.Vertexes[0].Point)
editpoints.append(App.Vector(0, 0, 0))
if obj.DrawMode == 'inscribed':
editpoints.append(obj.Placement.inverse().multVec(obj.Shape.Vertexes[0].Point))
else:
editpoints.append(obj.Placement.inverse().multVec((obj.Shape.Vertexes[0].Point +
obj.Shape.Vertexes[1].Point) / 2
))
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
obj.Placement.Base = obj.Placement.multVec(v)
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()
obj.Radius = v.Length
obj.recompute()
# -------------------------------------------------------------------------

View File

@@ -21,7 +21,7 @@
"""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
# \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, "
@@ -37,43 +37,40 @@ import DraftVecUtils
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)))
editpoints.append(App.Vector(obj.X1,obj.Y1,obj.Z1))
editpoints.append(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
obj.X1 = v.x
obj.Y1 = v.y
obj.Z1 = v.z
elif nodeIndex == 1:
obj.X2 = pt.x
obj.Y2 = pt.y
obj.Z2 = pt.z
obj.X2 = v.x
obj.Y2 = v.y
obj.Z2 = v.z
# PART::BOX---------------------------------------------------------------
def getPartBoxPts(self, obj):
def getPartBoxPts(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)))
editpoints.append(App.Vector(0, 0, 0))
editpoints.append(App.Vector(obj.Length, 0, 0))
editpoints.append(App.Vector(0, obj.Width, 0))
editpoints.append(App.Vector(0, 0, obj.Height))
return editpoints
def updatePartBox(self, obj, nodeIndex, v):
delta = obj.Placement.inverse().multVec(v)
def updatePartBox(obj, nodeIndex, v):
if nodeIndex == 0:
obj.Placement.Base = v
obj.Placement.Base = obj.Placement.Base + v
elif nodeIndex == 1:
_vector = DraftVecUtils.project(delta, App.Vector(1, 0, 0))
_vector = DraftVecUtils.project(v, App.Vector(1, 0, 0))
obj.Length = _vector.Length
elif nodeIndex == 2:
_vector = DraftVecUtils.project(delta, App.Vector(0, 1, 0))
_vector = DraftVecUtils.project(v, App.Vector(0, 1, 0))
obj.Width = _vector.Length
elif nodeIndex == 3:
_vector = DraftVecUtils.project(delta, App.Vector(0, 0, 1))
_vector = DraftVecUtils.project(v, App.Vector(0, 0, 1))
obj.Height = _vector.Length

View File

@@ -147,7 +147,7 @@ def autogroup(obj):
obj.X = real_point.x
obj.Y = real_point.y
obj.Z = real_point.z
elif get_type(obj) in ["Dimension"]:
elif get_type(obj) in ["Dimension", "LinearDimension"]:
obj.Start = inverse_placement.multVec(obj.Start)
obj.End = inverse_placement.multVec(obj.End)
obj.Dimline = inverse_placement.multVec(obj.Dimline)