| 9 | using namespace PyMesh; |
| 10 | |
| 11 | void VoxelRadiusEdgeRatioAttribute::compute_from_mesh(Mesh& mesh) { |
| 12 | const size_t dim = mesh.get_dim(); |
| 13 | const size_t num_voxels = mesh.get_num_voxels(); |
| 14 | const size_t vertex_per_voxel = mesh.get_vertex_per_voxel(); |
| 15 | if (dim != 3) { |
| 16 | throw RuntimeError("Voxel radius/edge ratio computation is for 3D only."); |
| 17 | } |
| 18 | if (num_voxels > 0 && vertex_per_voxel != 4) { |
| 19 | throw NotImplementedError( |
| 20 | "Voxel radius/edge ratio computation only support tet for now."); |
| 21 | } |
| 22 | |
| 23 | if (!mesh.has_attribute("voxel_circumradius")) { |
| 24 | mesh.add_attribute("voxel_circumradius"); |
| 25 | } |
| 26 | const auto& circum_radii = mesh.get_attribute("voxel_circumradius"); |
| 27 | assert(circum_radii.size() == num_voxels); |
| 28 | const auto& vertices = mesh.get_vertices(); |
| 29 | const auto& voxels = mesh.get_voxels(); |
| 30 | VectorF& re_ratio = m_values; |
| 31 | re_ratio.resize(num_voxels); |
| 32 | |
| 33 | for (size_t i=0; i<num_voxels; i++) { |
| 34 | Vector4I v = voxels.segment<4>(i*4); |
| 35 | Vector3F v0 = vertices.segment<3>(v[0]*3); |
| 36 | Vector3F v1 = vertices.segment<3>(v[1]*3); |
| 37 | Vector3F v2 = vertices.segment<3>(v[2]*3); |
| 38 | Vector3F v3 = vertices.segment<3>(v[3]*3); |
| 39 | |
| 40 | Eigen::Matrix<Float, 6, 1> edge_lengths; |
| 41 | edge_lengths[0] = (v0 -v1).norm(); |
| 42 | edge_lengths[1] = (v0 -v2).norm(); |
| 43 | edge_lengths[2] = (v0 -v3).norm(); |
| 44 | edge_lengths[3] = (v1 -v2).norm(); |
| 45 | edge_lengths[4] = (v2 -v3).norm(); |
| 46 | edge_lengths[5] = (v1 -v3).norm(); |
| 47 | |
| 48 | Float min_edge = edge_lengths.minCoeff(); |
| 49 | if (min_edge == 0.0) { |
| 50 | re_ratio[i] = std::numeric_limits<Float>::infinity(); |
| 51 | } else { |
| 52 | re_ratio[i] = circum_radii[i] / min_edge; |
| 53 | } |
| 54 | } |
| 55 | } |
nothing calls this directly
no test coverage detected