------------------------------------------------------------------------------ Compute the polygon centroid from a points list, the number of points, and an array of point ids that index into the points list. Returns false if the computation is invalid.
| 2264 | // array of point ids that index into the points list. Returns false if the |
| 2265 | // computation is invalid. |
| 2266 | vtkCellStatus vtkPolygon::ComputeCentroid( |
| 2267 | vtkPoints* p, int numPts, const vtkIdType* ids, double c[3], double tolerance) |
| 2268 | { |
| 2269 | if (numPts < 2) |
| 2270 | { |
| 2271 | return vtkCellStatus::WrongNumberOfPoints; |
| 2272 | } |
| 2273 | |
| 2274 | vtkVector3d normal; |
| 2275 | auto status = vtkPolygon::ComputeNormal(p, numPts, ids, normal.GetData()); |
| 2276 | if (!status) |
| 2277 | { |
| 2278 | return status; |
| 2279 | } |
| 2280 | |
| 2281 | // Set xx to be the average coordinate. This is not necessarily the centroid |
| 2282 | // but will generally produce accurate triangle areas used to compute the centroid. |
| 2283 | vtkVector3d xx(0, 0, 0); |
| 2284 | vtkVector3d pp; |
| 2285 | vtkVector3d qq; |
| 2286 | double wt = 1. / numPts; |
| 2287 | for (int ii = 0; ii < numPts; ++ii) |
| 2288 | { |
| 2289 | p->GetPoint(ids[ii], pp.GetData()); |
| 2290 | xx += wt * pp; |
| 2291 | } |
| 2292 | // Note that pp now contains the final point in the polygon. |
| 2293 | // If we start again with the first point, we can track pairs |
| 2294 | // of points along edges. |
| 2295 | |
| 2296 | // Now compute the centroid of each triangle formed by xx and |
| 2297 | // the endpoints of one edge in the polygon. Weight the |
| 2298 | // centroid by the triangle's signed area (negative if the polygon |
| 2299 | // winds clockwise) and sum them together. |
| 2300 | // |
| 2301 | // This is equivalent to computing (Integral(x_i dA) / Integral(dA)) |
| 2302 | // for each coordinate (x_0, x_1, x_2) using the "geometric decomposition" |
| 2303 | // method. |
| 2304 | double totalArea = 0.; |
| 2305 | double area; |
| 2306 | vtkVector3d accum(0, 0, 0); |
| 2307 | vtkVector3d ctr; |
| 2308 | double outOfPlane = 0; |
| 2309 | double inPlane2 = 0; |
| 2310 | for (int ii = 0; ii < numPts; ++ii, pp = qq) |
| 2311 | { |
| 2312 | p->GetPoint(ids[ii], qq.GetData()); |
| 2313 | // The centroid of xx-pp-qq is 2/3 of the way from xx to the midpoint of qq-pp |
| 2314 | auto pq = (pp + qq) * 0.5; |
| 2315 | ctr = (1. / 3. * xx) + (2. / 3. * pq); |
| 2316 | auto dqx = qq - xx; |
| 2317 | area = ((pp - xx).Cross(dqx)).Dot(normal) / 2; |
| 2318 | accum += area * ctr; |
| 2319 | totalArea += area; |
| 2320 | // Compute the in-plane and out-of-plane distance from xx to qq. |
| 2321 | // Note that because xx is the average coordinate, oop and |
| 2322 | // ip2 will both be half-distances; their ratio will be correct |
| 2323 | // for comparison to tolerance. |
nothing calls this directly
no test coverage detected