Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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.