Identified by LGTM. The toplevel superclass does initialize one data member to an empty array, but this didn't appear to cause any problems.
620 lines
27 KiB
Python
620 lines
27 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 create circular arc objects."""
|
|
## @package gui_arcs
|
|
# \ingroup draftguitools
|
|
# \brief Provides GUI tools to create circular arc objects.
|
|
|
|
## \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 draftguitools.gui_base_original as gui_base_original
|
|
import draftguitools.gui_base as gui_base
|
|
import draftguitools.gui_tool_utils as gui_tool_utils
|
|
import draftguitools.gui_trackers as trackers
|
|
import draftutils.utils as utils
|
|
|
|
from FreeCAD import Units as U
|
|
from draftutils.messages import _msg, _err
|
|
from draftutils.translate import translate
|
|
|
|
# The module is used to prevent complaints from code checkers (flake8)
|
|
True if Draft_rc.__name__ else False
|
|
|
|
|
|
class Arc(gui_base_original.Creator):
|
|
"""Gui command for the Circular Arc tool."""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.closedCircle = False
|
|
self.featureName = "Arc"
|
|
|
|
def GetResources(self):
|
|
"""Set icon, menu and tooltip."""
|
|
|
|
return {'Pixmap': 'Draft_Arc',
|
|
'Accel': "A, R",
|
|
'MenuText': QT_TRANSLATE_NOOP("Draft_Arc", "Arc"),
|
|
'ToolTip': QT_TRANSLATE_NOOP("Draft_Arc", "Creates a circular arc by a center point and a radius.\nCTRL to snap, SHIFT to constrain.")}
|
|
|
|
def Activated(self):
|
|
"""Execute when the command is called."""
|
|
super(Arc, self).Activated(name=translate("draft","Arc"))
|
|
if self.ui:
|
|
self.step = 0
|
|
self.center = None
|
|
self.rad = None
|
|
self.angle = 0 # angle inscribed by arc
|
|
self.tangents = []
|
|
self.tanpoints = []
|
|
if self.featureName == "Arc":
|
|
self.ui.arcUi()
|
|
else:
|
|
self.ui.circleUi()
|
|
self.altdown = False
|
|
self.ui.sourceCmd = self
|
|
self.linetrack = trackers.lineTracker(dotted=True)
|
|
self.arctrack = trackers.arcTracker()
|
|
self.call = self.view.addEventCallback("SoEvent", self.action)
|
|
_msg(translate("draft", "Pick center point"))
|
|
|
|
def finish(self, closed=False, cont=False):
|
|
"""Terminate the operation and close the arc if asked.
|
|
|
|
Parameters
|
|
----------
|
|
closed: bool, optional
|
|
Close the line if `True`.
|
|
"""
|
|
super(Arc, self).finish()
|
|
if self.ui:
|
|
self.linetrack.finalize()
|
|
self.arctrack.finalize()
|
|
self.doc.recompute()
|
|
if self.ui and self.ui.continueMode:
|
|
self.Activated()
|
|
|
|
def updateAngle(self, angle):
|
|
"""Update the angle with the new value."""
|
|
# previous absolute angle
|
|
lastangle = self.firstangle + self.angle
|
|
if lastangle <= -2 * math.pi:
|
|
lastangle += 2 * math.pi
|
|
if lastangle >= 2 * math.pi:
|
|
lastangle -= 2 * math.pi
|
|
# compute delta = change in angle:
|
|
d0 = angle - lastangle
|
|
d1 = d0 + 2 * math.pi
|
|
d2 = d0 - 2 * math.pi
|
|
if abs(d0) < min(abs(d1), abs(d2)):
|
|
delta = d0
|
|
elif abs(d1) < abs(d2):
|
|
delta = d1
|
|
else:
|
|
delta = d2
|
|
newangle = self.angle + delta
|
|
# normalize angle, preserving direction
|
|
if newangle >= 2 * math.pi:
|
|
newangle -= 2 * math.pi
|
|
if newangle <= -2 * math.pi:
|
|
newangle += 2 * math.pi
|
|
self.angle = newangle
|
|
|
|
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.
|
|
"""
|
|
import DraftGeomUtils
|
|
plane = App.DraftWorkingPlane
|
|
|
|
if arg["Type"] == "SoKeyboardEvent":
|
|
if arg["Key"] == "ESCAPE":
|
|
self.finish()
|
|
elif arg["Type"] == "SoLocation2Event": # mouse movement detection
|
|
self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg)
|
|
# this is to make sure radius is what you see on screen
|
|
if self.center and DraftVecUtils.dist(self.point, self.center) > 0:
|
|
viewdelta = DraftVecUtils.project(self.point.sub(self.center),
|
|
plane.axis)
|
|
if not DraftVecUtils.isNull(viewdelta):
|
|
self.point = self.point.add(viewdelta.negative())
|
|
if self.step == 0: # choose center
|
|
if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
|
|
if not self.altdown:
|
|
self.altdown = True
|
|
self.ui.switchUi(True)
|
|
else:
|
|
if self.altdown:
|
|
self.altdown = False
|
|
self.ui.switchUi(False)
|
|
elif self.step == 1: # choose radius
|
|
if len(self.tangents) == 2:
|
|
cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0],
|
|
self.tangents[1],
|
|
self.point)
|
|
_c = DraftGeomUtils.findClosestCircle(self.point, cir)
|
|
self.center = _c.Center
|
|
self.arctrack.setCenter(self.center)
|
|
elif self.tangents and self.tanpoints:
|
|
cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0],
|
|
self.tanpoints[0],
|
|
self.point)
|
|
_c = DraftGeomUtils.findClosestCircle(self.point, cir)
|
|
self.center = _c.Center
|
|
self.arctrack.setCenter(self.center)
|
|
if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
|
|
if not self.altdown:
|
|
self.altdown = True
|
|
if info:
|
|
ob = self.doc.getObject(info['Object'])
|
|
num = int(info['Component'].lstrip('Edge')) - 1
|
|
ed = ob.Shape.Edges[num]
|
|
if len(self.tangents) == 2:
|
|
cir = DraftGeomUtils.circleFrom3tan(self.tangents[0],
|
|
self.tangents[1],
|
|
ed)
|
|
cl = DraftGeomUtils.findClosestCircle(self.point, cir)
|
|
self.center = cl.Center
|
|
self.rad = cl.Radius
|
|
self.arctrack.setCenter(self.center)
|
|
else:
|
|
self.rad = self.center.add(DraftGeomUtils.findDistance(self.center, ed).sub(self.center)).Length
|
|
else:
|
|
self.rad = DraftVecUtils.dist(self.point, self.center)
|
|
else:
|
|
if self.altdown:
|
|
self.altdown = False
|
|
self.rad = DraftVecUtils.dist(self.point, self.center)
|
|
self.ui.setRadiusValue(self.rad, "Length")
|
|
self.arctrack.setRadius(self.rad)
|
|
self.linetrack.p1(self.center)
|
|
self.linetrack.p2(self.point)
|
|
self.linetrack.on()
|
|
elif (self.step == 2): # choose first angle
|
|
currentrad = DraftVecUtils.dist(self.point, self.center)
|
|
if currentrad != 0:
|
|
angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis)
|
|
else:
|
|
angle = 0
|
|
self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center))
|
|
self.ui.setRadiusValue(math.degrees(angle), unit="Angle")
|
|
self.firstangle = angle
|
|
else:
|
|
# choose second angle
|
|
currentrad = DraftVecUtils.dist(self.point, self.center)
|
|
if currentrad != 0:
|
|
angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis)
|
|
else:
|
|
angle = 0
|
|
self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center))
|
|
self.updateAngle(angle)
|
|
self.ui.setRadiusValue(math.degrees(self.angle), unit="Angle")
|
|
self.arctrack.setApertureAngle(self.angle)
|
|
|
|
gui_tool_utils.redraw3DView()
|
|
|
|
elif arg["Type"] == "SoMouseButtonEvent": # mouse click
|
|
if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1":
|
|
if self.point:
|
|
if self.step == 0: # choose center
|
|
if not self.support:
|
|
gui_tool_utils.getSupport(arg)
|
|
(self.point,
|
|
ctrlPoint, info) = gui_tool_utils.getPoint(self, arg)
|
|
if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
|
|
snapped = self.view.getObjectInfo((arg["Position"][0],
|
|
arg["Position"][1]))
|
|
if snapped:
|
|
ob = self.doc.getObject(snapped['Object'])
|
|
num = int(snapped['Component'].lstrip('Edge')) - 1
|
|
ed = ob.Shape.Edges[num]
|
|
self.tangents.append(ed)
|
|
if len(self.tangents) == 2:
|
|
self.arctrack.on()
|
|
self.ui.radiusUi()
|
|
self.step = 1
|
|
self.ui.setNextFocus()
|
|
self.linetrack.on()
|
|
_msg(translate("draft", "Pick radius"))
|
|
else:
|
|
if len(self.tangents) == 1:
|
|
self.tanpoints.append(self.point)
|
|
else:
|
|
self.center = self.point
|
|
self.node = [self.point]
|
|
self.arctrack.setCenter(self.center)
|
|
self.linetrack.p1(self.center)
|
|
self.linetrack.p2(self.view.getPoint(arg["Position"][0],
|
|
arg["Position"][1]))
|
|
self.arctrack.on()
|
|
self.ui.radiusUi()
|
|
self.step = 1
|
|
self.ui.setNextFocus()
|
|
self.linetrack.on()
|
|
_msg(translate("draft", "Pick radius"))
|
|
if self.planetrack:
|
|
self.planetrack.set(self.point)
|
|
elif self.step == 1: # choose radius
|
|
if self.closedCircle:
|
|
self.drawArc()
|
|
else:
|
|
self.ui.labelRadius.setText(translate("draft", "Start angle"))
|
|
self.ui.radiusValue.setToolTip(translate("draft", "Start angle"))
|
|
self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString)
|
|
self.linetrack.p1(self.center)
|
|
self.linetrack.on()
|
|
self.step = 2
|
|
_msg(translate("draft", "Pick start angle"))
|
|
elif self.step == 2: # choose first angle
|
|
self.ui.labelRadius.setText(translate("draft", "Aperture angle"))
|
|
self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle"))
|
|
self.step = 3
|
|
# scale center->point vector for proper display
|
|
# u = DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad) obsolete?
|
|
self.arctrack.setStartAngle(self.firstangle)
|
|
_msg(translate("draft", "Pick aperture"))
|
|
else: # choose second angle
|
|
self.step = 4
|
|
self.drawArc()
|
|
|
|
def drawArc(self):
|
|
"""Actually draw the arc object."""
|
|
rot, sup, pts, fil = self.getStrings()
|
|
if self.closedCircle:
|
|
try:
|
|
# The command to run is built as a series of text strings
|
|
# to be committed through the `draftutils.todo.ToDo` class.
|
|
if utils.getParam("UsePartPrimitives", False):
|
|
# Insert a Part::Primitive object
|
|
_base = DraftVecUtils.toString(self.center)
|
|
_cmd = 'FreeCAD.ActiveDocument.'
|
|
_cmd += 'addObject("Part::Circle", "Circle")'
|
|
_cmd_list = ['circle = ' + _cmd,
|
|
'circle.Radius = ' + str(self.rad),
|
|
'pl = FreeCAD.Placement()',
|
|
'pl.Rotation.Q = ' + rot,
|
|
'pl.Base = ' + _base,
|
|
'circle.Placement = pl',
|
|
'Draft.autogroup(circle)',
|
|
'FreeCAD.ActiveDocument.recompute()']
|
|
self.commit(translate("draft", "Create Circle (Part)"),
|
|
_cmd_list)
|
|
else:
|
|
# Insert a Draft circle
|
|
Gui.addModule("Draft")
|
|
_base = DraftVecUtils.toString(self.center)
|
|
_cmd = 'Draft.makeCircle'
|
|
_cmd += '('
|
|
_cmd += 'radius=' + str(self.rad) + ', '
|
|
_cmd += 'placement=pl, '
|
|
_cmd += 'face=' + fil + ', '
|
|
_cmd += 'support=' + sup
|
|
_cmd += ')'
|
|
_cmd_list = ['pl=FreeCAD.Placement()',
|
|
'pl.Rotation.Q=' + rot,
|
|
'pl.Base=' + _base,
|
|
'circle = ' + _cmd,
|
|
'Draft.autogroup(circle)',
|
|
'FreeCAD.ActiveDocument.recompute()']
|
|
self.commit(translate("draft", "Create Circle"),
|
|
_cmd_list)
|
|
except Exception:
|
|
_err("Draft: error delaying commit")
|
|
else:
|
|
# Not a closed circle, therefore a circular arc
|
|
sta = math.degrees(self.firstangle)
|
|
end = math.degrees(self.firstangle + self.angle)
|
|
if end < sta:
|
|
sta, end = end, sta
|
|
while True:
|
|
if sta > 360:
|
|
sta = sta - 360
|
|
elif end > 360:
|
|
end = end - 360
|
|
else:
|
|
break
|
|
try:
|
|
Gui.addModule("Draft")
|
|
if utils.getParam("UsePartPrimitives", False):
|
|
# Insert a Part::Primitive object
|
|
_base = DraftVecUtils.toString(self.center)
|
|
_cmd = 'FreeCAD.ActiveDocument.'
|
|
_cmd += 'addObject("Part::Circle", "Circle")'
|
|
_cmd_list = ['circle = ' + _cmd,
|
|
'circle.Radius = ' + str(self.rad),
|
|
'circle.Angle0 = ' + str(sta),
|
|
'circle.Angle1 = ' + str(end),
|
|
'pl = FreeCAD.Placement()',
|
|
'pl.Rotation.Q = ' + rot,
|
|
'pl.Base = ' + _base,
|
|
'circle.Placement = pl',
|
|
'Draft.autogroup(circle)',
|
|
'FreeCAD.ActiveDocument.recompute()']
|
|
self.commit(translate("draft", "Create Arc (Part)"),
|
|
_cmd_list)
|
|
else:
|
|
# Insert a Draft circle
|
|
_base = DraftVecUtils.toString(self.center)
|
|
_cmd = 'Draft.makeCircle'
|
|
_cmd += '('
|
|
_cmd += 'radius=' + str(self.rad) + ', '
|
|
_cmd += 'placement=pl, '
|
|
_cmd += 'face=' + fil + ', '
|
|
_cmd += 'startangle=' + str(sta) + ', '
|
|
_cmd += 'endangle=' + str(end) + ', '
|
|
_cmd += 'support=' + sup
|
|
_cmd += ')'
|
|
_cmd_list = ['pl = FreeCAD.Placement()',
|
|
'pl.Rotation.Q = ' + rot,
|
|
'pl.Base = ' + _base,
|
|
'circle = ' + _cmd,
|
|
'Draft.autogroup(circle)',
|
|
'FreeCAD.ActiveDocument.recompute()']
|
|
self.commit(translate("draft", "Create Arc"),
|
|
_cmd_list)
|
|
except Exception:
|
|
_err("Draft: error delaying commit")
|
|
|
|
# Finalize full circle or cirular arc
|
|
self.finish(cont=True)
|
|
|
|
def numericInput(self, numx, numy, numz):
|
|
"""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.center = App.Vector(numx, numy, numz)
|
|
self.node = [self.center]
|
|
self.arctrack.setCenter(self.center)
|
|
self.arctrack.on()
|
|
self.ui.radiusUi()
|
|
self.step = 1
|
|
self.ui.setNextFocus()
|
|
_msg(translate("draft", "Pick radius"))
|
|
|
|
def numericRadius(self, rad):
|
|
"""Validate the entry radius in the user interface.
|
|
|
|
This function is called by the toolbar or taskpanel interface
|
|
when a valid radius has been entered in the input field.
|
|
"""
|
|
import DraftGeomUtils
|
|
plane = App.DraftWorkingPlane
|
|
|
|
if self.step == 1:
|
|
self.rad = rad
|
|
if len(self.tangents) == 2:
|
|
cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0],
|
|
self.tangents[1],
|
|
rad)
|
|
if self.center:
|
|
_c = DraftGeomUtils.findClosestCircle(self.center, cir)
|
|
self.center = _c.Center
|
|
else:
|
|
self.center = cir[-1].Center
|
|
elif self.tangents and self.tanpoints:
|
|
cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0],
|
|
self.tanpoints[0],
|
|
rad)
|
|
if self.center:
|
|
_c = DraftGeomUtils.findClosestCircle(self.center, cir)
|
|
self.center = _c.Center
|
|
else:
|
|
self.center = cir[-1].Center
|
|
if self.closedCircle:
|
|
self.drawArc()
|
|
else:
|
|
self.step = 2
|
|
self.arctrack.setCenter(self.center)
|
|
self.ui.labelRadius.setText(translate("draft", "Start angle"))
|
|
self.ui.radiusValue.setToolTip(translate("draft", "Start angle"))
|
|
self.linetrack.p1(self.center)
|
|
self.linetrack.on()
|
|
self.ui.radiusValue.setText("")
|
|
self.ui.radiusValue.setFocus()
|
|
_msg(translate("draft", "Pick start angle"))
|
|
elif self.step == 2:
|
|
self.ui.labelRadius.setText(translate("draft", "Aperture angle"))
|
|
self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle"))
|
|
self.firstangle = math.radians(rad)
|
|
if DraftVecUtils.equals(plane.axis, App.Vector(1, 0, 0)):
|
|
u = App.Vector(0, self.rad, 0)
|
|
else:
|
|
u = DraftVecUtils.scaleTo(App.Vector(1, 0, 0).cross(plane.axis), self.rad)
|
|
urotated = DraftVecUtils.rotate(u, math.radians(rad), plane.axis)
|
|
self.arctrack.setStartAngle(self.firstangle)
|
|
self.step = 3
|
|
self.ui.radiusValue.setText("")
|
|
self.ui.radiusValue.setFocus()
|
|
_msg(translate("draft", "Pick aperture angle"))
|
|
else:
|
|
self.updateAngle(rad)
|
|
self.angle = math.radians(rad)
|
|
self.step = 4
|
|
self.drawArc()
|
|
|
|
|
|
Gui.addCommand('Draft_Arc', Arc())
|
|
|
|
|
|
class Arc_3Points(gui_base.GuiCommandSimplest):
|
|
"""GuiCommand for the Draft_Arc_3Points tool."""
|
|
|
|
def __init__(self):
|
|
super(Arc_3Points, self).__init__(name=translate("draft","Arc by 3 points"))
|
|
|
|
def GetResources(self):
|
|
"""Set icon, menu and tooltip."""
|
|
_menu = "Arc by 3 points"
|
|
_tip = ("Creates a circular arc by picking 3 points.\n"
|
|
"CTRL to snap, SHIFT to constrain.")
|
|
|
|
d = {'Pixmap': "Draft_Arc_3Points",
|
|
'MenuText': QT_TRANSLATE_NOOP("Draft_Arc_3Points", _menu),
|
|
'ToolTip': QT_TRANSLATE_NOOP("Draft_Arc_3Points", _tip),
|
|
'Accel': 'A,T'}
|
|
return d
|
|
|
|
def Activated(self):
|
|
"""Execute when the command is called."""
|
|
super(Arc_3Points, self).Activated()
|
|
|
|
# Reset the values
|
|
self.points = []
|
|
self.normal = None
|
|
self.tracker = trackers.arcTracker()
|
|
self.tracker.autoinvert = False
|
|
|
|
# Set up the working plane and launch the Snapper
|
|
# with the indicated callbacks: one for when the user clicks
|
|
# on the 3D view, and another for when the user moves the pointer.
|
|
if hasattr(App, "DraftWorkingPlane"):
|
|
App.DraftWorkingPlane.setup()
|
|
|
|
Gui.Snapper.getPoint(callback=self.getPoint,
|
|
movecallback=self.drawArc)
|
|
|
|
def getPoint(self, point, info):
|
|
"""Get the point by clicking on the 3D view.
|
|
|
|
Every time the user clicks on the 3D view this method is run.
|
|
In this case, a point is appended to the list of points,
|
|
and the tracker is updated.
|
|
The object is finally created when three points are picked.
|
|
|
|
Parameters
|
|
----------
|
|
point: Base::Vector
|
|
The point selected in the 3D view.
|
|
|
|
info: str
|
|
Some information obtained about the point passed by the Snapper.
|
|
"""
|
|
# If there is not point, the command was cancelled
|
|
# so the command exits.
|
|
if not point:
|
|
self.tracker.off()
|
|
return
|
|
|
|
# Avoid adding the same point twice
|
|
if point not in self.points:
|
|
self.points.append(point)
|
|
|
|
if len(self.points) < 3:
|
|
# If one or two points were picked, set up again the Snapper
|
|
# to get further points, but update the `last` property
|
|
# with the last selected point.
|
|
#
|
|
# When two points are selected then we can turn on
|
|
# the arc tracker to show the preview of the final curve.
|
|
if len(self.points) == 2:
|
|
self.tracker.on()
|
|
Gui.Snapper.getPoint(last=self.points[-1],
|
|
callback=self.getPoint,
|
|
movecallback=self.drawArc)
|
|
else:
|
|
# If three points were already picked in the 3D view
|
|
# proceed with creating the final object.
|
|
# Draw a simple `Part::Feature` if the parameter is `True`.
|
|
if utils.get_param("UsePartPrimitives", False):
|
|
Draft.make_arc_3points([self.points[0],
|
|
self.points[1],
|
|
self.points[2]], primitive=True)
|
|
else:
|
|
Draft.make_arc_3points([self.points[0],
|
|
self.points[1],
|
|
self.points[2]], primitive=False)
|
|
self.tracker.off()
|
|
self.doc.recompute()
|
|
|
|
def drawArc(self, point, info):
|
|
"""Draw preview arc when we move the pointer in the 3D view.
|
|
|
|
It uses the `gui_trackers.arcTracker.setBy3Points` method.
|
|
|
|
Parameters
|
|
----------
|
|
point: Base::Vector
|
|
The dynamic point passed by the callback
|
|
as we move the pointer in the 3D view.
|
|
|
|
info: str
|
|
Some information obtained from the point by the Snapper.
|
|
"""
|
|
if len(self.points) == 2:
|
|
if point.sub(self.points[1]).Length > 0.001:
|
|
self.tracker.setBy3Points(self.points[0],
|
|
self.points[1],
|
|
point)
|
|
|
|
|
|
Draft_Arc_3Points = Arc_3Points
|
|
Gui.addCommand('Draft_Arc_3Points', Arc_3Points())
|
|
|
|
|
|
class ArcGroup:
|
|
"""Gui Command group for the Arc tools."""
|
|
|
|
def GetResources(self):
|
|
"""Set icon, menu and tooltip."""
|
|
|
|
return {'MenuText': QT_TRANSLATE_NOOP("Draft_ArcTools", "Arc tools"),
|
|
'ToolTip': QT_TRANSLATE_NOOP("Draft_ArcTools", "Create various types of circular arcs.")}
|
|
|
|
def GetCommands(self):
|
|
"""Return a tuple of commands in the group."""
|
|
return ('Draft_Arc', 'Draft_Arc_3Points')
|
|
|
|
def IsActive(self):
|
|
"""Return True when this command should be available.
|
|
|
|
It is `True` when there is a document.
|
|
"""
|
|
if Gui.ActiveDocument:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
Gui.addCommand('Draft_ArcTools', ArcGroup())
|
|
|
|
## @}
|