primera subida
This commit is contained in:
501
Utils/profile_editor.py
Normal file
501
Utils/profile_editor.py
Normal file
@@ -0,0 +1,501 @@
|
||||
# from curve workbench
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import Part
|
||||
import PySide.QtCore as QtCore
|
||||
import PySide.QtGui as QtGui
|
||||
from pivy import coin
|
||||
|
||||
from Utils import graphics
|
||||
|
||||
|
||||
def parameterization(points, a, closed):
|
||||
"""Computes a knot Sequence for a set of points
|
||||
fac (0-1) : parameterization factor
|
||||
fac=0 -> Uniform / fac=0.5 -> Centripetal / fac=1.0 -> Chord-Length"""
|
||||
pts = points.copy()
|
||||
if closed and pts[0].distanceToPoint(pts[-1]) > 1e-7: # we need to add the first point as the end point
|
||||
pts.append(pts[0])
|
||||
params = [0]
|
||||
for i in range(1, len(pts)):
|
||||
p = pts[i] - pts[i - 1]
|
||||
if isinstance(p, FreeCAD.Vector):
|
||||
le = p.Length
|
||||
else:
|
||||
le = p.length()
|
||||
pl = pow(le, a)
|
||||
params.append(params[-1] + pl)
|
||||
return params
|
||||
|
||||
class ConnectionMarker(graphics.Marker):
|
||||
def __init__(self, points):
|
||||
super(ConnectionMarker, self).__init__(points, True)
|
||||
|
||||
class MarkerOnShape(graphics.Marker):
|
||||
def __init__(self, points, sh=None):
|
||||
super(MarkerOnShape, self).__init__(points, True)
|
||||
self._shape = None
|
||||
self._sublink = None
|
||||
self._tangent = None
|
||||
self._translate = coin.SoTranslation()
|
||||
self._text_font = coin.SoFont()
|
||||
self._text_font.name = "Arial:Bold"
|
||||
self._text_font.size = 13.0
|
||||
self._text = coin.SoText2()
|
||||
self._text_switch = coin.SoSwitch()
|
||||
self._text_switch.addChild(self._translate)
|
||||
self._text_switch.addChild(self._text_font)
|
||||
self._text_switch.addChild(self._text)
|
||||
self.on_drag_start.append(self.add_text)
|
||||
self.on_drag_release.append(self.remove_text)
|
||||
self.addChild(self._text_switch)
|
||||
if isinstance(sh, Part.Shape):
|
||||
self.snap_shape = sh
|
||||
elif isinstance(sh, (tuple, list)):
|
||||
self.sublink = sh
|
||||
|
||||
def subshape_from_sublink(self, o):
|
||||
name = o[1][0]
|
||||
print(name, " selected")
|
||||
if 'Vertex' in name:
|
||||
n = eval(name.lstrip('Vertex'))
|
||||
return o[0].Shape.Vertexes[n - 1]
|
||||
elif 'Edge' in name:
|
||||
n = eval(name.lstrip('Edge'))
|
||||
return o[0].Shape.Edges[n - 1]
|
||||
elif 'Face' in name:
|
||||
n = eval(name.lstrip('Face'))
|
||||
return o[0].Shape.Faces[n - 1]
|
||||
|
||||
def add_text(self):
|
||||
self._text_switch.whichChild = coin.SO_SWITCH_ALL
|
||||
self.on_drag.append(self.update_text)
|
||||
|
||||
def remove_text(self):
|
||||
self._text_switch.whichChild = coin.SO_SWITCH_NONE
|
||||
self.on_drag.remove(self.update_text)
|
||||
|
||||
def update_text(self):
|
||||
p = self.points[0]
|
||||
coords = ['{: 9.3f}'.format(p[0]), '{: 9.3f}'.format(p[1]), '{: 9.3f}'.format(p[2])]
|
||||
self._translate.translation = p
|
||||
self._text.string.setValues(0, 3, coords)
|
||||
|
||||
@property
|
||||
def tangent(self):
|
||||
return self._tangent
|
||||
|
||||
@tangent.setter
|
||||
def tangent(self, t):
|
||||
if isinstance(t, FreeCAD.Vector):
|
||||
if t.Length > 1e-7:
|
||||
self._tangent = t
|
||||
self._tangent.normalize()
|
||||
self.marker.markerIndex = coin.SoMarkerSet.DIAMOND_FILLED_9_9
|
||||
else:
|
||||
self._tangent = None
|
||||
self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9
|
||||
else:
|
||||
self._tangent = None
|
||||
self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9
|
||||
|
||||
@property
|
||||
def snap_shape(self):
|
||||
return self._shape
|
||||
|
||||
@snap_shape.setter
|
||||
def snap_shape(self, sh):
|
||||
if isinstance(sh, Part.Shape):
|
||||
self._shape = sh
|
||||
else:
|
||||
self._shape = None
|
||||
self.alter_color()
|
||||
|
||||
@property
|
||||
def sublink(self):
|
||||
return self._sublink
|
||||
|
||||
@sublink.setter
|
||||
def sublink(self, sl):
|
||||
if isinstance(sl, (tuple, list)) and not (sl == self._sublink):
|
||||
self._shape = self.subshape_from_sublink(sl)
|
||||
self._sublink = sl
|
||||
else:
|
||||
self._shape = None
|
||||
self._sublink = None
|
||||
self.alter_color()
|
||||
|
||||
def alter_color(self):
|
||||
if isinstance(self._shape, Part.Vertex):
|
||||
self.set_color("white")
|
||||
elif isinstance(self._shape, Part.Edge):
|
||||
self.set_color("cyan")
|
||||
elif isinstance(self._shape, Part.Face):
|
||||
self.set_color("magenta")
|
||||
else:
|
||||
self.set_color("black")
|
||||
|
||||
def __repr__(self):
|
||||
return "MarkerOnShape({})".format(self._shape)
|
||||
|
||||
def drag(self, mouse_coords, fact=1.):
|
||||
if self.enabled:
|
||||
pts = self.points
|
||||
for i, p in enumerate(pts):
|
||||
p[0] = mouse_coords[0] * fact + self._tmp_points[i][0]
|
||||
p[1] = mouse_coords[1] * fact + self._tmp_points[i][1]
|
||||
p[2] = mouse_coords[2] * fact + self._tmp_points[i][2]
|
||||
if self._shape:
|
||||
v = Part.Vertex(p[0], p[1], p[2])
|
||||
proj = v.distToShape(self._shape)[1][0][1]
|
||||
# FreeCAD.Console.PrintMessage("%s -> %s\n"%(p.getValue(), proj))
|
||||
p[0] = proj.x
|
||||
p[1] = proj.y
|
||||
p[2] = proj.z
|
||||
self.points = pts
|
||||
for foo in self.on_drag:
|
||||
foo()
|
||||
|
||||
|
||||
class ConnectionPolygon(graphics.Polygon):
|
||||
std_col = "green"
|
||||
|
||||
def __init__(self, markers):
|
||||
super(ConnectionPolygon, self).__init__(
|
||||
sum([m.points for m in markers], []), True)
|
||||
self.markers = markers
|
||||
|
||||
for m in self.markers:
|
||||
m.on_drag.append(self.updatePolygon)
|
||||
|
||||
def updatePolygon(self):
|
||||
self.points = sum([m.points for m in self.markers], [])
|
||||
|
||||
@property
|
||||
def drag_objects(self):
|
||||
return self.markers
|
||||
|
||||
def check_dependency(self):
|
||||
if any([m._delete for m in self.markers]):
|
||||
self.delete()
|
||||
|
||||
class ConnectionLine(graphics.Line):
|
||||
def __init__(self, markers):
|
||||
super(ConnectionLine, self).__init__(
|
||||
sum([m.points for m in markers], []), True)
|
||||
self.markers = markers
|
||||
self._linear = False
|
||||
for m in self.markers:
|
||||
m.on_drag.append(self.updateLine)
|
||||
|
||||
def updateLine(self):
|
||||
self.points = sum([m.points for m in self.markers], [])
|
||||
if self._linear:
|
||||
p1 = self.markers[0].points[0]
|
||||
p2 = self.markers[-1].points[0]
|
||||
t = p2 - p1
|
||||
tan = FreeCAD.Vector(t[0], t[1], t[2])
|
||||
for m in self.markers:
|
||||
m.tangent = tan
|
||||
|
||||
@property
|
||||
def linear(self):
|
||||
return self._linear
|
||||
|
||||
@linear.setter
|
||||
def linear(self, b):
|
||||
self._linear = bool(b)
|
||||
|
||||
@property
|
||||
def drag_objects(self):
|
||||
return self.markers
|
||||
|
||||
def check_dependency(self):
|
||||
if any([m._delete for m in self.markers]):
|
||||
self.delete()
|
||||
|
||||
|
||||
class Edit(object):
|
||||
|
||||
def __init__(self, obj=None):
|
||||
self.obj = obj
|
||||
self.root_inserted = False
|
||||
self.root = None
|
||||
|
||||
self.editing = None
|
||||
|
||||
# event callbacks
|
||||
self.selection_callback = None
|
||||
self._keyPressedCB = None
|
||||
self._mouseMovedCB = None
|
||||
self._mousePressedCB = None
|
||||
|
||||
# Setup coin objects
|
||||
self.guidoc = self.obj.ViewObject.Document
|
||||
self.view = self.guidoc.ActiveView
|
||||
self.rm = self.view.getViewer().getSoRenderManager()
|
||||
self.sg = self.view.getSceneGraph()
|
||||
self.setupInteractionSeparator()
|
||||
|
||||
# Callbacks
|
||||
self.unregister_editing_callbacks()
|
||||
self.register_editing_callbacks()
|
||||
|
||||
def setupInteractionSeparator(self):
|
||||
if self.root_inserted:
|
||||
self.sg.removeChild(self.root)
|
||||
self.root = graphics.InteractionSeparator(self.rm)
|
||||
self.root.setName("InteractionSeparator")
|
||||
self.root.pick_radius = 40
|
||||
|
||||
# Populate root node
|
||||
#self.root += self.points
|
||||
#self.build_lines()
|
||||
#self.root += self.lines
|
||||
|
||||
# set FreeCAD color scheme
|
||||
'''for o in self.points + self.lines:
|
||||
o.ovr_col = "yellow"
|
||||
o.sel_col = "green"'''
|
||||
|
||||
self.root.register()
|
||||
self.sg.addChild(self.root)
|
||||
self.root_inserted = True
|
||||
self.root.selected_objects = list()
|
||||
|
||||
def build_lines(self):
|
||||
for i in range(len(self.points) - 1):
|
||||
line = ConnectionLine([self.points[i], self.points[i + 1]])
|
||||
line.set_color("blue")
|
||||
self.lines.append(line)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# SCENE EVENTS CALLBACKS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def register_editing_callbacks(self):
|
||||
""" Register editing callbacks (former action function) """
|
||||
|
||||
print("Registering callbacks")
|
||||
|
||||
if self._keyPressedCB is None:
|
||||
self._keyPressedCB = self.root.events.addEventCallback(coin.SoKeyboardEvent.getClassTypeId(), self.keyPressed)
|
||||
|
||||
if self._mousePressedCB is None:
|
||||
self._mousePressedCB = self.root.events.addEventCallback(coin.SoMouseButtonEvent.getClassTypeId(), self.mousePressed)
|
||||
|
||||
if self._mouseMovedCB is None:
|
||||
self._mouseMovedCB = self.root.events.addEventCallback(coin.SoLocation2Event.getClassTypeId(), self.mouseMoved)
|
||||
|
||||
def unregister_editing_callbacks(self):
|
||||
""" Remove callbacks used during editing if they exist """
|
||||
|
||||
print("Unregistering")
|
||||
|
||||
if self._keyPressedCB:
|
||||
self.root.events.removeEventCallback(coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB)
|
||||
self._keyPressedCB = None
|
||||
|
||||
if self._mousePressedCB:
|
||||
self.root.events.removeEventCallback(coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB)
|
||||
self._mousePressedCB = None
|
||||
|
||||
if self._mouseMovedCB:
|
||||
self.root.events.removeEventCallback(coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB)
|
||||
self._mouseMovedCB = None
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# SCENE EVENT HANDLERS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def keyPressed(self, attr, event_callback):
|
||||
event = event_callback.getEvent()
|
||||
print(event.getKey())
|
||||
if event.getState() == event.UP:
|
||||
#FreeCAD.Console.PrintMessage("Key pressed : %s\n"%event.getKey())
|
||||
if event.getKey() == ord("i"):
|
||||
self.subdivide()
|
||||
elif event.getKey() == ord("q"):# or event.getKey() == ord(65307):
|
||||
if self.obj:
|
||||
self.obj.ViewObject.Proxy.doubleClicked(self.obj.ViewObject)
|
||||
else:
|
||||
self.quit()
|
||||
elif event.getKey() == ord("s"):
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
tup = None
|
||||
if len(sel) == 1:
|
||||
tup = (sel[0].Object, sel[0].SubElementNames)
|
||||
for i in range(len(self.root.selected_objects)):
|
||||
if isinstance(self.root.selected_objects[i], MarkerOnShape):
|
||||
self.root.selected_objects[i].sublink = tup
|
||||
#FreeCAD.Console.PrintMessage("Snapped to {}\n".format(str(self.root.selected_objects[i].sublink)))
|
||||
self.root.selected_objects[i].drag_start()
|
||||
self.root.selected_objects[i].drag((0, 0, 0.))
|
||||
self.root.selected_objects[i].drag_release()
|
||||
elif (event.getKey() == 65535) or (event.getKey() == 65288): # Suppr or Backspace
|
||||
# FreeCAD.Console.PrintMessage("Some objects have been deleted\n")
|
||||
pts = list()
|
||||
for o in self.root.dynamic_objects:
|
||||
if isinstance(o, MarkerOnShape):
|
||||
pts.append(o)
|
||||
self.points = pts
|
||||
self.setupInteractionSeparator()
|
||||
elif event.getKey() == 65307:
|
||||
self.quit()
|
||||
|
||||
def mousePressed(self, attr, event_callback):
|
||||
""" Mouse button event handler, calls: startEditing, endEditing, addPoint, delPoint """
|
||||
event = event_callback.getEvent()
|
||||
if (event.getState() == coin.SoMouseButtonEvent.DOWN) and (event.getButton() == event.BUTTON1): # left click
|
||||
print("Mouse button down and mouse button 1")
|
||||
if not event.wasAltDown():
|
||||
if self.editing is None:
|
||||
''' do something'''
|
||||
else:
|
||||
self.endEditing(self.obj, self.editing)
|
||||
|
||||
elif event.wasAltDown(): # left click with ctrl down
|
||||
self.display_tracker_menu(event)
|
||||
|
||||
elif (event.getState() == coin.SoMouseButtonEvent.DOWN) and (event.getButton() == event.BUTTON2): # right click
|
||||
self.display_tracker_menu(event)
|
||||
|
||||
def mouseMoved(self, attr, event_callback):
|
||||
""" Execute as callback for mouse movement. Update tracker position and update preview ghost. """
|
||||
|
||||
event = event_callback.getEvent()
|
||||
pos = event.getPosition()
|
||||
listObjects = FreeCADGui.ActiveDocument.ActiveView.getObjectsInfo((int(pos[0]), int(pos[1])))
|
||||
if listObjects:
|
||||
#{'x': 483239.09375, 'y': 783855.8125, 'z': 797695.0, 'Document': 'Salinas_II_GRG___v3',
|
||||
# 'Object': 'Wire023', 'Component': 'Edge30'}]
|
||||
for obj in listObjects:
|
||||
print(listObjects)
|
||||
if obj.Object == self.obj.Name:
|
||||
print(listObjects)
|
||||
|
||||
'''
|
||||
if self.editing is not None:
|
||||
self.updateTrackerAndGhost(event)
|
||||
else:
|
||||
# look for a node in mouse position and highlight it
|
||||
pos = event.getPosition()
|
||||
node = self.getEditNode(pos)
|
||||
ep = self.getEditNodeIndex(node)
|
||||
if ep is not None:
|
||||
if self.overNode is not None:
|
||||
self.overNode.setColor(COLORS["default"])
|
||||
self.trackers[str(node.objectName.getValue())][ep].setColor(COLORS["red"])
|
||||
self.overNode = self.trackers[str(node.objectName.getValue())][ep]
|
||||
print("show menu")
|
||||
# self.display_tracker_menu(event)
|
||||
else:
|
||||
if self.overNode is not None:
|
||||
self.overNode.setColor(COLORS["default"])
|
||||
self.overNode = None
|
||||
'''
|
||||
|
||||
def endEditing(self, obj, nodeIndex=None, v=None):
|
||||
self.editing = None
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# DRAFT EDIT Context menu
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
def display_tracker_menu(self, event):
|
||||
self.tracker_menu = QtGui.QMenu()
|
||||
self.event = event
|
||||
actions = None
|
||||
actions = ["add point"]
|
||||
|
||||
'''
|
||||
if self.overNode:
|
||||
# if user is over a node
|
||||
doc = self.overNode.get_doc_name()
|
||||
obj = App.getDocument(doc).getObject(self.overNode.get_obj_name())
|
||||
ep = self.overNode.get_subelement_index()
|
||||
|
||||
obj_gui_tools = self.get_obj_gui_tools(obj)
|
||||
if obj_gui_tools:
|
||||
actions = obj_gui_tools.get_edit_point_context_menu(obj, ep)
|
||||
|
||||
else:
|
||||
# try if user is over an edited object
|
||||
pos = self.event.getPosition()
|
||||
obj = self.get_selected_obj_at_position(pos)
|
||||
if utils.get_type(obj) in ["Line", "Wire", "BSpline", "BezCurve"]:
|
||||
actions = ["add point"]
|
||||
elif utils.get_type(obj) in ["Circle"] and obj.FirstAngle != obj.LastAngle:
|
||||
actions = ["invert arc"]
|
||||
|
||||
if actions is None:
|
||||
return
|
||||
'''
|
||||
for a in actions:
|
||||
self.tracker_menu.addAction(a)
|
||||
|
||||
self.tracker_menu.popup(FreeCADGui.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())
|
||||
|
||||
doc = None
|
||||
obj = None
|
||||
idx = None
|
||||
|
||||
if action_label == "add point":
|
||||
self.addPoint(self.event)
|
||||
|
||||
del self.event
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EDIT functions
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def addPoint(self, event):
|
||||
''' add point to the end '''
|
||||
pos = event.getPosition()
|
||||
pts = self.points.copy()
|
||||
new_select = list()
|
||||
point = FreeCAD.Vector(pos)
|
||||
mark = MarkerOnShape([point])
|
||||
pts.append(mark)
|
||||
new_select.append(mark)
|
||||
self.points = pts
|
||||
self.setupInteractionSeparator()
|
||||
self.root.selected_objects = new_select
|
||||
|
||||
def subdivide(self):
|
||||
# get selected lines and subdivide them
|
||||
pts = list()
|
||||
new_select = list()
|
||||
for o in self.lines:
|
||||
#FreeCAD.Console.PrintMessage("object %s\n"%str(o))
|
||||
if isinstance(o, ConnectionLine):
|
||||
pts.append(o.markers[0])
|
||||
if o in self.root.selected_objects:
|
||||
#idx = self.lines.index(o)
|
||||
#FreeCAD.Console.PrintMessage("Subdividing line #{}\n".format(idx))
|
||||
p1 = o.markers[0].points[0]
|
||||
p2 = o.markers[1].points[0]
|
||||
midpar = (FreeCAD.Vector(p1) + FreeCAD.Vector(p2)) / 2.0
|
||||
mark = MarkerOnShape([midpar])
|
||||
pts.append(mark)
|
||||
new_select.append(mark)
|
||||
pts.append(self.points[-1])
|
||||
self.points = pts
|
||||
self.setupInteractionSeparator()
|
||||
self.root.selected_objects = new_select
|
||||
return True
|
||||
|
||||
def quit(self):
|
||||
print("Quit")
|
||||
self.unregister_editing_callbacks()
|
||||
self.root.unregister()
|
||||
#self.sg.removeChild(self.root)
|
||||
self.root_inserted = False
|
||||
Reference in New Issue
Block a user