Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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