RH_C_FUNCTION ON_MassProperties* ON_Geometry_AreaMassProperties(const ON_SimpleArray<const ON_Geometry*>* pConstGeometryArray, double relativeTolerance, double absoluteTolerance) { ON_MassProperties* rc = NULL; if( pConstGeometryArray && pConstGeometryArray->Count() > 0 ) { ON_BoundingBox bbox; for( int i = 0; i < pConstGeometryArray->Count(); i++ ) { const ON_Geometry* geo = (*pConstGeometryArray)[i]; if( NULL==geo ) continue; geo->GetBoundingBox(bbox,TRUE); } ON_3dPoint basepoint = bbox.Center(); // Aggregate all mass properties for( int i = 0; i < pConstGeometryArray->Count(); i++ ) { const ON_Geometry* geo = (*pConstGeometryArray)[i]; if( NULL==geo ) continue; bool success = false; ON_MassProperties mp; const ON_Brep* pBrep = ON_Brep::Cast(geo); if( pBrep ) success = pBrep->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); const ON_Surface* pSurface = success?0:ON_Surface::Cast(geo); if( pSurface ) success = pSurface->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); const ON_Mesh* pMesh = success?0:ON_Mesh::Cast(geo); if( pMesh ) success = pMesh->AreaMassProperties(mp, true, true, true, true); const ON_Curve* pCurve = success?0:ON_Curve::Cast(geo); ON_Plane plane; if( pCurve && pCurve->IsPlanar(&plane, absoluteTolerance) && pCurve->IsClosed() ) success = pCurve->AreaMassProperties(basepoint, plane.Normal(), mp, true, true, true, true, relativeTolerance, absoluteTolerance); if( success ) { if( NULL==rc ) rc = new ON_MassProperties(mp); else rc->Sum(1, &mp, true); } } } return rc; }
RH_C_FUNCTION ON_MassProperties* ON_Hatch_AreaMassProperties(const ON_Hatch* pConstHatch, double rel_tol, double abs_tol) { ON_MassProperties* rc = NULL; if( pConstHatch ) { ON_BoundingBox bbox = pConstHatch->BoundingBox(); ON_3dPoint basepoint = bbox.Center(); basepoint = pConstHatch->Plane().ClosestPointTo(basepoint); ON_ClassArray<ON_MassProperties> list; for( int i=0; i<pConstHatch->LoopCount(); i++ ) { const ON_HatchLoop* pLoop = pConstHatch->Loop(i); if( NULL==pLoop ) continue; ON_Curve* pCurve = pConstHatch->LoopCurve3d(i); if( NULL==pCurve ) continue; ON_MassProperties mp; if( pCurve->AreaMassProperties(basepoint, pConstHatch->Plane().Normal(), mp, true, true, true, true, rel_tol, abs_tol) ) { mp.m_mass = fabs(mp.m_mass); if( pLoop->Type() == ON_HatchLoop::ltInner ) mp.m_mass = -mp.m_mass; list.Append(mp); } delete pCurve; } if( list.Count()==1 ) { rc = new ON_MassProperties(); *rc = list[0]; } else if( list.Count()>1 ) { int count = list.Count(); const ON_MassProperties* pieces = list.Array(); rc = new ON_MassProperties(); if( !rc->Sum(count, pieces) ) { delete rc; rc = NULL; } } } return rc; }
RH_C_FUNCTION ON_MassProperties* ON_GeometryMassProperties(bool bArea, ON_SimpleArray<const ON_Geometry*>* pGeometry, double relativeTolerance, double absoluteTolerance) { ON_MassProperties* rc = NULL; if( pGeometry && pGeometry->Count() > 0 ) { // Compute base-point of all geometry boundingboxes ON_3dPoint basePoint(0,0,0); if( !bArea ) { for( int i = 0; i < pGeometry->Count(); i++ ) { const ON_Geometry* geo = pGeometry->Array()[i]; ON_BoundingBox box = geo->BoundingBox(); basePoint += box.Center(); } basePoint /= pGeometry->Count(); } // Aggregate all mass properties rc = new ON_MassProperties(); for( int i = 0; i < pGeometry->Count(); i++ ) { const ON_Geometry* geo = pGeometry->Array()[i]; bool success = false; ON_MassProperties mp; ON::object_type type = pGeometry->Array()[i]->ObjectType(); const ON_Brep* pBrep; const ON_Surface* pSurface; const ON_Mesh* pMesh; const ON_Curve* pCurve; switch (type) { case ON::brep_object: pBrep = ON_Brep::Cast(geo); if( bArea ) success = pBrep->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); else success = pBrep->VolumeMassProperties(mp, true, true, true, true, basePoint, relativeTolerance, absoluteTolerance); break; case ON::surface_object: pSurface = ON_Surface::Cast(geo); if( bArea ) success = pSurface->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); else success = pSurface->VolumeMassProperties(mp, true, true, true, true, basePoint, relativeTolerance, absoluteTolerance); break; case ON::mesh_object: pMesh = ON_Mesh::Cast(geo); if( bArea ) success = pMesh->AreaMassProperties(mp, true, true, true, true); else success = pMesh->VolumeMassProperties(mp, true, true, true, true, basePoint); break; case ON::curve_object: if (bArea) { pCurve = ON_Curve::Cast(geo); ON_Plane plane; if( pCurve->IsPlanar(&plane, absoluteTolerance) && pCurve->IsClosed() ) { success = pCurve->AreaMassProperties(basePoint, plane.Normal(), mp, true, true, true, true, relativeTolerance, absoluteTolerance); if (success ) { mp.m_mass = fabs(mp.m_mass); } } } break; } if( success ) { rc->Sum(1, &mp, true); } } } return rc; }