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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
use crate;
use cratesat;
use crate;
/// Finds the best separating axis by testing a triangle's face normal against a segment (3D only).
///
/// In 3D, a triangle has a face normal (perpendicular to its plane). This function tests both
/// directions of this normal (+normal and -normal) to find the maximum separation from the segment.
///
/// # How It Works
///
/// The function computes support points on the segment in both the positive and negative normal
/// directions, then measures which direction gives greater separation from the triangle's surface.
///
/// # Parameters
///
/// - `triangle1`: The triangle whose face normal will be tested
/// - `segment2`: The line segment
/// - `pos12`: The position of the segment relative to the triangle
///
/// # Returns
///
/// A tuple containing:
/// - `Real`: The separation distance along the triangle's face normal
/// - **Positive**: Shapes are separated
/// - **Negative**: Shapes are overlapping
/// - **Very negative** if the triangle has no normal (degenerate triangle)
/// - `Vector`: The face normal direction (or its negation) that gives this separation
///
/// # Degenerate Triangles
///
/// If the triangle is degenerate (all three points are collinear), it has no valid normal.
/// In this case, the function returns `-Real::MAX` for separation and a zero vector for the normal.
///
/// # Example
///
/// ```rust
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// use parry3d::shape::{Triangle, Segment};
/// use parry3d::query::sat::triangle_segment_find_local_separating_normal_oneway;
/// use parry3d::math::{Vector, Pose};
///
/// // Triangle in the XY plane
/// let triangle = Triangle::new(
/// Vector::ZERO,
/// Vector::new(2.0, 0.0, 0.0),
/// Vector::new(1.0, 2.0, 0.0)
/// );
///
/// // Vertical segment above the triangle
/// let segment = Segment::new(
/// Vector::new(1.0, 1.0, 1.0),
/// Vector::new(1.0, 1.0, 3.0)
/// );
///
/// let pos12 = Pose::identity();
///
/// let (separation, normal) = triangle_segment_find_local_separating_normal_oneway(
/// &triangle,
/// &segment,
/// &pos12
/// );
///
/// if separation > 0.0 {
/// println!("Separated by {} along triangle normal", separation);
/// }
/// # }
/// ```
///
/// # Usage in Complete SAT
///
/// For a complete triangle-segment collision test, you must also test:
/// 1. Triangle face normal (this function)
/// 2. Segment normal (in 2D) or edge-edge axes (in 3D)
/// 3. Edge-edge cross products (see [`segment_triangle_find_local_separating_edge_twoway`])
/// Finds the best separating axis by testing edge-edge combinations between a segment and a triangle (3D only).
///
/// In 3D, when a line segment and triangle collide, the contact might occur along an axis
/// perpendicular to both the segment and one of the triangle's edges. This function tests all
/// such axes (cross products) to find the one with maximum separation.
///
/// # Parameters
///
/// - `segment1`: The line segment
/// - `triangle2`: The triangle
/// - `pos12`: The position of the triangle relative to the segment
///
/// # Returns
///
/// A tuple containing:
/// - `Real`: The maximum separation found across all edge-edge axes
/// - **Positive**: Shapes are separated
/// - **Negative**: Shapes are overlapping
/// - `Vector`: The axis direction that gives this separation
///
/// # The Axes Tested
///
/// The function computes cross products between:
/// - The segment's direction (B - A)
/// - Each of the 3 triangle edges (AB, BC, CA)
///
/// This gives 3 base axes. The function tests both each axis and its negation (6 total),
/// finding which gives the maximum separation.
///
/// # Example
///
/// ```rust
/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
/// use parry3d::shape::{Segment, Triangle};
/// use parry3d::query::sat::segment_triangle_find_local_separating_edge_twoway;
/// use parry3d::math::{Vector, Pose};
///
/// let segment = Segment::new(
/// Vector::ZERO,
/// Vector::new(0.0, 0.0, 2.0)
/// );
///
/// let triangle = Triangle::new(
/// Vector::new(1.0, 0.0, 1.0),
/// Vector::new(3.0, 0.0, 1.0),
/// Vector::new(2.0, 2.0, 1.0)
/// );
///
/// let pos12 = Pose::identity();
///
/// let (separation, axis) = segment_triangle_find_local_separating_edge_twoway(
/// &segment,
/// &triangle,
/// &pos12
/// );
///
/// if separation > 0.0 {
/// println!("Separated by {} along edge-edge axis", separation);
/// }
/// # }
/// ```
///
/// # Implementation Details
///
/// - Axes with near-zero length (parallel edges) are skipped
/// - The function uses [`support_map_support_map_compute_separation`](super::support_map_support_map_compute_separation)
/// to compute the actual separation along each axis
/// - Both positive and negative directions are tested for each cross product
///
/// # Usage in Complete SAT
///
/// For a complete segment-triangle collision test, you must also test:
/// 1. Triangle face normal ([`triangle_segment_find_local_separating_normal_oneway`])
/// 2. Segment-specific axes (depends on whether the segment has associated normals)
/// 3. Edge-edge cross products (this function)