From 287787031899ad0b93b119ec76784771047235a5 Mon Sep 17 00:00:00 2001 From: vocx-fc Date: Wed, 10 Jun 2020 23:14:18 -0500 Subject: [PATCH] Draft: new make_radial_dimension function for more precision 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. --- src/Mod/Draft/Draft.py | 1 + src/Mod/Draft/draftguitools/gui_dimensions.py | 8 +- src/Mod/Draft/draftmake/make_dimension.py | 124 ++++++++++++++++++ .../Draft/drafttests/draft_test_objects.py | 12 +- src/Mod/Draft/drafttests/test_creation.py | 16 ++- 5 files changed, 144 insertions(+), 17 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 37ef76039574..2f645a92bee8 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -392,6 +392,7 @@ makeDimension, make_linear_dimension, make_linear_dimension_obj, + make_radial_dimension_obj, make_angular_dimension, makeAngularDimension) diff --git a/src/Mod/Draft/draftguitools/gui_dimensions.py b/src/Mod/Draft/draftguitools/gui_dimensions.py index ec1bdba422db..805d18bd42b1 100644 --- a/src/Mod/Draft/draftguitools/gui_dimensions.py +++ b/src/Mod/Draft/draftguitools/gui_dimensions.py @@ -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_)', diff --git a/src/Mod/Draft/draftmake/make_dimension.py b/src/Mod/Draft/draftmake/make_dimension.py index 1532c3b5b835..50dacdfc21dc 100644 --- a/src/Mod/Draft/draftmake/make_dimension.py +++ b/src/Mod/Draft/draftmake/make_dimension.py @@ -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): diff --git a/src/Mod/Draft/drafttests/draft_test_objects.py b/src/Mod/Draft/drafttests/draft_test_objects.py index b0ee08527550..12a447d6712b 100644 --- a/src/Mod/Draft/drafttests/draft_test_objects.py +++ b/src/Mod/Draft/drafttests/draft_test_objects.py @@ -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 @@ -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 diff --git a/src/Mod/Draft/drafttests/test_creation.py b/src/Mod/Draft/drafttests/test_creation.py index c7b2e6530066..6a62617d546a 100644 --- a/src/Mod/Draft/drafttests/test_creation.py +++ b/src/Mod/Draft/drafttests/test_creation.py @@ -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)) @@ -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):