Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

CGALPlanarSubdivision.h
Go to the documentation of this file.
1 
31 #pragma once
32 
33 #ifdef OGDF_INCLUDE_CGAL
34 
40 
41 # include <boost/graph/breadth_first_search.hpp>
42 # include <boost/graph/visitors.hpp>
43 # include <tuple>
44 
45 # include <CGAL/Arr_extended_dcel.h>
46 # include <CGAL/Arr_face_index_map.h>
47 # include <CGAL/Arr_linear_traits_2.h>
48 # include <CGAL/Arr_segment_traits_2.h>
49 # include <CGAL/Arr_walk_along_line_point_location.h>
50 # include <CGAL/Arrangement_2.h>
51 # include <CGAL/Arrangement_with_history_2.h>
52 # include <CGAL/graph_traits_dual_arrangement_2.h>
53 
54 namespace ogdf {
55 namespace internal {
56 namespace gcm {
57 namespace geometry {
58 
61 template<typename kernel>
62 class CGALPlanarSubdivision {
63 private:
64  using LineSegment = geometry::LineSegment_t<kernel>;
65  using Point = geometry::Point_t<kernel>;
66  using Polygon = geometry::Polygon_t<kernel>;
67  using Line = geometry::Line_t<kernel>;
68  using Ray = geometry::Ray_t<kernel>;
69  using Direction = geometry::Direction_t<kernel>;
70  using Traits = CGAL::Arr_segment_traits_2<kernel>;
71 
72  using LinearTraits = CGAL::Arr_linear_traits_2<kernel>;
73 
74  using Dcel = CGAL::Arr_extended_dcel<Traits, unsigned int, unsigned int, unsigned int>;
75  using ArrWH = CGAL::Arrangement_with_history_2<Traits, Dcel>;
76 
77  using Arr = CGAL::Arrangement_2<Traits>;
78  using LinearArr = CGAL::Arrangement_2<LinearTraits>;
79 
80  using DualArr = CGAL::Dual<Arr>;
81  using Face_index_map = CGAL::Arr_face_index_map<Arr>;
82 
83  template<typename _Arr>
84  Polygon get_face(CGAL::Arr_walk_along_line_point_location<_Arr>& pl, const Point& q) {
85  auto obj = pl.locate(q);
86 
87  using Vertex_const_handle = typename _Arr::Vertex_const_handle;
88  using Halfedge_const_handle = typename _Arr::Halfedge_const_handle;
89  using Face_const_handle = typename _Arr::Face_const_handle;
90 
91  const Vertex_const_handle* v;
92  const Halfedge_const_handle* e;
93  const Face_const_handle* f;
94 
95  Polygon poly;
96  if ((f = boost::get<Face_const_handle>(&obj))) { // located inside a face
97  OGDF_ASSERT(!(*f)->is_unbounded());
98  auto c = (*f)->outer_ccb();
99  do {
100  poly.push_back(c->source()->point());
101  } while (++c != (*f)->outer_ccb());
102  } else if ((e = boost::get<Halfedge_const_handle>(&obj))) { // located on an edge
103 
104  poly.push_back((*e)->source()->point());
105  poly.push_back((*e)->target()->point());
106  } else if ((v = boost::get<Vertex_const_handle>(&obj))) { // located on a vertex
107  poly.push_back((*v)->point());
108  } else {
109  // undefined behaviour
110  OGDF_ASSERT(false);
111  }
112 
113  return poly;
114  }
115 
116 public:
117  using LCGEdge = std::tuple<unsigned int, unsigned int, unsigned int>;
118 
119  Polygon extract_face(const std::vector<Line>& lines, const Point& q) {
120  LinearArr arr;
121  CGAL::Arr_walk_along_line_point_location<LinearArr> pl(arr);
122  CGAL::insert(arr, lines.begin(), lines.end());
123  return get_face(pl, q);
124  }
125 
126  Polygon extract_face(const std::vector<LineSegment>& segments, const Point& q) {
127  Arr arr;
128  CGAL::Arr_walk_along_line_point_location<Arr> pl(arr);
129  CGAL::insert(arr, segments.begin(), segments.end());
130  return get_face(pl, q);
131  }
132 
140  void process(std::vector<LineSegment>& segments, std::vector<Line>& lines,
141  std::vector<Point>& node_to_point, std::vector<LCGEdge>& edge_list, int separator = -1) {
142  ArrWH arr;
143  if (separator < 0) {
144  separator = segments.size();
145  }
146  CGAL::insert(arr, segments.begin(), segments.begin() + separator);
147  CGAL::insert(arr, lines.begin(), lines.end());
148  //polygon edges
149  CGAL::insert(arr, segments.begin() + separator, segments.end());
150 
151  unsigned int node = 1;
152  for (auto v_it = arr.vertices_begin(); v_it != arr.vertices_end(); ++v_it) {
153  v_it->set_data(node++);
154  node_to_point.push_back(v_it->point());
155  }
156 
157  auto f_make_edge = [&](decltype(arr.induced_edges_begin(arr.curves_begin()))& e_itr,
158  const Direction& ref, unsigned int flag) {
159  auto e = *e_itr;
160  LineSegment t(e->source()->point(), e->target()->point());
161 
162  if (t.direction() == ref) {
163  return LCGEdge(e->source()->data() - 1, e->target()->data() - 1, flag);
164  } else {
165  return LCGEdge(e->target()->data() - 1, e->source()->data() - 1, flag);
166  }
167  };
168  auto itr = arr.curves_begin();
169  for (unsigned int i = 0; i < segments.size(); ++i, ++itr) {
170  LineSegment s(itr->source(), itr->target());
171  for (auto e_itr = arr.induced_edges_begin(itr); e_itr != arr.induced_edges_end(itr);
172  ++e_itr) {
173  edge_list.push_back(f_make_edge(e_itr, s.direction(), i));
174  }
175  }
176 
177  for (unsigned int i = 0; i < lines.size(); ++i, ++itr) {
178  OGDF_ASSERT(itr != arr.curves_end());
179  for (auto e_itr = arr.induced_edges_begin(itr); e_itr != arr.induced_edges_end(itr);
180  ++e_itr) {
181  auto e = *e_itr;
182  if (e->source()->data() > 0 && e->target()->data() > 0) {
183  edge_list.push_back(LCGEdge(e->source()->data() - 1, e->target()->data() - 1, i));
184  }
185  }
186  }
187  }
188 
196  void process(std::vector<LineSegment>& segments, std::vector<Point>& node_to_point,
197  std::vector<LCGEdge>& edge_list, unsigned int separator = 0) {
198  std::vector<Line> r;
199  process(segments, r, node_to_point, edge_list, separator);
200  }
201 };
202 
203 }
204 }
205 }
206 }
207 
208 #endif
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::Direction
Direction
Definition: basic.h:150
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
Point.h
r
int r[]
Definition: hierarchical-ranking.cpp:13
ogdf::node
NodeElement * node
The type of nodes.
Definition: Graph_d.h:70
LineSegment.h
Line.h
Polygon.h
ogdf::gml::Key::Point
@ Point
Direction.h