Skip to content

Instantly share code, notes, and snippets.

@zsln
Last active April 18, 2024 14:14
Show Gist options
  • Save zsln/1ef1cc414b8aec1f5175338a9b0d9ca4 to your computer and use it in GitHub Desktop.
Save zsln/1ef1cc414b8aec1f5175338a9b0d9ca4 to your computer and use it in GitHub Desktop.
#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