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}