diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 7c2464c8ad7371b19babdd14e87d7753a6da9774..b49f9a89062516d64cf9fdc2a46596f779a9f0b7 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -31,12 +31,24 @@ impl IEDGE { } } +#[derive(Debug)] +pub enum TriangulationError { + NotEnoughPoints, + InvalidTriangulation, +} + /// Triangulation subroutine. /// Allows one to triangulate a list of points in a O(n²) time complexity -pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, ntri: &mut i32) -> i32 { +pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>) -> Result<Vec<ITRIANGLE>, TriangulationError> { + if *nv < 3 { + return Err(TriangulationError::NotEnoughPoints) + } + let trimax = 4 * *nv; let mut _nedge: i32 = 0; - let mut status = 0; + + let mut v: Vec<ITRIANGLE> = vec![ITRIANGLE::new(-1, -1, -1); trimax as usize]; + let mut ntri: i32 = 0; let mut edges: Vec<IEDGE> = Vec::with_capacity(100000_usize); let mut complete: Vec<bool> = vec![false; trimax as usize]; @@ -102,7 +114,7 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt v[0].p2 = *nv+1; v[0].p3 = *nv+2; complete[0] = false; - *ntri = 1; + ntri = 1; /* Include each point one at a time into the existing mesh @@ -121,7 +133,7 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt */ _j = 0; - while _j < *ntri as isize { + while _j < ntri as isize { if complete[_j as usize] { _j += 1; continue; @@ -142,9 +154,9 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt edges.push(IEDGE::new(v[_j as usize].p2, v[_j as usize].p3)); edges.push(IEDGE::new(v[_j as usize].p3, v[_j as usize].p1)); _nedge += 3; - v[_j as usize] = v[(*ntri-1) as usize]; - complete[_j as usize] = complete[(*ntri-1) as usize]; - *ntri -= 1; + v[_j as usize] = v[(ntri-1) as usize]; + complete[_j as usize] = complete[(ntri-1) as usize]; + ntri -= 1; _j -= 1; } @@ -188,15 +200,14 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt _j += 1; continue; } - if (*ntri) >= trimax { - status = 4; - return status + if (ntri) >= trimax { + return Err(TriangulationError::InvalidTriangulation); } - v[*ntri as usize].p1 = edges[_j as usize].p1; - v[*ntri as usize].p2 = edges[_j as usize].p2; - v[*ntri as usize].p3 = i as i32; - complete[*ntri as usize] = false; - *ntri += 1; + v[ntri as usize].p1 = edges[_j as usize].p1; + v[ntri as usize].p2 = edges[_j as usize].p2; + v[ntri as usize].p3 = i as i32; + complete[ntri as usize] = false; + ntri += 1; _j += 1; } @@ -207,11 +218,11 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt These are triangles which have a vertex number greater than nv */ let mut i: isize = 0_isize; - while (i as i32) < *ntri { + while (i as i32) < ntri { if v[i as usize].p1 >= *nv || v[i as usize].p2 >= *nv || v[i as usize].p3 >= *nv { v.remove(i as usize); - *ntri -= 1; + ntri -= 1; i -=1 ; } i += 1; @@ -219,7 +230,7 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt // Removing unnecessary triangles i = v.len() as isize - 1; - while (i as i32) >= *ntri { + while (i as i32) >= ntri { v.remove(i as usize); i -= 1; } @@ -229,7 +240,7 @@ pub fn triangulate(nv: &mut i32, pxyz: &mut Vec<XYZ>, v: &mut Vec<ITRIANGLE>, nt pxyz.remove(pxyz.len()-1); pxyz.remove(pxyz.len()-1); - status + Ok(v) } /// Return true if a point (xp,yp) lies inside the circumcircle made up @@ -290,7 +301,7 @@ fn circum_circle(xp: f64, yp: f64, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, drsqr = dx*dx + dy*dy; // Original - //return((drsqr <= *rsqr) ? TRUE : FALSE); + // return((drsqr <= *rsqr) ? TRUE : FALSE); // Proposed by Chuck Morris return (drsqr - *rsqr) <= EPSILON; } diff --git a/src/main.rs b/src/main.rs index 1540805fc20773685b532ebad5c51869527c3732..69af20ab76aad6a727c8d6f916bbec832a63f0c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod lib; mod stl_writer; use las::reader::*; -use lib::{XYZ, ITRIANGLE,triangulate}; +use lib::{XYZ, TriangulationError, ITRIANGLE, triangulate}; use std::time::Instant; @@ -27,12 +27,10 @@ fn main() { points.sort_by(|a, b| a.partial_cmp(b).unwrap()); let mut nv: i32 = points.len() as i32; - let mut triangles: Vec<ITRIANGLE> = vec![ITRIANGLE::new(-1, -1, -1); 3*nv as usize]; - let mut ntri: i32 = triangles.len() as i32; println!("triangulating {} points ...", points.len()); let start_triangulation = Instant::now(); - triangulate(&mut nv, &mut points, &mut triangles, &mut ntri); + let triangles: Vec<ITRIANGLE> = triangulate(&mut nv, &mut points).expect("An error has been detected while triangulating"); let time_taken = start_triangulation.elapsed(); println!("time taken to triangulate {} points : {} [s]", points.len(), time_taken.as_secs_f64());