----------------------------------------------------------------------------
| 1196 | |
| 1197 | //---------------------------------------------------------------------------- |
| 1198 | bool vtkPolyhedron::GetCentroid(double centroid[3]) const |
| 1199 | { |
| 1200 | assert(this->Faces != nullptr && "Faces must be set before calling GetCentroid."); |
| 1201 | const vtkIdType numPts = this->Points->GetNumberOfPoints(); |
| 1202 | // compute apex center as the centroid of all points |
| 1203 | double apexCentroid[3] = { 0.0, 0.0, 0.0 }, x[3]; |
| 1204 | for (vtkIdType i = 0; i < numPts; i++) |
| 1205 | { |
| 1206 | this->Points->GetPoint(i, x); |
| 1207 | vtkMath::Add(apexCentroid, x, apexCentroid); |
| 1208 | } |
| 1209 | vtkMath::MultiplyScalar(apexCentroid, 1.0 / numPts); |
| 1210 | |
| 1211 | // computer the weighted barycenter of the pyramids formed by the apex and each face |
| 1212 | const vtkIdType numFaces = this->Faces->GetNumberOfCells(); |
| 1213 | std::fill_n(centroid, 3, 0.0); |
| 1214 | double totalVolume = 0.0, normal[3]; |
| 1215 | const vtkIdType* facePts = nullptr; |
| 1216 | vtkIdType numFacePts; |
| 1217 | for (vtkIdType i = 0; i < numFaces; ++i) |
| 1218 | { |
| 1219 | this->Faces->GetCellAtId(i, numFacePts, facePts); |
| 1220 | // compute centroid of the face |
| 1221 | double faceCentroid[3]; |
| 1222 | vtkPolygon::ComputeCentroid(this->Points, numFacePts, facePts, faceCentroid); |
| 1223 | // compute area and normal of the face |
| 1224 | const double faceArea = vtkPolygon::ComputeArea(this->Points, numFacePts, facePts, normal); |
| 1225 | // compute barycenter of the face |
| 1226 | double baryCenter[3] = { (0.75 * faceCentroid[0]) + (0.25 * apexCentroid[0]), |
| 1227 | (0.75 * faceCentroid[1]) + (0.25 * apexCentroid[1]), |
| 1228 | (0.75 * faceCentroid[2]) + (0.25 * apexCentroid[2]) }; |
| 1229 | // compute the volume of the pyramid formed by the face and the apex |
| 1230 | double centerDiff[3]; |
| 1231 | vtkMath::Subtract(apexCentroid, faceCentroid, centerDiff); |
| 1232 | // projection along normal that is signed to handle non-convex polyhedra |
| 1233 | const double height = vtkMath::Dot(centerDiff, normal); |
| 1234 | const double volume = faceArea * height / 3.0; |
| 1235 | totalVolume += volume; |
| 1236 | // accumulate the weighted barycenter and volume |
| 1237 | vtkMath::MultiplyScalar(baryCenter, volume); |
| 1238 | vtkMath::Add(centroid, baryCenter, centroid); |
| 1239 | } |
| 1240 | if (std::abs(totalVolume) > 1e-12) |
| 1241 | { |
| 1242 | vtkMath::MultiplyScalar(centroid, 1.0 / totalVolume); |
| 1243 | return true; |
| 1244 | } |
| 1245 | else |
| 1246 | { |
| 1247 | std::copy_n(apexCentroid, 3, centroid); |
| 1248 | return false; |
| 1249 | } |
| 1250 | } |
| 1251 | |
| 1252 | //---------------------------------------------------------------------------- |
| 1253 | int vtkPolyhedron::GetParametricCenter(double pcoords[3]) |
no test coverage detected