Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DebugApp/uniform_grid/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,9 @@ fn build_mesh_result(

// Reproduce the public float wrapper's single conversion into the integer pipeline.
let rect = FloatRect::with_iter(shape.iter().flatten())
.map_err(|error| format!("invalid input bounds: {error:?}"))?
.ok_or_else(|| "input shape is empty".to_owned())?;
let adapter = FloatPointAdapter::<Point, i32>::new(rect);
let adapter = FloatPointAdapter::<Point, i32>::new_conservative(rect);
let int_edge_length = adapter.round_len_to_int(edge_length);
if int_edge_length <= 1 {
return Err("edge_length is below integer adapter precision".to_owned());
Expand Down
4 changes: 2 additions & 2 deletions iTriangle/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "i_triangle"
version = "0.48.0"
version = "0.49.0"
edition = "2021"
authors = ["Nail Sharipov <nailxsharipov@gmail.com>"]
description = "Polygon Triangulation Library: Efficient Delaunay Triangulation for Complex Shapes."
Expand All @@ -20,7 +20,7 @@ serde = ["dep:serde", "i_overlay/serde"]
[dependencies]
serde = { version = "^1.0", default-features = false, features = ["derive"], optional = true }

i_overlay = { version = "^8.1.0"}
i_overlay = { version = "^9.0.0"}
i_tree = "~0.19.0"
i_key_sort = "~0.11.0"

Expand Down
2 changes: 1 addition & 1 deletion iTriangle/examples/eagle_svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn tessellation_svg(
append_shape_fill(&mut svg, shape);

let mut edges = BTreeSet::new();
for triangle in triangulation.indices.chunks_exact(3) {
for triangle in triangulation.indices.as_chunks::<3>().0 {
for (a, b) in [
(triangle[0], triangle[1]),
(triangle[1], triangle[2]),
Expand Down
8 changes: 4 additions & 4 deletions iTriangle/src/advanced/delaunay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ mod tests {
let p = IntPoint::new(0, -4);

let is_flip_not_required = DelaunayCondition::is_flip_not_required(p, a, b, c);
assert_eq!(is_flip_not_required, true);
assert!(is_flip_not_required);
}

#[test]
Expand All @@ -351,7 +351,7 @@ mod tests {
let p = IntPoint::new(0, -2);

let is_flip_not_required = DelaunayCondition::is_flip_not_required(p, a, b, c);
assert_eq!(is_flip_not_required, true);
assert!(is_flip_not_required);
}

#[test]
Expand All @@ -362,7 +362,7 @@ mod tests {
let p = IntPoint::new(0, -1);

let is_flip_not_required = DelaunayCondition::is_flip_not_required(p, a, b, c);
assert_eq!(is_flip_not_required, false);
assert!(!is_flip_not_required);
}

#[test]
Expand All @@ -373,7 +373,7 @@ mod tests {
let p = IntPoint::new(0, -1);

let is_flip_not_required = DelaunayCondition::is_flip_not_required(p, a, b, c);
assert_eq!(is_flip_not_required, false);
assert!(!is_flip_not_required);
}

#[test]
Expand Down
15 changes: 6 additions & 9 deletions iTriangle/src/advanced/relax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ fn displacement_is_safe<I: IntNumber>(
}

let sqr_displacement = displacement.sqr_length();
if sqr_displacement <= I::Wide::ZERO {
if sqr_displacement <= I::WideUInt::ZERO {
return false;
}

Expand All @@ -378,14 +378,11 @@ fn displacement_is_safe<I: IntNumber>(
.sqr_distance(b)
.max(b.sqr_distance(c))
.max(c.sqr_distance(a));
if max_sqr_edge <= I::Wide::ZERO {
if max_sqr_edge <= I::WideUInt::ZERO {
return false;
}

let left = <I::WideUInt as UIntNumber>::Product::multiply(
sqr_displacement.to_uint(),
max_sqr_edge.to_uint(),
);
let left = <I::WideUInt as UIntNumber>::Product::multiply(sqr_displacement, max_sqr_edge);

// |d| < h_min / 4, where h_min = area_two / longest_edge.
// Squaring and rearranging avoids both division and square roots:
Expand All @@ -409,12 +406,12 @@ fn displacement_is_safe<I: IntNumber>(
left16 < right
}

fn is_within_tolerance<I: IntNumber>(sqr_distance: I::Wide, tolerance: I::WideUInt) -> bool {
if sqr_distance < I::Wide::ZERO {
fn is_within_tolerance<I: IntNumber>(sqr_distance: I::WideUInt, tolerance: I::WideUInt) -> bool {
if sqr_distance < I::WideUInt::ZERO {
return false;
}

let distance = <I::WideUInt as UIntNumber>::Product::from_uint(sqr_distance.to_uint());
let distance = <I::WideUInt as UIntNumber>::Product::from_uint(sqr_distance);
let tolerance = <I::WideUInt as UIntNumber>::Product::multiply(tolerance, tolerance);
distance <= tolerance
}
Expand Down
40 changes: 22 additions & 18 deletions iTriangle/src/float/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_path(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_path(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let raw = self.to_int(&adapter).custom_triangulate(validation);
RawTriangulation { raw, adapter }
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -71,8 +71,8 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_path(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_path(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let float_points = points.to_int(&adapter);
let raw = self
.to_int(&adapter)
Expand All @@ -81,7 +81,7 @@ where
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -95,14 +95,14 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_paths(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let raw = self.to_int(&adapter).custom_triangulate(validation);
RawTriangulation { raw, adapter }
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -115,8 +115,8 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_paths(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let float_points = points.to_int(&adapter);
let raw = self
.to_int(&adapter)
Expand All @@ -125,7 +125,7 @@ where
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -139,14 +139,16 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_list_of_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) =
FloatRect::with_list_of_paths(self).expect("Invalid triangulation bounds")
{
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let raw = self.to_int(&adapter).custom_triangulate(validation);
RawTriangulation { raw, adapter }
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -159,8 +161,10 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_list_of_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) =
FloatRect::with_list_of_paths(self).expect("Invalid triangulation bounds")
{
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let float_points = points.to_int(&adapter);
let raw = self
.to_int(&adapter)
Expand All @@ -169,7 +173,7 @@ where
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions iTriangle/src/float/locator.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use alloc::vec::Vec;
use i_key_sort::sort::key::SortKey;
use i_overlay::i_float::adapter::FloatPointAdapter;
use i_overlay::i_float::float::compatible::FloatPointCompatible;
use i_overlay::i_float::float::number::FloatNumber;
use i_overlay::i_float::int::number::int::IntNumber;
use i_overlay::{i_float::adapter::FloatPointAdapter, i_shape::float::adapter::PathToInt};
use i_overlay::i_shape::float::adapter::PathToInt;

use crate::int::locator::IntPointInTriangulationLocator;
use crate::{
Expand All @@ -27,11 +28,13 @@ impl<P, N: IndexType> Triangulation<P, N> {
where
P: FloatPointCompatible<Scalar = T>,
{
let adapter = FloatPointAdapter::<P, I>::with_iter(self.points.iter().chain(points.iter()));
let adapter = FloatPointAdapter::<P, I>::with_iter_conservative(
self.points.iter().chain(points.iter()),
);

let int_points = points.to_int(&adapter);

let triangles = self.indices.chunks_exact(3).map(|triangle| {
let triangles = self.indices.as_chunks::<3>().0.iter().map(|triangle| {
let a = adapter.float_to_int(&self.points[triangle[0].into_usize()]);
let b = adapter.float_to_int(&self.points[triangle[1].into_usize()]);
let c = adapter.float_to_int(&self.points[triangle[2].into_usize()]);
Expand Down
11 changes: 11 additions & 0 deletions iTriangle/src/float/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
//! Floating-point triangulation uses the same coordinate contract as iOverlay.
//!
//! Coordinates must be finite, with absolute values at most `2^60` for `f32`
//! or `2^500` for `f64`. Invalid input bounds panic; empty geometry produces
//! an empty mesh. Automatic conversion uses the conservative adapter constructors,
//! reserving `I::BITS - 3` coordinate bits for integer differences, products, and
//! rounding, including unchecked APIs.
//! Unchecked APIs skip topology validation. Reusable `Triangulator` methods
//! validate individual points only in debug builds and final bounds in all builds;
//! callers must ensure every input point satisfies the coordinate contract.

pub mod builder;
pub mod centroid_net;
pub mod circumcenter;
Expand Down
40 changes: 22 additions & 18 deletions iTriangle/src/float/triangulatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_path(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_path(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let raw = self.to_int(&adapter).triangulate();
RawTriangulation { raw, adapter }
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -68,8 +68,8 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_path(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_path(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let float_points = points.to_int(&adapter);
let raw = self
.to_int(&adapter)
Expand All @@ -78,7 +78,7 @@ where
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -92,14 +92,14 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_paths(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let raw = self.to_int(&adapter).triangulate();
RawTriangulation { raw, adapter }
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -108,8 +108,8 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) = FloatRect::with_paths(self).expect("Invalid triangulation bounds") {
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let float_points = points.to_int(&adapter);
let raw = self
.to_int(&adapter)
Expand All @@ -118,7 +118,7 @@ where
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -132,14 +132,16 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_list_of_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) =
FloatRect::with_list_of_paths(self).expect("Invalid triangulation bounds")
{
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let raw = self.to_int(&adapter).triangulate();
RawTriangulation { raw, adapter }
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand All @@ -148,8 +150,10 @@ where
where
I: OverlayInt,
{
if let Some(rect) = FloatRect::with_list_of_paths(self) {
let adapter = FloatPointAdapter::<P, I>::new(rect);
if let Some(rect) =
FloatRect::with_list_of_paths(self).expect("Invalid triangulation bounds")
{
let adapter = FloatPointAdapter::<P, I>::new_conservative(rect);
let float_points = points.to_int(&adapter);
let raw = self
.to_int(&adapter)
Expand All @@ -158,7 +162,7 @@ where
} else {
RawTriangulation {
raw: RawIntTriangulation::default(),
adapter: FloatPointAdapter::<P, I>::new(FloatRect::zero()),
adapter: FloatPointAdapter::<P, I>::new_conservative(FloatRect::zero()),
}
}
}
Expand Down
Loading
Loading