| 9 | using namespace PyMesh; |
| 10 | |
| 11 | void FaceCircumCenterAttribute::compute_from_mesh(Mesh& mesh) { |
| 12 | const size_t dim = mesh.get_dim(); |
| 13 | const size_t num_faces = mesh.get_num_faces(); |
| 14 | const size_t vertex_per_face = mesh.get_vertex_per_face(); |
| 15 | |
| 16 | if (vertex_per_face != 3) { |
| 17 | throw RuntimeError("Circumcenter is only defined for triangle faces."); |
| 18 | } |
| 19 | |
| 20 | if (!mesh.has_attribute("edge_squared_length")) { |
| 21 | mesh.add_attribute("edge_squared_length"); |
| 22 | } |
| 23 | VectorF edge_sq_length = mesh.get_attribute("edge_squared_length"); |
| 24 | |
| 25 | VectorF& circum_centers = m_values; |
| 26 | circum_centers.resize(num_faces * dim); |
| 27 | |
| 28 | const VectorF& vertices = mesh.get_vertices(); |
| 29 | |
| 30 | for (size_t i=0; i<num_faces; i++) { |
| 31 | VectorI face = mesh.get_face(i); |
| 32 | |
| 33 | VectorF v0 = vertices.segment(face[0]*dim, dim); |
| 34 | VectorF v1 = vertices.segment(face[1]*dim, dim); |
| 35 | VectorF v2 = vertices.segment(face[2]*dim, dim); |
| 36 | |
| 37 | Float sq_l0 = edge_sq_length[i*3+1]; |
| 38 | Float sq_l1 = edge_sq_length[i*3+2]; |
| 39 | Float sq_l2 = edge_sq_length[i*3+0]; |
| 40 | |
| 41 | Vector3F coeff( |
| 42 | sq_l0 * (sq_l1 + sq_l2 - sq_l0), |
| 43 | sq_l1 * (sq_l0 + sq_l2 - sq_l1), |
| 44 | sq_l2 * (sq_l0 + sq_l1 - sq_l2)); |
| 45 | Float sum = coeff.sum(); |
| 46 | if (sum == 0.0) { |
| 47 | coeff.setConstant(std::numeric_limits<Float>::infinity()); |
| 48 | } else { |
| 49 | coeff /= coeff.sum(); |
| 50 | } |
| 51 | |
| 52 | circum_centers.segment(i*dim, dim) = |
| 53 | v0 * coeff[0] + |
| 54 | v1 * coeff[1] + |
| 55 | v2 * coeff[2]; |
| 56 | } |
| 57 | |
| 58 | if (!circum_centers.allFinite()) { |
| 59 | std::cerr << "Warning: " |
| 60 | << "circumcenter is not all finite due to degenearte triangles" |
| 61 | << std::endl; |
| 62 | } |
| 63 | } |
nothing calls this directly
no test coverage detected