EMODnet Quantized Mesh Generator for Cesium
extract_polylines_from_sharp_edges.h
1 // Copyright (c) 2018 Coronis Computing S.L. (Spain)
2 // All rights reserved.
3 //
4 // This file is part of EMODnet Quantized Mesh Generator for Cesium.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 //
19 // Author: Ricard Campos (ricardcd@gmail.com)
20 
21 #ifndef EMODNET_QMGC_POLYLINES_FROM_FEATURED_EDGES_H
22 #define EMODNET_QMGC_POLYLINES_FROM_FEATURED_EDGES_H
23 
24 #include <CGAL/boost/graph/properties.h>
25 #include <CGAL/boost/graph/properties_Surface_mesh.h>
26 #include <boost/graph/filtered_graph.hpp>
27 #include <CGAL/boost/graph/split_graph_into_polylines.h>
28 
29 
35 template<typename Surface_mesh, typename EdgeIsSharpMap>
36 struct IsSharpEdge {
37  typedef typename boost::graph_traits<Surface_mesh>::edge_descriptor edge_descriptor;
38 
39  IsSharpEdge() {} // required by boost::filtered_graph
40 
41  IsSharpEdge(EdgeIsSharpMap eisMap) : m_eisMap(eisMap) {}
42 
43  bool operator()(typename boost::graph_traits<Surface_mesh>::edge_descriptor e) const {
44  return get(m_eisMap, e);
45  }
46 
47  EdgeIsSharpMap m_eisMap;
48 };
49 
55 template<typename Graph,
56  typename Polyline>
58 {
59  std::vector<Polyline>& m_polylines;
60  const Graph& m_graph;
61 
62  ExtractPolylinesVisitor(const Graph& graph, typename std::vector<Polyline>& polylines)
63  : m_polylines(polylines), m_graph(graph)
64  {}
65 
66  void start_new_polyline()
67  {
68  m_polylines.push_back(Polyline());
69  }
70 
71  void add_node(typename boost::graph_traits<Graph>::vertex_descriptor vd)
72  {
73  if(m_polylines.back().empty()) {
74  m_polylines.back().push_back(m_graph[vd]);
75  }
76  }
77 
78  void add_edge(typename boost::graph_traits<Graph>::edge_descriptor ed)
79  {
80  typename boost::graph_traits<Graph>::vertex_descriptor
81  s = source(ed, m_graph),
82  t = target(ed, m_graph);
83  Polyline& polyline = m_polylines.back();
84  CGAL_assertion(!polyline.empty());
85  if(polyline.back() != m_graph[s]) {
86  polyline.push_back(m_graph[s]);
87  } else if(polyline.back() != m_graph[t]) {
88  // if the edge is zero-length, it is ignored
89  polyline.push_back(m_graph[t]);
90  }
91  }
92 
93  void end_polyline()
94  {
95  // ignore degenerated polylines
96  if(m_polylines.back().size() < 2)
97  m_polylines.resize(m_polylines.size() - 1);
98  }
99 };
100 
110 template <typename Surface_mesh, typename EdgeIsSharpMap, typename Polyline>
111 void extract_polylines_from_sharp_edges(const Surface_mesh& sm,
112  const EdgeIsSharpMap& eisMap,
113  std::vector<Polyline>& polylines)
114 {
115  typedef typename boost::property_traits<typename boost::property_map<Surface_mesh,CGAL::vertex_point_t>::type>::value_type Point_3;
116  typedef boost::adjacency_list<
117  boost::setS, // this avoids parallel edges
118  boost::vecS,
119  boost::undirectedS,
120  Point_3 > Featured_edges_copy_graph;
122 
123  // Filter the "graph" (i.e., the mesh) using the created property map
124  IsSharpEdge isSharpEdge(eisMap);
125  typedef boost::filtered_graph<Surface_mesh, IsSharpEdge > FilteredGraph;
126  FilteredGraph filteredGraph(sm, isSharpEdge);
127 
128  // Create a copy of the graph containing just the featured edges
129  Featured_edges_copy_graph feGraph;
130  typedef typename boost::property_map<Surface_mesh, CGAL::vertex_point_t>::const_type Vpm;
131  Vpm vpm = get(CGAL::vertex_point, sm);
132 
133  typedef std::map<Point_3, typename boost::graph_traits<Featured_edges_copy_graph>::vertex_descriptor> P2vmap;
134  P2vmap p2vmap;
135 
136  // --> Add vertices
137  BOOST_FOREACH(typename FilteredGraph::vertex_descriptor v, vertices(filteredGraph)){
138  typename Featured_edges_copy_graph::vertex_descriptor vc;
139  typename P2vmap::iterator it = p2vmap.find(get(vpm,v));
140  if(it == p2vmap.end()) {
141  vc = add_vertex(feGraph);
142  feGraph[vc] = get(vpm, v);
143  p2vmap[get(vpm,v)] = vc;
144  }
145  }
146 
147  // --> Add edges
148  BOOST_FOREACH(typename FilteredGraph::edge_descriptor e, edges(filteredGraph)) {
149  typename Featured_edges_copy_graph::vertex_descriptor vs = p2vmap[get(vpm, source(e, filteredGraph))];
150  typename Featured_edges_copy_graph::vertex_descriptor vt = p2vmap[get(vpm, target(e, filteredGraph))];
151  CGAL_warning_msg(vs != vt, "ignore self loop");
152  if (vs != vt) {
153  const std::pair<typename Featured_edges_copy_graph::edge_descriptor, bool> pair = add_edge(vs, vt, feGraph);
154  }
155  }
156 
157  // Create the polylines
159  CGAL::split_graph_into_polylines(feGraph, visitor);
160 }
161 
162 
163 #endif //EMODNET_QMGC_POLYLINES_FROM_FEATURED_EDGES_H
Struct/functor that returns true if the edge is sharp (given a previously computed edgeIsSharp map) ...
Definition: extract_polylines_from_sharp_edges.h:36
Visitor used by the extract_polylines_from_sharp_edges function.
Definition: extract_polylines_from_sharp_edges.h:57