parry3d/query/clip/
clip_segment_segment.rs1use crate::math::{Point, Real};
2#[cfg(feature = "dim2")]
3use crate::{math::Vector, utils};
4
5pub type ClippingPoints = (Point<Real>, Point<Real>, usize, usize);
10
11#[cfg(feature = "dim2")]
14pub fn clip_segment_segment_with_normal(
15 mut seg1: (Point<Real>, Point<Real>),
16 mut seg2: (Point<Real>, Point<Real>),
17 normal: Vector<Real>,
18) -> Option<(ClippingPoints, ClippingPoints)> {
19 use crate::utils::WBasis;
20 let tangent = normal.orthonormal_basis()[0];
21
22 let mut range1 = [seg1.0.coords.dot(&tangent), seg1.1.coords.dot(&tangent)];
23 let mut range2 = [seg2.0.coords.dot(&tangent), seg2.1.coords.dot(&tangent)];
24 let mut features1 = [0, 2];
25 let mut features2 = [0, 2];
26
27 if range1[1] < range1[0] {
28 range1.swap(0, 1);
29 features1.swap(0, 1);
30 core::mem::swap(&mut seg1.0, &mut seg1.1);
31 }
32
33 if range2[1] < range2[0] {
34 range2.swap(0, 1);
35 features2.swap(0, 1);
36 core::mem::swap(&mut seg2.0, &mut seg2.1);
37 }
38
39 if range2[0] > range1[1] || range1[0] > range2[1] {
40 return None;
42 }
43
44 let ca = if range2[0] > range1[0] {
45 let bcoord = (range2[0] - range1[0]) * utils::inv(range1[1] - range1[0]);
46 let p1 = seg1.0 + (seg1.1 - seg1.0) * bcoord;
47 let p2 = seg2.0;
48
49 (p1, p2, 1, features2[0])
50 } else {
51 let bcoord = (range1[0] - range2[0]) * utils::inv(range2[1] - range2[0]);
52 let p1 = seg1.0;
53 let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
54
55 (p1, p2, features1[0], 1)
56 };
57
58 let cb = if range2[1] < range1[1] {
59 let bcoord = (range2[1] - range1[0]) * utils::inv(range1[1] - range1[0]);
60 let p1 = seg1.0 + (seg1.1 - seg1.0) * bcoord;
61 let p2 = seg2.1;
62
63 (p1, p2, 1, features2[1])
64 } else {
65 let bcoord = (range1[1] - range2[0]) * utils::inv(range2[1] - range2[0]);
66 let p1 = seg1.1;
67 let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
68
69 (p1, p2, features1[1], 1)
70 };
71
72 Some((ca, cb))
73}
74
75pub fn clip_segment_segment(
77 mut seg1: (Point<Real>, Point<Real>),
78 mut seg2: (Point<Real>, Point<Real>),
79) -> Option<(ClippingPoints, ClippingPoints)> {
80 let tangent1 = seg1.1 - seg1.0;
82 let sqnorm_tangent1 = tangent1.norm_squared();
83
84 let mut range1 = [0.0, sqnorm_tangent1];
85 let mut range2 = [
86 (seg2.0 - seg1.0).dot(&tangent1),
87 (seg2.1 - seg1.0).dot(&tangent1),
88 ];
89 let mut features1 = [0, 2];
90 let mut features2 = [0, 2];
91
92 if range1[1] < range1[0] {
93 range1.swap(0, 1);
94 features1.swap(0, 1);
95 core::mem::swap(&mut seg1.0, &mut seg1.1);
96 }
97
98 if range2[1] < range2[0] {
99 range2.swap(0, 1);
100 features2.swap(0, 1);
101 core::mem::swap(&mut seg2.0, &mut seg2.1);
102 }
103
104 if range2[0] > range1[1] || range1[0] > range2[1] {
105 return None;
107 }
108
109 let length1 = range1[1] - range1[0];
110 let length2 = range2[1] - range2[0];
111
112 let ca = if range2[0] > range1[0] {
113 let bcoord = (range2[0] - range1[0]) / length1;
114 let p1 = seg1.0 + tangent1 * bcoord;
115 let p2 = seg2.0;
116
117 (p1, p2, 1, features2[0])
118 } else {
119 let bcoord = (range1[0] - range2[0]) / length2;
120 let p1 = seg1.0;
121 let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
122
123 (p1, p2, features1[0], 1)
124 };
125
126 let cb = if range2[1] < range1[1] {
127 let bcoord = (range2[1] - range1[0]) / length1;
128 let p1 = seg1.0 + tangent1 * bcoord;
129 let p2 = seg2.1;
130
131 (p1, p2, 1, features2[1])
132 } else {
133 let bcoord = (range1[1] - range2[0]) / length2;
134 let p1 = seg1.1;
135 let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
136
137 (p1, p2, features1[1], 1)
138 };
139
140 Some((ca, cb))
141}