diff --git a/src/polymesh/algorithms/properties.hh b/src/polymesh/algorithms/properties.hh index df2a8151303d5879cec6ac70b96ebf48f7ff99be..7b6988bec9182fcd2d4e7fdd07b3467b26c959d8 100644 --- a/src/polymesh/algorithms/properties.hh +++ b/src/polymesh/algorithms/properties.hh @@ -196,6 +196,12 @@ bool can_rotate_next(halfedge_handle h); /// returns true if m.halfedges().rotate_prev(h) would work bool can_rotate_prev(halfedge_handle h); +/// returns true if m.edges().add_or_get(v_from, v_to) would work +bool can_add_or_get_edge(vertex_handle v_from, vertex_handle v_to); + +/// returns true if m.edges().add_or_get(h_from, h_to) would work +bool can_add_or_get_edge(halfedge_handle h_from, halfedge_handle h_to); + /// ======== IMPLEMENTATION ======== inline bool is_boundary(vertex_handle v) { return v.is_boundary(); } @@ -741,4 +747,48 @@ inline bool can_rotate_prev(halfedge_handle h) return true; } +inline bool can_add_or_get_edge(vertex_handle v_from, vertex_handle v_to) +{ + POLYMESH_ASSERT(v_from.mesh == v_to.mesh); + auto ll = low_level_api(v_from.mesh); + + if (v_from == v_to) + return false; // no self-loops + + if (ll.find_halfedge(v_from, v_to).is_valid()) + return true; // existing + + if (!v_from.is_isolated() && ll.find_free_incident(v_from).is_invalid()) + return false; // from already full + + if (!v_to.is_isolated() && ll.find_free_incident(v_to).is_invalid()) + return false; // to already full + + return true; +} + +inline bool can_add_or_get_edge(halfedge_handle h_from, halfedge_handle h_to) +{ + POLYMESH_ASSERT(h_from.mesh == h_to.mesh); + auto ll = low_level_api(h_from.mesh); + + auto v_from = h_from.vertex_to(); + auto v_to = h_to.vertex_to(); + + if (v_from == v_to) + return false; // no self-loops + + auto ex_he = ll.find_halfedge(v_from, v_to); + if (ex_he.is_valid()) + return true; // existing + + if (!ll.is_free(h_from)) + return false; // cannot insert into face + + if (!ll.is_free(h_to)) + return false; // cannot insert into face + + return true; +} + } diff --git a/src/polymesh/impl/impl_low_level_api_mutable.hh b/src/polymesh/impl/impl_low_level_api_mutable.hh index 27fb5bbf352a9fd3797840cda6cdd208fdbca5c8..612af0e19d8026135fac0629ec5609534e97f7c0 100644 --- a/src/polymesh/impl/impl_low_level_api_mutable.hh +++ b/src/polymesh/impl/impl_low_level_api_mutable.hh @@ -172,15 +172,16 @@ inline halfedge_index low_level_api_mutable::add_or_get_halfedge(vertex_index v_ inline edge_index low_level_api_mutable::add_or_get_edge(halfedge_index h_from, halfedge_index h_to) const { - POLYMESH_ASSERT(h_from != h_to); - auto v_from = to_vertex_of(h_from); auto v_to = to_vertex_of(h_to); + POLYMESH_ASSERT(v_from != v_to); + auto ex_he = find_halfedge(v_from, v_to); if (ex_he.is_valid()) { - POLYMESH_ASSERT(prev_halfedge_of(ex_he) == h_from && prev_halfedge_of(opposite(ex_he)) == h_to); + // TODO: is this really required? + // POLYMESH_ASSERT(prev_halfedge_of(ex_he) == h_from && prev_halfedge_of(opposite(ex_he)) == h_to); // TODO: Maybe try rewriting an existing halfedge that does NOT yet have the right connection. return edge_of(ex_he); diff --git a/src/polymesh/low_level_api.hh b/src/polymesh/low_level_api.hh index aebcc64f74ab743701ffe0abfa7a1754087acbd6..54f7b67f8fb73b2410a2103c19eb81f52329b335 100644 --- a/src/polymesh/low_level_api.hh +++ b/src/polymesh/low_level_api.hh @@ -236,12 +236,12 @@ public: /// if edge already exists, returns it edge_index add_or_get_edge(halfedge_index h_from, halfedge_index h_to) const; - /// same as add_or_get_edge but returns the apattrriate half-edge + /// same as add_or_get_edge but returns the appropriate half-edge /// Assures: /// return_value.from_vertex == v_from /// return_value.to_vertex == v_to halfedge_index add_or_get_halfedge(vertex_index v_from, vertex_index v_to) const; - /// same as add_or_get_edge but returns the apattrriate half-edge + /// same as add_or_get_edge but returns the appropriate half-edge /// Assures: /// return_value.from_vertex == h_from.to_vertex /// return_value.to_vertex == h_to.to_vertex