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
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (c) 2023 lacklustr@protonmail.com https://github.com/eadf
// This file is part of the hronn crate.
use crateSearchResult;
use crateMaximumTracker;
use crateEdgeAndCenterType;
use ulps_eq;
use Float;
use ;
/// Calculates the Z-coordinate where a 2d circle (radius in X&Y) intersects with an edge. The circle can be considered to
/// fall from infinite Z, so the effect is the same as for a cylinder or square end mill.
///
/// This function determines the Z-coordinate at which a circle, defined by its `center` and `probe_radius`,
/// intersects with a line segment defined by points `p0` and `p1`.
///
/// # Arguments
///
/// * `center`: The XY-coordinates of the center of the circle.
/// * `probe_radius`: The radius of the sphere.
/// * `p0`: One end of the line segment. The function internally re-arranges `p0` and `p1` based on their Z-coordinates,
/// so their order in the argument list is not significant.
/// * `p1`: The other end of the line segment.
/// * `skip`: An enum value indicating whether to skip calculations related to one of the endpoints of the line segment.
///
/// # Returns
///
/// * An `Option<f64>` representing the highest Z-coordinate of intersection. If there is no intersection, it returns `None`.
///
/// # Notes
///
/// * The function may internally swap `p0` and `p1` to ensure `p0` always has a Z-coordinate less than or equal to `p1`.
/// This means callers do not need to pre-sort these points before calling the function.
/// * The `skip` argument allows for efficient handling of cases where one of the endpoints' calculations can be avoided.
///
/// # Examples
///
/// ```rust,ignore
/// let center = Vector2::new(1.0, 2.0);
/// let probe_radius = 1.5;
/// let p0 = Vector3::new(0.0, 0.0, 0.0);
/// let p1 = Vector3::new(2.0, 2.0, 2.0);
/// let z_value = square_end_to_edge_collision(center, probe_radius, p0, p1, SkipEndpoint::NoSkip);
/// ```
pub
/*
#[allow(dead_code)]
pub(crate) fn square_end_to_edge_collision_xz<T: GenericVector3>(
edge: EdgeAndCenterType<T>,
probe_radius: T::Scalar,
site_index: usize,
mt: &mut MaximumTracker<SearchResult<T>>,
) where
T::Scalar: approx::UlpsEq,
{
let r_sq = probe_radius * probe_radius;
/*if edge.center.is_abs_diff_eq(
T::Vector2::new_2d((2.04).into(), (0.12).into()),
0.01.into(),
) && edge.p1.x().abs_diff_eq(&(2.023047).into(), 0.01.into())
{
// used to set breakpoints for debugging
println!(
"center:{:?} site:{site_index} p0:{:?} p1:{:?}",
edge.center, edge.p0, edge.p1
);
}*/
// use translation and rotation to place center at origin and align p0-p1 with the x-axis
let transform = match RigidTransform2D::translate_rotate_align_x(
edge.center,
edge.p0.to_2d(),
edge.p1.to_2d(),
) {
Some(t) => t,
None => {
if edge.p1.to_2d().magnitude_sq() <= r_sq {
mt.insert(SearchResult::<T>::new(site_index, edge.p1.z()));
}
return;
}
};
let p0 = transform.transform_point(edge.p0);
let p1 = transform.transform_point(edge.p1);
// Calculate vector from p0 to p1
let dp = p1 - p0;
if ulps_eq!(dp.x(), T::Scalar::ZERO) {
// when the line is almost vertical we only use p1
if p1.to_2d().magnitude_sq() <= r_sq {
mt.insert(SearchResult::<T>::new(site_index, p1.z()));
}
return;
}
let dp_xy = dp.to_2d();
let t: T::Scalar = -(p0.to_2d().dot(dp_xy) / dp_xy.magnitude_sq());
let clamped_t = t.clamp(T::Scalar::ZERO, T::Scalar::ONE);
if (p0.to_2d() + dp_xy * clamped_t).magnitude_sq() > r_sq {
return;
}
// unclamped_closest_point is a point on the infinite line
let un_clamped_closest_point = p0 + dp * t;
let delta_d_sq = r_sq - un_clamped_closest_point.to_2d().magnitude_sq();
if delta_d_sq < T::Scalar::ZERO {
return;
}
// we know that dp.z >= 0 so we are skipping the .abs() for dp.z
let m_sq = (dp.z() / dp.x()).powi(2);
let cz = un_clamped_closest_point.z() + (m_sq * delta_d_sq).sqrt();
mt.insert(SearchResult::new(site_index, cz.clamp(p0.z(), p1.z())));
}
*/