600 lines
24 KiB
Python
600 lines
24 KiB
Python
# ***************************************************************************
|
|
# * (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
|
|
# * (c) 2009, 2010 Ken Cline <cline@frii.com> *
|
|
# * (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
|
|
# * *
|
|
# * This file is part of the FreeCAD CAx development system. *
|
|
# * *
|
|
# * 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. *
|
|
# * *
|
|
# * FreeCAD 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 FreeCAD; if not, write to the Free Software *
|
|
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
# * USA *
|
|
# * *
|
|
# ***************************************************************************
|
|
"""Provides GUI tools to trim and extend lines.
|
|
|
|
It also extends closed faces to create solids, that is, it can be used
|
|
to extrude a closed profile.
|
|
|
|
Make sure the snapping is active so that the extrusion is done following
|
|
the direction of a line, and up to the distance specified
|
|
by the snapping point.
|
|
"""
|
|
## @package gui_trimex
|
|
# \ingroup draftguitools
|
|
# \brief Provides GUI tools to trim and extend lines.
|
|
|
|
## \addtogroup draftguitools
|
|
# @{
|
|
import math
|
|
from PySide.QtCore import QT_TRANSLATE_NOOP
|
|
|
|
import FreeCAD as App
|
|
import FreeCADGui as Gui
|
|
import Draft
|
|
import Draft_rc
|
|
import DraftVecUtils
|
|
import draftutils.utils as utils
|
|
import draftutils.gui_utils as gui_utils
|
|
import draftguitools.gui_base_original as gui_base_original
|
|
import draftguitools.gui_tool_utils as gui_tool_utils
|
|
import draftguitools.gui_trackers as trackers
|
|
|
|
from draftutils.messages import _msg, _err, _toolmsg
|
|
from draftutils.translate import translate
|
|
|
|
# The module is used to prevent complaints from code checkers (flake8)
|
|
True if Draft_rc.__name__ else False
|
|
|
|
|
|
class Trimex(gui_base_original.Modifier):
|
|
"""Gui Command for the Trimex tool.
|
|
|
|
This tool trims or extends lines, wires and arcs,
|
|
or extrudes single faces.
|
|
|
|
SHIFT constrains to the last point
|
|
or extrudes in direction to the face normal.
|
|
"""
|
|
|
|
def GetResources(self):
|
|
"""Set icon, menu and tooltip."""
|
|
|
|
return {'Pixmap': 'Draft_Trimex',
|
|
'Accel': "T, R",
|
|
'MenuText': QT_TRANSLATE_NOOP("Draft_Trimex", "Trimex"),
|
|
'ToolTip': QT_TRANSLATE_NOOP("Draft_Trimex",
|
|
"Trims or extends the selected object, or extrudes single"
|
|
+ " faces.\nCTRL snaps, SHIFT constrains to current segment"
|
|
+ " or to normal, ALT inverts.")}
|
|
|
|
def Activated(self):
|
|
"""Execute when the command is called."""
|
|
super().Activated(name="Trimex")
|
|
self.edges = []
|
|
self.placement = None
|
|
self.ghost = []
|
|
self.linetrack = None
|
|
self.color = None
|
|
self.width = None
|
|
if self.ui:
|
|
if not Gui.Selection.getSelection():
|
|
self.ui.selectUi(on_close_call=self.finish)
|
|
_msg(translate("draft", "Select objects to trim or extend"))
|
|
self.call = \
|
|
self.view.addEventCallback("SoEvent",
|
|
gui_tool_utils.selectObject)
|
|
else:
|
|
self.proceed()
|
|
|
|
def proceed(self):
|
|
"""Proceed with execution of the command after proper selection."""
|
|
if self.call:
|
|
self.view.removeEventCallback("SoEvent", self.call)
|
|
sel = Gui.Selection.getSelection()
|
|
if len(sel) == 2:
|
|
self.trimObjects(sel)
|
|
self.finish()
|
|
return
|
|
self.obj = sel[0]
|
|
self.ui.trimUi(title=translate("draft",self.featureName))
|
|
self.linetrack = trackers.lineTracker()
|
|
|
|
import DraftGeomUtils
|
|
import Part
|
|
|
|
if "Shape" not in self.obj.PropertiesList:
|
|
self.obj = None
|
|
self.finish()
|
|
_err(translate("draft", "This object is not supported."))
|
|
return
|
|
if "Placement" in self.obj.PropertiesList:
|
|
self.placement = self.obj.Placement
|
|
if len(self.obj.Shape.Faces) == 1:
|
|
# simple extrude mode, the object itself is extruded
|
|
self.extrudeMode = True
|
|
self.ghost = [trackers.ghostTracker([self.obj])]
|
|
self.normal = self.obj.Shape.Faces[0].normalAt(0.5, 0.5)
|
|
self.ghost += [trackers.lineTracker() for _ in self.obj.Shape.Vertexes]
|
|
elif len(self.obj.Shape.Faces) > 1:
|
|
# face extrude mode, a new object is created
|
|
ss = Gui.Selection.getSelectionEx()[0]
|
|
if len(ss.SubObjects) == 1 and ss.SubObjects[0].ShapeType == "Face":
|
|
self.obj = self.doc.addObject("Part::Feature", "Face")
|
|
self.obj.Shape = ss.SubObjects[0]
|
|
self.extrudeMode = True
|
|
self.ghost = [trackers.ghostTracker([self.obj])]
|
|
self.normal = self.obj.Shape.Faces[0].normalAt(0.5, 0.5)
|
|
self.ghost += [trackers.lineTracker() for _ in self.obj.Shape.Vertexes]
|
|
else:
|
|
self.obj = None
|
|
self.finish()
|
|
_err(translate("draft", "Only a single face can be extruded."))
|
|
return
|
|
else:
|
|
# normal wire trimex mode
|
|
self.color = self.obj.ViewObject.LineColor
|
|
self.width = self.obj.ViewObject.LineWidth
|
|
if self.obj.Shape.Wires:
|
|
self.edges = self.obj.Shape.Wires[0].Edges
|
|
self.edges = Part.__sortEdges__(self.edges)
|
|
else:
|
|
self.edges = self.obj.Shape.Edges
|
|
for e in self.edges:
|
|
if isinstance(e.Curve,(Part.BSplineCurve, Part.BezierCurve)):
|
|
self.obj = None
|
|
self.finish()
|
|
_err(translate("draft", "Trimex is not supported yet on this type of object."))
|
|
return
|
|
# self.obj.ViewObject.Visibility = False
|
|
self.obj.ViewObject.LineColor = (0.5, 0.5, 0.5)
|
|
self.obj.ViewObject.LineWidth = 1
|
|
self.extrudeMode = False
|
|
self.ghost = []
|
|
lc = self.color
|
|
sc = (lc[0], lc[1], lc[2])
|
|
sw = self.width
|
|
for e in self.edges:
|
|
if DraftGeomUtils.geomType(e) == "Line":
|
|
self.ghost.append(trackers.lineTracker(scolor=sc,
|
|
swidth=sw))
|
|
else:
|
|
self.ghost.append(trackers.arcTracker(scolor=sc,
|
|
swidth=sw))
|
|
if not self.ghost:
|
|
self.obj = None
|
|
self.finish()
|
|
return
|
|
for g in self.ghost:
|
|
g.on()
|
|
self.activePoint = 0
|
|
self.nodes = []
|
|
self.shift = False
|
|
self.alt = False
|
|
self.force = None
|
|
self.cv = None
|
|
self.call = self.view.addEventCallback("SoEvent", self.action)
|
|
_toolmsg(translate("draft", "Pick distance"))
|
|
|
|
def action(self, arg):
|
|
"""Handle the 3D scene events.
|
|
|
|
This is installed as an EventCallback in the Inventor view.
|
|
|
|
Parameters
|
|
----------
|
|
arg: dict
|
|
Dictionary with strings that indicates the type of event received
|
|
from the 3D view.
|
|
"""
|
|
if arg["Type"] == "SoKeyboardEvent":
|
|
if arg["Key"] == "ESCAPE":
|
|
self.finish()
|
|
elif arg["Type"] == "SoLocation2Event": # mouse movement detection
|
|
self.shift = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_constrain_key())
|
|
self.alt = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())
|
|
self.ctrl = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_snap_key())
|
|
if self.extrudeMode:
|
|
arg["ShiftDown"] = False
|
|
elif hasattr(Gui, "Snapper"):
|
|
Gui.Snapper.setSelectMode(not self.ctrl)
|
|
self.point, cp, info = gui_tool_utils.getPoint(self, arg)
|
|
if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_snap_key()):
|
|
self.snapped = None
|
|
else:
|
|
self.snapped = self.view.getObjectInfo((arg["Position"][0],
|
|
arg["Position"][1]))
|
|
if self.extrudeMode:
|
|
dist, ang = (self.extrude(self.shift), None)
|
|
else:
|
|
# If the geomType of the edge is "Line" ang will be None,
|
|
# else dist will be None.
|
|
dist, ang = self.redraw(self.point, self.snapped,
|
|
self.shift, self.alt)
|
|
|
|
if dist:
|
|
self.ui.labelRadius.setText(translate("draft", "Distance"))
|
|
self.ui.radiusValue.setToolTip(translate("draft",
|
|
"Offset distance"))
|
|
self.ui.setRadiusValue(dist, unit="Length")
|
|
elif ang:
|
|
self.ui.labelRadius.setText(translate("draft", "Angle"))
|
|
self.ui.radiusValue.setToolTip(translate("draft",
|
|
"Offset angle"))
|
|
self.ui.setRadiusValue(ang, unit="Angle")
|
|
else:
|
|
# both dist and ang are None, this indicates an impossible
|
|
# situation. Setting 0 with no unit will show "0 ??" and not
|
|
# compute any value
|
|
self.ui.setRadiusValue(0)
|
|
self.ui.radiusValue.setFocus()
|
|
self.ui.radiusValue.selectAll()
|
|
gui_tool_utils.redraw3DView()
|
|
|
|
elif arg["Type"] == "SoMouseButtonEvent":
|
|
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
|
cursor = arg["Position"]
|
|
self.shift = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_constrain_key())
|
|
self.alt = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())
|
|
if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_snap_key()):
|
|
self.snapped = None
|
|
else:
|
|
self.snapped = self.view.getObjectInfo((cursor[0],
|
|
cursor[1]))
|
|
self.trimObject()
|
|
self.finish()
|
|
|
|
def extrude(self, shift=False, real=False):
|
|
"""Redraw the ghost in extrude mode."""
|
|
self.newpoint = self.obj.Shape.Faces[0].CenterOfMass
|
|
dvec = self.point.sub(self.newpoint)
|
|
if not shift:
|
|
delta = DraftVecUtils.project(dvec, self.normal)
|
|
else:
|
|
delta = dvec
|
|
if self.force and delta.Length:
|
|
ratio = self.force/delta.Length
|
|
delta.multiply(ratio)
|
|
if real:
|
|
return delta
|
|
self.ghost[0].trans.translation.setValue([delta.x, delta.y, delta.z])
|
|
for i in range(1, len(self.ghost)):
|
|
base = self.obj.Shape.Vertexes[i-1].Point
|
|
self.ghost[i].p1(base)
|
|
self.ghost[i].p2(base.add(delta))
|
|
return delta.Length
|
|
|
|
def redraw(self, point, snapped=None, shift=False, alt=False, real=None):
|
|
"""Redraw the ghost normally."""
|
|
# initializing
|
|
reverse = False
|
|
for g in self.ghost:
|
|
g.off()
|
|
if real:
|
|
newedges = []
|
|
|
|
import DraftGeomUtils
|
|
import Part
|
|
|
|
# finding the active point
|
|
vlist = []
|
|
for e in self.edges:
|
|
vlist.append(e.Vertexes[0].Point)
|
|
vlist.append(self.edges[-1].Vertexes[-1].Point)
|
|
if shift:
|
|
npoint = self.activePoint
|
|
else:
|
|
npoint = DraftGeomUtils.findClosest(point, vlist)
|
|
if npoint > len(self.edges)/2:
|
|
reverse = True
|
|
if alt:
|
|
reverse = not reverse
|
|
self.activePoint = npoint
|
|
|
|
# sorting out directions
|
|
if reverse and (npoint > 0):
|
|
npoint = npoint - 1
|
|
if (npoint > len(self.edges) - 1):
|
|
edge = self.edges[-1]
|
|
ghost = self.ghost[-1]
|
|
else:
|
|
edge = self.edges[npoint]
|
|
ghost = self.ghost[npoint]
|
|
if reverse:
|
|
v1 = edge.Vertexes[-1].Point
|
|
v2 = edge.Vertexes[0].Point
|
|
else:
|
|
v1 = edge.Vertexes[0].Point
|
|
v2 = edge.Vertexes[-1].Point
|
|
|
|
# snapping
|
|
if snapped:
|
|
snapped = self.doc.getObject(snapped['Object'])
|
|
if hasattr(snapped, "Shape"):
|
|
pts = []
|
|
for e in snapped.Shape.Edges:
|
|
int = DraftGeomUtils.findIntersection(edge, e, True, True)
|
|
if int:
|
|
pts.extend(int)
|
|
if pts:
|
|
point = pts[DraftGeomUtils.findClosest(point, pts)]
|
|
|
|
# modifying active edge
|
|
if DraftGeomUtils.geomType(edge) == "Line":
|
|
ang = None
|
|
ve = DraftGeomUtils.vec(edge)
|
|
chord = v1.sub(point)
|
|
n = ve.cross(chord)
|
|
if n.Length == 0:
|
|
self.newpoint = point
|
|
else:
|
|
perp = ve.cross(n)
|
|
proj = DraftVecUtils.project(chord, perp)
|
|
self.newpoint = App.Vector.add(point, proj)
|
|
dist = v1.sub(self.newpoint).Length
|
|
ghost.p1(self.newpoint)
|
|
ghost.p2(v2)
|
|
if real:
|
|
if self.force:
|
|
ray = self.newpoint.sub(v1)
|
|
if ray.Length:
|
|
ray.multiply(self.force / ray.Length)
|
|
self.newpoint = App.Vector.add(v1, ray)
|
|
newedges.append(Part.LineSegment(self.newpoint, v2).toShape())
|
|
else:
|
|
dist = None
|
|
center = edge.Curve.Center
|
|
rad = edge.Curve.Radius
|
|
ang1 = DraftVecUtils.angle(v2.sub(center))
|
|
ang2 = DraftVecUtils.angle(point.sub(center))
|
|
_rot_rad = DraftVecUtils.rotate(App.Vector(rad, 0, 0), -ang2)
|
|
self.newpoint = App.Vector.add(center, _rot_rad)
|
|
ang = math.degrees(-ang2)
|
|
# if ang1 > ang2:
|
|
# ang1, ang2 = ang2, ang1
|
|
# print("last calculated:",
|
|
# math.degrees(-ang1),
|
|
# math.degrees(-ang2))
|
|
ghost.setEndAngle(-ang2)
|
|
ghost.setStartAngle(-ang1)
|
|
ghost.setCenter(center)
|
|
ghost.setRadius(rad)
|
|
if real:
|
|
if self.force:
|
|
angle = math.radians(self.force)
|
|
newray = DraftVecUtils.rotate(App.Vector(rad, 0, 0),
|
|
-angle)
|
|
self.newpoint = App.Vector.add(center, newray)
|
|
chord = self.newpoint.sub(v2)
|
|
perp = chord.cross(App.Vector(0, 0, 1))
|
|
scaledperp = DraftVecUtils.scaleTo(perp, rad)
|
|
midpoint = App.Vector.add(center, scaledperp)
|
|
_sh = Part.Arc(self.newpoint, midpoint, v2).toShape()
|
|
newedges.append(_sh)
|
|
ghost.on()
|
|
|
|
# resetting the visible edges
|
|
if not reverse:
|
|
li = list(range(npoint + 1, len(self.edges)))
|
|
else:
|
|
li = list(range(npoint - 1, -1, -1))
|
|
for i in li:
|
|
edge = self.edges[i]
|
|
ghost = self.ghost[i]
|
|
if DraftGeomUtils.geomType(edge) == "Line":
|
|
ghost.p1(edge.Vertexes[0].Point)
|
|
ghost.p2(edge.Vertexes[-1].Point)
|
|
else:
|
|
ang1 = DraftVecUtils.angle(edge.Vertexes[0].Point.sub(center))
|
|
ang2 = DraftVecUtils.angle(edge.Vertexes[-1].Point.sub(center))
|
|
# if ang1 > ang2:
|
|
# ang1, ang2 = ang2, ang1
|
|
ghost.setEndAngle(-ang2)
|
|
ghost.setStartAngle(-ang1)
|
|
ghost.setCenter(edge.Curve.Center)
|
|
ghost.setRadius(edge.Curve.Radius)
|
|
if real:
|
|
newedges.append(edge)
|
|
ghost.on()
|
|
|
|
# finishing
|
|
if real:
|
|
return newedges
|
|
else:
|
|
return [dist, ang]
|
|
|
|
def trimObject(self):
|
|
"""Trim the actual object."""
|
|
import Part
|
|
|
|
if self.extrudeMode:
|
|
delta = self.extrude(self.shift, real=True)
|
|
# print("delta", delta)
|
|
self.doc.openTransaction("Extrude")
|
|
Gui.addModule("Draft")
|
|
obj = Draft.extrude(self.obj, delta, solid=True)
|
|
self.doc.commitTransaction()
|
|
self.obj = obj
|
|
else:
|
|
edges = self.redraw(self.point, self.snapped,
|
|
self.shift, self.alt, real=True)
|
|
newshape = Part.Wire(edges)
|
|
self.doc.openTransaction("Trim/extend")
|
|
if utils.getType(self.obj) in ["Wire", "BSpline"]:
|
|
p = []
|
|
if self.placement:
|
|
invpl = self.placement.inverse()
|
|
for v in newshape.Vertexes:
|
|
np = v.Point
|
|
if self.placement:
|
|
np = invpl.multVec(np)
|
|
p.append(np)
|
|
self.obj.Points = p
|
|
elif utils.getType(self.obj) == "Part::Line":
|
|
p = []
|
|
if self.placement:
|
|
invpl = self.placement.inverse()
|
|
for v in newshape.Vertexes:
|
|
np = v.Point
|
|
if self.placement:
|
|
np = invpl.multVec(np)
|
|
p.append(np)
|
|
if ((p[0].x == self.obj.X1)
|
|
and (p[0].y == self.obj.Y1)
|
|
and (p[0].z == self.obj.Z1)):
|
|
self.obj.X2 = p[-1].x
|
|
self.obj.Y2 = p[-1].y
|
|
self.obj.Z2 = p[-1].z
|
|
elif ((p[-1].x == self.obj.X1)
|
|
and (p[-1].y == self.obj.Y1)
|
|
and (p[-1].z == self.obj.Z1)):
|
|
self.obj.X2 = p[0].x
|
|
self.obj.Y2 = p[0].y
|
|
self.obj.Z2 = p[0].z
|
|
elif ((p[0].x == self.obj.X2)
|
|
and (p[0].y == self.obj.Y2)
|
|
and (p[0].z == self.obj.Z2)):
|
|
self.obj.X1 = p[-1].x
|
|
self.obj.Y1 = p[-1].y
|
|
self.obj.Z1 = p[-1].z
|
|
else:
|
|
self.obj.X1 = p[0].x
|
|
self.obj.Y1 = p[0].y
|
|
self.obj.Z1 = p[0].z
|
|
elif utils.getType(self.obj) == "Circle":
|
|
angles = self.ghost[0].getAngles()
|
|
# print("original", self.obj.FirstAngle," ",self.obj.LastAngle)
|
|
# print("new", angles)
|
|
if angles[0] > angles[1]:
|
|
angles = (angles[1], angles[0])
|
|
self.obj.FirstAngle = angles[0]
|
|
self.obj.LastAngle = angles[1]
|
|
else:
|
|
self.obj.Shape = newshape
|
|
self.doc.commitTransaction()
|
|
self.doc.recompute()
|
|
for g in self.ghost:
|
|
g.off()
|
|
|
|
def trimObjects(self, objectslist):
|
|
"""Attempt to trim two objects together."""
|
|
import Part
|
|
import DraftGeomUtils
|
|
|
|
wires = []
|
|
for obj in objectslist:
|
|
if not utils.getType(obj) in ["Wire", "Circle"]:
|
|
_err(translate("draft",
|
|
"Unable to trim these objects, "
|
|
"only Draft wires and arcs are supported."))
|
|
return
|
|
if len(obj.Shape.Wires) > 1:
|
|
_err(translate("draft",
|
|
"Unable to trim these objects, "
|
|
"too many wires"))
|
|
return
|
|
if len(obj.Shape.Wires) == 1:
|
|
wires.append(obj.Shape.Wires[0])
|
|
else:
|
|
wires.append(Part.Wire(obj.Shape.Edges))
|
|
ints = []
|
|
edge1 = None
|
|
edge2 = None
|
|
for i1, e1 in enumerate(wires[0].Edges):
|
|
for i2, e2 in enumerate(wires[1].Edges):
|
|
i = DraftGeomUtils.findIntersection(e1, e2, dts=False)
|
|
if len(i) == 1:
|
|
ints.append(i[0])
|
|
edge1 = i1
|
|
edge2 = i2
|
|
if not ints:
|
|
_err(translate("draft", "These objects don't intersect."))
|
|
return
|
|
if len(ints) != 1:
|
|
_err(translate("draft", "Too many intersection points."))
|
|
return
|
|
|
|
v11 = wires[0].Vertexes[0].Point
|
|
v12 = wires[0].Vertexes[-1].Point
|
|
v21 = wires[1].Vertexes[0].Point
|
|
v22 = wires[1].Vertexes[-1].Point
|
|
if DraftVecUtils.closest(ints[0], [v11, v12]) == 1:
|
|
last1 = True
|
|
else:
|
|
last1 = False
|
|
if DraftVecUtils.closest(ints[0], [v21, v22]) == 1:
|
|
last2 = True
|
|
else:
|
|
last2 = False
|
|
for i, obj in enumerate(objectslist):
|
|
if i == 0:
|
|
ed = edge1
|
|
la = last1
|
|
else:
|
|
ed = edge2
|
|
la = last2
|
|
if utils.getType(obj) == "Wire":
|
|
if la:
|
|
pts = obj.Points[:ed + 1] + ints
|
|
else:
|
|
pts = ints + obj.Points[ed + 1:]
|
|
obj.Points = pts
|
|
else:
|
|
vec = ints[0].sub(obj.Placement.Base)
|
|
vec = obj.Placement.inverse().Rotation.multVec(vec)
|
|
_x = App.Vector(1, 0, 0)
|
|
_ang = -DraftVecUtils.angle(vec,
|
|
obj.Placement.Rotation.multVec(_x),
|
|
obj.Shape.Edges[0].Curve.Axis)
|
|
ang = math.degrees(_ang)
|
|
if la:
|
|
obj.LastAngle = ang
|
|
else:
|
|
obj.FirstAngle = ang
|
|
self.doc.recompute()
|
|
|
|
def finish(self, cont=False):
|
|
"""Terminate the operation of the Trimex tool."""
|
|
self.end_callbacks(self.call)
|
|
self.force = None
|
|
if self.ui:
|
|
if self.linetrack:
|
|
self.linetrack.finalize()
|
|
if self.ghost:
|
|
for g in self.ghost:
|
|
g.finalize()
|
|
if self.obj:
|
|
self.obj.ViewObject.Visibility = True
|
|
if self.color:
|
|
self.obj.ViewObject.LineColor = self.color
|
|
if self.width:
|
|
self.obj.ViewObject.LineWidth = self.width
|
|
gui_utils.select(self.obj)
|
|
super().finish()
|
|
|
|
def numericRadius(self, dist):
|
|
"""Validate the entry fields in the user interface.
|
|
|
|
This function is called by the toolbar or taskpanel interface
|
|
when valid x, y, and z have been entered in the input fields.
|
|
"""
|
|
self.force = dist
|
|
self.trimObject()
|
|
self.finish()
|
|
|
|
|
|
Gui.addCommand('Draft_Trimex', Trimex())
|
|
|
|
## @}
|