diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 23dd1c9f9b..b912a09edd 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -91,6 +91,7 @@ SET(Creator_tools draftguitools/gui_arcs.py draftguitools/gui_circles.py draftguitools/gui_polygons.py + draftguitools/gui_ellipses.py ) SET(Draft_GUI_tools diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index c5cbaab806..05131957a8 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -160,125 +160,7 @@ from draftguitools.gui_arcs import Arc from draftguitools.gui_arcs import Draft_Arc_3Points from draftguitools.gui_circles import Circle from draftguitools.gui_polygons import Polygon - - -class Ellipse(Creator): - """the Draft_Ellipse FreeCAD command definition""" - - def GetResources(self): - return {'Pixmap' : 'Draft_Ellipse', - 'Accel' : "E, L", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Ellipse", "Ellipse"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Ellipse", "Creates an ellipse. CTRL to snap")} - - def Activated(self): - name = translate("draft","Ellipse") - Creator.Activated(self,name) - if self.ui: - self.refpoint = None - self.ui.pointUi(name) - self.ui.extUi() - self.call = self.view.addEventCallback("SoEvent",self.action) - self.rect = trackers.rectangleTracker() - FreeCAD.Console.PrintMessage(translate("draft", "Pick first point")+"\n") - - def finish(self,closed=False,cont=False): - """terminates the operation and closes the poly if asked""" - Creator.finish(self) - if self.ui: - self.rect.off() - self.rect.finalize() - if self.ui: - if self.ui.continueMode: - self.Activated() - - def createObject(self): - """creates the final object in the current doc""" - p1 = self.node[0] - p3 = self.node[-1] - diagonal = p3.sub(p1) - halfdiag = Vector(diagonal).multiply(0.5) - center = p1.add(halfdiag) - p2 = p1.add(DraftVecUtils.project(diagonal, plane.v)) - p4 = p1.add(DraftVecUtils.project(diagonal, plane.u)) - r1 = (p4.sub(p1).Length)/2 - r2 = (p2.sub(p1).Length)/2 - try: - # building command string - rot,sup,pts,fil = self.getStrings() - if r2 > r1: - r1,r2 = r2,r1 - m = FreeCAD.Matrix() - m.rotateZ(math.pi/2) - rot1 = FreeCAD.Rotation() - rot1.Q = eval(rot) - rot2 = FreeCAD.Placement(m) - rot2 = rot2.Rotation - rot = str((rot1.multiply(rot2)).Q) - FreeCADGui.addModule("Draft") - if Draft.getParam("UsePartPrimitives",False): - # Use Part Primitive - self.commit(translate("draft","Create Ellipse"), - ['import Part', - 'ellipse = FreeCAD.ActiveDocument.addObject("Part::Ellipse","Ellipse")', - 'ellipse.MajorRadius = '+str(r1), - 'ellipse.MinorRadius = '+str(r2), - 'pl = FreeCAD.Placement()', - 'pl.Rotation.Q='+rot, - 'pl.Base = '+DraftVecUtils.toString(center), - 'ellipse.Placement = pl', - 'Draft.autogroup(ellipse)', - 'FreeCAD.ActiveDocument.recompute()']) - else: - self.commit(translate("draft","Create Ellipse"), - ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = '+rot, - 'pl.Base = '+DraftVecUtils.toString(center), - 'ellipse = Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl,face='+fil+',support='+sup+')', - 'Draft.autogroup(ellipse)', - 'FreeCAD.ActiveDocument.recompute()']) - except: - print("Draft: Error: Unable to create object.") - self.finish(cont=True) - - def action(self,arg): - """scene event handler""" - if arg["Type"] == "SoKeyboardEvent": - if arg["Key"] == "ESCAPE": - self.finish() - elif arg["Type"] == "SoLocation2Event": #mouse movement detection - self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True) - self.rect.update(self.point) - redraw3DView() - elif arg["Type"] == "SoMouseButtonEvent": - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - if (arg["Position"] == self.pos): - self.finish() - else: - if (not self.node) and (not self.support): - getSupport(arg) - self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True) - if self.point: - self.ui.redraw() - self.appendPoint(self.point) - - def numericInput(self,numx,numy,numz): - """this function gets called by the toolbar when valid x, y, and z have been entered there""" - self.point = Vector(numx,numy,numz) - self.appendPoint(self.point) - - def appendPoint(self,point): - self.node.append(point) - if (len(self.node) > 1): - self.rect.update(point) - self.createObject() - else: - FreeCAD.Console.PrintMessage(translate("draft", "Pick opposite point")+"\n") - self.ui.setRelative() - self.rect.setorigin(point) - self.rect.on() - if self.planetrack: - self.planetrack.set(point) +from draftguitools.gui_ellipses import Ellipse class Text(Creator): @@ -3553,7 +3435,6 @@ from draftguitools.gui_snaps import ShowSnapBar FreeCADGui.addCommand('Draft_Text',Text()) FreeCADGui.addCommand('Draft_Dimension',Dimension()) FreeCADGui.addCommand('Draft_Point',Point()) -FreeCADGui.addCommand('Draft_Ellipse',Ellipse()) FreeCADGui.addCommand('Draft_ShapeString',ShapeString()) FreeCADGui.addCommand('Draft_Facebinder',Draft_Facebinder()) FreeCADGui.addCommand('Draft_Label',Draft_Label()) diff --git a/src/Mod/Draft/draftguitools/gui_ellipses.py b/src/Mod/Draft/draftguitools/gui_ellipses.py new file mode 100644 index 0000000000..15ea881a37 --- /dev/null +++ b/src/Mod/Draft/draftguitools/gui_ellipses.py @@ -0,0 +1,204 @@ +# *************************************************************************** +# * (c) 2009, 2010 Yorik van Havre * +# * (c) 2009, 2010 Ken Cline * +# * (c) 2020 Eliud Cabrera Castillo * +# * * +# * 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 tools for creating ellipses with the Draft Workbench.""" +## @package gui_ellipses +# \ingroup DRAFT +# \brief Provides tools for creating ellipses with the Draft Workbench. + +import math +from PySide.QtCore import QT_TRANSLATE_NOOP + +import FreeCAD as App +import FreeCADGui as Gui +import Draft_rc +import DraftVecUtils +import draftutils.utils as 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.translate import translate +from draftutils.messages import _msg, _err + +# The module is used to prevent complaints from code checkers (flake8) +True if Draft_rc.__name__ else False + + +class Ellipse(gui_base_original.Creator): + """Gui command for the Ellipse tool.""" + + def GetResources(self): + """Set icon, menu and tooltip.""" + _tip = "Creates an ellipse. CTRL to snap." + + return {'Pixmap': 'Draft_Ellipse', + 'Accel': "E, L", + 'MenuText': QT_TRANSLATE_NOOP("Draft_Ellipse", "Ellipse"), + 'ToolTip': QT_TRANSLATE_NOOP("Draft_Ellipse", _tip)} + + def Activated(self): + """Execute when the command is called.""" + name = translate("draft", "Ellipse") + super().Activated(name) + if self.ui: + self.refpoint = None + self.ui.pointUi(name) + self.ui.extUi() + self.call = self.view.addEventCallback("SoEvent", self.action) + self.rect = trackers.rectangleTracker() + _msg(translate("draft", "Pick first point")) + + def finish(self, closed=False, cont=False): + """Terminate the operation.""" + super().finish(self) + if self.ui: + self.rect.off() + self.rect.finalize() + if self.ui and self.ui.continueMode: + self.Activated() + + def createObject(self): + """Create the actual object in the current document.""" + plane = App.DraftWorkingPlane + p1 = self.node[0] + p3 = self.node[-1] + diagonal = p3.sub(p1) + halfdiag = App.Vector(diagonal).multiply(0.5) + center = p1.add(halfdiag) + p2 = p1.add(DraftVecUtils.project(diagonal, plane.v)) + p4 = p1.add(DraftVecUtils.project(diagonal, plane.u)) + r1 = (p4.sub(p1).Length)/2 + r2 = (p2.sub(p1).Length)/2 + try: + # The command to run is built as a series of text strings + # to be commited through the `draftutils.todo.ToDo` class. + rot, sup, pts, fil = self.getStrings() + if r2 > r1: + r1, r2 = r2, r1 + m = App.Matrix() + m.rotateZ(math.pi/2) + rot1 = App.Rotation() + rot1.Q = eval(rot) + rot2 = App.Placement(m) + rot2 = rot2.Rotation + rot = str((rot1.multiply(rot2)).Q) + if utils.getParam("UsePartPrimitives", False): + # Insert a Part::Primitive object + Gui.addModule("Part") + _cmd = 'FreeCAD.ActiveDocument.' + _cmd += 'addObject("Part::Ellipse", "Ellipse")' + _cmd_list = ['ellipse = ' + _cmd, + 'ellipse.MajorRadius = ' + str(r1), + 'ellipse.MinorRadius = ' + str(r2), + 'pl = FreeCAD.Placement()', + 'pl.Rotation.Q= ' + rot, + 'pl.Base = ' + DraftVecUtils.toString(center), + 'ellipse.Placement = pl', + 'Draft.autogroup(ellipse)', + 'FreeCAD.ActiveDocument.recompute()'] + self.commit(translate("draft", "Create Ellipse"), + _cmd_list) + else: + # Insert a Draft ellipse + Gui.addModule("Draft") + _cmd = 'Draft.makeEllipse' + _cmd += '(' + _cmd += str(r1) + ', ' + str(r2) + ', ' + _cmd += 'placement=pl, ' + _cmd += 'face=' + fil + ', ' + _cmd += 'support=' + sup + _cmd += ')' + _cmd_list = ['pl = FreeCAD.Placement()', + 'pl.Rotation.Q = ' + rot, + 'pl.Base = ' + DraftVecUtils.toString(center), + 'ellipse = ' + _cmd, + 'Draft.autogroup(ellipse)', + 'FreeCAD.ActiveDocument.recompute()'] + self.commit(translate("draft", "Create Ellipse"), + _cmd_list) + except Exception: + _err("Draft: Error: Unable to create object.") + self.finish(cont=True) + + 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.point, + ctrlPoint, info) = gui_tool_utils.getPoint(self, arg, + mobile=True, + noTracker=True) + self.rect.update(self.point) + gui_tool_utils.redraw3DView() + elif arg["Type"] == "SoMouseButtonEvent": + if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1": + if arg["Position"] == self.pos: + self.finish() + else: + if (not self.node) and (not self.support): + gui_tool_utils.getSupport(arg) + (self.point, + ctrlPoint, info) = gui_tool_utils.getPoint(self, arg, + mobile=True, + noTracker=True) + if self.point: + self.ui.redraw() + self.appendPoint(self.point) + + 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.point = App.Vector(numx, numy, numz) + self.appendPoint(self.point) + + def appendPoint(self, point): + """Append the point to the list of nodes.""" + self.node.append(point) + if len(self.node) > 1: + self.rect.update(point) + self.createObject() + else: + _msg(translate("draft", "Pick opposite point")) + self.ui.setRelative() + self.rect.setorigin(point) + self.rect.on() + if self.planetrack: + self.planetrack.set(point) + + +Gui.addCommand('Draft_Ellipse', Ellipse())