rs_math/graphical/arc.rs
1use crate::graphical::point_2d::Point2D;
2use crate::graphical::linear_equation::LinearEquation;
3
4/// 表示一个圆弧的结构体。
5#[derive(Debug, PartialEq)]
6pub struct Arc {
7 /// 弧的半径。
8 pub radius: f64,
9 /// 中心角,以弧度表示。
10 pub theta: f64,
11}
12
13
14#[allow(dead_code)]
15impl Arc {
16 /// 构造一个新的弧实例。
17 ///
18 /// # 参数
19 ///
20 /// * `radius` - 弧的半径。
21 /// * `theta` - 中心角,以弧度表示。
22 ///
23 /// # 返回值
24 ///
25 /// 返回一个包含给定半径和中心角的 Arc 结构体实例。
26 ///
27 /// # 示例
28 ///
29 /// ```
30 /// use rs_math::graphical::arc::Arc;
31 /// let arc = Arc::new(5.0, 1.2);
32 /// ```
33 pub fn new(radius: f64, theta: f64) -> Arc {
34 Arc { radius, theta }
35 }
36
37 /// 计算弧的长度。
38 ///
39 /// # 返回值
40 ///
41 /// 返回弧的长度,通过半径和中心角计算得出。
42 ///
43 /// # 示例
44 ///
45 /// ```
46 /// use rs_math::graphical::arc::Arc;
47 /// let arc = Arc::new(5.0, 1.2);
48 /// let arc_length = arc.calculate_arc_length();
49 /// ```
50 pub fn calculate_arc_length(&self) -> f64 {
51 self.radius * self.theta
52 }
53
54 /// 计算圆弧的长度。
55 ///
56 /// # 返回值
57 ///
58 /// 返回圆弧的长度,通过半径和中心角计算得出。
59 ///
60 /// # 示例
61 ///
62 /// ```
63 /// use rs_math::graphical::arc::Arc;
64 /// let arc = Arc::new(5.0, 1.2);
65 /// let arc_length = arc.arc_length();
66 /// ```
67 pub fn arc_length(&self) -> f64 {
68 // 返回圆弧的长度,即半径乘以中心角
69 self.radius * self.theta
70 }
71 /// 根据弧长和半径计算圆弧的属性并返回一个新的 Arc 实例。
72 ///
73 /// # 参数
74 ///
75 /// * `arc_length` - 圆弧的长度。
76 /// * `radius` - 圆弧的半径。
77 ///
78 /// # 返回值
79 ///
80 /// 返回一个包含给定弧长和半径计算得出的半径和中心角的 Arc 结构体实例。
81 ///
82 /// # 示例
83 ///
84 /// ```
85 /// use rs_math::graphical::arc::Arc;
86 /// let arc = Arc::from_arc_length_and_radius(10.0, 2.0);
87 /// ```
88 pub fn from_arc_length_and_radius(arc_length: f64, radius: f64) -> Arc {
89 // 初始猜测中心角的值
90 let mut theta_guess = arc_length / radius;
91
92 // 牛顿迭代法求解方程 s = r * theta
93 let epsilon = 1e-10; // 精度要求
94 let mut theta_prev;
95
96 // 迭代直到满足精度要求
97 loop {
98 theta_prev = theta_guess;
99 let f_theta = radius * theta_prev - arc_length;
100 let f_prime_theta = radius; // 导数 f'(θ) = r
101 theta_guess = theta_prev - f_theta / f_prime_theta;
102
103 // 判断是否达到精度要求,是则退出循环
104 if (theta_guess - theta_prev).abs() < epsilon {
105 break;
106 }
107 }
108
109 // 返回新的 Arc 结构体实例
110 Arc {
111 radius,
112 theta: theta_guess,
113 }
114 }
115
116 /// 根据弦长和半径计算圆弧的属性并返回一个新的 Arc 实例。
117 ///
118 /// # 参数
119 ///
120 /// * `chord_length` - 圆弧的弦长。
121 /// * `radius` - 圆弧的半径。
122 ///
123 /// # 返回值
124 ///
125 /// 返回一个包含给定弦长和半径计算得出的半径和中心角的 Arc 结构体实例。
126 ///
127 /// # 示例
128 ///
129 /// ```
130 /// use rs_math::graphical::arc::Arc;
131 /// let arc = Arc::from_chord_length_and_radius(6.0, 3.0);
132 /// ```
133 pub fn from_chord_length_and_radius(chord_length: f64, radius: f64) -> Arc {
134 // 计算中心角的值
135 let theta = 2.0 * f64::asin(chord_length / (2.0 * radius));
136
137 // 返回新的 Arc 结构体实例
138 Arc {
139 radius,
140 theta,
141 }
142 }
143
144
145 /// 根据圆弧的两个端点坐标计算圆弧的属性并返回一个新的 Arc 实例。
146 ///
147 /// # 参数
148 ///
149 /// * `x1` - 第一个端点的 x 坐标。
150 /// * `y1` - 第一个端点的 y 坐标。
151 /// * `x2` - 第二个端点的 x 坐标。
152 /// * `y2` - 第二个端点的 y 坐标。
153 ///
154 /// # 返回值
155 ///
156 /// 返回一个包含给定两个端点坐标计算得出的半径和中心角的 Arc 结构体实例。
157 ///
158 /// # 示例
159 ///
160 /// ```
161 /// use rs_math::graphical::arc::Arc;
162 /// let arc = Arc::from_endpoints(0.0, 0.0, 1.0, 0.0);
163 /// ```
164 pub fn from_endpoints(x1: f64, y1: f64, x2: f64, y2: f64) -> Arc {
165 // 计算半径
166 let radius = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt();
167
168 // 计算圆心坐标
169 let center_x = (x1 + x2) / 2.0;
170 let center_y = (y1 + y2) / 2.0;
171
172 // 计算中心角
173 let v1_x = x1 - center_x;
174 let v1_y = y1 - center_y;
175 let v2_x = x2 - center_x;
176 let v2_y = y2 - center_y;
177
178 let dot_product = v1_x * v2_x + v1_y * v2_y;
179 let magnitude_product = (v1_x.powi(2) + v1_y.powi(2)).sqrt() * (v2_x.powi(2) + v2_y.powi(2)).sqrt();
180
181 let cos_theta = dot_product / magnitude_product;
182 let theta = cos_theta.acos();
183
184 // 返回新的 Arc 结构体实例
185 Arc { radius, theta }
186 }
187
188 /// 根据圆弧的面积和半径计算圆弧的属性并返回一个新的 Arc 实例。
189 ///
190 /// # 参数
191 ///
192 /// * `area` - 圆弧的面积。
193 /// * `radius` - 圆弧的半径。
194 ///
195 /// # 返回值
196 ///
197 /// 返回一个包含给定面积和半径计算得出的半径和中心角的 Arc 结构体实例。
198 ///
199 /// # 示例
200 ///
201 /// ```
202 /// use rs_math::graphical::arc::Arc;
203 /// let arc = Arc::from_area_and_radius(10.0, 2.0);
204 /// ```
205 pub fn from_area_and_radius(area: f64, radius: f64) -> Arc {
206 // 计算弧长
207 let arc_length = (area * 2.0 / radius).sqrt();
208
209 // 计算中心角
210 let theta = arc_length / radius;
211
212 // 返回新的 Arc 结构体实例
213 Arc { radius, theta }
214 }
215 /// 生成圆弧上的点坐标并返回一个包含这些点的 Vector。
216 ///
217 /// # 参数
218 ///
219 /// * `num_points` - 生成的点的数量。
220 ///
221 /// # 返回值
222 ///
223 /// 返回一个包含生成的点坐标的 Vector。
224 ///
225 /// # 示例
226 ///
227 /// ```
228 /// use rs_math::graphical::arc::Arc;
229 /// use rs_math::geometry::point::Point2D;
230 ///
231 /// let arc = Arc::new(5.0, 1.2);
232 /// let points = arc.generate_points(10);
233 /// ```
234 pub fn generate_points(&self, num_points: usize) -> Vec<Point2D> {
235 // 创建一个 Vector 以存储生成的点
236 let mut points = Vec::with_capacity(num_points);
237
238 // 循环生成点坐标
239 for i in 0..num_points {
240 let theta_increment = self.theta / (num_points as f64 - 1.0);
241 let current_theta = i as f64 * theta_increment;
242 let x = self.radius * current_theta.cos();
243 let y = self.radius * current_theta.sin();
244
245 // 将点坐标添加到 Vector 中
246 points.push(Point2D { x, y });
247 }
248
249 // 返回包含生成的点坐标的 Vector
250 points
251 }
252 /// 计算圆弧上给定角度处的点坐标。
253 ///
254 /// # 参数
255 ///
256 /// * `angle` - 圆弧上的角度,以弧度表示。
257 ///
258 /// # 返回值
259 ///
260 /// 返回一个包含给定角度处的点坐标的元组。
261 ///
262 /// # 示例
263 ///
264 /// ```
265 /// use rs_math::graphical::arc::Arc;
266 ///
267 /// let arc = Arc::new(5.0, 1.2);
268 /// let point = arc.point_on_arc(0.5);
269 /// ```
270 pub fn point_on_arc(&self, angle: f64) -> (f64, f64) {
271 // 计算圆弧上给定角度处的点坐标
272 let x = self.radius * angle.cos();
273 let y = self.radius * angle.sin();
274
275 // 返回点坐标的元组
276 (x, y)
277 }
278
279 /// 计算圆弧上给定角度处的切线方程。
280 ///
281 /// # 参数
282 ///
283 /// * `angle` - 圆弧上的角度,以弧度表示。
284 ///
285 /// # 返回值
286 ///
287 /// 返回一个包含切线方程的一般式表示的 LinearEquation 实例。
288 ///
289 /// # 示例
290 ///
291 /// ```
292 /// use rs_math::graphical::arc::Arc;
293 /// use rs_math::geometry::linear_equation::LinearEquation;
294 ///
295 /// let arc = Arc::new(5.0, 1.2);
296 /// let tangent_equation = arc.tangent_at_point(0.5);
297 /// ```
298 pub fn tangent_at_point(&self, angle: f64) -> LinearEquation {
299 // 计算两个相邻点的坐标
300 let (x1, y1) = self.point_on_arc(angle);
301 let epsilon = 1e-8;
302 let (x2, y2) = self.point_on_arc(angle + epsilon);
303
304 // 计算切线方程的一般式表示
305 let a = y2 - y1;
306 let b = x1 - x2;
307 let c = x2 * y1 - x1 * y2;
308
309 // 返回切线方程的 LinearEquation 实例
310 LinearEquation { a, b, c }
311 }
312 /// 计算圆弧上给定角度处的法线方程。
313 ///
314 /// # 参数
315 ///
316 /// * `angle` - 圆弧上的角度,以弧度表示。
317 ///
318 /// # 返回值
319 ///
320 /// 返回一个包含法线方程的一般式表示的 LinearEquation 实例。
321 ///
322 /// # 示例
323 ///
324 /// ```
325 /// use rs_math::graphical::arc::Arc;
326 /// use rs_math::geometry::linear_equation::LinearEquation;
327 ///
328 /// let arc = Arc::new(5.0, 1.2);
329 /// let normal_equation = arc.normal_at_point(0.5);
330 /// ```
331 pub fn normal_at_point(&self, angle: f64) -> LinearEquation {
332 // 计算切线方程的斜率
333 let tangent_slope = -(self.radius * self.theta.sin()) / (self.radius * self.theta.cos());
334
335 // 计算法线斜率
336 let normal_slope = -1.0 / tangent_slope;
337
338 // 计算法线方程的常数
339 let (x0, y0) = self.point_on_arc(angle);
340 let normal_constant = y0 - normal_slope * x0;
341
342 // 返回法线方程的 LinearEquation 实例
343 LinearEquation {
344 a: normal_slope,
345 b: -1.0,
346 c: normal_constant,
347 }
348 }
349}