VectorF convert_voxel_attribute_to_vertex_attribute( Mesh& mesh, const VectorF& attribute) { const size_t num_vertices = mesh.get_num_vertices(); const size_t vertex_per_voxel = mesh.get_vertex_per_voxel(); const size_t num_voxels = mesh.get_num_voxels(); const size_t attr_size = attribute.size(); const size_t stride = attr_size / num_voxels; const VectorI& voxels = mesh.get_voxels(); if (!mesh.has_attribute("voxel_volume")) { mesh.add_attribute("voxel_volume"); } const VectorF& weights = mesh.get_attribute("voxel_volume"); VectorF result = VectorF::Zero(num_vertices * stride); VectorF result_weights = VectorF::Zero(num_vertices); for (size_t i=0; i<num_voxels; i++) { const VectorI& voxel = voxels.segment(i*vertex_per_voxel, vertex_per_voxel); Float per_vertex_weight = weights[i] / vertex_per_voxel; for (size_t j=0; j<vertex_per_voxel; j++) { result_weights[voxel[j]] += per_vertex_weight; result.segment(voxel[j]*stride, stride) += per_vertex_weight * attribute.segment(i*stride, stride); } } for (size_t i=0; i<num_vertices; i++) { result.segment(i*stride, stride) /= result_weights[i]; } return result; }
VectorF convert_face_attribute_to_vertex_attribute( Mesh& mesh, const VectorF& attribute) { const size_t num_vertices = mesh.get_num_vertices(); const size_t vertex_per_face = mesh.get_vertex_per_face(); const size_t num_faces = mesh.get_num_faces(); const size_t attr_size = attribute.size(); const size_t stride = attr_size / num_faces; const VectorI& faces = mesh.get_faces(); const VectorF& weights = mesh.get_attribute("face_area"); VectorF result = VectorF::Zero(num_vertices * stride); VectorF result_weights = VectorF::Zero(num_vertices); for (size_t i=0; i<num_faces; i++) { const VectorI& face = faces.segment(i*vertex_per_face, vertex_per_face); Float per_vertex_weight = weights[i] / vertex_per_face; for (size_t j=0; j<vertex_per_face; j++) { result_weights[face[j]] += per_vertex_weight; result.segment(face[j]*stride, stride) += per_vertex_weight * attribute.segment(i*stride, stride); } } for (size_t i=0; i<num_vertices; i++) { result.segment(i*stride, stride) /= result_weights[i]; } return result; }
void correct_tet_orientation(const VectorF& vertices, VectorI& voxels) { const size_t num_voxels = voxels.size() / 4; for (size_t i=0; i<num_voxels; i++) { const VectorI tet = voxels.segment(i*4, 4); const Vector3F& v1 = vertices.segment(tet[0]*3, 3); const Vector3F& v2 = vertices.segment(tet[1]*3, 3); const Vector3F& v3 = vertices.segment(tet[2]*3, 3); const Vector3F& v4 = vertices.segment(tet[3]*3, 3); if (!positive_orientated(v1, v2, v3, v4)) { voxels[i*4] = tet[1]; voxels[i*4+1] = tet[0]; } } }
void VertexIsotropicOffsetParameter::apply(VectorF& results, const PatternParameter::Variables& vars) { const size_t dim = m_wire_network->get_dim(); const size_t num_vertices = m_wire_network->get_num_vertices(); const size_t roi_size = m_roi.size(); const VectorF center = m_wire_network->center(); const VectorF bbox_max = m_wire_network->get_bbox_max(); assert(results.size() == dim * num_vertices); assert(roi_size == m_transforms.size()); if (m_formula != "") evaluate_formula(vars); const MatrixFr& vertices = m_wire_network->get_vertices(); size_t seed_vertex_index = m_roi.minCoeff(); VectorF seed_vertex = vertices.row(seed_vertex_index); VectorF seed_offset = VectorF::Zero(dim); seed_offset = (bbox_max - center).cwiseProduct(m_dof_dir) * m_value; for (size_t i=0; i<roi_size; i++) { size_t v_idx = m_roi[i]; assert(v_idx < num_vertices); const MatrixF& trans = m_transforms[i]; results.segment(v_idx*dim, dim) += trans * seed_offset; } }
VectorF convert_vertex_attribute_to_voxel_attribute(Mesh& mesh, const VectorF& attribute) { const size_t num_vertices = mesh.get_num_vertices(); const size_t num_voxels = mesh.get_num_voxels(); const size_t vertex_per_voxel = mesh.get_vertex_per_voxel(); const size_t attr_size = attribute.size(); const size_t stride = attr_size / num_vertices; const VectorI& voxels = mesh.get_voxels(); VectorF result = VectorF::Zero(num_voxels * stride); for (size_t i=0; i<num_voxels; i++) { const VectorI& voxel = voxels.segment(i*vertex_per_voxel, vertex_per_voxel); for (size_t j=0; j<vertex_per_voxel; j++) { result.segment(i*stride, stride) += attribute.segment(voxel[j]*stride, stride); } } result /= vertex_per_voxel; return result; }
VectorF convert_vertex_attribute_to_face_attribute(Mesh& mesh, const VectorF& attribute) { const size_t num_vertices = mesh.get_num_vertices(); const size_t num_faces = mesh.get_num_faces(); const size_t vertex_per_face = mesh.get_vertex_per_face(); const size_t attr_size = attribute.size(); const size_t stride = attr_size / num_vertices; const VectorI& faces = mesh.get_faces(); VectorF result = VectorF::Zero(num_faces * stride); for (size_t i=0; i<num_faces; i++) { const VectorI& face = faces.segment(i*vertex_per_face, vertex_per_face); for (size_t j=0; j<vertex_per_face; j++) { result.segment(i*stride, stride) += attribute.segment(face[j]*stride, stride); } } result /= vertex_per_face; return result; }
VectorF convert_voxel_attribute_to_face_attribute( Mesh& mesh, const VectorF& attribute) { const size_t num_faces = mesh.get_num_faces(); const size_t num_voxels = mesh.get_num_voxels(); const size_t attr_size = attribute.size(); const size_t stride = attr_size / num_voxels; const size_t vertex_per_voxel = mesh.get_vertex_per_voxel(); const size_t vertex_per_face = mesh.get_vertex_per_face(); if (vertex_per_voxel != 4) throw NotImplementedError("Voxel type is not yet supported"); if (vertex_per_face != 3) throw NotImplementedError("Face type is not yet supported"); const VectorI& faces = mesh.get_faces(); const VectorI& voxels = mesh.get_voxels(); std::map<Triplet, VectorF> per_face_values; for (size_t i=0; i<num_voxels; i++) { const VectorI& voxel = voxels.segment( i*vertex_per_voxel, vertex_per_voxel); const VectorF& value = attribute.segment( i*stride, stride); per_face_values[Triplet(voxel[0], voxel[1], voxel[2])] = value; per_face_values[Triplet(voxel[0], voxel[1], voxel[3])] = value; per_face_values[Triplet(voxel[0], voxel[2], voxel[3])] = value; per_face_values[Triplet(voxel[1], voxel[2], voxel[3])] = value; } VectorF result = VectorF::Zero(num_faces*stride); for (size_t i=0; i<num_faces; i++) { const VectorI& face = faces.segment(i*vertex_per_face, vertex_per_face); result.segment(i*stride, stride) = per_face_values[ Triplet(face[0], face[1], face[2])]; } return result; }
void VertexMeanCurvatureAttribute::compute_from_mesh(Mesh& mesh) { const size_t dim = mesh.get_dim(); const size_t num_vertices = mesh.get_num_vertices(); VectorF laplacian = compute_laplacian_vectors(mesh); VectorF normals = compute_vertex_normals(mesh); assert(laplacian.size() == dim*num_vertices); assert(normals.size() == dim*num_vertices); if (!mesh.has_attribute("vertex_voronoi_area")) { mesh.add_attribute("vertex_voronoi_area"); } const auto& area = mesh.get_attribute("vertex_voronoi_area"); VectorF& mean_curvature = m_values; mean_curvature = VectorF::Zero(num_vertices); for (size_t i=0; i<num_vertices; i++) { mean_curvature[i] = laplacian.segment(dim*i,dim).norm() * 0.5; Float sign = laplacian.segment(dim*i, dim).dot(normals.segment(dim*i,dim)); if (sign < 0) { mean_curvature[i] *= -1; } } mean_curvature = mean_curvature.array() / area.array(); }
void write_vertices(std::ofstream& fout, const VectorF& vertices, const size_t dim) { if (dim != 2 && dim != 3) { throw IOError("Unsupported mesh dimension: " + std::to_string(dim)); } fout.precision(16); size_t num_vertices = vertices.size() / dim; for (size_t i=0; i<num_vertices; i++) { const auto& v = vertices.segment(i*dim, dim); fout << "v"; for (size_t j=0; j<dim; j++) { fout << " " << v[j]; } fout << std::endl; } }
void EigenSolver::compute_batch_symmetric_2x2(const VectorF& matrices) { const size_t dim = 2; const size_t flatten_size = 3; const size_t num_matrices = matrices.size() / flatten_size; m_eigen_values = VectorF(num_matrices * dim); m_eigen_vectors = MatrixF(num_matrices * dim, dim); for (size_t i=0; i<num_matrices; i++) { const VectorF& entries = matrices.segment(i*flatten_size, flatten_size); MatrixF M(dim, dim); size_t base_idx = i*flatten_size; M << matrices[base_idx ], matrices[base_idx+2], matrices[base_idx+2], matrices[base_idx+1], m_solver.compute(M); m_eigen_values.segment(i*dim, dim) = m_solver.eigenvalues().real(); m_eigen_vectors.block(i*dim, 0, dim, dim) = m_solver.eigenvectors().real(); } }