Last active
April 18, 2024 14:14
-
-
Save zsln/1ef1cc414b8aec1f5175338a9b0d9ca4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h> | |
#include <CGAL/Segment_Delaunay_graph_2.h> | |
#include <CGAL/Segment_Delaunay_graph_filtered_traits_2.h> | |
/// slow choice, but did not fail | |
using K = CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt; | |
/// very important to have the same kernel for CK/EK/FK if your data possibly contains collinear segments | |
/// _without_intersections (here) for non-selfintersecting polygons | |
using GT = CGAL::Segment_Delaunay_graph_filtered_traits_without_intersections_2< | |
// | |
K, /// important | |
CGAL::Field_with_sqrt_tag, /// default CK_MTag | |
K, /// important | |
CGAL::Integral_domain_without_division_tag, /// default EK_MTag | |
K>; /// important | |
using SegDel = CGAL::Segment_Delaunay_graph_2<GT>; | |
/// shorthands for collector methods | |
using Ray2 = GT::Ray_2; | |
using Line2 = GT::Line_2; | |
using Seg2 = GT::Segment_2; | |
namespace | |
{ | |
/// helpers for checking if some component is NaN | |
bool is_valid(Ray2 const& r) | |
{ | |
if (!std::isfinite(CGAL::to_double(r.source().x())) // | |
|| !std::isfinite(CGAL::to_double(r.source().y())) // | |
|| !std::isfinite(CGAL::to_double(r.direction().dx())) // | |
|| !std::isfinite(CGAL::to_double(r.direction().dy())) // | |
) | |
return false; | |
return true; | |
} | |
bool is_valid(Line2 const& l) | |
{ | |
if (!std::isfinite(CGAL::to_double(l.point().x())) // | |
|| !std::isfinite(CGAL::to_double(l.point().y())) // | |
|| !std::isfinite(CGAL::to_double(l.direction().dx())) // | |
|| !std::isfinite(CGAL::to_double(l.direction().dy())) // | |
) | |
return false; | |
return true; | |
} | |
bool is_valid(Seg2 const& s) | |
{ | |
if (!std::isfinite(CGAL::to_double(s.source().x())) // | |
|| !std::isfinite(CGAL::to_double(s.source().y())) // | |
|| !std::isfinite(CGAL::to_double(s.target().x())) // | |
|| !std::isfinite(CGAL::to_double(s.target().y())) // | |
) | |
return false; | |
return true; | |
} | |
struct collector | |
{ | |
std::vector<Ray2> rays; | |
std::vector<Line2> lines; | |
std::vector<Seg2> segs; | |
/// optional: constructor that reserves rays/lines/segs | |
collector() | |
{ | |
constexpr int res_size = 100'000; | |
rays.reserve(res_size); | |
lines.reserve(res_size); | |
segs.reserve(res_size); | |
} | |
void operator<<(Ray2 const& r) | |
{ | |
if (!is_valid(r)) /// skip invalid | |
return; | |
rays.emplace_back(r); | |
} | |
void operator<<(Line2 const& l) | |
{ | |
if (l.is_degenerate() || !is_valid(l)) /// skip invalid | |
return; | |
lines.emplace_back(l); | |
} | |
void operator<<(Seg2 const& s) | |
{ | |
if (!is_valid(s)) /// skip invalid | |
return; | |
segs.emplace_back(s); | |
} | |
}; | |
} // namespace | |
int main() | |
{ | |
SegDel sd; | |
/// open polygon inputdata, that will trigger an assertion on non-default kernels (EK/FK) for GT due to almost colinear segments | |
std::vector<GT::Point_2> points{ | |
{-101.145103, 0.501979}, /// 0 | |
{-97.63135, -3.513653}, /// 1 | |
{-93.11374, -17.066684}, /// 2 | |
{-92.8627, -26.603884}, /// 3 | |
{-92.98822, -32.125453}, /// 4 | |
{-93.11374, -37.647021}, /// 5 | |
}; | |
std::vector<std::pair<std::size_t, std::size_t>> indices{ | |
{0, 1}, // | |
{1, 2}, // | |
{2, 3}, // | |
{3, 4}, // | |
{4, 5}, // | |
}; | |
/// fast insertion | |
sd.insert_segments(points, indices.begin(), indices.end()); | |
assert(sd.is_valid(true, 1)); | |
/// collect rays/lines/segs and use them e.g. to write to file, render, etc. | |
collector col; | |
sd.draw_dual(col); | |
std::cout << "\nSegment Voronoi:" << std::endl; | |
std::cout << "Rays: " << col.rays.size() << std::endl; | |
std::cout << "Lines: " << col.lines.size() << std::endl; | |
std::cout << "Segments: " << col.segs.size() << std::endl; | |
std::cout << " > Rays: " << std::endl; | |
for (auto const& r : col.rays) | |
{ | |
if (!is_valid(r)) | |
continue; | |
std::cout << " " << CGAL::to_double(r.source().x()) << "," << CGAL::to_double(r.source().y()) << " -> " << CGAL::to_double(r.direction().dx()) | |
<< ", " << CGAL::to_double(r.direction().dy()) << std::endl; // | |
} | |
std::cout << " > Lines: " << std::endl; | |
for (auto const& l : col.lines) | |
{ | |
if (!is_valid(l)) | |
continue; | |
std::cout << " " << CGAL::to_double(l.point().x()) << "," << CGAL::to_double(l.point().y()) << " -> " << CGAL::to_double(l.direction().dx()) | |
<< "," << CGAL::to_double(l.direction().dy()) << std::endl; // | |
} | |
std::cout << " > Segments: " << std::endl; | |
for (auto const& s : col.segs) | |
{ | |
if (!is_valid(s)) | |
continue; | |
std::cout << " " << CGAL::to_double(s.source().x()) << "," << CGAL::to_double(s.source().y()) << " -> " << CGAL::to_double(s.target().x()) | |
<< "," << CGAL::to_double(s.target().y()) << std::endl; // | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment