#include "order_facets_around_edge.h" #include namespace igl { namespace cgal { namespace order_facets_around_edges_helper { template std::vector index_sort(const std::vector& data) { const size_t len = data.size(); std::vector order(len); for (size_t i=0; i void igl::cgal::order_facets_around_edge( const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, size_t s, size_t d, const std::vector& adj_faces, Eigen::PlainObjectBase& order) { using namespace igl::cgal::order_facets_around_edges_helper; // Although we only need exact predicates in the algorithm, // exact constructions are needed to avoid degeneracies due to // casting to double. typedef CGAL::Exact_predicates_exact_constructions_kernel K; typedef K::Point_3 Point_3; typedef K::Plane_3 Plane_3; auto get_face_index = [&](int adj_f)->size_t{ return abs(adj_f) - 1; }; auto get_opposite_vertex = [&](size_t fid)->size_t { if (F(fid, 0) != s && F(fid, 0) != d) return F(fid, 0); if (F(fid, 1) != s && F(fid, 1) != d) return F(fid, 1); if (F(fid, 2) != s && F(fid, 2) != d) return F(fid, 2); assert(false); return -1; }; // Handle base cases if (adj_faces.size() == 0) { order.resize(0, 1); return; } else if (adj_faces.size() == 1) { order.resize(1, 1); order(0, 0) = 0; return; } else if (adj_faces.size() == 2) { const size_t o1 = get_opposite_vertex(get_face_index(adj_faces[0])); const size_t o2 = get_opposite_vertex(get_face_index(adj_faces[1])); const Point_3 ps(V(s, 0), V(s, 1), V(s, 2)); const Point_3 pd(V(d, 0), V(d, 1), V(d, 2)); const Point_3 p1(V(o1, 0), V(o1, 1), V(o1, 2)); const Point_3 p2(V(o2, 0), V(o2, 1), V(o2, 2)); order.resize(2, 1); switch (CGAL::orientation(ps, pd, p1, p2)) { case CGAL::POSITIVE: order(0, 0) = 1; order(1, 0) = 0; break; case CGAL::NEGATIVE: order(0, 0) = 0; order(1, 0) = 1; break; case CGAL::COPLANAR: order(0, 0) = adj_faces[0] < adj_faces[1] ? 0:1; order(1, 0) = adj_faces[0] < adj_faces[1] ? 1:0; break; default: assert(false); } return; } const size_t num_adj_faces = adj_faces.size(); const size_t o = get_opposite_vertex( get_face_index(adj_faces[0])); const Point_3 p_s(V(s, 0), V(s, 1), V(s, 2)); const Point_3 p_d(V(d, 0), V(d, 1), V(d, 2)); const Point_3 p_o(V(o, 0), V(o, 1), V(o, 2)); const Plane_3 separator(p_s, p_d, p_o); assert(!separator.is_degenerate()); std::vector opposite_vertices; for (size_t i=0; i positive_side; std::vector negative_side; std::vector tie_positive_oriented; std::vector tie_negative_oriented; std::vector positive_side_index; std::vector negative_side_index; std::vector tie_positive_oriented_index; std::vector tie_negative_oriented_index; for (size_t i=0; i positive_order, negative_order; order_facets_around_edge(V, F, s, d, positive_side, positive_order); order_facets_around_edge(V, F, s, d, negative_side, negative_order); std::vector tie_positive_order = index_sort(tie_positive_oriented); std::vector tie_negative_order = index_sort(tie_negative_oriented); // Copy results into order vector. const size_t tie_positive_size = tie_positive_oriented.size(); const size_t tie_negative_size = tie_negative_oriented.size(); const size_t positive_size = positive_order.size(); const size_t negative_size = negative_order.size(); order.resize(tie_positive_size + positive_size + tie_negative_size + negative_size, 1); size_t count=0; for (size_t i=0; i