Added option to center workplane of projected origin.
Add 'ProjectedOrigin' option to centerOptions parameter of workplane method. Added test converge for all of the centerOption paramter choices.
This commit is contained in:
@ -267,8 +267,10 @@ class CQ(object):
|
||||
|
||||
:param offset: offset for the work plane in the Z direction. Default
|
||||
:param invert: invert the Z direction from that of the face.
|
||||
:param centerOption: how local origin of workplane is determined
|
||||
:type offset: float or None=0.0
|
||||
:type invert: boolean or None=False
|
||||
:type centerOption: string or None='CenterOfMass'
|
||||
:rtype: Workplane object ( which is a subclass of CQ )
|
||||
|
||||
The first element on the stack must be a face, a set of
|
||||
@ -282,7 +284,8 @@ class CQ(object):
|
||||
* The origin will be located in the *center* of the
|
||||
face/faces, if a face/faces was selected. If a vertex was
|
||||
selected, the origin will be at the vertex, and located
|
||||
on the face.
|
||||
on the face. The centerOption paramter sets how the center is defined.
|
||||
Options are 'CenterOfMass', 'CenterOfBoundBox', or 'ProjectedOrigin'.
|
||||
* The Z direction will be normal to the plane of the face,computed
|
||||
at the center point.
|
||||
* The X direction will be parallel to the x-y plane. If the workplane is parallel to
|
||||
@ -331,6 +334,23 @@ class CQ(object):
|
||||
xd = Vector(1, 0, 0)
|
||||
return xd
|
||||
|
||||
def _pointOnPlane(center, normal, point):
|
||||
"""
|
||||
Returns the point on the plane defined by center and normal nearest to the input
|
||||
argument point.
|
||||
"""
|
||||
a = normal.x; b = normal.y; c = normal.z
|
||||
x0 = center.x; y0 = center.y; z0 = center.z
|
||||
x1 = point.x; y1 = point.y; z1 = point.z
|
||||
|
||||
denom = a**2 + b**2 + c**2
|
||||
|
||||
nearest_x = (-a*b*y1 - a*c*z1 + a*(a*x0 + b*y0 + c*z0) + x1*(b**2 + c**2))/denom
|
||||
nearest_y = (-a*b*x1 - b*c*z1 + b*(a*x0 + b*y0 + c*z0) + y1*(a**2 + c**2))/denom
|
||||
nearest_z = (-a*c*x1 - b*c*y1 + c*(a*x0 + b*y0 + c*z0) + z1*(a**2 + b**2))/denom
|
||||
|
||||
return Vector(nearest_x, nearest_y, nearest_z)
|
||||
|
||||
if len(self.objects) > 1:
|
||||
# are all objects 'PLANE'?
|
||||
if not all(o.geomType() in ('PLANE', 'CIRCLE') for o in self.objects):
|
||||
@ -341,7 +361,7 @@ class CQ(object):
|
||||
if not all(_isCoPlanar(self.objects[0], f) for f in self.objects[1:]):
|
||||
raise ValueError("Selected faces must be co-planar.")
|
||||
|
||||
if centerOption == 'CenterOfMass':
|
||||
if centerOption == 'CenterOfMass' or centerOption == 'ProjectedOrigin':
|
||||
center = Shape.CombinedCenter(self.objects)
|
||||
elif centerOption == 'CenterOfBoundBox':
|
||||
center = Shape.CombinedCenterOfBoundBox(self.objects)
|
||||
@ -353,7 +373,7 @@ class CQ(object):
|
||||
obj = self.objects[0]
|
||||
|
||||
if isinstance(obj, Face):
|
||||
if centerOption == 'CenterOfMass':
|
||||
if centerOption == 'CenterOfMass' or centerOption == 'ProjectedOrigin':
|
||||
center = obj.Center()
|
||||
elif centerOption == 'CenterOfBoundBox':
|
||||
center = obj.CenterOfBoundBox()
|
||||
@ -361,7 +381,7 @@ class CQ(object):
|
||||
xDir = _computeXdir(normal)
|
||||
else:
|
||||
if hasattr(obj, 'Center'):
|
||||
if centerOption == 'CenterOfMass':
|
||||
if centerOption == 'CenterOfMass' or centerOption == 'ProjectedOrigin':
|
||||
center = obj.Center()
|
||||
elif centerOption == 'CenterOfBoundBox':
|
||||
center = obj.CenterOfBoundBox()
|
||||
@ -371,6 +391,10 @@ class CQ(object):
|
||||
raise ValueError(
|
||||
"Needs a face or a vertex or point on a work plane")
|
||||
|
||||
# update center to projected origin if desired
|
||||
if centerOption == 'ProjectedOrigin':
|
||||
center = _pointOnPlane(center, normal, Vector(0, 0, 0))
|
||||
|
||||
# invert if requested
|
||||
if invert:
|
||||
normal = normal.multiply(-1.0)
|
||||
|
@ -1901,4 +1901,56 @@ class TestCadQuery(BaseTest):
|
||||
|
||||
self.assertEqual(len(solid.Vertices()),4)
|
||||
self.assertEqual(len(solid.Faces()),4)
|
||||
|
||||
def testWorkplaneCenterOptions(self):
|
||||
"""
|
||||
Test options for specifiying origin of workplane
|
||||
"""
|
||||
decimal_places = 9
|
||||
|
||||
pts = [(90,0),(90,30),(30,30),(30,60),(0.0,60)]
|
||||
|
||||
r = Workplane("XY").polyline(pts).close().extrude(10.0)
|
||||
|
||||
origin = r.faces(">Z").workplane(centerOption='ProjectedOrigin') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (0.0, 0.0, 10.0), decimal_places)
|
||||
|
||||
origin = r.faces(">Z").workplane(centerOption='CenterOfMass') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (37.5, 22.5, 10.0), decimal_places)
|
||||
|
||||
origin = r.faces(">Z").workplane(centerOption='CenterOfBoundBox') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (45.0, 30.0, 10.0), decimal_places)
|
||||
|
||||
r = Workplane("YZ").polyline(pts).close().extrude(10.0)
|
||||
|
||||
origin = r.faces(">X").workplane(centerOption='ProjectedOrigin') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (10.0, 0.0, 0.0), decimal_places)
|
||||
|
||||
origin = r.faces(">X").workplane(centerOption='CenterOfMass') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (10.0, 37.5, 22.5), decimal_places)
|
||||
|
||||
origin = r.faces(">X").workplane(centerOption='CenterOfBoundBox') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (10.0, 45.0, 30.0), decimal_places)
|
||||
|
||||
r = Workplane("XZ").polyline(pts).close().extrude(10.0)
|
||||
|
||||
origin = r.faces("<Y").workplane(centerOption='ProjectedOrigin') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (0.0, -10.0, 0.0), decimal_places)
|
||||
|
||||
origin = r.faces("<Y").workplane(centerOption='CenterOfMass') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (37.5, -10.0, 22.5), decimal_places)
|
||||
|
||||
origin = r.faces("<Y").workplane(centerOption='CenterOfBoundBox') \
|
||||
.plane.origin.toTuple()
|
||||
self.assertTupleAlmostEquals(origin, (45.0, -10.0, 30.0), decimal_places)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user