33#ifdef OGDF_INCLUDE_CGAL
35# ifndef OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE
36# define OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE false
49# include <CGAL/Segment_2.h>
50# include <boost/variant.hpp>
58template<
typename kernel>
59using LineSegment_t = CGAL::Segment_2<kernel>;
65template<
typename kernel>
66inline typename kernel::FT angle(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
69 return geometry::angle(l1.to_vector(), l2.to_vector());
76template<
typename kernel>
77inline typename kernel::FT full_angle(
const LineSegment_t<kernel>& l1,
78 const LineSegment_t<kernel>& l2) {
81 return full_angle(l1.to_vector(), l2.to_vector());
84template<
typename kernel>
85inline bool turn(
const LineSegment_t<kernel>& ls,
const Line_t<kernel>& l) {
86 return turn(ls.to_vector(), l.to_vector());
89template<
typename kernel>
90inline bool left_turn(
const LineSegment_t<kernel>& ls,
const LineSegment_t<kernel>& l) {
91 return left_turn(ls.to_vector(), l.to_vector());
94template<
typename kernel>
95inline bool right_turn(
const LineSegment_t<kernel>& ls,
const LineSegment_t<kernel>& l) {
96 return right_turn(ls.to_vector(), l.to_vector());
99template<
typename kernel>
100inline bool turn(
const LineSegment_t<kernel>& ls,
const Point_t<kernel>& p) {
101 return turn(ls.supporting_line(), p);
104template<
typename kernel>
105inline bool left_turn(
const LineSegment_t<kernel>& ls,
const Point_t<kernel>& p) {
106 return left_turn(ls.supporting_line(), p);
109template<
typename kernel>
110inline bool right_turn(
const LineSegment_t<kernel>& ls,
const Point_t<kernel>& p) {
111 return right_turn(ls.supporting_line(), p);
114template<
typename kernel>
115inline typename kernel::FT squared_convex_parameter_directed(
const LineSegment_t<kernel>& ls,
116 const Point_t<kernel>& p) {
118 return (ls.source() - p).squared_length() / ls.to_vector().squared_length();
121template<
typename kernel>
122inline typename kernel::FT squared_convex_parameter(
const LineSegment_t<kernel>& ls,
123 const Point_t<kernel>& point) {
125 return std::max(squared_convex_parameter_directed(ls, point),
126 squared_convex_parameter_directed(ls.opposite(), point));
129template<
typename kernel>
130inline Point_t<kernel> rel_point_at(
const LineSegment_t<kernel>& ls,
const typename kernel::FT l) {
132 return ls.source() + (ls.to_vector() * l);
135template<
typename kernel>
136inline typename kernel::FT value_at(
const LineSegment_t<kernel>& ls,
const typename kernel::FT x) {
137 if (ls.supporting_line().is_vertical()) {
138 return std::numeric_limits<typename kernel::FT>::infinity();
140 return ls.supporting_line().y_at_x(x);
144template<
typename kernel>
145inline typename kernel::FT value_at(
const LineSegment_t<kernel>& ls,
const Point_t<kernel>& p) {
146 if (ls.supporting_line().is_vertical()) {
149 return ls.supporting_line().y_at_x(p.x());
153template<
bool closed,
typename kernel>
154inline bool is_on(
const LineSegment_t<kernel>& ls,
const Point_t<kernel>& point) {
156 return ls.has_on(point) && ls.target() != point;
158 return ls.has_on(point);
162template<
typename kernel>
163inline bool is_on(
const LineSegment_t<kernel>& ls,
const Point_t<kernel>& point) {
164 return is_on<false>(ls, point);
167template<
typename kernel>
168inline bool overlapping(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
169 const bool parallel = CGAL::parallel(l1.supporting_line(), l2.supporting_line());
170 const bool on_l1 = is_on<true>(l1, l2.source()) || is_on<true>(l1, l2.target());
171 const bool on_l2 = is_on<true>(l2, l1.source()) || is_on<true>(l2, l1.target());
172 return (on_l1 || on_l2) && parallel;
175template<
typename kernel>
176inline bool overlapping(
const LineSegment_t<kernel>& ls,
const Line_t<kernel>& line) {
177 const bool parallel = parallel(ls.supporting_line(), line);
180 const bool on_line = line.has_on(ls.source()) || line.has_on(ls.target());
181 return on_line && parallel;
184template<
typename kernel>
185inline bool do_intersect_wo_targets(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
186 return CGAL::do_intersect(l1, l2) && !l1.has_on(l2.target()) && !l2.has_on(l1.target());
189template<
typename kernel>
190inline bool do_intersect_open(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
191 return CGAL::do_intersect(l1, l2) && !l1.has_on(l2.target()) && !l2.has_on(l1.target())
192 && !l1.has_on(l2.source()) && !l2.has_on(l1.source());
195template<
typename kernel>
196inline bool do_intersect_wo_target(
const LineSegment_t<kernel>& l1,
const Line_t<kernel>& l) {
197 return CGAL::do_intersect(l1, l) && !l.has_on(l1.target());
200template<
typename kernel>
201inline bool do_intersect_wo_target(
const Line_t<kernel>& l,
const LineSegment_t<kernel>& l1) {
202 return geometry::do_intersect_wo_target(l1, l);
205template<
typename kernel>
206inline bool do_intersect_wo_target(
const LineSegment_t<kernel>& l1,
const Ray_t<kernel>&
r) {
207 return CGAL::do_intersect(l1,
r) && !
r.has_on(l1.target());
210template<
typename kernel>
211inline bool do_intersect_wo_target(
const Ray_t<kernel>&
r,
const LineSegment_t<kernel>& l1) {
212 return geometry::do_intersect_wo_target(l1,
r);
215template<
typename kernel>
216inline bool have_common_endpoints(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
217 return l1.source() == l2.source() || l1.source() == l2.target() || l1.target() == l1.source()
218 || l1.target() == l2.target();
221template<
typename kernel>
222inline Point_t<kernel> get_common_endpoint(
const LineSegment_t<kernel>& l1,
223 const LineSegment_t<kernel>& l2) {
226 if (l1.source() == l2.source() || l1.source() == l2.target()) {
233template<
class T,
class Variant>
234auto get_if(Variant* v) ->
decltype(std::get_if<T>(v)) {
235 return std::get_if<T>(v);
238template<
class T,
class Variant>
239auto get_if(Variant* v) ->
decltype(boost::get<T>(v)) {
240 return boost::get<T>(v);
243template<
typename kernel>
244inline Point_t<kernel> intersect(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
248 auto result = CGAL::intersection(l1, l2);
250 return Point_t<kernel>(std::numeric_limits<double>::max(),
251 std::numeric_limits<double>::max());
255 if (
auto s = get_if<LineSegment_t<kernel>>(&*result)) {
257 }
else if (
auto p = get_if<Point_t<kernel>>(&*result)) {
266template<
typename kernel>
267inline Point_t<kernel> intersect(
const LineSegment_t<kernel>& l1,
const Line_t<kernel>& l2) {
270 auto result = CGAL::intersection(l1, l2);
272 return Point_t<kernel>(std::numeric_limits<unsigned int>::max(),
273 std::numeric_limits<unsigned int>::max());
277 if (
auto s = get_if<LineSegment_t<kernel>>(&*result)) {
279 }
else if (
auto p = get_if<Point_t<kernel>>(&*result)) {
287template<
typename kernel>
288inline Point_t<kernel> intersect(
const Line_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
289 return intersect(l2, l1);
292template<
typename kernel>
293inline Point_t<kernel> intersect(
const LineSegment_t<kernel>& l1,
const Ray_t<kernel>&
r) {
297 auto result = CGAL::intersection(l1,
r);
299 return Point_t<kernel>(std::numeric_limits<unsigned int>::max(),
300 std::numeric_limits<unsigned int>::max());
305 if (
auto s = get_if<LineSegment_t<kernel>>(&*result)) {
307 }
else if (
auto p = get_if<Point_t<kernel>>(&*result)) {
310 OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE || is_on<true>(l1, intersection));
311 OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE ||
r.has_on(intersection));
315template<
typename kernel>
316inline Point_t<kernel> intersect(
const Ray_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
317 return intersect(l2, l1);
320template<
typename kernel>
321inline typename kernel::FT order_along_seg(
const LineSegment_t<kernel>& reference
324 const LineSegment_t<kernel>& l_1,
const LineSegment_t<kernel>& l_2) {
325 auto cross = [&](
const Vector_t<kernel>& v_1,
const Vector_t<kernel>& v_2) {
326 return v_1.x() * v_2.y() - v_1.y() * v_2.x();
329 auto s = reference.target() - reference.source();
330 auto r_1 = l_1.target() - l_1.source();
331 auto r_2 = l_2.target() - l_2.source();
333 auto c_1 = cross(reference.source() - l_1.source(), s);
334 auto c_2 = cross(reference.source() - l_2.source(), s);
336 auto d_1 = cross(r_1, s);
337 auto d_2 = cross(r_2, s);
339 return c_1 * d_2 - c_2 * d_1;
342template<
typename kernel>
343void serialize(
const LineSegment_t<kernel>& ls, std::ostream& os) {
344 serialize(ls.source(), os);
345 serialize(ls.target(), os);
348template<
typename kernel>
349inline bool operator<(
const LineSegment_t<kernel>& l1,
const LineSegment_t<kernel>& l2) {
350 return l1.source() < l2.source() || (l1.source() == l2.source() && l1.target() < l2.target());
353template<
typename Kernel,
typename T>
354LineSegment_t<Kernel> cast(
const LineSegment_t<T>& segment) {
355 return {cast<Kernel>(segment.source()), cast<Kernel>(segment.target())};
void intersection(Graph &G1, const Graph &G2, const NodeArray< node > &nodeMap, bool directed=false)
Computes the intersection of G1 and G2.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
bool operator<(const MDMFLengthAttribute &x, const MDMFLengthAttribute &y)
The namespace for all OGDF objects.