Determining the centre of mass of a mesh

When printing a three-dimensional object in plastic or metal, a seemingly innocent question might pop up once we create our first toy based on a mesh we created; what is its center of mass? If our model has legs but we don't want it to keel over, its center of mass better be somewhere over its feet and, preferably, as low as possible to keep it stable. This figure shows this schematically:

Determining the centre of mass of a mesh

Once we know how to determine the volume of a mesh we can reuse many of the concepts to devise a script to determine the center of mass. Two additional bits of knowledge are needed to compute the position of the center of mass:

  • The centers of mass of the projected volumes we construct when calculating the volume of the mesh
  • How to add up the calculated centers of mass of all these individual volumes

All of this assumes that solid sections of our mesh have a uniform density. A mesh may have any form or even be hollow but the solid parts are assumed to be of a uniform density. This is valid assumption for the materials deposited by 3D printers.

The first issue is a bit of geometry: the projected volume is essentially a triangular column (or triangular prism) capped by a possibly slanted triangular face. Calculating the center of mass might be done as follows: the x and y coordinates of the center of mass are the x and y coordinates of the center of the projected triangle on the xy-plane—those are simply the averages of the x and y coordinates respectively of the three points defining the triangular face. The z-coordinate of the center of mass is halfway along the average height of our projected column. This is the average of the z-coordinates of the three points of the triangular face divided by two.

The second issue is mainly common sense: given two masses m1 and m2 with their centers of mass at v1 and v2 respectively, their combined center of mass is the weighted average. That is to say, the center of mass is proportionally closer to the center of the mass of the heaviest component.

Note

Of course it is common sense to us now, but it took someone like Archimedes to see that it actually was common sense. After finding out about this 'law of levers' (as he called it), he didn't shout 'eureka' or went running around naked, so it took somewhat longer to attract attention.

Let's put all this information into a recipe that we can follow:

  1. Make sure all face normals consistently point outward.
  2. For all faces:
    • Calculate the z-component of face normal vector Nz
    • Calculate the product P of the average z-coordinates and the projected surface area
    • Calculate CM(x, y, z) with x, y the average of the projected x, y coordinates of the face and z (the average of the z-coordinates of the face)/2
    • If Nz is positive: add P times CM
    • If Nz is negative: subtract P times CM

From the outline above, it is clear that calculating the center of mass goes hand in hand with the calculation of the partial volumes, so it makes sense to redefine the meshvolume() function to the following:

def meshvolume(me):
volume = 0.0

cm = vec((0,0,0))
for f in me.faces:
xy_area = Mathutils.TriangleArea(vec(f.v[0].co[:2]), vec(f.v[1].co[:2]),vec(f.v[2].co[:2]))
Nz = f.no[2]
avg_z = sum([f.v[i].co[2] for i in range(3)])/3.0
partial_volume = avg_z * xy_area
if Nz < 0: volume -= partial_volume
if Nz > 0: volume += partial_volume

avg_x = sum([f.v[i].co[0] for i in range(3)])/3.0
avg_y = sum([f.v[i].co[1] for i in range(3)])/3.0
centroid = vec((avg_x,avg_y,avg_z/2))
if Nz < 0: cm -= partial_volume * centroid
if Nz > 0: cm += partial_volume * centroid
return volume,cm/volume

The added or changed lines of code are highlighted.

Some remarks about accuracy

Although most of us are artists and not engineers, we still may ask how accurate the number is that we calculate for our mesh volume or center of mass. There are two things to consider—intrinsic accuracy and computational accuracy of our algorithm.

Intrinsic accuracy is what we refer to when we consider the fact that our model is made out of small polygons that approximate some imagined shape. When doing organic modeling this hardly matters; if our model looks good, it is good. However, if we try to approximate some ideal form, for example a sphere, by a polygonal model (a uv-sphere say, or an icosphere) there will be a difference between the calculated volume and the known volume of the ideal sphere. We can improve this approximation by increasing the number of subdivisions (or equivalent the size of the polygons) but we will never be able to completely eliminate this difference and the algorithm used to calculate the volume cannot change that.

Computational accuracy has several aspects. First, there is the precision of the numbers we calculate with. On most platforms that Blender runs on, calculations are performed using double precision floating point numbers. This amounts to about 17 digits of precision and there is nothing we can do to improve that. Luckily, that is ample precision to work with.

Then there is the accuracy of our algorithm. When you look at the code you will see that we are adding and multiplying a potentially huge amount of values, as a typical high-resolution model may well contain over a hundred thousand faces or even a million. For each face we calculate the volume of the projected column and all of these volumes are added (or subtracted) together. The problem is that these volumes may differ considerably in size, not only because the areas of the faces may differ but especially because the projected area of a near vertical face is very small compared to a near horizontal one.

Now if we add a very large and a very small number with limited precision calculations we will lose the small number. For example, if our precision would be limited to three significant digits, adding 0.001 and 0.0001 would end up as 0.001, losing the effect of the small number. Now our precision is a lot better (about 17 digits) but we add a lot more than two numbers. If we implement the volume() function by using one of the cited algorithms however, the difference never adds up to more than one in million, so as long as we don't aim to do nuclear science with Blender there is no need to bother. (For those who do, an alternative is provided in the script as the function volume2(). Still, be careful that you know what you are doing).

Note

Python is able to work with numbers of potentially infinite size and precision but this is much slower than doing normal floating point calculations. The functions and classes provided in Mathutils are primarily coded in C for speed and limited to double precision floats. See http://code.activestate.com/recipes/393090/ http://code.activestate.com/recipes/298339/ or Section 18.5 of Python Cookbook, 2nd edition, by O'Reilly for some other techniques and mathematical background.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.222.185