为了学好Rust也是拼了系列-数学库-三角形

为了学好Rust也是拼了系列-数学库-三角形

定义

三角形是一个具有三条边和三个角的几何形状。以下是三角形的一些基本特性:

  1. 三边: 三角形有三条边,分别记为 <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a、 <math xmlns="http://www.w3.org/1998/Math/MathML"> b b </math>b和 <math xmlns="http://www.w3.org/1998/Math/MathML"> c c </math>c。

  2. 三角形的内角和: 任何三角形的内角和都等于180度(或π弧度)。这可以表示为等式: <math xmlns="http://www.w3.org/1998/Math/MathML"> ∠ A + ∠ B + ∠ C = 18 0 ∘ 或 π 弧度 \angle A + \angle B + \angle C = 180^\circ \text{ 或 } \pi \text{ 弧度} </math>∠A+∠B+∠C=180∘ 或 π 弧度

  3. 三角形的分类: 三角形根据边和角的性质可以分为不同的类型,包括:

    • 等边三角形: 三条边都相等。
    • 等腰三角形: 至少两条边相等。
    • 直角三角形: 有一个90度的角。
    • 锐角三角形: 三个角都小于90度。
    • 钝角三角形: 有一个角大于90度。
  4. 勾股定理: 对于直角三角形,勾股定理成立,即: <math xmlns="http://www.w3.org/1998/Math/MathML"> a 2 + b 2 = c 2 a^2 + b^2 = c^2 </math>a2+b2=c2 这里, <math xmlns="http://www.w3.org/1998/Math/MathML"> c c </math>c是斜边, <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a和 <math xmlns="http://www.w3.org/1998/Math/MathML"> b b </math>b是直角边。

  5. 三角形的面积: 三角形的面积可以用以下公式之一来计算:

    • 使用三角形的底和高: <math xmlns="http://www.w3.org/1998/Math/MathML"> 面积 = 1 2 × 底 × 高 \text{面积} = \frac{1}{2} \times \text{底} \times \text{高} </math>面积=21×底×高
    • 使用三边的长度(海伦公式): <math xmlns="http://www.w3.org/1998/Math/MathML"> 面积 = s ⋅ ( s − a ) ⋅ ( s − b ) ⋅ ( s − c ) \text{面积} = \sqrt{s \cdot (s-a) \cdot (s-b) \cdot (s-c)} </math>面积=s⋅(s−a)⋅(s−b)⋅(s−c) 这里, <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s是半周长, <math xmlns="http://www.w3.org/1998/Math/MathML"> s = a + b + c 2 s = \frac{a+b+c}{2} </math>s=2a+b+c。

Rust结构如下

rust 复制代码
#[derive(Debug, PartialEq)]
pub struct Triangle {
    pub vertex_a: Point,
    pub vertex_b: Point,
    pub vertex_c: Point,
}

内切圆

内切圆是一个与三角形的三条边都相切的圆。设三角形的三边长度分别为 <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a、 <math xmlns="http://www.w3.org/1998/Math/MathML"> b b </math>b 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> c c </math>c,对应的三个内角为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∠ A \angle A </math>∠A、 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∠ B \angle B </math>∠B 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∠ C \angle C </math>∠C。

内切圆半径 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r 可以通过以下方式计算:

  1. 半周长 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s: 首先计算三角形的半周长,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> s = a + b + c 2 s = \frac{a + b + c}{2} </math>s=2a+b+c。

  2. 内切圆半径 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r: 利用半周长,内切圆半径可以通过以下公式计算: <math xmlns="http://www.w3.org/1998/Math/MathML"> r = 三角形的面积 s r = \frac{\text{三角形的面积}}{s} </math>r=s三角形的面积

  3. 三角形的面积 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A: 三角形的面积可以使用海伦公式计算: <math xmlns="http://www.w3.org/1998/Math/MathML"> A = s ⋅ ( s − a ) ⋅ ( s − b ) ⋅ ( s − c ) A = \sqrt{s \cdot (s - a) \cdot (s - b) \cdot (s - c)} </math>A=s⋅(s−a)⋅(s−b)⋅(s−c)

程序解如下

swift 复制代码
impl Triangle {
    // 构造函数,创建一个新的三角形实例
    pub fn new(a: Point, b: Point, c: Point) -> Self {
        Triangle {
            vertex_a: a,
            vertex_b: b,
            vertex_c: c,
        }
    }

    // 计算三角形的边长
    pub fn side_length(&self, start: &Point, end: &Point) -> f64 {
        ((end.x - start.x).powi(2) + (end.y - start.y).powi(2)).sqrt()
    }

    // 计算三角形的周长
    pub fn perimeter(&self) -> f64 {
        let side_ab = self.side_length(&self.vertex_a, &self.vertex_b);
        let side_bc = self.side_length(&self.vertex_b, &self.vertex_c);
        let side_ca = self.side_length(&self.vertex_c, &self.vertex_a);
        side_ab + side_bc + side_ca
    }

    // 计算三角形的面积
    pub fn area(&self) -> f64 {
        let side_ab = self.side_length(&self.vertex_a, &self.vertex_b);
        let side_bc = self.side_length(&self.vertex_b, &self.vertex_c);
        let side_ca = self.side_length(&self.vertex_c, &self.vertex_a);
        let s = self.perimeter() / 2.0; // 半周长
        (s * (s - side_ab) * (s - side_bc) * (s - side_ca)).sqrt()
    }


    // 计算三角形的半周长
    fn semi_perimeter(&self) -> f64 {
        let side_ab = self.side_length(&self.vertex_a, &self.vertex_b);
        let side_bc = self.side_length(&self.vertex_b, &self.vertex_c);
        let side_ca = self.side_length(&self.vertex_c, &self.vertex_a);
        (side_ab + side_bc + side_ca) / 2.0
    }


    // 计算内切圆
    pub fn in_circle(&self) -> Circle {
        let s = self.semi_perimeter();
        let side_ab = self.side_length(&self.vertex_a, &self.vertex_b);
        let side_bc = self.side_length(&self.vertex_b, &self.vertex_c);
        let side_ca = self.side_length(&self.vertex_c, &self.vertex_a);

        let radius = self.area() / s;

        // 计算内切圆的中心坐标
        let center_x = (side_bc * self.vertex_a.x + side_ca * self.vertex_b.x + side_ab * self.vertex_c.x) / (side_ab + side_bc + side_ca);
        let center_y = (side_bc * self.vertex_a.y + side_ca * self.vertex_b.y + side_ab * self.vertex_c.y) / (side_ab + side_bc + side_ca);

        Circle {
            x: center_x,
            y: center_y,
            radius,
        }
    }
}

旋转三角形

当一个点 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y) 绕着另一个点 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( h , k ) (h, k) </math>(h,k) 逆时针旋转一个角度 <math xmlns="http://www.w3.org/1998/Math/MathML"> θ \theta </math>θ 时,新的坐标 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x ′ , y ′ ) (x', y') </math>(x′,y′) 可以通过以下公式计算得到:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> x ′ = ( x − h ) cos ⁡ ( θ ) − ( y − k ) sin ⁡ ( θ ) + h y ′ = ( x − h ) sin ⁡ ( θ ) + ( y − k ) cos ⁡ ( θ ) + k \begin{align*} x' &= (x - h) \cos(\theta) - (y - k) \sin(\theta) + h \\ y' &= (x - h) \sin(\theta) + (y - k) \cos(\theta) + k \end{align*} </math>x′y′=(x−h)cos(θ)−(y−k)sin(θ)+h=(x−h)sin(θ)+(y−k)cos(θ)+k

在这里, <math xmlns="http://www.w3.org/1998/Math/MathML"> cos ⁡ ( θ ) \cos(\theta) </math>cos(θ) 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> sin ⁡ ( θ ) \sin(\theta) </math>sin(θ) 分别是旋转角度 <math xmlns="http://www.w3.org/1998/Math/MathML"> θ \theta </math>θ 的余弦和正弦值。

对于三角形,每个顶点 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x , y ) (x, y) </math>(x,y) 绕着中心点 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( h , k ) (h, k) </math>(h,k) 逆时针旋转一个角度 <math xmlns="http://www.w3.org/1998/Math/MathML"> θ \theta </math>θ 后的新坐标可以通过上述公式计算得到。

ini 复制代码
// 绕着指定点旋转三角形,返回新的三角形实例
pub fn rotate_around_point(&self, center: &Point, angle_degrees: f64) -> Triangle {
    // 将角度转换为弧度
    let angle_radians = angle_degrees.to_radians();

    // 定义旋转矩阵
    let rotation_matrix = [
        [angle_radians.cos(), -angle_radians.sin()],
        [angle_radians.sin(), angle_radians.cos()],
    ];

    // 对每个顶点进行旋转
    let new_vertex_a = self.rotate_point(&self.vertex_a, center, rotation_matrix);
    let new_vertex_b = self.rotate_point(&self.vertex_b, center, rotation_matrix);
    let new_vertex_c = self.rotate_point(&self.vertex_c, center, rotation_matrix);

    Triangle {
        vertex_a: new_vertex_a,
        vertex_b: new_vertex_b,
        vertex_c: new_vertex_c,
    }
}
/// 旋转单个点
fn rotate_point(&self, point: &Point, center: &Point, matrix: [[f64; 2]; 2]) -> Point {
    let translated_x = point.x - center.x;
    let translated_y = point.y - center.y;

    let rotated_x = matrix[0][0] * translated_x + matrix[0][1] * translated_y;
    let rotated_y = matrix[1][0] * translated_x + matrix[1][1] * translated_y;

    Point {
        x: rotated_x + center.x,
        y: rotated_y + center.y,
    }
}

判断点是否在三角形内

判断一个点是否在三角形内可以使用重心坐标法。重心坐标是一组数值,描述了一个点在三角形内的位置。在一个平面三角形 ABC 中,给定点 P 的重心坐标 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( p 1 , p 2 , p 3 ) (p_1, p_2, p_3) </math>(p1,p2,p3) 满足以下条件:

  1. <math xmlns="http://www.w3.org/1998/Math/MathML"> p 1 + p 2 + p 3 = 1 p_1 + p_2 + p_3 = 1 </math>p1+p2+p3=1
  2. <math xmlns="http://www.w3.org/1998/Math/MathML"> p 1 ⋅ A + p 2 ⋅ B + p 3 ⋅ C = P p_1 \cdot A + p_2 \cdot B + p_3 \cdot C = P </math>p1⋅A+p2⋅B+p3⋅C=P

其中,A、B、C 是三角形的三个顶点,P 是要判断的点。

如果 <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 ≤ p 1 , p 2 , p 3 ≤ 1 0 \leq p_1, p_2, p_3 \leq 1 </math>0≤p1,p2,p3≤1,则点 P 在三角形内。如果有一个 <math xmlns="http://www.w3.org/1998/Math/MathML"> p i < 0 p_i < 0 </math>pi<0 或 <math xmlns="http://www.w3.org/1998/Math/MathML"> p i > 1 p_i > 1 </math>pi>1,则点 P 在三角形外。

rust 复制代码
// 判断点是否在三角形内
pub fn point_inside_triangle(&self, p: &Point) -> bool {
    // 计算重心坐标
    let barycentric_coords = self.barycentric_coordinates(p);

    // 判断点是否在三角形内
    barycentric_coords.iter().all(|&coord| coord >= 0.0 && coord <= 1.0)
}

// 辅助方法,计算点的重心坐标
pub fn barycentric_coordinates(&self, p: &Point) -> [f64; 3] {
    // 计算三个子三角形的面积
    let area_triangle = self.area();
    let area_sub_triangle_a = Triangle::new(p.clone(), self.vertex_b.clone(), self.vertex_c.clone()).area();
    let area_sub_triangle_b = Triangle::new(self.vertex_a.clone(), p.clone(), self.vertex_c.clone()).area();
    let area_sub_triangle_c = Triangle::new(self.vertex_a.clone(), self.vertex_b.clone(), p.clone()).area();

    // 计算重心坐标
    let p1 = area_sub_triangle_a / area_triangle;
    let p2 = area_sub_triangle_b / area_triangle;
    let p3 = area_sub_triangle_c / area_triangle;

    [p1, p2, p3]
}

垂心、重心、内心、外心计算

垂心、重心、内心、外心的数学解法,我们将考虑一个一般的三角形,其中顶点分别为 <math xmlns="http://www.w3.org/1998/Math/MathML"> A ( x 1 , y 1 ) A(x_1, y_1) </math>A(x1,y1), <math xmlns="http://www.w3.org/1998/Math/MathML"> B ( x 2 , y 2 ) B(x_2, y_2) </math>B(x2,y2), <math xmlns="http://www.w3.org/1998/Math/MathML"> C ( x 3 , y 3 ) C(x_3, y_3) </math>C(x3,y3)。

  1. 垂心(Orthocenter):

    • 垂心是三角形的三条高的交点。
    • 设 <math xmlns="http://www.w3.org/1998/Math/MathML"> H H </math>H 为垂心的坐标,分别在三条高 <math xmlns="http://www.w3.org/1998/Math/MathML"> B C : x = x 1 BC: x = x_1 </math>BC:x=x1, <math xmlns="http://www.w3.org/1998/Math/MathML"> A C : y = y 2 AC: y = y_2 </math>AC:y=y2, <math xmlns="http://www.w3.org/1998/Math/MathML"> A B : y = y 3 − ( x 3 − x 1 ) ( y 1 − y 2 ) x 2 − x 1 AB: y = y_3 - \frac{(x_3 - x_1)(y_1 - y_2)}{x_2 - x_1} </math>AB:y=y3−x2−x1(x3−x1)(y1−y2) 上求交点。
    • 解方程组: <math xmlns="http://www.w3.org/1998/Math/MathML"> x = x 1 x = x_1 </math>x=x1 <math xmlns="http://www.w3.org/1998/Math/MathML"> y = y 2 y = y_2 </math>y=y2 <math xmlns="http://www.w3.org/1998/Math/MathML"> y = y 3 − ( x 3 − x 1 ) ( y 1 − y 2 ) x 2 − x 1 y = y_3 - \frac{(x_3 - x_1)(y_1 - y_2)}{x_2 - x_1} </math>y=y3−x2−x1(x3−x1)(y1−y2)
    • 求解得到垂心坐标 <math xmlns="http://www.w3.org/1998/Math/MathML"> H ( x H , y H ) H(x_H, y_H) </math>H(xH,yH)。
  2. 重心(Centroid):

    • 重心是三角形的三条中线的交点,中线是每个顶点和对边中点的连线。
    • 重心坐标为 <math xmlns="http://www.w3.org/1998/Math/MathML"> G ( x 1 + x 2 + x 3 3 , y 1 + y 2 + y 3 3 ) G\left(\frac{x_1 + x_2 + x_3}{3}, \frac{y_1 + y_2 + y_3}{3}\right) </math>G(3x1+x2+x3,3y1+y2+y3)。
  3. 内心(Incenter):

    • 内心是三角形的三条角平分线的交点。
    • 设 <math xmlns="http://www.w3.org/1998/Math/MathML"> I I </math>I 为内心的坐标,角平分线的方程可以通过点斜式 <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 1 = m ( x − x 1 ) y - y_1 = m(x - x_1) </math>y−y1=m(x−x1) 求解,其中 <math xmlns="http://www.w3.org/1998/Math/MathML"> m m </math>m 是角平分线的斜率。
    • 设 <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a, <math xmlns="http://www.w3.org/1998/Math/MathML"> b b </math>b, <math xmlns="http://www.w3.org/1998/Math/MathML"> c c </math>c 为三边的长度, <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s 为半周长。则角平分线的斜率 <math xmlns="http://www.w3.org/1998/Math/MathML"> m m </math>m 分别为: <math xmlns="http://www.w3.org/1998/Math/MathML"> m A = y 2 − y 1 x 2 − x 1 m_A = \frac{y_2 - y_1}{x_2 - x_1} </math>mA=x2−x1y2−y1 <math xmlns="http://www.w3.org/1998/Math/MathML"> m B = y 3 − y 2 x 3 − x 2 m_B = \frac{y_3 - y_2}{x_3 - x_2} </math>mB=x3−x2y3−y2 <math xmlns="http://www.w3.org/1998/Math/MathML"> m C = y 1 − y 3 x 1 − x 3 m_C = \frac{y_1 - y_3}{x_1 - x_3} </math>mC=x1−x3y1−y3
    • 解方程组: <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 1 = m A ⋅ ( x − x 1 ) y - y_1 = m_A \cdot (x - x_1) </math>y−y1=mA⋅(x−x1) <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 2 = m B ⋅ ( x − x 2 ) y - y_2 = m_B \cdot (x - x_2) </math>y−y2=mB⋅(x−x2) <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 3 = m C ⋅ ( x − x 3 ) y - y_3 = m_C \cdot (x - x_3) </math>y−y3=mC⋅(x−x3)
    • 求解得到内心坐标 <math xmlns="http://www.w3.org/1998/Math/MathML"> I ( x I , y I ) I(x_I, y_I) </math>I(xI,yI)。
  4. 外心(Circumcenter):

    • 外心是三角形的三条边的垂直平分线的交点。
    • 设 <math xmlns="http://www.w3.org/1998/Math/MathML"> O O </math>O 为外心的坐标,垂直平分线的方程可以通过求两个边中点的斜率和斜率的负倒数得到。
    • 设 <math xmlns="http://www.w3.org/1998/Math/MathML"> M A B M_{AB} </math>MAB, <math xmlns="http://www.w3.org/1998/Math/MathML"> M B C M_{BC} </math>MBC, <math xmlns="http://www.w3.org/1998/Math/MathML"> M C A M_{CA} </math>MCA 分别为 <math xmlns="http://www.w3.org/1998/Math/MathML"> A B AB </math>AB, <math xmlns="http://www.w3.org/1998/Math/MathML"> B C BC </math>BC, <math xmlns="http://www.w3.org/1998/Math/MathML"> C A CA </math>CA 中点。垂直平分线的斜率分别为: <math xmlns="http://www.w3.org/1998/Math/MathML"> m A B = − x 2 − x 1 y 2 − y 1 m_{AB} = -\frac{x_2 - x_1}{y_2 - y_1} </math>mAB=−y2−y1x2−x1 <math xmlns="http://www.w3.org/1998/Math/MathML"> m B C = − x 3 − x 2 y 3 − y 2 m_{BC} = -\frac{x_3 - x_2}{y_3 - y_2} </math>mBC=−y3−y2x3−x2 <math xmlns="http://www.w3.org/1998/Math/MathML"> m C A = − x 1 − x 3 y 1 − y 3 m_{CA} = -\frac{x_1 - x_3}{y_1 - y_3} </math>mCA=−y1−y3x1−x3
    • 解方程组: <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 1 + y 2 2 = m A B ⋅ ( x − x 1 + x 2 2 ) y - \frac{y_1 + y_2}{2} = m_{AB} \cdot (x - \frac{x_1 + x_2}{2}) </math>y−2y1+y2=mAB⋅(x−2x1+x2) <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 2 + y 3 2 = m B C ⋅ ( x − x 2 + x 3 2 ) y - \frac{y_2 + y_3}{2} = m_{BC} \cdot (x - \frac{x_2 + x_3}{2}) </math>y−2y2+y3=mBC⋅(x−2x2+x3) <math xmlns="http://www.w3.org/1998/Math/MathML"> y − y 3 + y 1 2 = m C A ⋅ ( x − x 3 + x 1 2 ) y - \frac{y_3 + y_1}{2} = m_{CA} \cdot (x - \frac{x_3 + x_1}{2}) </math>y−2y3+y1=mCA⋅(x−2x3+x1)
    • 求解得到外心坐标 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( x O , y O ) O(x_O, y_O) </math>O(xO,yO)。

程序解如下

swift 复制代码
// 计算垂心
pub fn orthocenter(&self) -> Point {
    let x_h = self.vertex_a.x;
    let y_h = self.vertex_b.y;
    Point { x: x_h, y: y_h }
}

// 计算重心
pub fn centroid(&self) -> Point {
    let x_g = (self.vertex_a.x + self.vertex_b.x + self.vertex_c.x) / 3.0;
    let y_g = (self.vertex_a.y + self.vertex_b.y + self.vertex_c.y) / 3.0;
    Point { x: x_g, y: y_g }
}

// 计算内心
pub fn incenter(&self) -> Point {
    let a = self.vertex_b.distance_to(&self.vertex_c);
    let b = self.vertex_c.distance_to(&self.vertex_a);
    let c = self.vertex_a.distance_to(&self.vertex_b);


    let x_i = (a * self.vertex_a.x + b * self.vertex_b.x + c * self.vertex_c.x) / (a + b + c);
    let y_i = (a * self.vertex_a.y + b * self.vertex_b.y + c * self.vertex_c.y) / (a + b + c);

    Point { x: x_i, y: y_i }
}

// 计算外心
pub fn circumcenter(&self) -> Point {
    let m_ab = Point {
        x: (self.vertex_a.x + self.vertex_b.x) / 2.0,
        y: (self.vertex_a.y + self.vertex_b.y) / 2.0,
    };

    let m_bc = Point {
        x: (self.vertex_b.x + self.vertex_c.x) / 2.0,
        y: (self.vertex_b.y + self.vertex_c.y) / 2.0,
    };

    let m_ca = Point {
        x: (self.vertex_c.x + self.vertex_a.x) / 2.0,
        y: (self.vertex_c.y + self.vertex_a.y) / 2.0,
    };

    let m_ab_slope = -(self.vertex_b.x - self.vertex_a.x) / (self.vertex_b.y - self.vertex_a.y);
    let m_bc_slope = -(self.vertex_c.x - self.vertex_b.x) / (self.vertex_c.y - self.vertex_b.y);
    let m_ca_slope = -(self.vertex_a.x - self.vertex_c.x) / (self.vertex_a.y - self.vertex_c.y);

    let x_o = (m_ab.y - m_ab_slope * m_ab.x + m_bc.y - m_bc_slope * m_bc.x + m_ca.y - m_ca_slope * m_ca.x)
        / (m_ab_slope + m_bc_slope + m_ca_slope);

    let y_o = m_ab_slope * (x_o - m_ab.x) + m_ab.y;

    Point { x: x_o, y: y_o }
}

判断三角形种类

已知三个点求这个三角形属于直角、锐角、钝角中的哪一种,计算逻辑如下。

  1. 计算两点之间的距离:

    • 两点 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 1 ( x 1 , y 1 ) P_1(x_1, y_1) </math>P1(x1,y1) 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> P 2 ( x 2 , y 2 ) P_2(x_2, y_2) </math>P2(x2,y2) 之间的距离可以使用欧几里得距离公式计算: <math xmlns="http://www.w3.org/1998/Math/MathML"> d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2} </math>d=(x2−x1)2+(y2−y1)2
  2. 计算三角形的角度:

    • 对于三角形ABC,以A为例,可以使用余弦定理计算角A( <math xmlns="http://www.w3.org/1998/Math/MathML"> ∠ A \angle A </math>∠A): <math xmlns="http://www.w3.org/1998/Math/MathML"> cos ⁡ ( ∠ A ) = b 2 + c 2 − a 2 2 b c \cos(\angle A) = \frac{b^2 + c^2 - a^2}{2bc} </math>cos(∠A)=2bcb2+c2−a2 其中, <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a, <math xmlns="http://www.w3.org/1998/Math/MathML"> b b </math>b, <math xmlns="http://www.w3.org/1998/Math/MathML"> c c </math>c 分别是BC、CA、AB三边的长度。
  3. 弧度与角度的转换:

    • 使用反余弦函数将余弦值转换为角度: <math xmlns="http://www.w3.org/1998/Math/MathML"> angle_rad = cos ⁡ − 1 ( cos ⁡ ( ∠ A ) ) \text{angle\_rad} = \cos^{-1}(\cos(\angle A)) </math>angle_rad=cos−1(cos(∠A)) <math xmlns="http://www.w3.org/1998/Math/MathML"> angle_deg = angle_rad × 180 π \text{angle\_deg} = \text{angle\_rad} \times \frac{180}{\pi} </math>angle_deg=angle_rad×π180
  4. 分类三角形:

    • 如果三个角都小于90度,那么这是一个锐角三角形。
    • 如果有一个角等于90度,那么这是一个直角三角形。
    • 如果有一个角大于90度,那么这是一个钝角三角形。

程序解如下

rust 复制代码
// 计算三角形的角度
pub fn classify_triangle(&self) -> TriangleType {
    let (angle_a, angle_b, angle_c) = self.classify_angles();

    if angle_a < 90.0 && angle_b < 90.0 && angle_c < 90.0 {
        TriangleType::Acute
    } else if angle_a == 90.0 || angle_b == 90.0 || angle_c == 90.0 {
        TriangleType::Right
    } else {
        TriangleType::Obtuse
    }
}
// 计算三角形的角度
pub fn classify_angles(&self) -> (f64, f64, f64) {
    let angle_a = self.angle_between(&self.vertex_b, &self.vertex_c, &self.vertex_a);
    let angle_b = self.angle_between(&self.vertex_a, &self.vertex_c, &self.vertex_b);
    let angle_c = self.angle_between(&self.vertex_a, &self.vertex_b, &self.vertex_c);

    (angle_a, angle_b, angle_c)
}

// 计算两条边之间的角度
fn angle_between(&self, p1: &Point, p2: &Point, p3: &Point) -> f64 {
    let a = p1.distance_to(p2);
    let b = p2.distance_to(p3);
    let c = p3.distance_to(p1);

    let cos_angle = (a.powi(2) + b.powi(2) - c.powi(2)) / (2.0 * a * b);
    let angle_rad = cos_angle.acos();

    // 将弧度转换为角度
    let angle_deg = angle_rad.to_degrees();

    angle_deg
}
相关推荐
zopple7 小时前
常见的 Spring 项目目录结构
java·后端·spring
cjy0001119 小时前
springboot的 nacos 配置获取不到导致启动失败及日志不输出问题
java·spring boot·后端
小江的记录本10 小时前
【事务】Spring Framework核心——事务管理:ACID特性、隔离级别、传播行为、@Transactional底层原理、失效场景
java·数据库·分布式·后端·sql·spring·面试
sheji341610 小时前
【开题答辩全过程】以 基于springboot的校园失物招领系统为例,包含答辩的问题和答案
java·spring boot·后端
程序员cxuan10 小时前
人麻了,谁把我 ssh 干没了
人工智能·后端·程序员
wuyikeer11 小时前
Spring Framework 中文官方文档
java·后端·spring
Victor35611 小时前
MongoDB(61)如何避免大文档带来的性能问题?
后端
Victor35611 小时前
MongoDB(62)如何避免锁定问题?
后端
wuyikeer12 小时前
Spring BOOT 启动参数
java·spring boot·后端
子木HAPPY阳VIP13 小时前
Ubuntu 22.04 VMware 设置固定IP配置
人工智能·后端·目标检测·机器学习·目标跟踪