33 #ifdef OGDF_INCLUDE_CGAL
42 # include <CGAL/Exact_predicates_exact_constructions_kernel.h>
44 # ifndef OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE
45 # define OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE false
55 Intersection(
unsigned int _seg_a,
unsigned int _seg_b) : seg_a(_seg_a), seg_b(_seg_b) {
59 unsigned int seg_a = -1;
60 unsigned int seg_b = -1;
61 unsigned int pos_on_a = -1;
62 unsigned int pos_on_b = -1;
65 bool is_source =
false;
66 bool is_target =
false;
68 bool is_incident(
const unsigned int segment)
const {
69 return seg_a == segment || seg_b == segment;
72 unsigned int opposite(
const unsigned int segment)
const {
73 if (seg_a == segment) {
80 unsigned int pos(
const unsigned int segment)
const {
81 if (seg_a == segment) {
91 template<
typename Kernel,
bool OPEN = true>
92 class PlanarSubdivision {
94 using LineSegment = geometry::LineSegment_t<Kernel>;
95 using Point = geometry::Point_t<Kernel>;
96 using Polygon = geometry::Polygon_t<Kernel>;
97 using Line = geometry::Line_t<Kernel>;
98 using Ray = geometry::Ray_t<Kernel>;
99 using Direction = geometry::Direction_t<Kernel>;
101 using ExactKernel = CGAL::Exact_predicates_exact_constructions_kernel;
102 using ExactLineSegment = geometry::LineSegment_t<ExactKernel>;
103 using ExactPoint = geometry::Point_t<ExactKernel>;
106 enum class EventType { Start, End };
110 unsigned int segment_id;
113 Event(Point _p,
unsigned int _id, EventType _ev) : p(_p), segment_id(_id), event(_ev) {
120 using LCGEdge = std::tuple<unsigned int, unsigned int, unsigned int>;
126 template<
typename IntersectionEvent>
127 void sweep(std::vector<LineSegment>& segments, IntersectionEvent&& intersection_event) {
128 std::vector<unsigned int> segment_to_active(segments.size(), -1);
129 std::vector<unsigned int> active;
131 auto add_to_active = [&](
unsigned int segment_id) {
132 segment_to_active[segment_id] = active.size();
133 active.push_back(segment_id);
136 auto remove_from_active = [&](
unsigned int segment_id) {
137 unsigned int active_id = segment_to_active[segment_id];
138 std::swap(active[active_id], active.back());
139 segment_to_active[active[active_id]] = active_id;
141 segment_to_active[segment_id] = -1;
143 std::vector<Event> events;
144 events.reserve(2 * segments.size());
147 for (
unsigned int i = 0; i < segments.size(); ++i) {
148 Event ev_start(std::min(segments[i].source(), segments[i].target()), i, EventType::Start);
149 Event ev_end(std::max(segments[i].source(), segments[i].target()), i, EventType::End);
151 events.push_back(ev_start);
152 events.push_back(ev_end);
156 std::sort(events.begin(), events.end(), [&](
const Event& a,
const Event& b) ->
bool {
157 return a.p < b.p || (a.p == b.p && a.event == EventType::Start);
161 for (
const Event& e : events) {
162 auto& new_segment = segments[e.segment_id];
163 if (e.event == EventType::Start) {
164 for (
unsigned int active_id : active) {
166 auto& active_segment = segments[active_id];
168 if (OPEN && geometry::do_intersect_open(new_segment, active_segment)) {
169 intersection_event(e.segment_id, active_id);
172 if (!OPEN && CGAL::do_intersect(new_segment, active_segment)) {
173 intersection_event(e.segment_id, active_id);
176 add_to_active(e.segment_id);
178 remove_from_active(e.segment_id);
184 void subdivision(std::vector<LineSegment>& segment,
185 std::vector<Point>& intersections
187 std::vector<LCGEdge>& edge_list) {
189 std::vector<std::vector<unsigned int>> intersections_of_segment(segment.size());
193 auto intersection_event = [&](
unsigned int seg_1,
unsigned int seg_2) {
196 unsigned int v = intersections.size();
198 intersections_of_segment[seg_1].push_back(v);
199 intersections_of_segment[seg_2].push_back(v);
201 Point is = geometry::intersect(segment[seg_1], segment[seg_2]);
202 intersections.push_back(is);
204 OGDF_ASSERT(CGAL::squared_distance(segment[seg_1], is) < 1);
205 OGDF_ASSERT(CGAL::squared_distance(segment[seg_2], is) < 1);
207 OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE || segment[seg_1].has_on(is));
208 OGDF_ASSERT(OGDF_GEOMETRIC_INEXACT_NUMBER_TYPE || segment[seg_2].has_on(is));
211 for (
unsigned int i = 0; i < segment.size(); ++i) {
212 auto& s = segment[i];
213 intersections_of_segment[i].push_back(intersections.size());
214 intersections.push_back(s.source());
215 intersections_of_segment[i].push_back(intersections.size());
216 intersections.push_back(s.target());
218 sweep(segment, intersection_event);
222 datastructure::UnionFind node_mapping(intersections.size());
223 node_mapping.all_to_singletons();
225 std::vector<unsigned int> same(intersections.size(), 0);
226 for (
unsigned int i = 0; i < same.size(); ++i) {
231 [&](
unsigned int a,
unsigned int b) { return intersections[a] < intersections[b]; });
233 for (
unsigned int i = 0; i + 1 < same.size(); ++i) {
234 unsigned int u = same[i];
235 unsigned int v = same[i + 1];
236 if (intersections[u] == intersections[v]) {
237 node_mapping.merge(u, v);
242 for (
unsigned int i = 0; i < segment.size(); ++i) {
243 auto& is = intersections_of_segment[i];
245 std::sort(is.begin(), is.end(), [&](
const unsigned int a,
unsigned int b) {
246 const Point& p_a = intersections[a];
247 const Point& p_b = intersections[b];
249 auto d_a = CGAL::squared_distance(segment[i].source(), p_a);
250 auto d_b = CGAL::squared_distance(segment[i].source(),
254 for (
unsigned int j = 0; j + 1 < is.size(); ++j) {
255 unsigned int u = node_mapping[is[j]];
256 unsigned int v = node_mapping[is[j + 1]];
260 || segment[i].has_on(intersections[u]));
262 || segment[i].has_on(intersections[v]));
264 edge_list.push_back(LCGEdge(u, v, i));
270 std::vector<Intersection> subdivision(std::vector<LineSegment>& segment) {
272 std::vector<Intersection> intersecting_segments;
275 auto intersection_event = [&](
unsigned int seg_1,
unsigned int seg_2) {
276 intersecting_segments.push_back({seg_1, seg_2});
279 sweep(segment, intersection_event);
280 return intersecting_segments;