Skip to content

Commit

Permalink
Draft: new make_radial_dimension function for more precision
Browse files Browse the repository at this point in the history
A single `make_dimension` handles three types of dimensions,
(1) simple linear, (2) linear linked to an object, and (3) linked
to a circular edge.

So, we provide a new function, `make_radial_dimension_obj`,
to handle the third case. In this way we can check the input
parameters much better.

We adjust the `Draft_Dimension` Gui Command accordingly.
  • Loading branch information
vocx-fc authored and yorikvanhavre committed Jun 17, 2020
1 parent 984de3b commit 2877870
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/Mod/Draft/Draft.py
Expand Up @@ -392,6 +392,7 @@
makeDimension,
make_linear_dimension,
make_linear_dimension_obj,
make_radial_dimension_obj,
make_angular_dimension,
makeAngularDimension)

Expand Down
8 changes: 4 additions & 4 deletions src/Mod/Draft/draftguitools/gui_dimensions.py
Expand Up @@ -305,12 +305,12 @@ def create_linear_dimension_obj(self, direction=None):

def create_radial_dimension_obj(self):
"""Create a radial dimension linked to a circular edge."""
_cmd = 'Draft.make_dimension'
_cmd = 'Draft.make_radial_dimension_obj'
_cmd += '('
_cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
_cmd += str(self.link[1]) + ', '
_cmd += '"' + str(self.arcmode) + '", '
_cmd += DraftVecUtils.toString(self.node[2])
_cmd += 'index=' + str(self.link[1] + 1) + ', '
_cmd += 'mode="' + str(self.arcmode) + '", '
_cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2])
_cmd += ')'
_cmd_list = ['_dim_ = ' + _cmd,
'Draft.autogroup(_dim_)',
Expand Down
124 changes: 124 additions & 0 deletions src/Mod/Draft/draftmake/make_dimension.py
Expand Up @@ -384,6 +384,130 @@ def make_linear_dimension_obj(edge_object, i1=1, i2=2, dim_line=None):
return new_obj


def make_radial_dimension_obj(edge_object, index=1, mode="radius",
dim_line=None):
"""Create a radial or diameter dimension from an arc object.
Parameters
----------
edge_object: Part::Feature
The object which has a circular edge which will be measured.
It must have a `Part::TopoShape`, and at least one element
must be a circular edge in `Shape.Edges` to be able to measure
its radius.
index: int, optional
It defaults to `1`.
It is the index of the edge in `edge_object` which is going to
be measured.
The minimum value should be `1`, which will be interpreted
as `'Edge1'`. If the value is below `1`, it will be set to `1`.
mode: str, optional
It defaults to `'radius'`; the other option is `'diameter'`.
It determines whether the dimension will be shown as a radius
or as a diameter.
dim_line: Base::Vector3, optional
It defaults to `None`.
This is a point through which the extension of the dimension line
will pass. The dimension line will be a radius or diameter
of the measured arc, extending from the center to the arc itself.
If it is `None`, this point will be set to one unit to the right
of the center of the arc, which will create a dimension line that is
horizontal, that is, parallel to the +X axis.
Returns
-------
App::FeaturePython
A scripted object of type `'LinearDimension'`.
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_radial_dimension_obj"
utils.print_header(_name, "Radial dimension")

found, doc = utils.find_doc(App.activeDocument())
if not found:
_err(_tr("No active document. Aborting."))
return None

if isinstance(edge_object, str):
edge_object_str = edge_object

found, edge_object = utils.find_object(edge_object, doc)
if not found:
_msg("edge_object: {}".format(edge_object_str))
_err(_tr("Wrong input: object not in document."))
return None

_msg("edge_object: {}".format(edge_object.Label))
if not hasattr(edge_object, "Shape"):
_err(_tr("Wrong input: object doesn't have a 'Shape' to measure."))
return None
if (not hasattr(edge_object.Shape, "Edges")
or len(edge_object.Shape.Edges) < 1):
_err(_tr("Wrong input: object doesn't have at least one element "
"in 'Edges' to use for measuring."))
return None

_msg("index: {}".format(index))
try:
utils.type_check([(index, int)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be an integer."))
return None

if index < 1:
index = 1
_wrn(_tr("index: values below 1 are not allowed; will be set to 1."))

edge = edge_object.getSubObject("Edge" + str(index))
if not edge:
_err(_tr("Wrong input: index doesn't correspond to an edge "
"in the object."))
return None

if not hasattr(edge, "Curve") or edge.Curve.TypeId != 'Part::GeomCircle':
_err(_tr("Wrong input: index doesn't correspond to a circular edge."))
return None

_msg("mode: {}".format(mode))
try:
utils.type_check([(mode, str)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be a string, 'radius' or 'diameter'."))
return None

if mode not in ("radius", "diameter"):
_err(_tr("Wrong input: must be a string, 'radius' or 'diameter'."))
return None

_msg("dim_line: {}".format(dim_line))
if dim_line:
try:
utils.type_check([(dim_line, App.Vector)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be a vector."))
return None
else:
center = edge_object.Shape.Edges[index - 1].Curve.Center
dim_line = center + App.Vector(1, 0, 0)

# TODO: the internal function expects an index starting with 0
# so we need to decrease the value here.
# This should be changed in the future in the internal function.
index -= 1

new_obj = make_dimension(edge_object, index, mode, dim_line)

return new_obj


def make_angular_dimension(center=App.Vector(0, 0, 0),
angles=[0, 90],
dim_line=App.Vector(10, 10, 0), normal=None):
Expand Down
12 changes: 6 additions & 6 deletions src/Mod/Draft/drafttests/draft_test_objects.py
Expand Up @@ -247,9 +247,9 @@ def _create_objects(doc=None,
arc_h.Placement.Base = Vector(9500, 0, 0)
doc.recompute()

dimension_r = Draft.make_dimension(arc_h, 0,
"radius",
Vector(9750, 200, 0))
dimension_r = Draft.make_radial_dimension_obj(arc_h, 1,
"radius",
Vector(9750, 200, 0))
if App.GuiUp:
dimension_r.ViewObject.ArrowSize = 15
dimension_r.ViewObject.FontSize = 100
Expand All @@ -259,9 +259,9 @@ def _create_objects(doc=None,
arc_h2.Placement.Base = Vector(10000, 1000, 0)
doc.recompute()

dimension_d = Draft.make_dimension(arc_h2, 0,
"diameter",
Vector(10750, 900, 0))
dimension_d = Draft.make_radial_dimension_obj(arc_h2, 1,
"diameter",
Vector(10750, 900, 0))
if App.GuiUp:
dimension_d.ViewObject.ArrowSize = 15
dimension_d.ViewObject.FontSize = 100
Expand Down
16 changes: 9 additions & 7 deletions src/Mod/Draft/drafttests/test_creation.py
Expand Up @@ -199,11 +199,11 @@ def test_dimension_linear_obj(self):
dim_line=Vector(5, 3, 0))
self.assertTrue(obj, "'{}' failed".format(operation))

def test_dimension_radial(self):
"""Create a circle and then a radial dimension."""
def test_dimension_radial_obj(self):
"""Create a circle and then a radial and a diameter dimension."""
operation = "Draft Dimension Radial"
_msg(" Test '{}'".format(operation))
radius = 3
radius = 10
start_angle = 0
end_angle = 90
_msg(" radius={}".format(radius))
Expand All @@ -213,10 +213,12 @@ def test_dimension_radial(self):
startangle=start_angle, endangle=end_angle)
self.doc.recompute()

obj1 = Draft.make_dimension(circ, 0,
p3="radius", p4=Vector(1, 1, 0))
obj2 = Draft.make_dimension(circ, 0,
p3="diameter", p4=Vector(3, 1, 0))
obj1 = Draft.make_radial_dimension_obj(circ, index=1,
mode="radius",
dim_line=Vector(1, 1, 0))
obj2 = Draft.make_radial_dimension_obj(circ, index=1,
mode="diameter",
dim_line=Vector(3, 1, 0))
self.assertTrue(obj1 and obj2, "'{}' failed".format(operation))

def test_dimension_angular(self):
Expand Down

0 comments on commit 2877870

Please sign in to comment.