Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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 
50 namespace ogdf {
51 namespace internal {
52 namespace gcm {
53 namespace geometry {
54 using namespace tools;
55 
56 template<typename kernel>
57 using 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  * */
63 template<typename kernel>
64 inline 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  * */
74 template<typename kernel>
75 inline typename kernel::FT full_angle(const LineSegment_t<kernel>& l1,
76  const LineSegment_t<kernel>& l2) {
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 
82 template<typename kernel>
83 inline bool turn(const LineSegment_t<kernel>& ls, const Line_t<kernel>& l) {
84  return turn(ls.to_vector(), l.to_vector());
85 }
86 
87 template<typename kernel>
88 inline 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 
92 template<typename kernel>
93 inline 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 
97 template<typename kernel>
98 inline bool turn(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
99  return turn(ls.supporting_line(), p);
100 }
101 
102 template<typename kernel>
103 inline bool left_turn(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
104  return left_turn(ls.supporting_line(), p);
105 }
106 
107 template<typename kernel>
108 inline bool right_turn(const LineSegment_t<kernel>& ls, const Point_t<kernel>& p) {
109  return right_turn(ls.supporting_line(), p);
110 }
111 
112 template<typename kernel>
113 inline 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 
119 template<typename kernel>
120 inline 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 
127 template<typename kernel>
128 inline 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 
133 template<typename kernel>
134 inline typename kernel::FT value_at(const LineSegment_t<kernel>& ls, const typename kernel::FT x) {
135  if (ls.supporting_line().is_vertical()) {
137  } else {
138  return ls.supporting_line().y_at_x(x);
139  }
140 }
141 
142 template<typename kernel>
143 inline 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 
151 template<bool closed, typename kernel>
152 inline 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 
160 template<typename kernel>
161 inline bool is_on(const LineSegment_t<kernel>& ls, const Point_t<kernel>& point) {
162  return is_on<false>(ls, point);
163 }
164 
165 template<typename kernel>
166 inline 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 
173 template<typename kernel>
174 inline 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 
182 template<typename kernel>
183 inline bool do_intersect_wo_targets(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
184  return CGAL::do_intersect(l1, l2) && !l1.has_on(l2.target()) && !l2.has_on(l1.target());
185 }
186 
187 template<typename kernel>
188 inline bool do_intersect_open(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
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 
193 template<typename kernel>
194 inline bool do_intersect_wo_target(const LineSegment_t<kernel>& l1, const Line_t<kernel>& l) {
195  return CGAL::do_intersect(l1, l) && !l.has_on(l1.target());
196 }
197 
198 template<typename kernel>
199 inline bool do_intersect_wo_target(const Line_t<kernel>& l, const LineSegment_t<kernel>& l1) {
200  return geometry::do_intersect_wo_target(l1, l);
201 }
202 
203 template<typename kernel>
204 inline bool do_intersect_wo_target(const LineSegment_t<kernel>& l1, const Ray_t<kernel>& r) {
205  return CGAL::do_intersect(l1, r) && !r.has_on(l1.target());
206 }
207 
208 template<typename kernel>
209 inline bool do_intersect_wo_target(const Ray_t<kernel>& r, const LineSegment_t<kernel>& l1) {
210  return geometry::do_intersect_wo_target(l1, r);
211 }
212 
213 template<typename kernel>
214 inline bool have_common_endpoints(const LineSegment_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
215  return l1.source() == l2.source() || l1.source() == l2.target() || l1.target() == l1.source()
216  || l1.target() == l2.target();
217 }
218 
219 template<typename kernel>
220 inline Point_t<kernel> get_common_endpoint(const LineSegment_t<kernel>& l1,
221  const LineSegment_t<kernel>& l2) {
222  OGDF_ASSERT(have_common_endpoints(l1, 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 
231 template<typename kernel>
232 inline 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 
255 template<typename kernel>
256 inline 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 
277 template<typename kernel>
278 inline Point_t<kernel> intersect(const Line_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
279  return intersect(l2, l1);
280 }
281 
282 template<typename kernel>
283 inline 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  }
301  OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE || is_on<true>(l1, intersection));
302  OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE || r.has_on(intersection));
303  return intersection;
304 }
305 
306 template<typename kernel>
307 inline Point_t<kernel> intersect(const Ray_t<kernel>& l1, const LineSegment_t<kernel>& l2) {
308  return intersect(l2, l1);
309 }
310 
311 template<typename kernel>
312 inline typename kernel::FT order_along_seg(const LineSegment_t<kernel>& reference
313 
314  ,
315  const LineSegment_t<kernel>& l_1, const LineSegment_t<kernel>& l_2) {
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 
333 template<typename kernel>
334 void serialize(const LineSegment_t<kernel>& ls, std::ostream& os) {
335  serialize(ls.source(), os);
336  serialize(ls.target(), os);
337 }
338 
339 template<typename kernel>
340 inline 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 
344 template<typename Kernel, typename T>
345 LineSegment_t<Kernel> cast(const LineSegment_t<T>& segment) {
346  return {cast<Kernel>(segment.source()), cast<Kernel>(segment.target())};
347 }
348 
349 } //namespace
350 }
351 }
352 }
353 
354 #endif
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
math.h
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::matching_blossom::infinity
TWeight infinity()
Helper function to get the maximum value for a given weight type.
Definition: utils.h:46
ogdf::embedder::operator<
bool operator<(const MDMFLengthAttribute &x, const MDMFLengthAttribute &y)
Definition: MDMFLengthAttribute.h:90
Point.h
Vector.h
r
int r[]
Definition: hierarchical-ranking.cpp:13
Ray.h
Line.h