33#ifdef OGDF_INCLUDE_CGAL
37# ifdef OGDF_GEOMETRIC_CR_MIN_DEBUG
39# define OGDF_GEOMETRIC_BD_ECHO(x) Logger::slout() << "[BD] " << x << std::endl;
41# define OGDF_GEOMETRIC_BD_ECHO(x)
49template<
typename Kernel,
bool parallel = false>
52 using Point = geometry::Point_t<Kernel>;
54 using ExactKernel = CGAL::Simple_cartesian<CGAL::Gmpq>;
56 using BD = graph::BloatedDualGraph<Kernel>;
57 using Node =
typename BD::Node;
58 using Edge =
typename BD::Edge;
61 inline bool consider_equal(
const Point& p,
const Point&
q)
const {
return p ==
q; }
64 if (reference.has_on(p)) {
66 }
else if (
consider_equal(p, reference.supporting_line().projection(p))) {
67 auto ex_p = geometry::cast<ExactKernel>(p);
68 auto ex_segment = geometry::cast<ExactKernel>(reference);
80 std::set<std::pair<unsigned int, unsigned int>> seen;
90 if (seen.find({pair.seg_a, pair.seg_b}) == seen.end()
91 && seen.find({pair.seg_b, pair.seg_a}) == seen.end()) {
93 if (pair.seg_a != pair.seg_b) {
102 }
else if (pair.is_target) {
105 }
else if (geometry::have_common_endpoints(
seg_a,
seg_b)) {
122 auto compare = [&](
const unsigned int a,
const unsigned int b) {
128 auto d_b = CGAL::squared_distance(
segments[i].source(),
137 std::sort(
is.begin(),
is.end(), compare);
139 std::sort(
is.begin(),
is.end(), compare);
175 for (
unsigned int j = 0;
j
199 if (segment ==
opp) {
224 [&](
const unsigned int a,
const unsigned int b) {
225 auto& seg_a = segments[intersecting_segments[a].opposite(segment)];
226 auto& seg_b = segments[intersecting_segments[b].opposite(segment)];
230 if (is_proper_left_turn(segments[segment], seg_a.source())
231 || segments[segment].source() == seg_a.target()) {
240 return geometry::right_turn(
seg_a.to_vector() *
sign_a,
248 [&](
const unsigned int a,
const unsigned int b) {
249 auto& seg_a = segments[intersecting_segments[a].opposite(segment)];
250 auto& seg_b = segments[intersecting_segments[b].opposite(segment)];
255 if (is_proper_right_turn(segments[segment], seg_a.source())
256 || segments[segment].source() == seg_a.target()) {
265 return geometry::left_turn(
seg_a.to_vector() *
sign_a,
288 if (
li.left_is_valid()
289 && (
bd.intersecting_segments[
li.left_intersection_ids[0]].is_source
290 ||
bd.intersecting_segments[
li.left_intersection_ids[0]].is_target)) {
309 if (
li.left_is_valid()) {
315 for (
unsigned int i = 0; i < 2; ++i) {
317 bd.intersecting_segments[
li.left_intersection_ids[i]].opposite(
ref_seg);
320 bd.get_intersection_point(
li))
321 && geometry::left_turn(
bd.segments[
ref_seg],
335 bd.get_intersection_point(
li))) {
341 bd.add_edge(
u1,
v1,
true);
350 bd.get_intersection_point(
li))) {
356 bd.add_edge(
u2,
v2,
true);
362 bd.add_edge(
u1,
v1,
true);
364 auto id =
li.right_intersection_ids[0];
368 unsigned int opp =
bd.intersecting_segments[id].opposite(
ref_seg);
375 bd.add_edge(
u1,
v1,
true);
378 auto id =
li.right_intersection_ids[1];
382 unsigned int opp =
bd.intersecting_segments[id].opposite(
ref_seg);
389 bd.add_edge(
u1,
v1,
true);
392 if (
li.right_is_valid()) {
395 for (
unsigned int i = 0; i < 2; ++i) {
397 bd.intersecting_segments[
li.right_intersection_ids[i]].opposite(
ref_seg);
400 bd.get_intersection_point(
li))
401 && geometry::right_turn(
bd.segments[
ref_seg],
414 bd.get_intersection_point(
li))) {
420 bd.add_edge(
u1,
v1,
true);
429 bd.get_intersection_point(
li))) {
435 bd.add_edge(
u2,
v2,
true);
440 bd.add_edge(
u1,
v1,
true);
443 auto id =
li.left_intersection_ids[0];
447 unsigned int opp =
bd.intersecting_segments[id].opposite(
ref_seg);
454 bd.add_edge(
u1,
v1,
true);
456 auto id =
li.left_intersection_ids[1];
460 unsigned int opp =
bd.intersecting_segments[id].opposite(
ref_seg);
467 bd.add_edge(
u1,
v1,
true);
477# pragma omp parallel for num_threads(nof_threads)
478 for (
unsigned int i = 0; i <
bd.segments.size(); ++i) {
479 for (
unsigned int j = 0;
j <
bd.segment_to_intersections[i].size(); ++
j) {
497 void construct(
BD&
bd) {
502 for (
unsigned int i = 0; i <
bd.segments.size(); ++i) {
506 bd.intersecting_segments.push_back(s);
510 bd.intersecting_segments.push_back(s);
519 bd.segment_to_intersections.resize(
bd.segments.size());
520 for (
unsigned int i = 0; i <
bd.segments.size(); ++i) {
521 clean_up(i,
bd.segments,
bd.intersecting_segments,
bd.intersections,
524 ||
bd.segment_to_intersections[i].size() >= 1);
527 for (
unsigned int i = 0; i <
bd.segment_to_intersections.size(); ++i) {
528 auto&
is =
bd.segment_to_intersections[i];
530 for (
unsigned int j = 0;
j <
is.size(); ++
j) {
545 set_pos(x.left_intersection_ids[0]);
546 set_pos(x.left_intersection_ids[1]);
547 set_pos(x.right_intersection_ids[0]);
548 set_pos(x.right_intersection_ids[1]);
552 bd.segm_to_node_range.reserve(
bd.intersections.size());
553 bd.edges.reserve(3 *
bd.intersections.size());
554 bd.node_to_segment.reserve(
bd.intersections.size());
558 for (
unsigned int i = 0; i <
bd.segments.size(); ++i) {
559 bd.segm_to_node_range.push_back(
bd.number_of_nodes());
561 auto&
is =
bd.segment_to_intersections[i];
563 for (
unsigned int j = 0;
j + 1 <
is.size(); ++
j) {
564 Node left =
bd.add_node(i);
565 Node right =
bd.add_node(i);
566 bd.add_edge(left, right,
false);
569 bd.segm_to_node_range.push_back(
bd.number_of_nodes());
574 static std::vector<Segment>
compute_drawing(graph::BloatedDualGraph<Kernel>&
bd) {
578 for (
unsigned int i = 0; i <
bd.segments.size(); ++i) {
579 auto left_dir = geometry::normalize(
bd.segments[i].to_vector())
580 .perpendicular(CGAL::COUNTERCLOCKWISE);
582 geometry::normalize(
bd.segments[i].to_vector()).perpendicular(CGAL::CLOCKWISE);
583 if (i >=
bd.segment_to_intersections.size()) {
587 auto&
is =
bd.segment_to_intersections[i];
592 Point last =
bd.intersections[
is[0].intersection_id()];
594 for (
unsigned int j = 0;
j + 1 <
is.size();
j =
j + 1) {
599 auto left =
bd.segm_to_node_range[i] + 2 *
j;
600 auto right =
bd.segm_to_node_range[i] + 2 *
j + 1;
603 CGAL::sqrt(CGAL::to_double(CGAL::squared_distance(
current,
mid))) / 10, 0.0);
616 for (
unsigned int v = 0; v <
bd.number_of_nodes(); ++v) {
Contains logging functionality.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.