#[macro_use]
extern crate derive_builder;
extern crate triangle_sys as sys;
#[cfg(test)]
mod tests;
use std::{ffi::CString, mem::MaybeUninit, ptr};
use anyhow::Result;
#[derive(Builder)]
pub struct TrianglulateOpts
{
point_list: P,
/// Generates a Voronoi diagram
#[builder(default)]
voronoi: bool,
}
impl TrianglulateOpts {
pub fn builder() -> TrianglulateOptsBuilder
{
TrianglulateOptsBuilder::default()
}
}
#[derive(Clone, Copy, Debug)]
pub struct Point {
x: f64,
y: f64,
}
#[derive(Debug)]
pub struct TriangulateResult {
pub point_list: Vec,
}
pub fn triangulate(opts: TrianglulateOpts
) -> Result
where
P: IntoIterator- ,
{
let mut switches = Vec::new();
if opts.voronoi {
switches.push("v");
}
let switches = CString::new(switches.join(""))?;
let point_list = opts.point_list.into_iter().collect::>();
let mut flat_point_list = point_list
.iter()
.flat_map(|point| [point.x, point.y])
.collect::>();
let input = MaybeUninit::::uninit();
let output = MaybeUninit::::uninit();
let mut vorout = ptr::null::();
let mut input = unsafe { input.assume_init() };
let mut output = unsafe { output.assume_init() };
input.pointlist = flat_point_list.as_mut_ptr();
input.numberofpoints = point_list.len() as i32;
// TODO: Implement point attributes
input.numberofpointattributes = 0;
unsafe {
sys::triangulate(
switches.as_ptr() as *mut _,
&mut input as *mut _,
&mut output as *mut _,
vorout as *mut _,
)
};
let flat_point_list = unsafe {
Vec::from_raw_parts(
output.pointlist,
output.numberofpoints as usize * 2,
output.numberofpoints as usize * 2,
)
};
let point_list = flat_point_list
.chunks(2)
.map(|points| Point {
x: points[0],
y: points[1],
})
.collect::>();
Ok(TriangulateResult { point_list })
}