1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! # NFP Library - No Fit Polygon Computation
//!
//! A Rust library for calculating No Fit Polygon (NFP) for shape nesting and packing problems.
//!
//! ## What is NFP?
//!
//! The No Fit Polygon is a computational geometry tool used in 2D nesting and packing optimization.
//! It defines the forbidden region where one polygon cannot be placed relative to another without
//! collision. When the origin of polygon B is outside the NFP, the two polygons do not overlap.
//!
//! ## Current Implementation
//!
//! This library provides **NFP for convex polygons** using the Minkowski sum approach:
//!
//! 1. **Algorithm**: Minkowski Sum via vertex combinations and convex hull
//! 2. **Input**: Two convex polygons represented as `Vec<Point>` (counter-clockwise orientation)
//! 3. **Output**: NFP boundary as a convex polygon (counter-clockwise)
//! 4. **Complexity**: O(n² log n) where n is the total number of vertices
//!
//! ### How it Works
//!
//! The algorithm computes the Minkowski sum A ⊕ (-B):
//! - For each vertex in A and each vertex in -B, compute their sum
//! - Compute the convex hull of all resulting points
//! - The convex hull boundary is the NFP
//!
//! ## Examples
//!
//! ### Basic Usage with Simple Polygons
//!
//! ```rust
//! use nfp::{point, NFPConvex};
//!
//! // Triangle A at origin
//! let triangle_a = vec![
//! point(0.0, 0.0),
//! point(10.0, 0.0),
//! point(5.0, 10.0),
//! ];
//!
//! // Triangle B at origin
//! let triangle_b = vec![
//! point(0.0, 0.0),
//! point(5.0, 0.0),
//! point(2.5, 5.0),
//! ];
//!
//! // Calculate NFP
//! let nfp = NFPConvex::nfp(&triangle_a, &triangle_b).unwrap();
//! println!("NFP has {} vertices", nfp.len());
//! ```
//!
//! ### Collision Detection Using NFP
//!
//! ```rust
//! use nfp::{point, NFPConvex};
//!
//! // Define two squares
//! let square_a = vec![
//! point(0.0, 0.0),
//! point(10.0, 0.0),
//! point(10.0, 10.0),
//! point(0.0, 10.0),
//! ];
//!
//! let square_b = vec![
//! point(0.0, 0.0),
//! point(5.0, 0.0),
//! point(5.0, 5.0),
//! point(0.0, 5.0),
//! ];
//!
//! // Calculate NFP
//! let nfp = NFPConvex::nfp(&square_a, &square_b).unwrap();
//!
//! // To check if placing B at position (px, py) collides with A:
//! // If B's origin at (px, py) is OUTSIDE the NFP, there is NO collision
//! // If B's origin at (px, py) is INSIDE the NFP, there IS a collision
//! let test_position = point(12.0, 12.0);
//! println!("Position valid for placement: {}",
//! !point_in_polygon(test_position, &nfp));
//!
//! fn point_in_polygon(pt: nfp::prelude::Point, polygon: &[nfp::prelude::Point]) -> bool {
//! let mut inside = false;
//! let mut p1 = polygon[polygon.len() - 1];
//! for p2 in polygon {
//! if ((p2.y > pt.y) != (p1.y > pt.y))
//! && (pt.x < (p1.x - p2.x) * (pt.y - p2.y) / (p1.y - p2.y) + p2.x)
//! {
//! inside = !inside;
//! }
//! p1 = *p2;
//! }
//! inside
//! }
//! ```
//!
//! ## Key Properties
//!
//! - **Convexity**: NFP of two convex polygons is convex
//! - **Orientation**: NFP is always counter-clockwise (CCW)
//! - **No Self-Intersections**: NFP boundary has no crossing edges
//! - **Minkowski Sum**: NFP(A, B) = A ⊕ (-B)
//!
//! ## Requirements
//!
//! - Both input polygons must be **convex**
//! - Both input polygons must have at least **3 vertices**
//! - Polygons should be in **counter-clockwise (CCW) orientation**
//! (the library will auto-correct if needed)
//!
// Re-export main public API
pub use Point;
pub use point;
pub use ;