Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

RestrictedTriangulation.h
Go to the documentation of this file.
1 
31 #pragma once
32 
33 #ifdef OGDF_INCLUDE_CGAL
34 
35 //CGAL example
37 
38 # include <iostream>
39 
40 # include <CGAL/Constrained_Delaunay_triangulation_2.h>
41 # include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
42 # include <CGAL/Point_2.h>
43 # include <CGAL/Polygon_2.h>
44 # include <CGAL/Triangulation_face_base_with_info_2.h>
45 
46 namespace ogdf {
47 namespace internal {
48 namespace gcm {
49 namespace geometry {
52 template<typename Kernel>
53 class RestrictedTriangulation {
54 private:
55  struct FaceInfo2 {
56  FaceInfo2() { }
57 
58  int nesting_level;
59 
60  bool in_domain() { return nesting_level % 2 == 1; }
61  };
62 
63  using K = Kernel;
64  using Vb = CGAL::Triangulation_vertex_base_2<K>;
65  using Fbb = CGAL::Triangulation_face_base_with_info_2<FaceInfo2, K>;
66  using Fb = CGAL::Constrained_triangulation_face_base_2<K, Fbb>;
67  using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
68  using Itag = CGAL::Exact_predicates_tag;
69  using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
70  using Point = CGAL::Point_2<K>;
71  using Polygon_2 = CGAL::Polygon_2<K>;
72 
73  void mark_domains(CDT& ct, typename CDT::Face_handle start, int index,
74  std::list<typename CDT::Edge>& border) {
75  if (start->info().nesting_level != -1) {
76  return;
77  }
78  std::list<typename CDT::Face_handle> queue;
79  queue.push_back(start);
80  while (!queue.empty()) {
81  typename CDT::Face_handle fh = queue.front();
82  queue.pop_front();
83  if (fh->info().nesting_level == -1) {
84  fh->info().nesting_level = index;
85  for (int i = 0; i < 3; i++) {
86  typename CDT::Edge e(fh, i);
87  typename CDT::Face_handle n = fh->neighbor(i);
88  if (n->info().nesting_level == -1) {
89  if (ct.is_constrained(e)) {
90  border.push_back(e);
91  } else {
92  queue.push_back(n);
93  }
94  }
95  }
96  }
97  }
98  }
99 
100  //explore set of facets connected with non constrained edges,
101  //and attribute to each such set a nesting level.
102  //We start from facets incident to the infinite vertex, with a nesting
103  //level of 0. Then we recursively consider the non-explored facets incident
104  //to constrained edges bounding the former set and increase the nesting level by 1.
105  //Facets in the domain are those with an odd nesting level.
106  void mark_domains(CDT& cdt) {
107  for (typename CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end();
108  ++it) {
109  it->info().nesting_level = -1;
110  }
111  std::list<typename CDT::Edge> border;
112  mark_domains(cdt, cdt.infinite_face(), 0, border);
113  while (!border.empty()) {
114  typename CDT::Edge e = border.front();
115  border.pop_front();
116  typename CDT::Face_handle n = e.first->neighbor(e.second);
117  if (n->info().nesting_level == -1) {
118  mark_domains(cdt, n, e.first->info().nesting_level + 1, border);
119  }
120  }
121  }
122 
123  void insert_polygon(CDT& cdt, const Polygon_2& polygon) {
124  if (polygon.is_empty()) {
125  return;
126  }
127  typename CDT::Vertex_handle v_prev = cdt.insert(*CGAL::cpp11::prev(polygon.vertices_end()));
128  for (typename Polygon_2::Vertex_iterator vit = polygon.vertices_begin();
129  vit != polygon.vertices_end(); ++vit) {
130  typename CDT::Vertex_handle vh = cdt.insert(*vit);
131  cdt.insert_constraint(vh, v_prev);
132  v_prev = vh;
133  }
134  }
135 
136 public:
137  CDT run(const Polygon_t<Kernel>& polygon) {
138  CDT cdt;
139  insert_polygon(cdt, polygon);
140  mark_domains(cdt);
141  return std::move(cdt);
142  }
143 };
144 }
145 }
146 }
147 }
148 
149 #endif
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
backward::details::move
const T & move(const T &v)
Definition: backward.hpp:243
Polygon.h
ogdf::gml::Key::Point
@ Point