diff --git a/CadQuery/Libs/cadquery-lib/cadquery/CQ.py b/CadQuery/Libs/cadquery-lib/cadquery/CQ.py index f6c043a..8d21173 100644 --- a/CadQuery/Libs/cadquery-lib/cadquery/CQ.py +++ b/CadQuery/Libs/cadquery-lib/cadquery/CQ.py @@ -262,7 +262,7 @@ class CQ(object): return self.objects[0].wrapped - def workplane(self, offset=0.0, invert=False): + def workplane(self, offset=0.0, invert=False, centerOption='CenterOfMass'): """ Creates a new 2-D workplane, located relative to the first face on the stack. @@ -341,7 +341,11 @@ 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.") - center = Shape.CombinedCenter(self.objects) + if centerOption == 'CenterOfMass': + center = Shape.CombinedCenter(self.objects) + elif centerOption == 'CenterOfBoundBox': + center = Shape.CombinedCenterOfBoundBox(self.objects) + normal = self.objects[0].normalAt() xDir = _computeXdir(normal) @@ -349,12 +353,18 @@ class CQ(object): obj = self.objects[0] if isinstance(obj, Face): - center = obj.Center() + if centerOption == 'CenterOfMass': + center = obj.Center() + elif centerOption == 'CenterOfBoundBox': + center = obj.CenterOfBoundBox() normal = obj.normalAt(center) xDir = _computeXdir(normal) else: if hasattr(obj, 'Center'): - center = obj.Center() + if centerOption == 'CenterOfMass': + center = obj.Center() + elif centerOption == 'CenterOfBoundBox': + center = obj.CenterOfBoundBox() normal = self.plane.zDir xDir = self.plane.xDir else: diff --git a/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py b/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py index b870271..27b97a6 100644 --- a/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py +++ b/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py @@ -199,6 +199,20 @@ class Shape(object): else: raise ValueError("Cannot find the center of %s object type" % str(type(self.Solids()[0].wrapped))) + def CenterOfBoundBox(self): + if isinstance(self.wrapped, FreeCADPart.Shape): + # If there are no Solids, we're probably dealing with a Face or something similar + if len(self.Solids()) == 0: + return Vector(self.wrapped.BoundBox.Center) + elif len(self.Solids()) == 1: + return Vector(self.Solids()[0].wrapped.BoundBox.Center) + elif len(self.Solids()) > 1: + return self.CombinedCenterOfBoundBox(self.Solids()) + elif isinstance(self.wrapped, FreeCADPart.Solid): + return Vector(self.wrapped.BoundBox.Center) + else: + raise ValueError("Cannot find the center(BoundBox's) of %s object type" % str(type(self.Solids()[0].wrapped))) + @staticmethod def CombinedCenter(objects): """ @@ -215,6 +229,22 @@ class Shape(object): return Vector(sum_wc.multiply(1./total_mass)) + @staticmethod + def CombinedCenterOfBoundBox(objects): + """ + Calculates the center of BoundBox of multiple objects. + + :param objects: a list of objects with mass 1 + """ + total_mass = len(objects) + weighted_centers = [o.wrapped.BoundBox.Center.multiply(1.0) for o in objects] + + sum_wc = weighted_centers[0] + for wc in weighted_centers[1:] : + sum_wc = sum_wc.add(wc) + + return Vector(sum_wc.multiply(1./total_mass)) + def Closed(self): return self.wrapped.Closed diff --git a/CadQuery/Libs/cadquery-lib/changes.md b/CadQuery/Libs/cadquery-lib/changes.md index f97825c..f39d829 100644 --- a/CadQuery/Libs/cadquery-lib/changes.md +++ b/CadQuery/Libs/cadquery-lib/changes.md @@ -62,3 +62,4 @@ v0.3.0 (Unreleased) * Fixed a bug with the close function not resetting the first point of the context correctly (thanks @huskier) * Fixed the findSolid function so that it handles compounds #107 * Changed the polyline function so that it adds edges to the stack instead of a wire #102 + * Add the ability to find the center of the bounding box, rather than the center of mass (thanks @huskier)