Check loop self intersection in cgal

This commit is contained in:
Thomas Krijnen
2020-09-01 12:22:10 +02:00
parent 6685aa16d3
commit 842dcb7579
+62
View File
@@ -403,6 +403,61 @@ namespace {
}
}
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/box_intersection_d.h>
#include <vector>
#include <fstream>
typedef CGAL::Box_intersection_d::Box_with_handle_d<double, 3, int*> Box;
namespace {
void loop_to_segments(const cgal_wire_t& wire, std::vector<Kernel_::Segment_3>& segments) {
for (int i = 0; i < wire.size(); ++i) {
int j = (i + 1) % wire.size();
segments.emplace_back(wire[i], wire[j]);
}
}
struct intersection_collector {
const std::vector<Kernel_::Segment_3>& segments;
int num_self_intersections = 0;
void operator()(const Box& a, const Box& b) {
int aid = *a.handle();
int bid = *b.handle();
if (aid > bid) {
std::swap(aid, bid);
}
if (((aid + 1) == bid) || ((aid == 0) && (bid = (segments.size() - 1)))) {
// consecutive segments.
return;
}
auto s0 = segments[aid];
auto s1 = segments[bid];
if (CGAL::do_intersect(s0, s1)) {
num_self_intersections++;
}
}
};
bool do_segments_intersect(const std::vector<Kernel_::Segment_3>& segments) {
std::vector<Box> boxes;
std::vector<int> handles(segments.size());
std::iota(handles.begin(), handles.end(), 0);
for (auto it = segments.begin(); it != segments.end(); ++it) {
boxes.push_back(Box(it->bbox(), &*(handles.begin() + std::distance(segments.begin(), it))));
}
intersection_collector x{ segments };
CGAL::box_self_intersection_d(boxes.begin(), boxes.end(), x);
return !!x.num_self_intersections;
}
}
bool CgalKernel::convert(const taxonomy::loop* loop, cgal_wire_t& result) {
// @todo only implement polygonal loops
@@ -458,6 +513,13 @@ bool CgalKernel::convert(const taxonomy::loop* loop, cgal_wire_t& result) {
Logger::Message(Logger::LOG_WARNING, ss.str(), loop->instance);
}
std::vector<Kernel_::Segment_3> segments;
loop_to_segments(polygon, segments);
if (do_segments_intersect(segments)) {
Logger::Message(Logger::LOG_WARNING, "Skipping self-intersecting loop", loop->instance);
return false;
}
/*
std::wcerr << "[" << std::endl;
for (auto& p : polygon) {