McNeel Wiki
Calculating the Volume Centroid of Solid Objects
edit · print · help · all topics
Main Pages

AccuRender

Bongo

Brazil r/s

Developer

Flamingo

Penguin

Rhino Blogs

Rhino

Search

Languages

Česky

Deutsch

English

Español

Français

Italiano

Polish

日本語

한국어

中文(繁體)

 
.
DeveloperC++, .NET
VersionRhino 4
SummaryDemonstrates how to calculating the volume centroid of closed surface and polysurface objects using Rhino 4 SDK.

The following sample code demonstrates how to calculating the volume centroid of closed surface and polysurface.

C++

  CRhinoCommand::result CCommandTest::RunCommand( const CRhinoCommandContext& context )
  {
    CRhinoGetObject go;
    go.SetCommandPrompt( L"Select solids for volume centroid calculation" );
    go.SetGeometryFilter( 
          CRhinoGetObject::surface_object | 
          CRhinoGetObject::polysrf_object
          );
    go.SetGeometryAttributeFilter( 
          CRhinoGetObject::closed_surface | 
          CRhinoGetObject::closed_polysrf
          );
    go.EnableSubObjectSelect( false );
    go.EnableGroupSelect( true );
    go.GetObjects( 1, 0 );
    if( go.CommandResult() != success )
      return go.CommandResult();


    ON_SimpleArray<const ON_Geometry*> geom( go.ObjectCount() );
    int i;
    for( i = 0; i < go.ObjectCount(); i++ ) 
    {
      const ON_Geometry* geo = go.Object(i).Geometry();
      if( 0 == geo )
        return failure;
      geom.Append( geo );
    }


    // Get bounding box of all objects
    ON_BoundingBox bbox;
    for( i = 0; i < geom.Count(); i++ )
      geom[i]->GetBoundingBox( bbox, bbox.IsValid() );


    ON_3dPoint base_point = bbox.Center();
    ON_SimpleArray<ON_MassProperties> MassProp;
    MassProp.Reserve( geom.Count() );


    for( i = 0; i < geom.Count(); i++ )
    {
      ON_MassProperties* mp = &MassProp.AppendNew();


      if( const ON_Surface* srf = ON_Surface::Cast(geom[i]) )
        srf->VolumeMassProperties( *mp, true, true, false, false, base_point );       


      else if( const ON_Brep* brep = ON_Brep::Cast(geom[i]) )
        brep->VolumeMassProperties( *mp, true, true, false, false, base_point );
    }


    ON_MassProperties results;
    results.Sum( MassProp.Count(), MassProp.Array() ); 


    ON_3dPoint pt( results.m_x0, results.m_y0, results.m_z0 );
    context.m_doc.AddPointObject( pt );
    context.m_doc.Redraw();


    RhinoApp().Print( L"Volume centroid = %g,%g,%g\n", pt.x, pt.y, pt.z );


    return success;
  }

C# (Rhino 4)

  public override IRhinoCommand.result RunCommand(IRhinoCommandContext context)
  {
    MRhinoGetObject go = new MRhinoGetObject();
    go.SetCommandPrompt( "Select solids for volume centroid calculation" );
    go.SetGeometryFilter( IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object |
                          IRhinoGetObject.GEOMETRY_TYPE_FILTER.polysrf_object );
    go.SetGeometryAttributeFilter( IRhinoGetObject.GEOMETRY_ATTRIBUTE_FILTER.closed_surface |
                                   IRhinoGetObject.GEOMETRY_ATTRIBUTE_FILTER.closed_polysrf );
    go.EnableSubObjectSelect( false );
    go.EnableGroupSelect( true );
    go.GetObjects( 1, 0 );
    if( go.CommandResult() != IRhinoCommand.result.success )
      return go.CommandResult();


    System.Collections.Generic.List<IOnGeometry> geom =
      new System.Collections.Generic.List<IOnGeometry>();
    for( int i = 0; i < go.ObjectCount(); i++ ) 
    {
      IOnGeometry geo = go.Object(i).Geometry();
      if( geo == null )
        return IRhinoCommand.result.failure;
      geom.Add( geo );
    }


    // Get bounding box of all objects
    OnBoundingBox bbox = new OnBoundingBox();
    for( int i = 0; i < geom.Count; i++ )
      geom[i].GetBoundingBox( ref bbox, 1);


    On3dPoint base_point = bbox.Center();


    System.Collections.Generic.List<OnMassProperties> MassProp =
      new System.Collections.Generic.List<OnMassProperties>();


    for(int i = 0; i < geom.Count; i++ )
    {
      OnMassProperties mp = new OnMassProperties();


      IOnSurface srf = OnSurface.ConstCast(geom[i]);
      IOnBrep brep = OnBrep.ConstCast(geom[i]);


      if( srf != null )
        srf.VolumeMassProperties( ref mp, true, true, false, false, base_point );
      else if( brep != null )
        brep.VolumeMassProperties( ref mp, true, true, false, false, base_point );
      else
        mp = null;


      if( mp != null )
        MassProp.Add(mp);
    }


    OnMassProperties results = new OnMassProperties();
    results.Sum( MassProp.ToArray() );


    On3dPoint pt = new On3dPoint(results.m_x0, results.m_y0, results.m_z0 );
    context.m_doc.AddPointObject( pt );
    context.m_doc.Redraw();


    string msg = string.Format("Volume centroid = {0}\n",pt);
    RhUtil.RhinoApp().Print( msg );
    return IRhinoCommand.result.success;
  }

VB.NET (Rhino 4)

  Public Overrides Function RunCommand(ByVal context As RMA.Rhino.IRhinoCommandContext) _
    As RMA.Rhino.IRhinoCommand.result
    Dim go As New MRhinoGetObject()
    go.SetCommandPrompt("Select solids for volume centroid calculation")
    go.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object Or _
                        IRhinoGetObject.GEOMETRY_TYPE_FILTER.polysrf_object)
    go.SetGeometryAttributeFilter(IRhinoGetObject.GEOMETRY_ATTRIBUTE_FILTER.closed_surface Or _
                                  IRhinoGetObject.GEOMETRY_ATTRIBUTE_FILTER.closed_polysrf)
    go.EnableSubObjectSelect(False)
    go.EnableGroupSelect(True)
    go.GetObjects(1, 0)
    If (go.CommandResult() <> IRhinoCommand.result.success) Then
      Return go.CommandResult()
    End If


    Dim geom As New System.Collections.Generic.List(Of IOnGeometry)()
    For i As Integer = 0 To go.ObjectCount() - 1
      Dim geo As IOnGeometry = go.Object(i).Geometry()
      If (geo Is Nothing) Then
        Return IRhinoCommand.result.failure
      End If
      geom.Add(geo)
    Next


    ' Get bounding box of all objects
    Dim bbox As New OnBoundingBox()
    For i As Integer = 0 To geom.Count - 1
      geom(i).GetBoundingBox(bbox, 1)
    Next


    Dim base_point As On3dPoint = bbox.Center()
    Dim MassProp As New System.Collections.Generic.List(Of OnMassProperties)()


    For i As Integer = 0 To geom.Count - 1
      Dim mp As New OnMassProperties()


      Dim srf As IOnSurface = OnSurface.ConstCast(geom(i))
      Dim brep As IOnBrep = OnBrep.ConstCast(geom(i))


      If (srf IsNot Nothing) Then
        srf.VolumeMassProperties(mp, True, True, False, False, base_point)
      ElseIf (brep IsNot Nothing) Then
        brep.VolumeMassProperties(mp, True, True, False, False, base_point)
      Else
        mp = Nothing
      End If


      If (mp IsNot Nothing) Then MassProp.Add(mp)
    Next


    Dim results As New OnMassProperties()
    results.Sum(MassProp.ToArray())


    Dim pt As New On3dPoint(results.m_x0, results.m_y0, results.m_z0)
    context.m_doc.AddPointObject(pt)
    context.m_doc.Redraw()


    Dim msg As String = String.Format("Volume centroid = {0}", pt)
    RhUtil.RhinoApp().Print(msg + vbCrLf)
    Return IRhinoCommand.result.success
  End Function
rename · changes · history · subscriptions · lost and found · references · file upload