Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
Polygon.h
Go to the documentation of this file.
1
31#pragma once
32
33#ifdef OGDF_INCLUDE_CGAL
34
43
44# include <limits>
45# include <list>
46# include <vector>
47
48# include <CGAL/Polygon_2.h>
49
50namespace ogdf {
51namespace internal {
52namespace gcm {
53namespace geometry {
54
55using namespace tools;
56
57template<typename kernel>
58class Polygon_t : public CGAL::Polygon_2<kernel> {
59private:
60 using poly = CGAL::Polygon_2<kernel>;
61
62public:
63 using poly::poly; //inherit constructors
64
65 Polygon_t(const poly& p) : poly(p) { }
66
67 Polygon_t(const poly&& p) : poly(std::move(p)) { }
68
69 Polygon_t() { }
70
71 Polygon_t(const Polygon_t<kernel>& p) : poly(p) { }
72
73 inline typename poly::Edge_const_iterator begin() const { return poly::edges_begin(); }
74
75 inline typename poly::Edge_const_iterator end() const { return poly::edges_end(); };
76
77 void push_back(const Point_t<kernel>& x) {
78 if (poly::is_empty() || (poly::container().back() != x)) {
79 poly::push_back(x);
80 }
81 }
82
83 Polygon_t<kernel> operator=(const Polygon_t<kernel>& p) {
84 (poly)(*this) = p;
85 return *this;
86 }
87};
88
89template<typename kernel, typename Graph>
90inline Polygon_t<kernel> get_polygon(const graph::GeometricDrawing<kernel, Graph>& drawing,
91 const graph::Path& path) { //TODO
92 Polygon_t<kernel> polygon;
93 for (auto& v : path.nodes()) {
94 polygon.push_back(drawing.get_point(v));
95 }
96 return polygon;
97}
98
99template<typename kernel, typename Graph>
100inline Polygon_t<kernel> get_polygon(const graph::PolylineDrawing<kernel, Graph>& drawing,
101 const graph::Path& path) {
102 Polygon_t<kernel> polygon;
103
104 for (unsigned int i = 0; i < path.edges().size(); ++i) {
105 auto e = path.edges()[i];
106
107 if (!path.is_reversed(i)) {
108 for (auto& p : drawing.get_polyline(e)) {
109 polygon.push_back(p);
110 }
111 } else {
112 auto& p = drawing.get_polyline(e);
113 for (auto itr = p.rbegin(); itr != p.rend(); ++itr) {
114 polygon.push_back(*itr);
115 }
116 }
117 }
118 return polygon;
119}
120
121template<typename kernel>
124 for (unsigned int i = 0; i < 4; ++i) {
125 p.push_back(rect[i]);
126 }
127 return p;
128}
129
130template<typename kernel>
131inline Polygon_t<kernel> get_polygon(const CGAL::Bbox_2& bb) {
133}
134
135//TODO move somewhere usefull ;)
136template<typename kernel>
138 //assume line intersects rect twice
139 std::vector<Point_t<kernel>> is;
141 for (auto s : p) {
142 if (geometry::do_intersect_wo_target(line, s)) {
143 is.push_back(geometry::intersect(line, s));
144 }
145 }
146
147 return LineSegment_t<kernel>(is[0], is[1]);
148}
149
150template<typename kernel, typename Graph>
151inline std::vector<typename Graph::Node> graph_from_polygon(const Polygon_t<kernel>& polygon,
152 graph::GeometricDrawing<kernel, Graph>& drawing) {
153 std::vector<typename Graph::Node> node_map;
154 for (unsigned int i = 0; i < polygon.size(); ++i) {
155 typename Graph::Node u = drawing.get_graph().add_node();
156 drawing.set_point(u, polygon[i]);
157 node_map.push_back(u);
158 }
159
160 for (unsigned int i = 0; i < polygon.size(); ++i) {
161 drawing.get_graph().add_edge(node_map[i], node_map[(i + 1) % polygon.size()]);
162 }
163
164 return node_map;
165}
166
167template<typename kernel>
168inline unsigned int next(const Polygon_t<kernel>& p, unsigned int i) {
169 return (i + 1) % p.size();
170}
171
172template<typename kernel>
173inline unsigned int prev(const Polygon_t<kernel>& p, unsigned int i) {
174 return std::min((size_t)i - 1, p.size() - 1);
175}
176
177template<typename kernel>
178inline Polygon_t<kernel> reverse(const Polygon_t<kernel>& polygon) {
179 return std::move(Polygon_t<kernel>(polygon.container().rbegin(), polygon.container().rend()));
180}
181
182template<typename kernel>
183inline bool contains(const Polygon_t<kernel>& polygon, const geometry::Point_t<kernel>& p) {
184 OGDF_ASSERT(!is_clockwise(polygon));
185 if (polygon.size() == 0) {
186 return false;
187 }
188 if (polygon.size() == 1) {
189 return polygon[0] == p;
190 }
191 if (CGAL::is_zero(CGAL::abs(polygon.area()))) {
192 // all segments are nearly colinear, check if p is on one of them
193 for (const auto& s : polygon) {
194 if (is_on(s, p)) {
195 return true;
196 }
197 }
198 return false;
199 }
200
201 unsigned int segment = -1;
202 geometry::LineSegment_t<kernel> l;
203 do {
204 ++segment;
205 l = {p, polygon[segment] + polygon.edge(segment).to_vector() * 0.5};
206 } while (overlapping(l, polygon.edge(segment)));
207
208 OGDF_ASSERT((size_t)segment < polygon.size());
209
210 geometry::Ray_t<kernel> r(p, l.to_vector());
211 unsigned int nof_intersections = 0;
212 bool is_on_border = false;
213
214 for (unsigned int i = 0; i < polygon.size(); ++i) {
215 auto s = polygon.edge(i);
216
217 if (geometry::do_intersect_wo_target(s, r)) {
218 auto is = geometry::intersect(s, r);
219 if (is == s.source()) {
220 auto prev_seg = polygon.edge(prev(polygon, i));
221 if (!geometry::right_turn(prev_seg, s)) { // not a concave corner
223 }
224 } else {
226 }
227 }
229 }
230 return nof_intersections % 2 == 1 || is_on_border;
231}
232
233//returns the distance of the point to the polygon. The Value is negative, if the point is not contained in the interior of the polygon.
234template<typename Kernel>
235typename Kernel::FT squared_distance(const Polygon_t<Kernel>& polygon, const Point_t<Kernel>& point) {
236 typename Kernel::FT min_dist = CGAL::squared_distance(*polygon.begin(), point);
237 for (const auto& e : polygon) {
238 typename Kernel::FT sq = CGAL::squared_distance(e, point);
239 if (sq < min_dist) {
240 min_dist = sq;
241 }
242 }
243 if (min_dist > 1e-12 && !contains(polygon, point)) {
245 }
246
247 return min_dist;
248}
249
250//returns the distance of the point to the polygon. The Value is negative, if the point is not contained in the interior of the polygon.
251template<typename Kernel>
253 Point_t<Kernel> p(0, 0);
254 for (const Point_t<Kernel>& q : polygon.container()) {
255 p = p + q;
256 }
257 p = p * (1.0 / polygon.size());
258 return p;
259}
260
261template<typename kernel>
262inline Point_t<kernel> intersect(const Polygon_t<kernel>& polygon, const Ray_t<kernel>& ray,
263 unsigned int& idx) {
264 // FIXME implement me
265 OGDF_ASSERT(false);
266 (void)polygon;
267 (void)ray;
268 (void)idx;
269}
270
271template<typename kernel>
272inline Point_t<kernel> intersect(const Polygon_t<kernel>& polygon, const Ray_t<kernel>& ray) {
273 OGDF_ASSERT(contains(polygon, ray.source()));
275 for (auto s : polygon) {
276 if (geometry::do_intersect_wo_target(s, ray)) {
277 return geometry::intersect(s, ray);
278 }
279 }
280 return {-1, -1};
281}
282
283template<typename kernel>
284inline bool is_clockwise(const Polygon_t<kernel>& polygon) {
285 return polygon.area() < 0;
286}
287
288template<typename kernel>
289std::vector<unsigned int> find_duplicates(const Polygon_t<kernel>& polygon) {
290 std::vector<unsigned int> segment_ids(polygon.size(), 0);
291 for (unsigned int i = 0; i < polygon.size(); ++i) {
292 segment_ids[i] = i;
293 }
294 std::sort(segment_ids.begin(), segment_ids.end(), [&](unsigned int i, unsigned int j) {
295 return (polygon.edge(i).min() < polygon.edge(j).min())
296 || (polygon.edge(i).min() == polygon.edge(j).min()
297 && polygon.edge(i).max() < polygon.edge(j).max());
298 });
299
300 std::vector<unsigned int> is_duplicate(polygon.size(), -1);
301 for (unsigned int i = 0; i + 1 < polygon.size(); ++i) {
302 unsigned int a = segment_ids[i];
303 unsigned int b = segment_ids[i + 1];
304 if (polygon.edge(a).min() == polygon.edge(b).min()
305 && polygon.edge(a).max() == polygon.edge(b).max()) {
306 is_duplicate[a] = b;
307 is_duplicate[b] = a;
308 }
309 }
310 return is_duplicate;
311}
312
313template<typename kernel>
314std::string ggb(const Polygon_t<kernel>& polygon) {
315 std::stringstream os;
316 os << "polygon[";
317 for (unsigned int i = 0; i < polygon.size(); ++i) {
318 os << polygon[i];
319 if (i + 1 < polygon.size()) {
320 os << ",";
321 }
322 }
323 os << "]";
324 return os.str();
325}
326
327template<typename kernel>
328std::ostream& operator<<(std::ostream& os, const Polygon_t<kernel>& p) {
329 os << ggb(p);
330 return os;
331}
332
333
334} //namespace
335}
336}
337}
338
339#endif
Reverse< T > reverse(T &container)
Provides iterators for container to make it easily iterable in reverse.
Definition Reverse.h:74
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
const T & move(const T &v)
Definition backward.hpp:243
The namespace for all OGDF objects.
std::ostream & operator<<(std::ostream &os, const ogdf::Array< E, INDEX > &a)
Prints array a to output stream os.
Definition Array.h:978
Definition GML.h:110