extern crate libc;
use libc::{c_void, size_t};
use std::mem;
type Scalar = f64;
extern "C" {
fn p2t_polyline_new() -> *mut c_void;
fn p2t_polyline_free(polygon: *mut c_void);
fn p2t_polyline_add_point(polygon: *mut c_void, x: Scalar, y: Scalar);
fn p2t_cdt_new(polygon: *mut c_void) -> *mut c_void;
fn p2t_cdt_free(cdt: *mut c_void);
fn p2t_cdt_triangulate(cdt: *mut c_void);
fn p2t_cdt_get_triangles(cdt: *mut c_void) -> *mut c_void;
fn p2t_triangles_free(triangles: *mut c_void);
fn p2t_triangles_count(triangles: *mut c_void) -> size_t;
fn p2t_triangles_get_triangle(triangles: *const c_void, idx: size_t) -> *const c_void;
fn p2t_triangle_get_point(
triangle: *const c_void,
idx: size_t,
x_out: *mut Scalar,
y_out: *mut Scalar,
);
}
pub(crate) struct Polygon {
ll: *mut c_void,
}
pub(crate) struct CDT {
ll: *mut c_void,
}
pub(crate) struct TriangleVec {
ll: *mut c_void,
#[allow(dead_code)]
cdt: CDT,
}
#[derive(Copy, Clone, PartialEq)]
pub(crate) struct Triangle {
pub(crate) points: [[Scalar; 2]; 3],
}
impl Polygon {
pub(crate) fn new() -> Polygon {
unsafe {
Polygon {
ll: p2t_polyline_new(),
}
}
}
pub(crate) fn from_iterator<'a, I>(points: I) -> Polygon
where
I: Iterator<Item = &'a [Scalar; 2]>,
{
let mut rv = Polygon::new();
for point in points {
rv.add_point(point[0], point[1]);
}
rv
}
pub(crate) fn add_point(&mut self, x: Scalar, y: Scalar) {
unsafe {
p2t_polyline_add_point(self.ll, x, y);
}
}
}
impl Drop for Polygon {
fn drop(&mut self) {
unsafe {
p2t_polyline_free(self.ll);
}
}
}
impl CDT {
pub(crate) fn new(polygon: Polygon) -> CDT {
unsafe {
let rv = CDT {
ll: p2t_cdt_new(polygon.ll),
};
mem::forget(polygon);
rv
}
}
pub(crate) fn triangulate(self) -> TriangleVec {
unsafe {
p2t_cdt_triangulate(self.ll);
let ll = p2t_cdt_get_triangles(self.ll);
TriangleVec { cdt: self, ll }
}
}
}
impl Drop for CDT {
fn drop(&mut self) {
unsafe {
p2t_cdt_free(self.ll);
}
}
}
impl TriangleVec {
pub(crate) fn size(&self) -> usize {
unsafe { p2t_triangles_count(self.ll) as usize }
}
pub(crate) fn get_triangle(&self, idx: usize) -> Triangle {
assert!(idx < self.size(), "Out of range");
let mut p0 = [0.0; 2];
let mut p1 = [0.0; 2];
let mut p2 = [0.0; 2];
unsafe {
let tri = p2t_triangles_get_triangle(self.ll, idx as size_t);
p2t_triangle_get_point(tri, 0, &mut p0[0], &mut p0[1]);
p2t_triangle_get_point(tri, 1, &mut p1[0], &mut p1[1]);
p2t_triangle_get_point(tri, 2, &mut p2[0], &mut p2[1]);
}
Triangle {
points: [p0, p1, p2],
}
}
}
impl Drop for TriangleVec {
fn drop(&mut self) {
unsafe {
p2t_triangles_free(self.ll);
}
}
}
pub(crate) fn triangulate_points<'a, I>(points: I) -> TriangleVec
where
I: Iterator<Item = &'a [Scalar; 2]>,
{
CDT::new(Polygon::from_iterator(points)).triangulate()
}