33 #ifdef OGDF_INCLUDE_CGAL
38 # include <functional>
42 # include <CGAL/Algebraic_kernel_for_circles_2_2.h>
43 # include <CGAL/Boolean_set_operations_2.h>
44 # include <CGAL/Circle_2.h>
45 # include <CGAL/Circular_kernel_2.h>
46 # include <CGAL/General_polygon_set_2.h>
47 # include <CGAL/Gps_circle_segment_traits_2.h>
54 using namespace tools;
56 template<
typename kernel>
57 using Circle_t = CGAL::Circle_2<kernel>;
59 template<
typename kernel>
60 typename CGAL::Circular_kernel_2<kernel, CGAL::Algebraic_kernel_for_circles_2_2<typename kernel::FT>>::Point_2
61 convert(
const typename kernel::Point_2& p) {
62 return {p.x(), p.y()};
65 template<
typename kernel>
66 typename CGAL::Circular_kernel_2<kernel, CGAL::Algebraic_kernel_for_circles_2_2<typename kernel::FT>>::Circle_2
67 convert(
const Circle_t<kernel>& circle) {
68 return {{circle.center().x(), circle.center().y()}, circle.squared_radius()};
71 template<
typename kernel>
72 typename CGAL::Circular_kernel_2<kernel, CGAL::Algebraic_kernel_for_circles_2_2<typename kernel::FT>>::Line_2
73 convert(
const geometry::Line_t<kernel>& line) {
74 return {line.a(), line.b(), line.c()};
77 template<
typename kernel>
78 typename CGAL::Circular_kernel_2<kernel, CGAL::Algebraic_kernel_for_circles_2_2<typename kernel::FT>>::Segment_2
79 convert(
const geometry::LineSegment_t<kernel>& ls) {
80 return {convert<kernel>(ls.source()), convert<kernel>(ls.target())};
83 template<
typename kernel>
84 bool do_intersect(
const Circle_t<kernel>& circle,
const LineSegment_t<kernel>& ls) {
85 if (circle.has_on_boundary(ls.source())) {
87 }
else if (circle.has_on_unbounded_side(ls.source()) && circle.has_on_bounded_side(ls.target())) {
89 }
else if (circle.has_on_unbounded_side(ls.target()) && circle.has_on_bounded_side(ls.source())) {
96 template<
typename kernel>
97 void intersect(
const Circle_t<kernel>& circle,
const LineSegment_t<kernel>& ls,
98 Point_t<kernel>& intersection_1, Point_t<kernel>& intersection_2) {
99 using AKernel = CGAL::Algebraic_kernel_for_circles_2_2<typename kernel::FT>;
100 using CKernel = CGAL::Circular_kernel_2<kernel, AKernel>;
101 using CCircle =
typename CKernel::Circle_2;
102 using CLine =
typename CKernel::Line_2;
105 auto c = convert(circle);
106 auto l = convert(ls);
107 typename CKernel::Line_arc_2 line_arc(l);
112 std::vector<IS_Result> is;
113 CGAL::intersection(c, line_arc, std::back_inserter(is));
115 using R = std::pair<CGAL::Circular_arc_point_2<CKernel>,
unsigned int>;
118 auto is_1 = boost::get<R>(&is[0]);
119 intersection_1 = {CGAL::to_double(is_1->first.x()), CGAL::to_double(is_1->first.y())};
122 auto is_2 = boost::get<R>(&is[1]);
123 intersection_2 = {CGAL::to_double(is_2->first.x()), CGAL::to_double(is_2->first.y())};
127 template<
typename kernel>
128 void intersect(
const Circle_t<kernel>& c1,
const Circle_t<kernel>& c2,
129 Point_t<kernel>& intersection_1, Point_t<kernel>& intersection_2) {
130 using AKernel = CGAL::Algebraic_kernel_for_circles_2_2<typename kernel::FT>;
131 using CKernel = CGAL::Circular_kernel_2<kernel, AKernel>;
132 using CCircle =
typename CKernel::Circle_2;
134 auto cc1 = convert(c1);
135 auto cc2 = convert(c2);
139 using R = std::pair<CGAL::Circular_arc_point_2<CKernel>,
unsigned int>;
141 std::vector<IS_Result> is;
142 CGAL::intersection(cc1, cc2, std::back_inserter(is));
145 auto is_1 = boost::get<R>(&is[0]);
147 intersection_1 = {CGAL::to_double(is_1->first.x()), CGAL::to_double(is_1->first.y())};
152 auto is_2 = boost::get<R>(&is[1]);
154 intersection_2 = {CGAL::to_double(is_2->first.x()), CGAL::to_double(is_2->first.y())};
159 template<
typename kernel>
160 bool contains(
const Circle_t<kernel>& c,
const Point_t<kernel>& p) {
161 return c.has_on_boundary(p) || c.has_on_bounded_side(p);
164 template<
typename kernel>
165 class CircleOperation_t {
167 using Point = Point_t<kernel>;
168 using LineSegment = LineSegment_t<kernel>;
169 using Circle = Circle_t<kernel>;
173 void intersect_pair(
const Circle& c_1,
const Circle& c_2, F&& f)
const {
174 if (CGAL::do_intersect(c_1, c_2)) {
176 geometry::intersect(c_1, c_2, is_1, is_2);
185 const Circle& circle_1;
186 const Circle& circle_2;
188 CircleOperation_t(
const Circle& circle1,
const Circle& circle2)
189 : circle_1(circle1), circle_2(circle2) {
193 virtual ~CircleOperation_t() {
196 virtual void intersect(
const LineSegment&, std::function<
void(
const Point)>&&)
const = 0;
197 virtual void intersect(
const CircleOperation_t<kernel>&,
198 std::function<
void(
const Point)>&&)
const = 0;
199 virtual bool do_intersect(
const LineSegment_t<kernel>&)
const = 0;
200 virtual bool contains(
const Point_t<kernel>&)
const = 0;
201 virtual bool contains(
const Circle& other,
const Point& p)
const = 0;
203 friend std::ostream&
operator<<(std::ostream& os,
const CircleOperation_t<kernel>& c) {
204 os << c.circle_1 <<
" " << c.circle_2;
209 template<
typename kernel>
210 class IntersectingCircles_t :
public CircleOperation_t<kernel> {
212 using CircleOperation = CircleOperation_t<kernel>;
213 using parent = CircleOperation;
214 using ICOp = IntersectingCircles_t<kernel>;
215 using Circle = Circle_t<kernel>;
216 using LineSegment = LineSegment_t<kernel>;
217 using Point = Point_t<kernel>;
220 void intersect_circle(
const LineSegment& ls,
const Circle& c,
const Circle& other, F&& f)
const {
221 if (geometry::do_intersect(c, ls)) {
223 geometry::intersect(c, ls, is_1, is_2);
225 if (contains(other, is_1)) {
228 if (is_1 != is_2 && contains(other, is_2) && is_on(ls, is_2)) {
235 bool contains(
const Circle& other,
const Point& p)
const {
236 return geometry::contains(other, p);
239 IntersectingCircles_t(
const Circle& circle_1,
const Circle& circle_2)
240 : parent(circle_1, circle_2) {
244 void intersect(
const CircleOperation& op, std::function<
void(
const Point)>&& f)
const {
245 parent::intersect_pair(parent::circle_1, op.circle_1, [&](
const Point& p) {
246 if (contains(parent::circle_2, p) && op.contains(op.circle_2, p)) {
251 parent::intersect_pair(parent::circle_1, op.circle_2, [&](
const Point& p) {
252 if (contains(parent::circle_2, p) && op.contains(op.circle_1, p)) {
257 parent::intersect_pair(parent::circle_2, op.circle_1, [&](
const Point& p) {
258 if (contains(parent::circle_1, p) && op.contains(op.circle_2, p)) {
263 parent::intersect_pair(parent::circle_2, op.circle_2, [&](
const Point& p) {
264 if (contains(parent::circle_1, p) && op.contains(op.circle_1, p)) {
269 parent::intersect_pair(parent::circle_1, parent::circle_2, [&](
const Point& p) {
270 if (op.contains(p)) {
275 parent::intersect_pair(op.circle_1, op.circle_2, [&](
const Point& p) {
281 if (op.contains(parent::circle_1.center()) && contains(parent::circle_1.center())) {
282 f(parent::circle_1.center());
284 if (op.contains(op.circle_1.center()) && contains(op.circle_1.center())) {
285 f(op.circle_1.center());
289 void intersect(
const LineSegment& ls, std::function<
void(
const Point)>&& f)
const {
290 intersect_circle(ls, parent::circle_1, parent::circle_2, f);
291 intersect_circle(ls, parent::circle_2, parent::circle_1, f);
294 bool do_intersect(
const LineSegment& ls)
const {
295 return geometry::do_intersect(parent::circle_1, ls)
296 && geometry::do_intersect(parent::circle_2, ls);
299 bool contains(
const Point& p)
const {
300 return geometry::contains(parent::circle_1, p) && geometry::contains(parent::circle_2, p);
304 template<
typename kernel>
305 class CombinedCircles_t :
public CircleOperation_t<kernel> {
307 using CircleOperation = CircleOperation_t<kernel>;
308 using parent = CircleOperation;
309 using CCOp = CombinedCircles_t<kernel>;
310 using Circle = Circle_t<kernel>;
311 using LineSegment = LineSegment_t<kernel>;
312 using Point = Point_t<kernel>;
315 void intersect_circle(
const LineSegment& ls,
const Circle& c, F&& f)
const {
316 if (geometry::do_intersect(c, ls)) {
318 geometry::intersect(c, ls, is_1, is_2);
320 if (is_1 != is_2 && is_on(ls, is_2)) {
327 CombinedCircles_t(
const Circle& circle_1,
const Circle& circle_2) : parent(circle_1, circle_2) {
331 void intersect(
const LineSegment& ls, std::function<
void(
const Point)>&& f)
const {
332 intersect_circle(ls, parent::circle_1, f);
333 intersect_circle(ls, parent::circle_2, f);
337 void intersect(
const CircleOperation& op, std::function<
void(
const Point)>&& f)
const {
338 parent::intersect_pair(parent::circle_1, op.circle_1, f);
339 parent::intersect_pair(parent::circle_1, op.circle_2, f);
340 parent::intersect_pair(parent::circle_2, op.circle_1, f);
341 parent::intersect_pair(parent::circle_2, op.circle_2, f);
343 parent::intersect_pair(parent::circle_1, parent::circle_2, [&](
const Point& p) {
344 if (op.contains(p)) {
348 parent::intersect_pair(op.circle_1, op.circle_2, [&](
const Point& p) {
354 if (op.contains(parent::circle_1.center())) {
355 f(parent::circle_1.center());
358 if (op.contains(parent::circle_2.center())) {
359 f(parent::circle_1.center());
362 if (contains(op.circle_1.center())) {
363 f(op.circle_1.center());
366 if (contains(op.circle_2.center())) {
367 f(op.circle_2.center());
371 bool do_intersect(
const LineSegment& ls)
const {
372 return geometry::do_intersect(parent::circle_1, ls)
373 || geometry::do_intersect(parent::circle_2, ls);
376 bool contains(
const Circle&,
const Point&)
const {
return true; }
378 bool contains(
const Point& p)
const {
379 return geometry::contains(parent::circle_1, p) || geometry::contains(parent::circle_2, p);
383 template<
typename Kernel>
384 typename CGAL::Gps_circle_segment_traits_2<Kernel>::General_polygon_2 construct_polygon_from_circle(
385 const Circle_t<Kernel>& circle) {
386 using Traits_2 = CGAL::Gps_circle_segment_traits_2<Kernel>;
387 using Polygon_2 =
typename Traits_2::General_polygon_2;
388 using Curve_2 =
typename Traits_2::Curve_2;
389 using X_monotone_curve_2 =
typename Traits_2::X_monotone_curve_2;
393 Curve_2 curve(circle);
394 std::list<CGAL::Object> objects;
395 traits.make_x_monotone_2_object()(curve, std::back_inserter(objects));
399 X_monotone_curve_2 arc;
400 std::list<CGAL::Object>::iterator iter;
401 for (iter = objects.begin(); iter != objects.end(); ++iter) {
402 CGAL::assign(arc, *iter);