Draft: organize execute code of the dimension classes

Instead of placing the entire code in the `execute` method,
we use three medthods to extract the `Start` and `End` dimension
points from different combinations of edges.

One method to get the dimension from a single object, from the edge,
either linear or circular; one method to get the dimension
from a single object, from two vertices; one method to measure
the distance between two objects, from two different vertices.
This commit is contained in:
vocx-fc
2020-06-13 06:24:20 -05:00
committed by Yorik van Havre
parent c042eb7454
commit 4ef2063715

View File

@@ -247,58 +247,48 @@ class LinearDimension(DimensionBase):
def execute(self, obj):
"""Execute when the object is created or recomputed.
Set start point and end point according to the linked geometry.
Set start point and end point according to the linked geometry
and the number of subelements.
If it has one subelement, we assume a straight edge or a circular edge.
If it has two subelements, we assume a straight edge (two vertices).
"""
if obj.LinkedGeometry:
if len(obj.LinkedGeometry) == 1:
lobj = obj.LinkedGeometry[0][0]
lsub = obj.LinkedGeometry[0][1]
if len(lsub) == 1:
if "Edge" in lsub[0]:
n = int(lsub[0][4:]) - 1
edge = lobj.Shape.Edges[n]
if DraftGeomUtils.geomType(edge) == "Line":
obj.Start = edge.Vertexes[0].Point
obj.End = edge.Vertexes[-1].Point
elif DraftGeomUtils.geomType(edge) == "Circle":
c = edge.Curve.Center
r = edge.Curve.Radius
a = edge.Curve.Axis
ray = obj.Dimline.sub(c).projectToPlane(App.Vector(0, 0, 0), a)
if ray.Length == 0:
ray = a.cross(App.Vector(1, 0, 0))
if ray.Length == 0:
ray = a.cross(App.Vector(0, 1, 0))
ray = DraftVecUtils.scaleTo(ray, r)
if hasattr(obj, "Diameter"):
if obj.Diameter:
obj.Start = c.add(ray.negative())
obj.End = c.add(ray)
else:
obj.Start = c
obj.End = c.add(ray)
elif len(lsub) == 2:
if ("Vertex" in lsub[0]) and ("Vertex" in lsub[1]):
n1 = int(lsub[0][6:]) - 1
n2 = int(lsub[1][6:]) - 1
obj.Start = lobj.Shape.Vertexes[n1].Point
obj.End = lobj.Shape.Vertexes[n2].Point
elif len(obj.LinkedGeometry) == 2:
lobj1 = obj.LinkedGeometry[0][0]
lobj2 = obj.LinkedGeometry[1][0]
lsub1 = obj.LinkedGeometry[0][1]
lsub2 = obj.LinkedGeometry[1][1]
if (len(lsub1) == 1) and (len(lsub2) == 1):
if ("Vertex" in lsub1[0]) and ("Vertex" in lsub2[1]):
n1 = int(lsub1[0][6:]) - 1
n2 = int(lsub2[0][6:]) - 1
obj.Start = lobj1.Shape.Vertexes[n1].Point
obj.End = lobj2.Shape.Vertexes[n2].Point
linked_obj = obj.LinkedGeometry[0][0]
sub_list = obj.LinkedGeometry[0][1]
# set the distance property
total_len = (obj.Start.sub(obj.End)).Length
if round(obj.Distance.Value, utils.precision()) != round(total_len, utils.precision()):
obj.Distance = total_len
if len(sub_list) == 1:
# If it has one subelement, we assume an edge
# that can be a straight line, or a circular edge
subelement = sub_list[0]
(obj.Start,
obj.End) = measure_one_obj_edge(linked_obj,
subelement,
obj.Dimline,
obj.Diameter)
elif len(sub_list) == 2:
# If it has two subelements, we assume a straight edge
# that is measured by two vertices
(obj.Start,
obj.End) = measure_one_obj_vertices(linked_obj,
sub_list)
elif len(obj.LinkedGeometry) == 2:
# If the list has two objects, it measures the distance
# between the two vertices in those two objects
(obj.Start,
obj.End) = measure_two_objects(obj.LinkedGeometry[0],
obj.LinkedGeometry[1])
# Update the distance property by comparing the floats
# with the precision
net_length = (obj.Start.sub(obj.End)).Length
rounded_1 = round(obj.Distance.Value, utils.precision())
rounded_2 = round(net_length, utils.precision())
if rounded_1 != rounded_2:
obj.Distance = net_length
# The lines and text are created in the viewprovider, so we should
# update it whenever the object is recomputed
@@ -306,6 +296,117 @@ class LinearDimension(DimensionBase):
obj.ViewObject.update()
def measure_one_obj_edge(obj, subelement, dim_point, diameter=False):
"""Measure one object with one subelement, a straight or circular edge.
Parameters
----------
obj: Part::Feature
The object that is measured.
subelement: str
The subelement that is measured, for example, `'Edge1'`.
dim_line: Base::Vector3
A point through which the dimension goes through.
"""
start = App.Vector()
end = App.Vector()
if "Edge" in subelement:
n = int(subelement[4:]) - 1
edge = obj.Shape.Edges[n]
if DraftGeomUtils.geomType(edge) == "Line":
start = edge.Vertexes[0].Point
end = edge.Vertexes[-1].Point
elif DraftGeomUtils.geomType(edge) == "Circle":
center = edge.Curve.Center
radius = edge.Curve.Radius
axis = edge.Curve.Axis
dim_line = dim_point.sub(center)
# The ray is projected to the plane on which the circle lies,
# but if the projection is not succesful, try in the other planes
ray = dim_line.projectToPlane(App.Vector(0, 0, 0), axis)
if ray.Length == 0:
ray = axis.cross(App.Vector(1, 0, 0))
if ray.Length == 0:
ray = axis.cross(App.Vector(0, 1, 0))
# The ray is made as large as the arc's radius
# and optionally the diameter
ray = DraftVecUtils.scaleTo(ray, radius)
if diameter:
# The start and end points lie on the arc
start = center.add(ray.negative())
end = center.add(ray)
else:
# The start is th center and the end lies on the arc
start = center
end = center.add(ray)
return start, end
def measure_one_obj_vertices(obj, subelements):
"""Measure two vertices in the same object."""
start = App.Vector()
end = App.Vector()
subelement1 = subelements[0]
subelement2 = subelements[1]
if "Vertex" in subelement1 and "Vertex" in subelement2:
n1 = int(subelement1[6:]) - 1
n2 = int(subelement2[6:]) - 1
start = obj.Shape.Vertexes[n1].Point
end = obj.Shape.Vertexes[n2].Point
return start, end
def measure_two_objects(link_sub_1, link_sub_2):
"""Measure two vertices from two different objects.
Parameters
----------
link_sub_1: tuple
A tuple containing one object and a list of subelement strings,
which may be empty. Only the first subelement is considered, which
must be a vertex.
::
link_sub_1 = (obj1, ['VertexN', ...])
link_sub_2: tuple
Same.
"""
start = App.Vector()
end = App.Vector()
obj1 = link_sub_1[0]
lsub1 = link_sub_1[1]
obj2 = link_sub_2[0]
lsub2 = link_sub_2[1]
# The subelement list may be empty so we test it first
# and pick only the first item
if lsub1 and lsub2:
subelement1 = lsub1[0]
subelement2 = lsub2[0]
if "Vertex" in subelement1 and "Vertex" in subelement2:
n1 = int(subelement1[6:]) - 1
n2 = int(subelement2[6:]) - 1
start = obj1.Shape.Vertexes[n1].Point
end = obj2.Shape.Vertexes[n2].Point
return start, end
# Alias for compatibility with v0.18 and earlier
_Dimension = LinearDimension