| 7 | using namespace PyMesh; |
| 8 | |
| 9 | void VoxelInradiusAttribute::compute_from_mesh(Mesh& mesh) { |
| 10 | const size_t dim = mesh.get_dim(); |
| 11 | const size_t num_voxels = mesh.get_num_voxels(); |
| 12 | const size_t vertex_per_voxel = mesh.get_vertex_per_voxel(); |
| 13 | |
| 14 | if (num_voxels > 0 && vertex_per_voxel != 4) { |
| 15 | throw NotImplementedError( |
| 16 | "Voxel inradius is defined for 3D tet mesh only."); |
| 17 | } |
| 18 | if (dim != 3) { |
| 19 | throw RuntimeError("Voxel inradius is defined for 3D tet mesh only."); |
| 20 | } |
| 21 | |
| 22 | VectorF& inradius = m_values; |
| 23 | inradius.resize(num_voxels); |
| 24 | |
| 25 | const auto& voxels = mesh.get_voxels(); |
| 26 | const auto& vertices = mesh.get_vertices(); |
| 27 | if (!mesh.has_attribute("voxel_volume")) { |
| 28 | mesh.add_attribute("voxel_volume"); |
| 29 | } |
| 30 | const auto& volumes = mesh.get_attribute("voxel_volume"); |
| 31 | |
| 32 | for (size_t i=0; i<num_voxels; i++) { |
| 33 | Vector4I voxel = voxels.segment<4>(i*4); |
| 34 | Vector3F v0 = vertices.segment<3>(voxel[0]*3); |
| 35 | Vector3F v1 = vertices.segment<3>(voxel[1]*3); |
| 36 | Vector3F v2 = vertices.segment<3>(voxel[2]*3); |
| 37 | Vector3F v3 = vertices.segment<3>(voxel[3]*3); |
| 38 | |
| 39 | Float a012 = ((v1-v0).cross(v2-v0)).norm(); |
| 40 | Float a023 = ((v2-v0).cross(v3-v0)).norm(); |
| 41 | Float a013 = ((v1-v0).cross(v3-v0)).norm(); |
| 42 | Float a123 = ((v1-v3).cross(v2-v3)).norm(); |
| 43 | Float sum = (a012 + a023 + a013 + a123) * 0.5; |
| 44 | |
| 45 | inradius[i] = volumes[i] / sum * 3.0; |
| 46 | } |
| 47 | } |
nothing calls this directly
no test coverage detected