Simpler way to get Centroid of multiple items


#1

Is there a simpler way to find the Centroid of a group of items?

Things that didn’t work:

  1. Bounding box all items inclusive, but its not actually the centre of the group, and is quite far off visually in most cases.

  2. Getting volume centroids of all items then adding and dividing to get the average, no good as user objects might be open or planes etc.

  3. BU of the BoundingBoxes of all items then pulling a centroid. if parts are too far apart it fails.

What I have.

Bounding box each item in list and extract centre to a point. Then draw a curve between the points, then extract another point from the bounding box of that curve. Visually in most my tests this seems to “feel” right, but its clunky. Occurs to me I wont be the first guy to walk this road, so any input on optimising this appreciated.

my current code:

 #region Get Centres
            List<Guid> ObjectIDs = new List<Guid>();
            List<ObjRef> ObjList = new List<ObjRef>();
            Point3d[] points = new Point3d[GetObjects.ObjectCount];
            for (int loop = 0; loop < GetObjects.ObjectCount; loop++)
                {
                ObjList.Add(GetObjects.Object(loop));
                ObjectIDs.Add(GetObjects.Object(loop).ObjectId);
                var TempConstructor = ObjList[loop].Brep();
                BoundingBox BBox = TempConstructor.GetBoundingBox(true); 
                points[loop] = BBox.Center;
                }
            Polyline poly = new Polyline(points);
            var CentreOfObjects = poly.BoundingBox.Center;

#endregion


#2

So BoundingBox.Union does not do what you need? Or gives the wrong result?


#3

If the items are far apart the bounding boxes don’t become one so inaccurate centroid.

this is what it looks like at current, if there isn’t a simpler way, it will suffice, i just hate mucky code…


(David Cockey) #4

In regular, interactive Rhino the area centroid or volume centroid of a several objects can be found using AreaCentroid or VolumeCentroid as appropriate, and selecting the objects.

The area centroid of a group of surfaces is the (sum of the each surface’s area centroid multiplied by the surface’s area) divided by the (sum of the surfaces’ areas).

The volume centroid of a group of closed objects is the (sum of the each object’s volume centroid multiplied by the object’s area) divided by the (sum of the objects’ volumes).


#5

any idea of the rhinocommon workflow for that? I had imagine you could apply a method to a group but unfortunately not…


(Steve Baer) #6

Call the VolumeMassProperties.Compute function for each item and sum them together using the Sum function

http://developer.rhino3d.com/api/RhinoCommonWin/html/T_Rhino_Geometry_VolumeMassProperties.htm


#7

Thanks. So pretty similar to my original code above. The code i posted crashes if the object is more than slightly convoluted or of there are curves etc in the selection. So alter to grab everything that needs moving then setup second collection that filters out everything that could feasably break it.

In the other direction Is there a a simple way to get a single bounding box from a selection¿


(David Cockey) #8

Why do you need the centroid - engineering/physics calculations, a target point for viewing, or ???

If it’s a target point for viewing or similar then a bounding box method or similar may be more useful than Rhino functions which calculate the centroid using numerical integration.


#9

Yes. Agreed. KISS. but I am as yet unsure how to pull one all encompassing bounding box from a selection list of geometry. I may be missing something (likely) but it looks like i can only get a per item bounding box currently. Unless i run boundingbox command via runscript then select the only new geometry in the scene which would be the new bounding box?


(Dale Fugier) #10

See the following example code:

https://github.com/dalefugier/SampleCsCommands/blob/master/SampleCsBoundingBox.cs

– Dale


#11

WOW. Lot of code for what seems should be reasonably simple thing, but thanks, I’ll copy paste my happy little butt off.

FYI, I learn a bit more every day, have never seen or thought to use the for( ; ; ) break combo… perhaps I need to do a C# course, will save me heaps of longhand!

Oh and HNY!


(Dale Fugier) #12

Well, I highly doubt you need all of the code, as the example demonstrates how to write your own version of Rhino’s BoundingBox command. The highlights here are:

1.) How to get an object’s bounding box, and
2.) How to union BoundingBox objects.

– Dale


#13

all good, got what I needed and completed my command, many thanks.