From 44260a88fcaeae7ab2979c94b55501d47dd1bc28 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 13 Jan 2021 20:56:34 +0000 Subject: [PATCH 1/9] Store vertex handles in the MPQ and have a map from Vertex_handle to Vertices_in_constaint_iterator --- .../CGAL/Polyline_simplification_2/simplify.h | 126 +++++++++++++++--- .../Polyline_constraint_hierarchy_2.h | 4 +- 2 files changed, 108 insertions(+), 22 deletions(-) diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h index 77b150ea9b2..26416805d72 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h @@ -57,11 +57,15 @@ class Polyline_simplification_2 public: typedef typename PCT::Point Point; + typedef typename PCT::Edge Edge; typedef typename PCT::Constraint_id Constraint_id; + typedef typename PCT::Constrained_edges_iterator Constrained_edges_iterator; typedef typename PCT::Constraint_iterator Constraint_iterator; typedef typename PCT::Vertices_in_constraint_iterator Vertices_in_constraint_iterator; + typedef typename PCT::Finite_vertices_iterator Finite_vertices_iterator; //typedef typename PCT::Points_in_constraint_iterator Points_in_constraint_iterator; typedef typename PCT::Vertex_handle Vertex_handle; + typedef typename PCT::Face_handle Face_handle; typedef typename PCT::Vertex_circulator Vertex_circulator; typedef typename PCT::Geom_traits::FT FT; @@ -71,6 +75,11 @@ public: StopFunction stop; std::size_t pct_initial_number_of_vertices, number_of_unremovable_vertices; + std::map > vertex_to_iterator; + + typedef std::map Vertex_index_map; + + Vertex_index_map vertex_index_map; struct Compare_cost { @@ -79,6 +88,12 @@ public: { return (*x)->cost() < (*y)->cost(); } + + bool operator() (const Vertex_handle& x,const Vertex_handle& y) const + { + return x->cost() < y->cost(); + } + } ; struct Id_map : public boost::put_get_helper @@ -86,12 +101,24 @@ public: typedef boost::readable_property_map_tag category; typedef std::size_t value_type; typedef value_type reference; - typedef Vertices_in_constraint_iterator key_type; + // typedef Vertices_in_constraint_iterator key_type; + typedef Vertex_handle key_type; - reference operator[] ( key_type const& x ) const { return x.base()->id ; } + Vertex_index_map* vertex_index_map; + + Id_map(const Vertex_index_map& vertex_index_map) + : vertex_index_map(& const_cast(vertex_index_map)) + {} + + reference operator[] ( key_type const& x ) const + { + // return x.base()->id ; + return (*vertex_index_map)[x]; + } } ; - typedef CGAL::Modifiable_priority_queue MPQ ; + //typedef CGAL::Modifiable_priority_queue MPQ ; + typedef CGAL::Modifiable_priority_queue MPQ ; MPQ* mpq; @@ -101,7 +128,7 @@ public: int m = initialize_indices(); initialize_unremovable(); Compare_cost cc; - Id_map idm; + Id_map idm(vertex_index_map); mpq = new MPQ(m, cc, idm); initialize_costs(); } @@ -124,8 +151,60 @@ public: delete mpq; } + // endpoints of constraints are unremovable + // vertices which are not endpoint and have != 2 incident constained edges are unremovable void initialize_unremovable() { + Constraint_iterator cit = pct.constraints_begin(), e = pct.constraints_end(); + for(; cit!=e; ++cit){ + Constraint_id cid = *cit; + Vertices_in_constraint_iterator it = pct.vertices_in_constraint_begin(cid); + (*it)->set_removable(false); + it = pct.vertices_in_constraint_end(cid); + it = boost::prior(it); + (*it)->set_removable(false); + } + + std::map degrees; + for (Constrained_edges_iterator it = pct.constrained_edges_begin(); it != pct.constrained_edges_end(); ++it) { + Edge e = *it; + Face_handle fh = e.first; + int ei = e.second; + Vertex_handle vh = fh->vertex(pct.cw(ei)); + ++degrees[vh]; + vh = fh->vertex(pct.ccw(ei)); + ++degrees[vh]; + } + + for(Finite_vertices_iterator it = pct.finite_vertices_begin(); it != pct.finite_vertices_end(); ++it){ + if( it->is_removable() && (degrees[it] != 2) ){ + it->set_removable(false); + } + } + + cit = pct.constraints_begin(), e = pct.constraints_end(); + for(; cit!=e; ++cit){ + Constraint_id cid = *cit; + for(Vertices_in_constraint_iterator it = pct.vertices_in_constraint_begin(cid); + it != pct.vertices_in_constraint_end(cid); + ++it){ + if((*it)->is_removable()){ + vertex_to_iterator[*it].push_back(it); + } + } + } + + /* + // debug output + for(Finite_vertices_iterator it = pct.finite_vertices_begin(); it != pct.finite_vertices_end(); ++it){ + if(it->is_removable()){ + std::cout << it->point() << " is removable" << std::endl; + } + } + */ + + /* + // the previous code does mark vertices with more than one constraint on it as unremovable std::set vertices; Constraint_iterator cit = pct.constraints_begin(), e = pct.constraints_end(); for(; cit!=e; ++cit){ @@ -142,6 +221,7 @@ public: it = boost::prior(it); (*it)->set_removable(false); } + */ } // For all polyline constraints we compute the cost of all unremovable and not removed vertices @@ -156,7 +236,7 @@ public: boost::optional dist = cost(pct, it); if(dist){ (*it)->set_cost(*dist); - (*mpq).push(it); + (*mpq).push(*it); ++n; } else { // no need to set the costs as this vertex is not in the priority queue @@ -239,10 +319,15 @@ public: initialize_indices() { int id = 0; + /* Constraint_iterator b = pct.constraints_begin(), e = pct.constraints_end(); for(; b!=e; ++b){ id = initialize_indices(*b, id); } + */ + for(Finite_vertices_iterator it = pct.finite_vertices_begin(); it != pct.finite_vertices_end(); ++it){ + vertex_index_map[it] = id++; + } return id; } @@ -252,29 +337,30 @@ operator()() if((*mpq).empty()){ return false; } - Vertices_in_constraint_iterator v = (*mpq).top(); + Vertex_handle v = (*mpq).top(); (*mpq).pop(); - if(stop(pct, *v, (*v)->cost(), pct_initial_number_of_vertices, pct.number_of_vertices())){ + if(stop(pct, v, v->cost(), pct_initial_number_of_vertices, pct.number_of_vertices())){ return false; } - if(is_removable(v)){ - Vertices_in_constraint_iterator u = boost::prior(v), w = boost::next(v); - pct.simplify(v); + Vertices_in_constraint_iterator vit = vertex_to_iterator[v].front(); + if(is_removable(vit)){ + Vertices_in_constraint_iterator u = boost::prior(vit), w = boost::next(vit); + pct.simplify(vit); if((*u)->is_removable()){ boost::optional dist = cost(pct, u); if(! dist){ // cost is undefined - if( mpq->contains(u) ){ - mpq->erase(u); + if( mpq->contains(*u) ){ + mpq->erase(*u); } } else { (*u)->set_cost(*dist); - if(mpq->contains(u)){ - mpq->update(u, true); + if(mpq->contains(*u)){ + mpq->update(*u, true); } else{ - mpq->push(u); + mpq->push(*u); } } } @@ -283,16 +369,16 @@ operator()() boost::optional dist = cost(pct, w); if(! dist){ // cost is undefined - if( mpq->contains(w) ){ - mpq->erase(w); + if( mpq->contains(*w) ){ + mpq->erase(*w); } } else { (*w)->set_cost(*dist); - if(mpq->contains(w)){ - mpq->update(w, true); + if(mpq->contains(*w)){ + mpq->update(*w, true); } else{ - mpq->push(w); + mpq->push(*w); } } diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index be275140aec..d46c76a3666 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -46,14 +46,14 @@ private: class Node { public: explicit Node(Vertex_handle vh, bool input = false) - : vertex_(vh), id(-1), input(input) + : vertex_(vh), /* id(-1),*/ input(input) {} const Point& point() const { return vertex_->point(); } Vertex_handle vertex() const { return vertex_; } private: Vertex_handle vertex_; public: - int id; + // int id; bool input; }; From 105b93b35add01308e1fbba4c5cd3e0b718c265f Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 14 Jan 2021 08:51:39 +0000 Subject: [PATCH 2/9] Now it should work with overlapping polylines --- .../simplify_overlapping_polyline.cpp | 51 +++++++++++++ .../CGAL/Polyline_simplification_2/simplify.h | 42 ++++------ .../Polyline_constraint_hierarchy_2.h | 76 +++++++++++-------- 3 files changed, 111 insertions(+), 58 deletions(-) create mode 100644 Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp diff --git a/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp b/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp new file mode 100644 index 00000000000..2df47f53932 --- /dev/null +++ b/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace PS = CGAL::Polyline_simplification_2; + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef PS::Vertex_base_2 Vb; +typedef CGAL::Constrained_triangulation_face_base_2 Fb; +typedef CGAL::Triangulation_data_structure_2 TDS; +typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; +typedef CGAL::Constrained_triangulation_plus_2 CT; + +typedef CT::Point Point; +typedef CT::Constraint_iterator Constraint_iterator; +typedef CT::Vertices_in_constraint_iterator Vertices_in_constraint_iterator; +typedef CT::Points_in_constraint_iterator Points_in_constraint_iterator; +typedef PS::Stop_below_count_ratio_threshold Stop; +typedef PS::Squared_distance_cost Cost; + +int main() +{ + CT ct; + + std::vector P = { Point(0,1), Point(1,1), Point(2,2), Point(3,1), Point(4,1), Point(5,1) }; + std::vector Q = { Point(5,0), Point(4,1), Point(3,1), Point(2,2), Point(1,1), Point(0,0) }; + std::vector R = { Point(3,1), Point(4,1) }; + + ct.insert_constraint(P); + ct.insert_constraint(Q); + ct.insert_constraint(R); + + PS::simplify(ct, Cost(), Stop(0.5)); + + for(Constraint_iterator cit = ct.constraints_begin(); + cit != ct.constraints_end(); + ++cit) { + std::cout << "simplified polyline" << std::endl; + for(Points_in_constraint_iterator vit = + ct.points_in_constraint_begin(*cit); + vit != ct.points_in_constraint_end(*cit); + ++vit) + std::cout << *vit << std::endl; + } + return 0; +} diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h index 26416805d72..579bcfc9707 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h @@ -101,7 +101,6 @@ public: typedef boost::readable_property_map_tag category; typedef std::size_t value_type; typedef value_type reference; - // typedef Vertices_in_constraint_iterator key_type; typedef Vertex_handle key_type; Vertex_index_map* vertex_index_map; @@ -112,12 +111,10 @@ public: reference operator[] ( key_type const& x ) const { - // return x.base()->id ; - return (*vertex_index_map)[x]; + return (*vertex_index_map)[x]; } } ; - //typedef CGAL::Modifiable_priority_queue MPQ ; typedef CGAL::Modifiable_priority_queue MPQ ; MPQ* mpq; @@ -189,7 +186,17 @@ public: it != pct.vertices_in_constraint_end(cid); ++it){ if((*it)->is_removable()){ - vertex_to_iterator[*it].push_back(it); + typename std::map >::iterator lit; + lit = vertex_to_iterator.find(*it); + + if(lit != vertex_to_iterator.end()){ + std::list& ilist = lit->second; + if(std::find(ilist.begin(),ilist.end(),it) == ilist.end()){ + ilist.push_back(it); + } + }else{ + vertex_to_iterator[*it].push_back(it); + } } } } @@ -202,26 +209,6 @@ public: } } */ - - /* - // the previous code does mark vertices with more than one constraint on it as unremovable - std::set vertices; - Constraint_iterator cit = pct.constraints_begin(), e = pct.constraints_end(); - for(; cit!=e; ++cit){ - Constraint_id cid = *cit; - Vertices_in_constraint_iterator it = pct.vertices_in_constraint_begin(cid); - (*it)->set_removable(false); - for(; it != pct.vertices_in_constraint_end(cid); ++it){ - if(vertices.find(*it) != vertices.end()){ - (*it)->set_removable(false); - } else { - vertices.insert(*it); - } - } - it = boost::prior(it); - (*it)->set_removable(false); - } - */ } // For all polyline constraints we compute the cost of all unremovable and not removed vertices @@ -236,7 +223,9 @@ public: boost::optional dist = cost(pct, it); if(dist){ (*it)->set_cost(*dist); - (*mpq).push(*it); + if(! (*mpq).contains(*it)){ + (*mpq).push(*it); + } ++n; } else { // no need to set the costs as this vertex is not in the priority queue @@ -342,6 +331,7 @@ operator()() if(stop(pct, v, v->cost(), pct_initial_number_of_vertices, pct.number_of_vertices())){ return false; } + Vertices_in_constraint_iterator vit = vertex_to_iterator[v].front(); if(is_removable(vit)){ Vertices_in_constraint_iterator u = boost::prior(vit), w = boost::next(vit); diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index d46c76a3666..4b739c74f2c 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -46,14 +46,13 @@ private: class Node { public: explicit Node(Vertex_handle vh, bool input = false) - : vertex_(vh), /* id(-1),*/ input(input) + : vertex_(vh), input(input) {} const Point& point() const { return vertex_->point(); } Vertex_handle vertex() const { return vertex_; } private: Vertex_handle vertex_; public: - // int id; bool input; }; @@ -585,45 +584,58 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, Vertex_it wc) { + // TODO: How do we (want to) deal with u == w ??? Vertex_handle u = *uc, v = *vc, w = *wc; typename Sc_to_c_map::iterator uv_sc_iter = sc_to_c_map.find(make_edge(u, v)); - CGAL_assertion_msg( uv_sc_iter != sc_to_c_map.end(), "not a subconstraint" ); + typename Sc_to_c_map::iterator vw_sc_iter = sc_to_c_map.find(make_edge(v, w)); Context_list* uv_hcl = uv_sc_iter->second; - CGAL_assertion_msg((u == w) || (uv_hcl->size() == 1), "more than one constraint passing through the subconstraint" ); - - if(*(uv_hcl->front().current()) != u) { - std::swap(u,w); - uv_sc_iter = sc_to_c_map.find(make_edge(u, v)); - CGAL_assertion_msg( uv_sc_iter != sc_to_c_map.end(), "not a subconstraint" ); - uv_hcl = (*uv_sc_iter).second; - CGAL_assertion_msg((u == w) || (uv_hcl->size() == 1), "more than one constraint passing through the subconstraint" ); - } - // now u,v, and w are ordered along the polyline constraint + Context_list* vw_hcl = vw_sc_iter->second; + // AF: what is input() about??? if(vc.input()){ uc.input() = true; wc.input() = true; } - typename Sc_to_c_map::iterator vw_sc_iter = sc_to_c_map.find(make_edge(v, w)); - CGAL_assertion_msg( vw_sc_iter != sc_to_c_map.end(), "not a subconstraint" ); - Context_list* vw_hcl = vw_sc_iter->second; - CGAL_assertion_msg((u == w) || (vw_hcl->size() == 1), "more than one constraint passing through the subconstraint" ); - Vertex_list* vertex_list = uv_hcl->front().id().vl_ptr(); - CGAL_assertion_msg(vertex_list == vw_hcl->front().id().vl_ptr(), "subconstraints from different polyline constraints" ); - // Remove the list item which points to v - vertex_list->skip(vc.base()); - - if(u != w){ - // Remove the entries for [u,v] and [v,w] - sc_to_c_map.erase(uv_sc_iter); - sc_to_c_map.erase(vw_sc_iter); - delete vw_hcl; - // reuse other context list - sc_to_c_map[make_edge(u,w)] = uv_hcl; - }else{ - sc_to_c_map.erase(uv_sc_iter); - delete vw_hcl; + // Take contexts from the two context lists depending on the orientation of the constraints + // These are the contexts where current is either u or w + // remove from uv_hcl the contexts where current is not u + // remove from vw_hcl the contexts where current is not w + // splice into uv_hcl + typename Context_list::iterator it = uv_hcl->begin(); + while(it != uv_hcl->end()){ + if((*it->current()) != u){ + it = uv_hcl->erase(it); + }else{ + // Remove the list item which points to v + Vertex_list* vertex_list = it->id().vl_ptr(); + Vertex_it vc_in_context = it->current(); + vc_in_context = boost::next(vc_in_context); + vertex_list->skip(vc_in_context.base()); + ++it; + } } + it = vw_hcl->begin(); + while(it != vw_hcl->end()){ + if((*it->current()) != w){ + it = vw_hcl->erase(it); + }else{ + // Remove the list item which points to v + Vertex_list* vertex_list = it->id().vl_ptr(); + Vertex_it vc_in_context = it->current(); + vc_in_context = boost::next(vc_in_context); + vertex_list->skip(vc_in_context.base()); + ++it; + } + } + + uv_hcl->splice(uv_hcl->end(),*vw_hcl); + delete vw_hcl; + + sc_to_c_map.erase(uv_sc_iter); + sc_to_c_map.erase(vw_sc_iter); + + // reuse other context list + sc_to_c_map[make_edge(u,w)] = uv_hcl; } From 7a91d9f1a575c85036d604c3a2b4ed8ac8ac3497 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 1 Feb 2021 12:36:34 +0000 Subject: [PATCH 3/9] With a subsequence p-q-p we do not simplify q --- .../simplify_overlapping_polyline.cpp | 2 +- .../include/CGAL/Polyline_simplification_2/simplify.h | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp b/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp index 2df47f53932..96fa16269a3 100644 --- a/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp +++ b/Polyline_simplification_2/examples/Polyline_simplification_2/simplify_overlapping_polyline.cpp @@ -27,7 +27,7 @@ int main() { CT ct; - std::vector P = { Point(0,1), Point(1,1), Point(2,2), Point(3,1), Point(4,1), Point(5,1) }; + std::vector P = { Point(0,1), Point(1,1), Point(2,2), Point(3,1), Point(4,1), Point(4,2), Point(4,1), Point(5,1) }; std::vector Q = { Point(5,0), Point(4,1), Point(3,1), Point(2,2), Point(1,1), Point(0,0) }; std::vector R = { Point(3,1), Point(4,1) }; diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h index 579bcfc9707..1b40efc3202 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h @@ -155,9 +155,15 @@ public: Constraint_iterator cit = pct.constraints_begin(), e = pct.constraints_end(); for(; cit!=e; ++cit){ Constraint_id cid = *cit; - Vertices_in_constraint_iterator it = pct.vertices_in_constraint_begin(cid); + Vertices_in_constraint_iterator it = pct.vertices_in_constraint_begin(cid), + ite = pct.vertices_in_constraint_end(cid); (*it)->set_removable(false); - it = pct.vertices_in_constraint_end(cid); + ++it; + for(; it != ite; ++it){ + if((boost::next(it) != ite) && (boost::prior(it)== boost::next(it))){ + (*it)->set_removable(false); + } + } it = boost::prior(it); (*it)->set_removable(false); } From f339c25635bae2b4959b6ac02094e331dbc22b7f Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 1 Feb 2021 13:03:58 +0000 Subject: [PATCH 4/9] Use unordered_map --- .../include/CGAL/Polyline_simplification_2/simplify.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h index 1b40efc3202..41a046e9e69 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -75,9 +76,9 @@ public: StopFunction stop; std::size_t pct_initial_number_of_vertices, number_of_unremovable_vertices; - std::map > vertex_to_iterator; + std::unordered_map > vertex_to_iterator; - typedef std::map Vertex_index_map; + typedef std::unordered_map Vertex_index_map; Vertex_index_map vertex_index_map; @@ -149,7 +150,7 @@ public: } // endpoints of constraints are unremovable - // vertices which are not endpoint and have != 2 incident constained edges are unremovable + // vertices which are not endpoint and have != 2 incident constrained edges are unremovable void initialize_unremovable() { Constraint_iterator cit = pct.constraints_begin(), e = pct.constraints_end(); @@ -168,7 +169,7 @@ public: (*it)->set_removable(false); } - std::map degrees; + std::unordered_map degrees; for (Constrained_edges_iterator it = pct.constrained_edges_begin(); it != pct.constrained_edges_end(); ++it) { Edge e = *it; Face_handle fh = e.first; @@ -192,7 +193,7 @@ public: it != pct.vertices_in_constraint_end(cid); ++it){ if((*it)->is_removable()){ - typename std::map >::iterator lit; + typename std::unordered_map >::iterator lit; lit = vertex_to_iterator.find(*it); if(lit != vertex_to_iterator.end()){ From 6dc30a144289381a5274b6b6f102aeeb54011321 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 1 Feb 2021 13:09:49 +0000 Subject: [PATCH 5/9] Update the change log --- Installation/CHANGES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 1bd032a7859..a7f93ab440a 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -21,10 +21,13 @@ A comprehensive list of the supported file formats is available in the Stream_su Bolun Wang, Teseo Schneider, Yixin Hu, Marco Attene, and Daniele Panozzo. "Exact and efficient polyhedral envelope containment check." (ACM Trans. Graph., 39-4, July 2020). -### [Surface Mesh Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgSurfaceMeshSimplification) +### [Surface Mesh Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgSurfaceMeshSimplification2) - Added a filtering mechanism so that costly tests get only applied to the next candidate for the edge collapse. - Added the class `Polyhedral_envelope_filter` that enables to perform mesh simplification inside a polyhedral envelope of the input mesh. +### [2D Polyline Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgPolylineSiimplification) +- Subsequences of polylines that are shared are no longer marked as unremovable. + [Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2) ----------- From 4953ff71e0d31d2a1c3b463a2e4edf63f047c6d8 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 4 Feb 2021 11:22:06 +0000 Subject: [PATCH 6/9] fix typo --- Installation/CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index a7f93ab440a..f03ce6d5d42 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -21,11 +21,11 @@ A comprehensive list of the supported file formats is available in the Stream_su Bolun Wang, Teseo Schneider, Yixin Hu, Marco Attene, and Daniele Panozzo. "Exact and efficient polyhedral envelope containment check." (ACM Trans. Graph., 39-4, July 2020). -### [Surface Mesh Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgSurfaceMeshSimplification2) +### [Surface Mesh Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgSurfaceMeshSimplification) - Added a filtering mechanism so that costly tests get only applied to the next candidate for the edge collapse. - Added the class `Polyhedral_envelope_filter` that enables to perform mesh simplification inside a polyhedral envelope of the input mesh. -### [2D Polyline Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgPolylineSiimplification) +### [2D Polyline Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgPolylineSimplification2) - Subsequences of polylines that are shared are no longer marked as unremovable. [Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2) From ed44ebff0fc9ade061f03bed01972f806a0348c9 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 16 Feb 2021 10:43:04 +0000 Subject: [PATCH 7/9] Improve documentation of overlapping polylines --- Installation/CHANGES.md | 2 +- .../Polyline_simplification_2.txt | 10 ++++++++++ .../doc/Polyline_simplification_2/examples.txt | 1 + .../fig/overlapping_polylines.png | Bin 0 -> 6604 bytes ...ne.cpp => simplify_overlapping_polylines.cpp} | 0 5 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Polyline_simplification_2/doc/Polyline_simplification_2/fig/overlapping_polylines.png rename Polyline_simplification_2/examples/Polyline_simplification_2/{simplify_overlapping_polyline.cpp => simplify_overlapping_polylines.cpp} (100%) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index f03ce6d5d42..4e57c07e69b 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -26,7 +26,7 @@ A comprehensive list of the supported file formats is available in the Stream_su - Added the class `Polyhedral_envelope_filter` that enables to perform mesh simplification inside a polyhedral envelope of the input mesh. ### [2D Polyline Simplification](https://doc.cgal.org/5.3/Manual/packages.html#PkgPolylineSimplification2) -- Subsequences of polylines that are shared are no longer marked as unremovable. +- When polylines have common subsequences of vertices these subsequences may be simplifified simultaneously. [Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2) ----------- diff --git a/Polyline_simplification_2/doc/Polyline_simplification_2/Polyline_simplification_2.txt b/Polyline_simplification_2/doc/Polyline_simplification_2/Polyline_simplification_2.txt index 63a0387263f..1900522d579 100644 --- a/Polyline_simplification_2/doc/Polyline_simplification_2/Polyline_simplification_2.txt +++ b/Polyline_simplification_2/doc/Polyline_simplification_2/Polyline_simplification_2.txt @@ -167,6 +167,16 @@ over all vertices of all polyline constraints. \cgalExample{Polyline_simplification_2/simplify.cpp} +Note that when polylines share subsequences of polyline vertices they can get simplified simultaneously. + +\cgalFigureBegin{figure_overlapping_polylines, overlapping_polylines.png} +Simplification of overlapping subsequence of polyline vertices +\cgalFigureEnd + +\cgalExample{Polyline_simplification_2/simplify_overlapping_polylines.cpp} + + + \subsection Subsection_PolylineSimplification_Keeping Keeping Points While Removing Vertices diff --git a/Polyline_simplification_2/doc/Polyline_simplification_2/examples.txt b/Polyline_simplification_2/doc/Polyline_simplification_2/examples.txt index a0713d4fd20..4f5338858ee 100644 --- a/Polyline_simplification_2/doc/Polyline_simplification_2/examples.txt +++ b/Polyline_simplification_2/doc/Polyline_simplification_2/examples.txt @@ -1,6 +1,7 @@ /*! \example Polyline_simplification_2/simplify_polygon.cpp \example Polyline_simplification_2/simplify.cpp +\example Polyline_simplification_2/simplify_overlapping_polylines.cpp \example Polyline_simplification_2/simplify_terrain.cpp \example Polyline_simplification_2/points_and_vertices.cpp */ diff --git a/Polyline_simplification_2/doc/Polyline_simplification_2/fig/overlapping_polylines.png b/Polyline_simplification_2/doc/Polyline_simplification_2/fig/overlapping_polylines.png new file mode 100644 index 0000000000000000000000000000000000000000..83b27735ab3ca4a71db849926f9cafe3d4e51a24 GIT binary patch literal 6604 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 Date: Tue, 16 Feb 2021 13:33:55 +0000 Subject: [PATCH 8/9] bug fix so that it compiles --- .../include/CGAL/Polyline_simplification_2/simplify.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h index 790ab4c9f13..82855c7af63 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h @@ -137,7 +137,7 @@ public: int m = initialize_indices(cid); initialize_unremovable(); Compare_cost cc; - Id_map idm; + Id_map idm(vertex_index_map); mpq = new MPQ(m, cc, idm); initialize_costs(cid); } @@ -306,7 +306,8 @@ public: for(Vertices_in_constraint_iterator it = pct.vertices_in_constraint_begin(cid); it != pct.vertices_in_constraint_end(cid); ++it){ - it.base()->id = id++; + Vertex_handle vh = *it; + vertex_index_map[vh] = id++; } return id; } From 53cb7cd6647134f79208dd5b6ddf46caddb6f70f Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 16 Feb 2021 13:41:28 +0000 Subject: [PATCH 9/9] Simplify the code --- .../Polyline_simplification_2/Vertex_base_2.h | 3 ++ .../CGAL/Polyline_simplification_2/simplify.h | 36 ++++--------------- 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/Vertex_base_2.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/Vertex_base_2.h index b1d090583f8..d5f2856e239 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/Vertex_base_2.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/Vertex_base_2.h @@ -37,6 +37,9 @@ class Vertex_base_2 bool m_removable; FT m_cost; +public: + std::size_t ID; + #ifndef DOXYGEN_RUNNING public: template < typename TDS2 > diff --git a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h index 82855c7af63..ee681c767d4 100644 --- a/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h +++ b/Polyline_simplification_2/include/CGAL/Polyline_simplification_2/simplify.h @@ -78,10 +78,6 @@ public: std::unordered_map > vertex_to_iterator; - typedef std::unordered_map Vertex_index_map; - - Vertex_index_map vertex_index_map; - struct Compare_cost { bool operator() ( Vertices_in_constraint_iterator const& x, @@ -104,15 +100,10 @@ public: typedef value_type reference; typedef Vertex_handle key_type; - Vertex_index_map* vertex_index_map; - - Id_map(const Vertex_index_map& vertex_index_map) - : vertex_index_map(& const_cast(vertex_index_map)) - {} reference operator[] ( key_type const& x ) const { - return (*vertex_index_map)[x]; + return x->ID; } } ; @@ -126,7 +117,7 @@ public: int m = initialize_indices(); initialize_unremovable(); Compare_cost cc; - Id_map idm(vertex_index_map); + Id_map idm; mpq = new MPQ(m, cc, idm); initialize_costs(); } @@ -137,7 +128,7 @@ public: int m = initialize_indices(cid); initialize_unremovable(); Compare_cost cc; - Id_map idm(vertex_index_map); + Id_map idm; mpq = new MPQ(m, cc, idm); initialize_costs(cid); } @@ -207,15 +198,6 @@ public: } } } - - /* - // debug output - for(Finite_vertices_iterator it = pct.finite_vertices_begin(); it != pct.finite_vertices_end(); ++it){ - if(it->is_removable()){ - std::cout << it->point() << " is removable" << std::endl; - } - } - */ } // For all polyline constraints we compute the cost of all unremovable and not removed vertices @@ -307,7 +289,8 @@ public: it != pct.vertices_in_constraint_end(cid); ++it){ Vertex_handle vh = *it; - vertex_index_map[vh] = id++; + vh->ID = id++; + //vertex_index_map[vh] = id++; } return id; } @@ -316,14 +299,9 @@ public: initialize_indices() { int id = 0; - /* - Constraint_iterator b = pct.constraints_begin(), e = pct.constraints_end(); - for(; b!=e; ++b){ - id = initialize_indices(*b, id); - } - */ + for(Finite_vertices_iterator it = pct.finite_vertices_begin(); it != pct.finite_vertices_end(); ++it){ - vertex_index_map[it] = id++; + it->ID = id++; } return id; }