void SimpleInflator::connect_end_loops() { const size_t dim = m_wire_network->get_dim(); const Float ave_thickness = m_thickness.sum() / m_thickness.size(); const auto& edge_lengths = m_wire_network->get_attribute("edge_length"); const size_t num_edges = m_wire_network->get_num_edges(); const size_t loop_size = m_profile->size(); const MatrixIr connecting_faces = generate_faces_connecting_loops( loop_size, dim != 2); const size_t num_connecting_faces = connecting_faces.rows(); for (size_t i=0; i<num_edges; i++) { Float edge_length = edge_lengths(i, 0); const auto& end_loops = m_end_loops[i]; const size_t num_segments = std::max(1.0, std::round(edge_length / ave_thickness)); MatrixFr pts((num_segments+1)*loop_size, dim); for (size_t j=0; j<num_segments+1; j++) { Float alpha = Float(j) / Float(num_segments); pts.block(j*loop_size, 0, loop_size, dim) = end_loops.first * (1.0 - alpha) + end_loops.second * alpha; } MatrixIr faces(num_connecting_faces * num_segments, 3); for (size_t j=0; j<num_segments; j++) { faces.block(j*num_connecting_faces, 0, num_connecting_faces, 3) = connecting_faces.array() + j*loop_size; } m_vertex_list.push_back(pts); m_face_list.push_back(faces.array() + m_num_vertex_accumulated); m_face_source_list.push_back(int(i)*(-1)-1); m_num_vertex_accumulated += pts.rows(); } }
void LongEdgeRemoval::triangulate_chain( std::vector<VectorI>& faces, const std::vector<size_t>& chain, size_t v0_idx, size_t v1_idx, size_t v2_idx) { const size_t chain_size = chain.size(); auto next = [&](size_t i) { return (i+1) % chain_size; }; auto prev = [&](size_t i) { return (i+chain_size-1) % chain_size; }; auto length = [&](size_t vi, size_t vj) { return (m_vertices.row(vi) - m_vertices.row(vj)).norm(); }; MatrixIr visited = MatrixIr::Zero(chain_size, 3); visited(v0_idx, 0) = 1; visited(v1_idx, 1) = 1; visited(v2_idx, 2) = 1; MatrixIr candidates(3, 6); candidates << v0_idx, next(v0_idx), prev(v0_idx), 0, 0, 0, v1_idx, next(v1_idx), prev(v1_idx), 0, 0, 0, v2_idx, next(v2_idx), prev(v2_idx), 0, 0, 0; MatrixFr candidate_lengths(3, 2); const Float NOT_USED = std::numeric_limits<Float>::max(); candidate_lengths << length(chain[candidates(0, 1)], chain[candidates(0, 2)]), NOT_USED, length(chain[candidates(1, 1)], chain[candidates(1, 2)]), NOT_USED, length(chain[candidates(2, 1)], chain[candidates(2, 2)]), NOT_USED; auto index_comp = [&](size_t i, size_t j) { // Use greater than operator so the queue is a min heap. return candidate_lengths.row(i).minCoeff() > candidate_lengths.row(j).minCoeff(); }; std::priority_queue<size_t, std::vector<size_t>, decltype(index_comp)> Q(index_comp); Q.push(0); Q.push(1); Q.push(2); while (!Q.empty()) { size_t idx = Q.top(); Q.pop(); size_t selection; if (candidate_lengths(idx, 0) != NOT_USED && candidate_lengths(idx, 0) <= candidate_lengths(idx, 1)) { selection = 0; } else if (candidate_lengths(idx, 1) != NOT_USED && candidate_lengths(idx, 1) < candidate_lengths(idx, 0)){ selection = 1; } else { continue; } size_t base_v = candidates(idx, selection * 3 + 0); size_t right_v = candidates(idx, selection * 3 + 1); size_t left_v = candidates(idx, selection * 3 + 2); assert(visited(base_v, idx) >= 1); if (visited.row(base_v).sum() > 1 || visited(right_v, idx) > 1 || visited(left_v, idx) > 1) { candidate_lengths(idx, selection) = NOT_USED; Q.push(idx); continue; } visited(right_v, idx) = 1; visited(left_v, idx) = 1; visited(base_v, idx) = 2; faces.push_back(Vector3I(chain[base_v], chain[right_v], chain[left_v])); if (visited.row(right_v).sum() == 1) { size_t right_to_right = next(right_v); Float edge_len = length(chain[left_v], chain[right_to_right]); candidate_lengths(idx, 0) = edge_len; candidates.block(idx, 0, 1, 3) = Vector3I(right_v, right_to_right, left_v).transpose(); } else { candidate_lengths(idx, 0) = NOT_USED; } if (visited.row(left_v).sum() == 1) { size_t left_to_left = prev(left_v); Float edge_len = length(chain[right_v], chain[left_to_left]); candidate_lengths(idx, 1) = edge_len; candidates.block(idx, 3, 1, 3) = Vector3I(left_v, right_v, left_to_left).transpose(); } else { candidate_lengths(idx, 1) = NOT_USED; } Q.push(idx); } auto visited_sum = (visited.array() > 0).rowwise().count().eval(); if ((visited_sum.array() > 1).count() == 3) { Vector3I face; size_t count = 0; for (size_t i=0; i<chain_size; i++) { if (visited_sum[i] > 1) { assert(count < 3); face[count] = chain[i]; count++; } } faces.push_back(face); } }