Draft: move make_dimension function to its own module
Previously the `make_dimension` and `make_angular_dimension` functions were in `draftobjects/dimension.py`. Now they are moved to `draftmake/make_dimension.py`. The original `makeAngularDimension` function requires angles in radians which is counterintuitive for most cases. Also the order is `[big, small]`. The new function `make_angular_dimension` accepts angles in degrees, and the order is `[small, big]`. The older function is retained for compatibility purposes. Also perform several improvements such as PEP8 cleanup, writing complete docstrings, type checking the input arguments, and depreacting the older call. The `Draft.py` module, Gui Command, unit test, and test script are updated accordingly.
This commit is contained in:
@@ -109,6 +109,7 @@ SET(Draft_make_functions
|
||||
draftmake/make_circulararray.py
|
||||
draftmake/make_clone.py
|
||||
draftmake/make_copy.py
|
||||
draftmake/make_dimension.py
|
||||
draftmake/make_drawingview.py
|
||||
draftmake/make_ellipse.py
|
||||
draftmake/make_facebinder.py
|
||||
|
||||
@@ -383,21 +383,22 @@ if FreeCAD.GuiUp:
|
||||
# Draft annotation objects
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
from draftobjects.dimension import make_dimension, make_angular_dimension
|
||||
from draftobjects.dimension import LinearDimension, AngularDimension
|
||||
from draftobjects.dimension import (LinearDimension,
|
||||
_Dimension,
|
||||
AngularDimension,
|
||||
_AngularDimension)
|
||||
|
||||
makeDimension = make_dimension
|
||||
makeAngularDimension = make_angular_dimension
|
||||
_Dimension = LinearDimension
|
||||
_AngularDimension = AngularDimension
|
||||
from draftmake.make_dimension import (make_dimension,
|
||||
makeDimension,
|
||||
make_angular_dimension,
|
||||
makeAngularDimension)
|
||||
|
||||
if gui:
|
||||
if FreeCAD.GuiUp:
|
||||
from draftviewproviders.view_dimension import ViewProviderLinearDimension
|
||||
from draftviewproviders.view_dimension import ViewProviderAngularDimension
|
||||
_ViewProviderDimension = ViewProviderLinearDimension
|
||||
_ViewProviderAngularDimension = ViewProviderAngularDimension
|
||||
|
||||
|
||||
from draftobjects.label import (Label,
|
||||
DraftLabel)
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ and circular arcs.
|
||||
And it can also be an angular dimension measuring the angle between
|
||||
two straight lines.
|
||||
"""
|
||||
## @package gui_texts
|
||||
## @package gui_dimensions
|
||||
# \ingroup DRAFT
|
||||
# \brief Provides tools for creating dimensions with the Draft Workbench.
|
||||
|
||||
import math
|
||||
import lazy_loader.lazy_loader as lz
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
import sys
|
||||
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
@@ -49,6 +49,8 @@ import draftguitools.gui_trackers as trackers
|
||||
from draftutils.translate import translate
|
||||
from draftutils.messages import _msg
|
||||
|
||||
DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
|
||||
|
||||
# The module is used to prevent complaints from code checkers (flake8)
|
||||
True if Draft_rc.__name__ else False
|
||||
|
||||
@@ -71,14 +73,24 @@ class Dimension(gui_base_original.Creator):
|
||||
|
||||
def GetResources(self):
|
||||
"""Set icon, menu and tooltip."""
|
||||
_tip = ("Creates a dimension. "
|
||||
"Select a straight line to create a linear dimension.\n"
|
||||
"Select an arc or circle to create a radius or diameter "
|
||||
"dimension.\n"
|
||||
"Select two straight lines to create an angular dimension "
|
||||
_tip = ("Creates a dimension.\n"
|
||||
"\n"
|
||||
"- Pick three points to create a simple linear dimension.\n"
|
||||
"- Select a straight line to create a linear dimension "
|
||||
"linked to that line.\n"
|
||||
"- Select an arc or circle to create a radius or diameter "
|
||||
"dimension linked to that arc.\n"
|
||||
"- Select two straight lines to create an angular dimension "
|
||||
"between them.\n"
|
||||
"CTRL to snap, SHIFT to constrain, "
|
||||
"ALT to select an edge or arc.")
|
||||
"ALT to select an edge or arc.\n"
|
||||
"\n"
|
||||
"You may select a single line or single circular arc "
|
||||
"before launching this command\n"
|
||||
"to create the corresponding linked dimension.\n"
|
||||
"You may also select an 'App::MeasureDistance' object "
|
||||
"before launching this command\n"
|
||||
"to turn it into a 'Draft Dimension' object.")
|
||||
|
||||
return {'Pixmap': 'Draft_Dimension',
|
||||
'Accel': "D, I",
|
||||
@@ -123,8 +135,6 @@ class Dimension(gui_base_original.Creator):
|
||||
|
||||
def setFromSelection(self):
|
||||
"""Fill the nodes according to the selected geometry."""
|
||||
import DraftGeomUtils
|
||||
|
||||
sel = Gui.Selection.getSelectionEx()
|
||||
if len(sel) == 1:
|
||||
if len(sel[0].SubElementNames) == 1:
|
||||
@@ -180,23 +190,22 @@ class Dimension(gui_base_original.Creator):
|
||||
pt = _ch.getChildren()[3]
|
||||
p3 = App.Vector(pt.point.getValues()[2].getValue())
|
||||
Gui.addModule("Draft")
|
||||
_cmd = 'Draft.makeDimension'
|
||||
_cmd = 'Draft.make_dimension'
|
||||
_cmd += '('
|
||||
_cmd += DraftVecUtils.toString(p1) + ', '
|
||||
_cmd += DraftVecUtils.toString(p2) + ', '
|
||||
_cmd += DraftVecUtils.toString(p3)
|
||||
_cmd += ')'
|
||||
_rem = 'FreeCAD.ActiveDocument.removeObject("' + o.Name + '")'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
_rem,
|
||||
'Draft.autogroup(dim)',
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
|
||||
def createObject(self):
|
||||
"""Create the actual object in the current document."""
|
||||
import DraftGeomUtils
|
||||
Gui.addModule("Draft")
|
||||
|
||||
if self.angledata:
|
||||
@@ -206,92 +215,96 @@ class Dimension(gui_base_original.Creator):
|
||||
v2 = DraftGeomUtils.vec(self.edges[1])
|
||||
normal = DraftVecUtils.toString((v1.cross(v2)).normalize())
|
||||
|
||||
_cmd = 'Draft.makeAngularDimension('
|
||||
_cmd = 'Draft.make_angular_dimension'
|
||||
_cmd += '('
|
||||
_cmd += 'center=' + DraftVecUtils.toString(self.center) + ', '
|
||||
_cmd += 'angles='
|
||||
_cmd += '['
|
||||
_cmd += str(self.angledata[0]) + ', '
|
||||
_cmd += str(self.angledata[1])
|
||||
_cmd += str(math.degrees(self.angledata[1])) + ', '
|
||||
_cmd += str(math.degrees(self.angledata[0]))
|
||||
_cmd += '], '
|
||||
_cmd += 'p3=' + DraftVecUtils.toString(self.node[-1]) + ', '
|
||||
_cmd += 'dim_line=' + DraftVecUtils.toString(self.node[-1]) + ', '
|
||||
_cmd += 'normal=' + normal
|
||||
_cmd += ')'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
'Draft.autogroup(dim)',
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
|
||||
elif self.link and not self.arcmode:
|
||||
ops = []
|
||||
# Linear dimension, linked
|
||||
if self.force == 1:
|
||||
_cmd = 'Draft.makeDimension'
|
||||
_cmd = 'Draft.make_dimension'
|
||||
_cmd += '('
|
||||
_cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
|
||||
_cmd += str(self.link[1]) + ', '
|
||||
_cmd += str(self.link[2]) + ', '
|
||||
_cmd += DraftVecUtils.toString(self.node[2])
|
||||
_cmd += ')'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
'dim.Direction = FreeCAD.Vector(0, 1, 0)',
|
||||
'Draft.autogroup(dim)',
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
'_dim_.Direction = FreeCAD.Vector(0, 1, 0)',
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
elif self.force == 2:
|
||||
_cmd = 'Draft.makeDimension'
|
||||
_cmd = 'Draft.make_dimension'
|
||||
_cmd += '('
|
||||
_cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
|
||||
_cmd += str(self.link[1]) + ', '
|
||||
_cmd += str(self.link[2]) + ', '
|
||||
_cmd += DraftVecUtils.toString(self.node[2])
|
||||
_cmd += ')'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
'dim.Direction = FreeCAD.Vector(1, 0, 0)',
|
||||
'Draft.autogroup(dim)',
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
'_dim_.Direction = FreeCAD.Vector(1, 0, 0)',
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
else:
|
||||
_cmd = 'Draft.makeDimension'
|
||||
_cmd = 'Draft.make_dimension'
|
||||
_cmd += '('
|
||||
_cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
|
||||
_cmd += str(self.link[1]) + ', '
|
||||
_cmd += str(self.link[2]) + ', '
|
||||
_cmd += DraftVecUtils.toString(self.node[2])
|
||||
_cmd += ')'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
'Draft.autogroup(dim)',
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
|
||||
elif self.arcmode:
|
||||
# Radius or dimeter dimension, linked
|
||||
_cmd = 'Draft.makeDimension'
|
||||
_cmd = 'Draft.make_dimension'
|
||||
_cmd += '('
|
||||
_cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
|
||||
_cmd += str(self.link[1]) + ', '
|
||||
_cmd += '"' + str(self.arcmode) + '", '
|
||||
_cmd += DraftVecUtils.toString(self.node[2])
|
||||
_cmd += ')'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
'Draft.autogroup(dim)',
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
|
||||
else:
|
||||
# Linear dimension, non-linked
|
||||
_cmd = 'Draft.makeDimension'
|
||||
_cmd = 'Draft.make_dimension'
|
||||
_cmd += '('
|
||||
_cmd += DraftVecUtils.toString(self.node[0]) + ', '
|
||||
_cmd += DraftVecUtils.toString(self.node[1]) + ', '
|
||||
_cmd += DraftVecUtils.toString(self.node[2])
|
||||
_cmd += ')'
|
||||
_cmd_list = ['dim = ' + _cmd,
|
||||
'Draft.autogroup(dim)',
|
||||
_cmd_list = ['_dim_ = ' + _cmd,
|
||||
'Draft.autogroup(_dim_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Dimension"),
|
||||
_cmd_list)
|
||||
|
||||
if self.ui.continueMode:
|
||||
self.cont = self.node[2]
|
||||
if not self.dir:
|
||||
@@ -323,7 +336,6 @@ class Dimension(gui_base_original.Creator):
|
||||
if arg["Key"] == "ESCAPE":
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event": # mouse movement detection
|
||||
import DraftGeomUtils
|
||||
shift = gui_tool_utils.hasMod(arg, gui_tool_utils.MODCONSTRAIN)
|
||||
if self.arcmode or self.point2:
|
||||
gui_tool_utils.setMod(arg, gui_tool_utils.MODCONSTRAIN, False)
|
||||
@@ -423,7 +435,6 @@ class Dimension(gui_base_original.Creator):
|
||||
gui_tool_utils.redraw3DView()
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
import DraftGeomUtils
|
||||
if self.point:
|
||||
self.ui.redraw()
|
||||
if (not self.node) and (not self.support):
|
||||
|
||||
311
src/Mod/Draft/draftmake/make_dimension.py
Normal file
311
src/Mod/Draft/draftmake/make_dimension.py
Normal file
@@ -0,0 +1,311 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
|
||||
# * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> *
|
||||
# * Copyright (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 functions to crate dimension objects."""
|
||||
## @package make_dimension
|
||||
# \ingroup DRAFT
|
||||
# \brief Provides functions to crate dimension objects.
|
||||
|
||||
import math
|
||||
|
||||
import FreeCAD as App
|
||||
import draftutils.utils as utils
|
||||
import draftutils.gui_utils as gui_utils
|
||||
|
||||
from draftutils.messages import _msg, _wrn, _err
|
||||
from draftutils.translate import _tr
|
||||
from draftobjects.dimension import (LinearDimension,
|
||||
AngularDimension)
|
||||
|
||||
if App.GuiUp:
|
||||
from draftviewproviders.view_dimension import ViewProviderLinearDimension
|
||||
from draftviewproviders.view_dimension import ViewProviderAngularDimension
|
||||
|
||||
|
||||
def make_dimension(p1, p2, p3=None, p4=None):
|
||||
"""Create one of three types of dimension objects.
|
||||
|
||||
In all dimensions the p3 parameter defines a point through which
|
||||
the dimension line will go through.
|
||||
|
||||
The current line width and color will be used.
|
||||
|
||||
Linear dimension
|
||||
----------------
|
||||
- (p1, p2, p3): a simple linear dimension from p1 to p2
|
||||
|
||||
- (object, i1, i2, p3): creates a linked dimension to the provided
|
||||
object (edge), measuring the distance between its vertices
|
||||
indexed i1 and i2
|
||||
|
||||
Circular dimension
|
||||
------------------
|
||||
- (arc, i1, mode, p3): creates a linked dimension to the given arc
|
||||
object, i1 is the index of the arc edge that will be measured;
|
||||
mode is either "radius" or "diameter".
|
||||
"""
|
||||
if not App.ActiveDocument:
|
||||
_err("No active document. Aborting")
|
||||
return None
|
||||
|
||||
new_obj = App.ActiveDocument.addObject("App::FeaturePython",
|
||||
"Dimension")
|
||||
LinearDimension(new_obj)
|
||||
|
||||
if App.GuiUp:
|
||||
ViewProviderLinearDimension(new_obj.ViewObject)
|
||||
|
||||
if isinstance(p1, App.Vector) and isinstance(p2, App.Vector):
|
||||
# Measure a straight distance between p1 and p2
|
||||
new_obj.Start = p1
|
||||
new_obj.End = p2
|
||||
if not p3:
|
||||
p3 = p2.sub(p1)
|
||||
p3.multiply(0.5)
|
||||
p3 = p1.add(p3)
|
||||
|
||||
elif isinstance(p2, int) and isinstance(p3, int):
|
||||
# p1 is an object, and measure the distance between vertices p2 and p3
|
||||
# of this object
|
||||
linked = []
|
||||
idx = (p2, p3)
|
||||
linked.append((p1, "Vertex" + str(p2 + 1)))
|
||||
linked.append((p1, "Vertex" + str(p3 + 1)))
|
||||
new_obj.LinkedGeometry = linked
|
||||
new_obj.Support = p1
|
||||
|
||||
# p4, and now p3, is the point through which the dimension line
|
||||
# will go through
|
||||
p3 = p4
|
||||
if not p3:
|
||||
# When used from the GUI command, this will never run
|
||||
# because p4 will always be assinged to a vector,
|
||||
# so p3 will never be `None`.
|
||||
# Moreover, `new_obj.Base` doesn't exist, and certainly `Shape`
|
||||
# doesn't exist, so if this ever runs it will be an error.
|
||||
v1 = new_obj.Base.Shape.Vertexes[idx[0]].Point
|
||||
v2 = new_obj.Base.Shape.Vertexes[idx[1]].Point
|
||||
p3 = v2.sub(v1)
|
||||
p3.multiply(0.5)
|
||||
p3 = v1.add(p3)
|
||||
|
||||
elif isinstance(p3, str):
|
||||
# If the original p3 is a string, we are measuring a circular arc
|
||||
# p2 should be an integer number starting from 0
|
||||
linked = []
|
||||
linked.append((p1, "Edge" + str(p2 + 1)))
|
||||
|
||||
if p3 == "radius":
|
||||
# linked.append((p1, "Center"))
|
||||
if App.GuiUp:
|
||||
new_obj.ViewObject.Override = "R $dim"
|
||||
new_obj.Diameter = False
|
||||
elif p3 == "diameter":
|
||||
# linked.append((p1, "Diameter"))
|
||||
if App.GuiUp:
|
||||
new_obj.ViewObject.Override = "Ø $dim"
|
||||
new_obj.Diameter = True
|
||||
new_obj.LinkedGeometry = linked
|
||||
new_obj.Support = p1
|
||||
|
||||
# p4, and now p3, is the point through which the dimension line
|
||||
# will go through
|
||||
p3 = p4
|
||||
if not p3:
|
||||
p3 = p1.Shape.Edges[p2].Curve.Center.add(App.Vector(1, 0, 0))
|
||||
|
||||
# This p3 is the point through which the dimension line will pass,
|
||||
# but this may not be the original p3, it could have been p4
|
||||
# depending on the first three parameter values
|
||||
new_obj.Dimline = p3
|
||||
|
||||
if hasattr(App, "DraftWorkingPlane"):
|
||||
normal = App.DraftWorkingPlane.axis
|
||||
else:
|
||||
normal = App.Vector(0, 0, 1)
|
||||
|
||||
if App.GuiUp:
|
||||
# invert the normal if we are viewing it from the back
|
||||
vnorm = gui_utils.get3DView().getViewDirection()
|
||||
|
||||
if vnorm.getAngle(normal) < math.pi/2:
|
||||
normal = normal.negative()
|
||||
|
||||
new_obj.Normal = normal
|
||||
|
||||
if App.GuiUp:
|
||||
gui_utils.format_object(new_obj)
|
||||
gui_utils.select(new_obj)
|
||||
|
||||
return new_obj
|
||||
|
||||
|
||||
def makeDimension(p1, p2, p3=None, p4=None):
|
||||
"""Create a dimension. DEPRECATED. Use 'make_dimension'."""
|
||||
_wrn(_tr("This function is deprecated. "
|
||||
"Do not use this function directly."))
|
||||
_wrn(_tr("Use one of 'make_linear_dimension', or "
|
||||
"'make_linear_dimension_obj'."))
|
||||
|
||||
return make_dimension(p1, p2, p3, p4)
|
||||
|
||||
|
||||
def make_angular_dimension(center=App.Vector(0, 0, 0),
|
||||
angles=[0, 90],
|
||||
dim_line=App.Vector(3, 3, 0), normal=None):
|
||||
"""Create an angular dimension from the given center and angles.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
center: Base::Vector3, optional
|
||||
It defaults to the origin `Vector(0, 0, 0)`.
|
||||
Center of the dimension line, which is a circular arc.
|
||||
|
||||
angles: list of two floats, optional
|
||||
It defaults to `[0, 90]`.
|
||||
It is a list of two angles, given in degrees, that determine
|
||||
the apperture of the dimension line, that is, of the circular arc.
|
||||
It is drawn counter-clockwise.
|
||||
::
|
||||
angles = [0 90]
|
||||
angles = [330 60] # the arc crosses the X axis
|
||||
angles = [-30 60] # same angle
|
||||
|
||||
dim_line: Base::Vector3, optional
|
||||
It defaults to `Vector(3, 3, 0)`.
|
||||
Point through which the dimension line will pass.
|
||||
This defines the radius of the dimension line, the circular arc.
|
||||
|
||||
normal: Base::Vector3, optional
|
||||
It defaults to `None`, in which case the `normal` is taken
|
||||
from the currently active `App.DraftWorkingPlane.axis`.
|
||||
|
||||
If the working plane is not available, then the `normal`
|
||||
defaults to +Z or `Vector(0, 0, 1)`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
App::FeaturePython
|
||||
A scripted object of type `'AngularDimension'`.
|
||||
This object does not have a `Shape` attribute, as the text and lines
|
||||
are created on screen by Coin (pivy).
|
||||
|
||||
None
|
||||
If there is a problem it will return `None`.
|
||||
"""
|
||||
_name = "make_angular_dimension"
|
||||
utils.print_header(_name, "Angular dimension")
|
||||
|
||||
found, doc = utils.find_doc(App.activeDocument())
|
||||
if not found:
|
||||
_err(_tr("No active document. Aborting."))
|
||||
return None
|
||||
|
||||
_msg("center: {}".format(center))
|
||||
try:
|
||||
utils.type_check([(center, App.Vector)], name=_name)
|
||||
except TypeError:
|
||||
_err(_tr("Wrong input: must be a vector."))
|
||||
return None
|
||||
|
||||
_msg("angles: {}".format(angles))
|
||||
try:
|
||||
utils.type_check([(angles, (tuple, list))], name=_name)
|
||||
|
||||
if len(angles) != 2:
|
||||
_err(_tr("Wrong input: must be a list with two angles."))
|
||||
return None
|
||||
|
||||
ang1, ang2 = angles
|
||||
utils.type_check([(ang1, (int, float)),
|
||||
(ang2, (int, float))], name=_name)
|
||||
except TypeError:
|
||||
_err(_tr("Wrong input: must be a list with two angles."))
|
||||
return None
|
||||
|
||||
# If the angle is larger than 360 degrees, make sure
|
||||
# it is smaller than 360
|
||||
for n in range(len(angles)):
|
||||
if angles[n] > 360:
|
||||
angles[n] = angles[n] - 360
|
||||
|
||||
_msg("dim_line: {}".format(dim_line))
|
||||
try:
|
||||
utils.type_check([(dim_line, App.Vector)], name=_name)
|
||||
except TypeError:
|
||||
_err(_tr("Wrong input: must be a vector."))
|
||||
return None
|
||||
|
||||
_msg("normal: {}".format(normal))
|
||||
if normal:
|
||||
try:
|
||||
utils.type_check([(dim_line, App.Vector)], name=_name)
|
||||
except TypeError:
|
||||
_err(_tr("Wrong input: must be a vector."))
|
||||
return None
|
||||
|
||||
if not normal:
|
||||
if hasattr(App, "DraftWorkingPlane"):
|
||||
normal = App.DraftWorkingPlane.axis
|
||||
else:
|
||||
normal = App.Vector(0, 0, 1)
|
||||
|
||||
new_obj = App.ActiveDocument.addObject("App::FeaturePython",
|
||||
"Dimension")
|
||||
AngularDimension(new_obj)
|
||||
|
||||
new_obj.Center = center
|
||||
new_obj.FirstAngle = angles[0]
|
||||
new_obj.LastAngle = angles[1]
|
||||
new_obj.Dimline = dim_line
|
||||
|
||||
if App.GuiUp:
|
||||
ViewProviderAngularDimension(new_obj.ViewObject)
|
||||
|
||||
# Invert the normal if we are viewing it from the back.
|
||||
# This is determined by the angle between the current
|
||||
# 3D view and the provided normal being below 90 degrees
|
||||
vnorm = gui_utils.get3DView().getViewDirection()
|
||||
if vnorm.getAngle(normal) < math.pi/2:
|
||||
normal = normal.negative()
|
||||
|
||||
new_obj.Normal = normal
|
||||
|
||||
if App.GuiUp:
|
||||
gui_utils.format_object(new_obj)
|
||||
gui_utils.select(new_obj)
|
||||
|
||||
return new_obj
|
||||
|
||||
|
||||
def makeAngularDimension(center, angles, p3, normal=None):
|
||||
"""Create an angle dimension. DEPRECATED. Use 'make_angular_dimension'."""
|
||||
utils.use_instead("make_angular_dimension")
|
||||
|
||||
ang1, ang2 = angles
|
||||
angles = [math.degrees(ang2), math.degrees(ang1)]
|
||||
|
||||
return make_angular_dimension(center=center, angles=angles,
|
||||
dim_line=p3, normal=normal)
|
||||
@@ -22,152 +22,32 @@
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""This module provides the object code for Draft Dimension.
|
||||
"""
|
||||
"""This module provides the object code for Draft Dimension."""
|
||||
## @package dimension
|
||||
# \ingroup DRAFT
|
||||
# \brief This module provides the object code for Draft Dimension.
|
||||
|
||||
import FreeCAD as App
|
||||
import math
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
import DraftGeomUtils, DraftVecUtils
|
||||
import draftutils.gui_utils as gui_utils
|
||||
|
||||
import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
import DraftGeomUtils
|
||||
import draftutils.utils as utils
|
||||
|
||||
from draftobjects.draft_annotation import DraftAnnotation
|
||||
|
||||
if App.GuiUp:
|
||||
from draftviewproviders.view_dimension import ViewProviderDimensionBase
|
||||
from draftviewproviders.view_dimension import ViewProviderLinearDimension
|
||||
from draftviewproviders.view_dimension import ViewProviderAngularDimension
|
||||
|
||||
def make_dimension(p1,p2,p3=None,p4=None):
|
||||
"""makeDimension(p1,p2,[p3]) or makeDimension(object,i1,i2,p3)
|
||||
or makeDimension(objlist,indices,p3): Creates a Dimension object with
|
||||
the dimension line passign through p3.The current line width and color
|
||||
will be used. There are multiple ways to create a dimension, depending on
|
||||
the arguments you pass to it:
|
||||
- (p1,p2,p3): creates a standard dimension from p1 to p2
|
||||
- (object,i1,i2,p3): creates a linked dimension to the given object,
|
||||
measuring the distance between its vertices indexed i1 and i2
|
||||
- (object,i1,mode,p3): creates a linked dimension
|
||||
to the given object, i1 is the index of the (curved) edge to measure,
|
||||
and mode is either "radius" or "diameter".
|
||||
"""
|
||||
if not App.ActiveDocument:
|
||||
App.Console.PrintError("No active document. Aborting\n")
|
||||
return
|
||||
obj = App.ActiveDocument.addObject("App::FeaturePython","Dimension")
|
||||
LinearDimension(obj)
|
||||
if App.GuiUp:
|
||||
ViewProviderLinearDimension(obj.ViewObject)
|
||||
if isinstance(p1,App.Vector) and isinstance(p2,App.Vector):
|
||||
obj.Start = p1
|
||||
obj.End = p2
|
||||
if not p3:
|
||||
p3 = p2.sub(p1)
|
||||
p3.multiply(0.5)
|
||||
p3 = p1.add(p3)
|
||||
elif isinstance(p2,int) and isinstance(p3,int):
|
||||
l = []
|
||||
idx = (p2,p3)
|
||||
l.append((p1,"Vertex"+str(p2+1)))
|
||||
l.append((p1,"Vertex"+str(p3+1)))
|
||||
obj.LinkedGeometry = l
|
||||
obj.Support = p1
|
||||
p3 = p4
|
||||
if not p3:
|
||||
v1 = obj.Base.Shape.Vertexes[idx[0]].Point
|
||||
v2 = obj.Base.Shape.Vertexes[idx[1]].Point
|
||||
p3 = v2.sub(v1)
|
||||
p3.multiply(0.5)
|
||||
p3 = v1.add(p3)
|
||||
elif isinstance(p3,str):
|
||||
l = []
|
||||
l.append((p1,"Edge"+str(p2+1)))
|
||||
if p3 == "radius":
|
||||
#l.append((p1,"Center"))
|
||||
if App.GuiUp:
|
||||
obj.ViewObject.Override = "R $dim"
|
||||
obj.Diameter = False
|
||||
elif p3 == "diameter":
|
||||
#l.append((p1,"Diameter"))
|
||||
if App.GuiUp:
|
||||
obj.ViewObject.Override = "Ø $dim"
|
||||
obj.Diameter = True
|
||||
obj.LinkedGeometry = l
|
||||
obj.Support = p1
|
||||
p3 = p4
|
||||
if not p3:
|
||||
p3 = p1.Shape.Edges[p2].Curve.Center.add(App.Vector(1,0,0))
|
||||
obj.Dimline = p3
|
||||
if hasattr(App,"DraftWorkingPlane"):
|
||||
normal = App.DraftWorkingPlane.axis
|
||||
else:
|
||||
normal = App.Vector(0,0,1)
|
||||
if App.GuiUp:
|
||||
# invert the normal if we are viewing it from the back
|
||||
vnorm = gui_utils.get3DView().getViewDirection()
|
||||
if vnorm.getAngle(normal) < math.pi/2:
|
||||
normal = normal.negative()
|
||||
obj.Normal = normal
|
||||
|
||||
if App.GuiUp:
|
||||
gui_utils.format_object(obj)
|
||||
gui_utils.select(obj)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def make_angular_dimension(center,angles,p3,normal=None):
|
||||
"""makeAngularDimension(center,angle1,angle2,p3,[normal]): creates an angular Dimension
|
||||
from the given center, with the given list of angles, passing through p3.
|
||||
"""
|
||||
if not App.ActiveDocument:
|
||||
App.Console.PrintError("No active document. Aborting\n")
|
||||
return
|
||||
obj = App.ActiveDocument.addObject("App::FeaturePython","Dimension")
|
||||
AngularDimension(obj)
|
||||
if App.GuiUp:
|
||||
ViewProviderAngularDimension(obj.ViewObject)
|
||||
obj.Center = center
|
||||
for a in range(len(angles)):
|
||||
if angles[a] > 2*math.pi:
|
||||
angles[a] = angles[a]-(2*math.pi)
|
||||
obj.FirstAngle = math.degrees(angles[1])
|
||||
obj.LastAngle = math.degrees(angles[0])
|
||||
obj.Dimline = p3
|
||||
if not normal:
|
||||
if hasattr(App,"DraftWorkingPlane"):
|
||||
normal = App.DraftWorkingPlane.axis
|
||||
else:
|
||||
normal = App.Vector(0,0,1)
|
||||
if App.GuiUp:
|
||||
# invert the normal if we are viewing it from the back
|
||||
vnorm = gui_utils.get3DView().getViewDirection()
|
||||
if vnorm.getAngle(normal) < math.pi/2:
|
||||
normal = normal.negative()
|
||||
|
||||
obj.Normal = normal
|
||||
|
||||
if App.GuiUp:
|
||||
gui_utils.format_object(obj)
|
||||
gui_utils.select(obj)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
|
||||
class DimensionBase(DraftAnnotation):
|
||||
"""
|
||||
The Draft Dimension Base object
|
||||
"""The base objects for dimension objects.
|
||||
|
||||
This class inherits `DraftAnnotation` to define the basic properties
|
||||
of all annotation type objects, like a scaling multiplier.
|
||||
|
||||
This class is not used directly, but inherited by all dimension
|
||||
objects.
|
||||
"""
|
||||
|
||||
def __init__(self, obj, tp = "Dimension"):
|
||||
"""Add common dimension properties to the object and set them"""
|
||||
|
||||
def __init__(self, obj, tp="Dimension"):
|
||||
super(DimensionBase, self).__init__(obj, tp)
|
||||
|
||||
# Draft
|
||||
@@ -190,21 +70,12 @@ class DimensionBase(DraftAnnotation):
|
||||
def onDocumentRestored(self, obj):
|
||||
super(DimensionBase, self).onDocumentRestored(obj)
|
||||
|
||||
def execute(self, obj):
|
||||
'''Do something when recompute object'''
|
||||
|
||||
return
|
||||
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
'''Do something when a property has changed'''
|
||||
|
||||
return
|
||||
|
||||
|
||||
class LinearDimension(DimensionBase):
|
||||
"""
|
||||
The Draft Linear Dimension object
|
||||
"""The linear dimension object.
|
||||
|
||||
This inherits `DimensionBase` to provide the basic functionality of
|
||||
a dimension.
|
||||
"""
|
||||
|
||||
def __init__(self, obj):
|
||||
@@ -238,7 +109,6 @@ class LinearDimension(DimensionBase):
|
||||
obj.Start = App.Vector(0,0,0)
|
||||
obj.End = App.Vector(1,0,0)
|
||||
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
super(LinearDimension, self).onDocumentRestored(obj)
|
||||
|
||||
@@ -251,7 +121,6 @@ class LinearDimension(DimensionBase):
|
||||
if hasattr(obj, "Support"):
|
||||
obj.setEditorMode('Support', 2)
|
||||
|
||||
|
||||
def execute(self, obj):
|
||||
""" Set start point and end point according to the linked geometry"""
|
||||
if obj.LinkedGeometry:
|
||||
@@ -308,20 +177,21 @@ class LinearDimension(DimensionBase):
|
||||
obj.ViewObject.update()
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
_Dimension = LinearDimension
|
||||
|
||||
|
||||
class AngularDimension(DimensionBase):
|
||||
"""
|
||||
The Draft AngularDimension object
|
||||
"""The angular dimension object.
|
||||
|
||||
This inherits `DimensionBase` to provide the basic functionality of
|
||||
a dimension.
|
||||
"""
|
||||
|
||||
def __init__(self, obj):
|
||||
|
||||
super(AngularDimension, self).__init__(obj, "AngularDimension")
|
||||
|
||||
self.init_properties(obj)
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
def init_properties(self, obj):
|
||||
"""Add Angular Dimension specific properties to the object and set them"""
|
||||
@@ -352,7 +222,6 @@ class AngularDimension(DimensionBase):
|
||||
if fp.ViewObject:
|
||||
fp.ViewObject.update()
|
||||
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
'''Do something when a property has changed'''
|
||||
super(AngularDimension, self).onChanged(obj, prop)
|
||||
@@ -362,3 +231,7 @@ class AngularDimension(DimensionBase):
|
||||
obj.setEditorMode('Normal',2)
|
||||
if hasattr(obj,"Support"):
|
||||
obj.setEditorMode('Support',2)
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
_AngularDimension = AngularDimension
|
||||
|
||||
@@ -39,7 +39,6 @@ Or load it as a module and use the defined function.
|
||||
# @{
|
||||
|
||||
import datetime
|
||||
import math
|
||||
import os
|
||||
|
||||
import FreeCAD as App
|
||||
@@ -260,8 +259,8 @@ def _create_objects(doc=None,
|
||||
_msg("Angular dimension")
|
||||
Draft.make_line(Vector(10500, 300, 0), Vector(11500, 1000, 0))
|
||||
Draft.make_line(Vector(10500, 300, 0), Vector(11500, 0, 0))
|
||||
angle1 = math.radians(40)
|
||||
angle2 = math.radians(-20)
|
||||
angle1 = -20
|
||||
angle2 = 40
|
||||
dimension_a = Draft.make_angular_dimension(Vector(10500, 300, 0),
|
||||
[angle1, angle2],
|
||||
Vector(11500, 300, 0))
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
"""Unit test for the Draft Workbench, object creation tests."""
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
import FreeCAD as App
|
||||
import Draft
|
||||
@@ -210,14 +209,13 @@ class DraftCreation(unittest.TestCase):
|
||||
_msg(" Test '{}'".format(operation))
|
||||
_msg(" Occasionally crashes")
|
||||
center = Vector(0, 0, 0)
|
||||
angle1 = math.radians(60)
|
||||
angle2 = math.radians(10)
|
||||
p3 = Vector(3, 1, 0)
|
||||
angle1 = 20
|
||||
angle2 = 70
|
||||
dim_line = Vector(3, 1, 0)
|
||||
_msg(" center={}".format(center))
|
||||
_msg(" angle1={0}, angle2={1}".format(math.degrees(angle1),
|
||||
math.degrees(angle2)))
|
||||
_msg(" point={}".format(p3))
|
||||
obj = Draft.make_angular_dimension(center, [angle1, angle2], p3)
|
||||
_msg(" angle1={0}, angle2={1}".format(angle1, angle2))
|
||||
_msg(" dim_line={}".format(dim_line))
|
||||
obj = Draft.make_angular_dimension(center, [angle1, angle2], dim_line)
|
||||
self.assertTrue(obj, "'{}' failed".format(operation))
|
||||
|
||||
def test_bspline(self):
|
||||
|
||||
Reference in New Issue
Block a user