From c42dbacc0b676d9d21d20d8a63b2af2e6b0f12a3 Mon Sep 17 00:00:00 2001 From: Youmu Date: Thu, 9 Jul 2020 21:55:03 -0400 Subject: [PATCH] WIP: Correctly handle case when there are more than 2 vertices in the minimal quadrangulation. Correctly check well-pairedness up to rotation. --- .../internal/Minimal_quadrangulation.h | 238 ++++++++++-------- 1 file changed, 136 insertions(+), 102 deletions(-) diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h index fed2c0bfd7b..90299212f42 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h @@ -588,18 +588,17 @@ public: // Compute the backward cyclic KMP failure table for the curve std::vector suffix_len = compute_common_circular_suffix(pr); pr.compute_switchable(); - size_type src_degree = degree(get_local_map(), get_local_map().darts().begin()); typedef typename boost::intrusive::rbtree> rbtree; std::vector rb_nodes; rb_nodes.reserve(pr.length()); - std::vector trees(src_degree); + std::unordered_map trees; for (std::size_t i = 0; i < pr.length(); ++i) { Dart_const_handle dh = pr[i]; - auto dart_id = get_dart_absolute_order_relative_to(pr[i], pr[0]); + auto dart_id = get_absolute_idx(dh); rb_nodes.emplace_back(i); auto& node = rb_nodes.back(); @@ -608,7 +607,7 @@ public: { // Look at the t-1 turn of [i-1, i, i + 1] Dart_const_handle dleft = get_local_map().template beta<0, 2>(dh); - auto dleft_id = get_dart_absolute_order_relative_to(dleft, pr[0]); + auto dleft_id = get_absolute_idx(dleft); // Binary search within potential switch trigger // TODO: apply the optimization Francis mentioned by only look at the largest one // Convert a dart to a circular ordering index @@ -618,7 +617,7 @@ public: return this->get_order_relative_to(dprev, dleft); }; size_type key_val = get_order_relative_to(pr[i - 1], dleft); - if (get_local_map().template belong_to_same_cell<0>(dh, pr[0])) + if (is_absolutely_directed(dleft)) { auto comparator = [&to_order] (const std::size_t& key, const rbtree::value_type& b) -> bool { return key > to_order(b.m_idx); @@ -641,7 +640,7 @@ public: } } dh = pr[i]; - dart_id = get_dart_absolute_order_relative_to(pr[i], pr[0]); + dart_id = get_absolute_idx(pr[i]); } // Insert current darts if (trees[dart_id].empty()) @@ -650,7 +649,7 @@ public: } else { - size_type prev_dart_id = get_dart_absolute_order_relative_to(pr[i - 1], pr[0]); + size_type prev_dart_id = get_absolute_idx(pr[i - 1]); auto it_prev = trees[prev_dart_id].iterator_to(rb_nodes[i - 1]); if (it_prev != trees[prev_dart_id].begin() && is_same_corner(pr, std::prev(it_prev)->m_idx, i - 1)) { @@ -664,128 +663,153 @@ public: } else { - if (get_local_map().template belong_to_same_cell<0>(dh, pr[0])) - { - auto comparator = [this, &pr, &p_original, &suffix_len] (const std::size_t& key, const rbtree::value_type& b) -> bool { - if (b.m_idx == 0 && pr[key] == pr[0]) + auto less_than_in_tree = is_absolutely_directed(dh)? + std::function{std::less()} : std::function{std::greater()}; + auto comparator = [this, &pr, &p_original, &suffix_len, &less_than_in_tree] (const std::size_t& key, const rbtree::value_type& b) -> bool { + if (b.m_idx == 0 && pr[key] == pr[0]) + { + if(pr[key] != p_original[key]) { + // current edge was switched so it should always be on the right side (more counter-clockwise) + return false; + } + std::size_t current_dividing_idx = key + p_original.length() - 1 - suffix_len[key - 1]; + std::size_t path_end_dividing_idx = p_original.length() - 1 - suffix_len[key - 1]; + std::size_t last_same_idx = (path_end_dividing_idx == p_original.length() - 1) ? 0 : path_end_dividing_idx + 1; + if (current_dividing_idx >= p_original.length()) { - if(pr[key] != p_original[key]) { - // current edge was switched so it should always be on the right side (more counter-clockwise) - return false; - } - std::size_t current_dividing_idx = key + p_original.length() - 1 - suffix_len[key - 1]; - std::size_t path_end_dividing_idx = p_original.length() - 1 - suffix_len[key - 1]; - std::size_t last_same_idx = (path_end_dividing_idx == p_original.length() - 1) ? 0 : path_end_dividing_idx + 1; - if (current_dividing_idx >= p_original.length()) - { - current_dividing_idx -= p_original.length(); - } - Dart_const_handle dbase = p_original[last_same_idx], - dcur = p_original[current_dividing_idx], - d0 = p_original[path_end_dividing_idx]; + current_dividing_idx -= p_original.length(); + } + Dart_const_handle dbase = p_original[last_same_idx], + dcur = p_original[current_dividing_idx], + d0 = p_original[path_end_dividing_idx]; - std::size_t key_prev_order = this->get_order_relative_to(dcur, dbase); - std::size_t b_prev_order = this->get_order_relative_to(d0, dbase); - return b_prev_order < key_prev_order; - } - else - { - std::size_t key_prev_order = this->get_order_relative_to(pr[key - 1], pr[key]); - Dart_const_handle bprev = this->get_previous_relative_to(pr, b.m_idx, pr[key]); - std::size_t b_prev_order = this->get_order_relative_to(bprev, pr[key]); - return b_prev_order < key_prev_order; - } - }; - auto it_after = trees[dart_id].upper_bound(i, comparator); - trees[dart_id].insert_before(it_after, node); - } - else - { - auto comparator = [this, &pr, &p_original] (const std::size_t& key, const rbtree::value_type& b) -> bool { - /// It is impossible that pr[key] == pr[b.m_idx] == pr[0] + std::size_t key_prev_order = this->get_order_relative_to(dcur, dbase); + std::size_t b_prev_order = this->get_order_relative_to(d0, dbase); + return less_than_in_tree(b_prev_order, key_prev_order); + } + else + { std::size_t key_prev_order = this->get_order_relative_to(pr[key - 1], pr[key]); Dart_const_handle bprev = this->get_previous_relative_to(pr, b.m_idx, pr[key]); std::size_t b_prev_order = this->get_order_relative_to(bprev, pr[key]); - return b_prev_order > key_prev_order; - }; - auto it_after = trees[dart_id].upper_bound(i, comparator); - trees[dart_id].insert_before(it_after, node); - } + return less_than_in_tree(b_prev_order, key_prev_order); + } + }; + auto it_after = trees[dart_id].upper_bound(i, comparator); + trees[dart_id].insert_before(it_after, node); } } } // Check whether orders form a valid parenthesis expression // First for the same direction of pr[0] res = true; - Dart_const_handle dcur = pr[0], dstart = pr[0]; - std::stack parenthesis_pairing; - do { - auto dart_id = get_dart_absolute_order_relative_to(dcur, pr[0]); - for (auto it = trees[dart_id].begin(); it != trees[dart_id].end(); ++it) + + pr.display(); + std::cout << std::endl; + pr.display_pos_and_neg_turns(); + std::cout << std::endl; + p_original.display(); + std::cout << std::endl; + p_original.display_pos_and_neg_turns(); + std::cout << std::endl; + auto marktemp=get_local_map().get_new_mark(); + for (auto it=get_local_map().darts().begin(); + it!=get_local_map().darts().end(); ++it) + { + if (!get_local_map().is_marked(it, marktemp)) { - if (parenthesis_pairing.empty()) - { - parenthesis_pairing.push(it->m_idx); - } - else - { - std::size_t prev = parenthesis_pairing.top(); - std::size_t next = it->m_idx; - if(prev > next) + std::stack parenthesis_pairing; + std::vector rotated_darts; + bool start_pairing = false; + Dart_const_handle dh2=it; + auto construct_parenthesis = [&pr, &it, &parenthesis_pairing, &start_pairing, &rotated_darts, this] (const rbtree::value_type& node) { + std::cout << get_local_map().darts().index(pr[node.m_idx]) << '@' << node.m_idx << ' '; + if (!start_pairing) { - std::swap(prev, next); + if (rotated_darts.empty()) + { + rotated_darts.emplace_back(node); + return; + } + else + { + std::size_t prev = rotated_darts.back().m_idx; + std::size_t next = node.m_idx; + if(prev > next) + { + std::swap(prev, next); + } + std::size_t distance = next - prev; + if(next == pr.length() - 1 && prev == 0) + { + distance = 1; + std::swap(prev, next); + } + if(distance == 1 && this->get_local_map().template belong_to_same_cell<0>(pr[next], it)) + { + start_pairing = true; + std::cout << "starting "; + } + else + { + rotated_darts.emplace_back(node); + return; + } + } } - if(next == prev + 1 && get_local_map().template belong_to_same_cell<0>(pr[next], dstart)) + if (parenthesis_pairing.empty()) { - parenthesis_pairing.pop(); - } - else if(next == pr.length() - 1 && prev == 0) - { - parenthesis_pairing.pop(); + parenthesis_pairing.push(node.m_idx); } else { - parenthesis_pairing.push(it->m_idx); + std::size_t prev = parenthesis_pairing.top(); + std::size_t next = node.m_idx; + if(prev > next) + { + std::swap(prev, next); + } + std::size_t distance = next - prev; + if(next == pr.length() - 1 && prev == 0) + { + distance = 1; + std::swap(prev, next); + } + if(distance == 1 && this->get_local_map().template belong_to_same_cell<0>(pr[next], it)) + { + parenthesis_pairing.pop(); + } + else + { + parenthesis_pairing.push(node.m_idx); + } } - } - } - dcur = get_local_map().template beta<2, 1>(dcur); - } while (dcur != dstart); - res = parenthesis_pairing.empty(); - while (!parenthesis_pairing.empty()) - { parenthesis_pairing.pop(); } - // Next check for the opposite direction of pr[0] - dcur = get_local_map().opposite2(pr[0]); - dstart = get_local_map().opposite2(pr[0]); - do { - auto dart_id = get_dart_absolute_order_relative_to(dcur, pr[0]); - for (auto it = trees[dart_id].rbegin(); it != trees[dart_id].rend(); ++it) - { - if (parenthesis_pairing.empty()) + }; + do { - parenthesis_pairing.push(it->m_idx); - } - else - { - std::size_t prev = parenthesis_pairing.top(); - std::size_t next = it->m_idx; - if(prev > next) + get_local_map().mark(dh2, marktemp); + auto dart_id = get_absolute_idx(dh2); + std::cout << get_local_map().darts().index(dh2) << ':'; + if(is_absolutely_directed(dh2)) { - std::swap(prev, next); - } - if(next == prev + 1 && get_local_map().template belong_to_same_cell<0>(pr[next], dstart)) - { - parenthesis_pairing.pop(); + std::for_each(trees[dart_id].begin(), trees[dart_id].end(), construct_parenthesis); } else { - parenthesis_pairing.push(it->m_idx); + std::for_each(trees[dart_id].rbegin(), trees[dart_id].rend(), construct_parenthesis); } + std::cout << std::endl; + dh2 = get_local_map().template beta<2, 1>(dh2); } + while(dh2!=it); + std::cout << "leftover:"; + std::for_each(rotated_darts.begin(), rotated_darts.end(), construct_parenthesis); + std::cout << std::endl; + std::cout << std::endl; + res = res && parenthesis_pairing.empty(); } - dcur = get_local_map().template beta<2, 1>(dcur); - } while (dcur != dstart); - res = res && parenthesis_pairing.empty(); + } + get_local_map().free_mark(marktemp); } } @@ -2020,6 +2044,16 @@ protected: return p[j]; } + size_type get_absolute_idx(Dart_const_handle dh) const + { + return std::min(get_local_map().darts().index(dh), get_local_map().darts().index(get_local_map().opposite(dh))); + } + + bool is_absolutely_directed(Dart_const_handle dh) const + { + return get_local_map().darts().index(dh) < get_local_map().darts().index(get_local_map().opposite(dh)); + } + size_type get_dart_absolute_order_relative_to(Dart_const_handle x, Dart_const_handle ref) const { size_type ref_degree = degree(get_local_map(), get_local_map().darts().begin());