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
LineSegment.h
Go to the documentation of this file.
1
31#pragma once
32
33#ifdef OGDF_INCLUDE_CGAL
34
35# ifndef OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE
36# define OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE false
37# endif
38
44
45# include <iomanip>
46# include <limits>
47
48# include <CGAL/Segment_2.h>
49
50namespace ogdf {
51namespace internal {
52namespace gcm {
53namespace geometry {
54using namespace tools;
55
56template<typename kernel>
57using LineSegment_t = CGAL::Segment_2<kernel>;
58
59/* computes angle between this segment and @ls
60 * @ls line segment
61 * @return angle in [0, \Pi]
62 * */
63template<typename kernel>
64inline typename kernel::FT angle(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
65 OGDF_ASSERT(l1.to_vector().squared_length() > 0);
66 OGDF_ASSERT(l2.to_vector().squared_length() > 0);
67 return geometry::angle(l1.to_vector(), l2.to_vector());
68}
69
70/* compute the full angle between this segment and @ls counterclockwise order
71 * @ls line segment
72 * @return angle in [0, 2 * \Pi]
73 * */
74template<typename kernel>
75inline typename kernel::FT full_angle(const LineSegment_t<kernel>& l1,
77 OGDF_ASSERT(l1.to_vector().squared_length() > 0);
78 OGDF_ASSERT(l2.to_vector().squared_length() > 0);
79 return full_angle(l1.to_vector(), l2.to_vector());
80}
81
82template<typename kernel>
83inline bool turn(const LineSegment_t<kernel>& ls, const Line_t<kernel>& l) {
84 return turn(ls.to_vector(), l.to_vector());
85}
86
87template<typename kernel>
88inline bool left_turn(const LineSegment_t<kernel>& ls, const LineSegment_t<kernel>& l) {
89 return left_turn(ls.to_vector(), l.to_vector());
90}
91
92template<typename kernel>
93inline bool right_turn(const LineSegment_t<kernel>& ls, const LineSegment_t<kernel>& l) {
94 return right_turn(ls.to_vector(), l.to_vector());
95}
96
97template<typename kernel>
98inline bool turn(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
99 return turn(ls.supporting_line(), p);
100}
101
102template<typename kernel>
103inline bool left_turn(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
104 return left_turn(ls.supporting_line(), p);
105}
106
107template<typename kernel>
108inline bool right_turn(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
109 return right_turn(ls.supporting_line(), p);
110}
111
112template<typename kernel>
113inline typename kernel::FT squared_convex_parameter_directed(const LineSegment_t<kernel>& ls,
114 const Point_t<kernel>& p) {
115 OGDF_ASSERT(ls.has_on(p));
116 return (ls.source() - p).squared_length() / ls.to_vector().squared_length();
117}
118
119template<typename kernel>
120inline typename kernel::FT squared_convex_parameter(const LineSegment_t<kernel>& ls,
121 const Point_t<kernel>& point) {
122 OGDF_ASSERT(ls.has_on(point));
123 return std::max(squared_convex_parameter_directed(ls, point),
124 squared_convex_parameter_directed(ls.opposite(), point));
125}
126
127template<typename kernel>
128inline Point_t<kernel> rel_point_at(const LineSegment_t<kernel>& ls, const typename kernel::FT l) {
129 OGDF_ASSERT(0 <= l && l <= 1.0);
130 return ls.source() + (ls.to_vector() * l);
131}
132
133template<typename kernel>
134inline typename kernel::FT value_at(const LineSegment_t<kernel>& ls, const typename kernel::FT x) {
135 if (ls.supporting_line().is_vertical()) {
136 return std::numeric_limits<typename kernel::FT>::infinity();
137 } else {
138 return ls.supporting_line().y_at_x(x);
139 }
140}
141
142template<typename kernel>
143inline typename kernel::FT value_at(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
144 if (ls.supporting_line().is_vertical()) {
145 return p.y();
146 } else {
147 return ls.supporting_line().y_at_x(p.x());
148 }
149}
150
151template<bool closed, typename kernel>
152inline bool is_on(const LineSegment_t<kernel>& ls, const Point_t<kernel>& point) {
153 if (!closed) {
154 return ls.has_on(point) && ls.target() != point;
155 } else {
156 return ls.has_on(point);
157 }
158}
159
160template<typename kernel>
161inline bool is_on(const LineSegment_t<kernel>& ls, const Point_t<kernel>& point) {
162 return is_on<false>(ls, point);
163}
164
165template<typename kernel>
166inline bool overlapping(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
167 const bool parallel = CGAL::parallel(l1.supporting_line(), l2.supporting_line());
168 const bool on_l1 = is_on<true>(l1, l2.source()) || is_on<true>(l1, l2.target());
169 const bool on_l2 = is_on<true>(l2, l1.source()) || is_on<true>(l2, l1.target());
170 return (on_l1 || on_l2) && parallel;
171}
172
173template<typename kernel>
174inline bool overlapping(const LineSegment_t<kernel>& ls, const Line_t<kernel>& line) {
175 const bool parallel = parallel(ls.supporting_line(), line);
176 // if both segments are parallel, then it would be sufficient to check wheather base or end is on the line
177 // to be a little more robust, check if one of both is on the line. therefore small error are overseen
178 const bool on_line = line.has_on(ls.source()) || line.has_on(ls.target());
179 return on_line && parallel;
180}
181
182template<typename kernel>
184 return CGAL::do_intersect(l1, l2) && !l1.has_on(l2.target()) && !l2.has_on(l1.target());
185}
186
187template<typename kernel>
189 return CGAL::do_intersect(l1, l2) && !l1.has_on(l2.target()) && !l2.has_on(l1.target())
190 && !l1.has_on(l2.source()) && !l2.has_on(l1.source());
191}
192
193template<typename kernel>
195 return CGAL::do_intersect(l1, l) && !l.has_on(l1.target());
196}
197
198template<typename kernel>
200 return geometry::do_intersect_wo_target(l1, l);
201}
202
203template<typename kernel>
205 return CGAL::do_intersect(l1, r) && !r.has_on(l1.target());
206}
207
208template<typename kernel>
210 return geometry::do_intersect_wo_target(l1, r);
211}
212
213template<typename kernel>
215 return l1.source() == l2.source() || l1.source() == l2.target() || l1.target() == l1.source()
216 || l1.target() == l2.target();
217}
218
219template<typename kernel>
221 const LineSegment_t<kernel>& l2) {
223
224 if (l1.source() == l2.source() || l1.source() == l2.target()) {
225 return l1.source();
226 } else {
227 return l1.target();
228 }
229}
230
231template<typename kernel>
232inline Point_t<kernel> intersect(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
233 OGDF_ASSERT(!l1.is_degenerate());
234 OGDF_ASSERT(!l2.is_degenerate());
235
236 auto result = CGAL::intersection(l1, l2);
237 if (!result) {
238 return Point_t<kernel>(std::numeric_limits<double>::max(),
239 std::numeric_limits<double>::max());
240 }
241
242 Point_t<kernel> intersection;
243 if (boost::get<LineSegment_t<kernel>>(&*result)) {
244 auto s = boost::get<LineSegment_t<kernel>>(&*result);
245 intersection = s->source();
246 } else if (boost::get<Point_t<kernel>>(&*result)) {
247 intersection = *boost::get<Point_t<kernel>>(&*result);
248 }
249 //TODO
250 //OGDF_ASSERT(is_on<true>(l1, intersection));
251 //OGDF_ASSERT(is_on<true>(l2, intersection));
252 return intersection;
253}
254
255template<typename kernel>
256inline Point_t<kernel> intersect(const LineSegment_t<kernel>& l1, const Line_t<kernel>& l2) {
257 OGDF_ASSERT(!l1.is_degenerate());
258 OGDF_ASSERT(!l2.is_degenerate());
259 auto result = CGAL::intersection(l1, l2);
260 if (!result) {
261 return Point_t<kernel>(std::numeric_limits<unsigned int>::max(),
262 std::numeric_limits<unsigned int>::max());
263 }
264
265 Point_t<kernel> intersection;
266 if (boost::get<LineSegment_t<kernel>>(&*result)) {
267 auto s = boost::get<LineSegment_t<kernel>>(&*result);
268 intersection = s->source();
269 } else {
270 intersection = *boost::get<Point_t<kernel>>(&*result);
271 }
272 OGDF_ASSERT(is_on<true>(l1, intersection));
273 OGDF_ASSERT(l2.has_on(intersection));
274 return intersection;
275}
276
277template<typename kernel>
278inline Point_t<kernel> intersect(const Line_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
279 return intersect(l2, l1);
280}
281
282template<typename kernel>
283inline Point_t<kernel> intersect(const LineSegment_t<kernel>& l1, const Ray_t<kernel>& r) {
284 OGDF_ASSERT(!l1.is_degenerate());
285 OGDF_ASSERT(!r.is_degenerate());
286
287 auto result = CGAL::intersection(l1, r);
288 if (!result) {
289 return Point_t<kernel>(std::numeric_limits<unsigned int>::max(),
290 std::numeric_limits<unsigned int>::max());
291 }
292
293
294 Point_t<kernel> intersection;
295 if (boost::get<LineSegment_t<kernel>>(&*result)) {
296 auto s = boost::get<LineSegment_t<kernel>>(&*result);
297 intersection = s->source();
298 } else {
299 intersection = *boost::get<Point_t<kernel>>(&*result);
300 }
302 OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE || r.has_on(intersection));
303 return intersection;
304}
305
306template<typename kernel>
307inline Point_t<kernel> intersect(const Ray_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
308 return intersect(l2, l1);
309}
310
311template<typename kernel>
312inline typename kernel::FT order_along_seg(const LineSegment_t<kernel>& reference
313
314 ,
316 auto cross = [&](const Vector_t<kernel>& v_1, const Vector_t<kernel>& v_2) {
317 return v_1.x() * v_2.y() - v_1.y() * v_2.x();
318 };
319
320 auto s = reference.target() - reference.source();
321 auto r_1 = l_1.target() - l_1.source();
322 auto r_2 = l_2.target() - l_2.source();
323
324 auto c_1 = cross(reference.source() - l_1.source(), s);
325 auto c_2 = cross(reference.source() - l_2.source(), s);
326
327 auto d_1 = cross(r_1, s);
328 auto d_2 = cross(r_2, s);
329
330 return c_1 * d_2 - c_2 * d_1;
331}
332
333template<typename kernel>
334void serialize(const LineSegment_t<kernel>& ls, std::ostream& os) {
335 serialize(ls.source(), os);
336 serialize(ls.target(), os);
337}
338
339template<typename kernel>
340inline bool operator<(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
341 return l1.source() < l2.source() || (l1.source() == l2.source() && l1.target() < l2.target());
342}
343
344template<typename Kernel, typename T>
346 return {cast<Kernel>(segment.source()), cast<Kernel>(segment.target())};
347}
348
349} //namespace
350}
351}
352}
353
354#endif
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
bool operator<(const MDMFLengthAttribute &x, const MDMFLengthAttribute &y)
The namespace for all OGDF objects.