# 三角形 Trigonometry

# 角度与弧度

# 角度

把一个圆周平均分成360份,其中每一份都是1º的角。这种以“度”作为单位度量角度单位制叫做角度制。

下图使我们常见的180º角度尺:

# 弧度

长度为半径长的弧,所对的圆心角是1弧度(Radian),用符号rad表示。

半径为r的圆的圆心角α所对的弧度长为l,那么角α的弧度数的绝对值是|α| = l/r

# 换算

360º = 2π rad
180º  = π rad

1º =(π / 180)rad ≈ 0.01745 rad
1 rad =180 /π)º ≈ 57.30º

α 度的角 =  α ·(π / 180)rad

1
2
3
4
5
6
7
8

常用的角度与弧度对照图

# 三角函数

# 在直角三角形ABC中,∠C = 90º

  • 正弦(Sine):sinA = ∠A的对边斜边的比
  • 余弦(Cosine) :cosA = ∠A的邻边斜边的比
  • 正切(Tangent):tanA = ∠A的对边邻边的比
  • sin²A + cos²A = 1

# 在单位圆(Unit Circle)中,任意角 α 的三角函数(Trigonometric Function)

在相似三角形 Rt△ABC 与 Rt△AB′C′ 中,对于∠A,对边与斜边的比是一致的,邻边与斜边的比也是一致的。所以我们力求简单与方便计算,设定斜边为1,单位圆刚好能满足这个条件。

  • 圆的圆心与直角坐标系的原点重合,圆的半径 r = 1,圆周上任意一点的坐标为(x, y)
  • 自变量为角 α
  • 函数是圆周上的坐标,或坐标和坐标的比值:sin α = y,cos α = x,tan α = y / x (x≠0)

# 三角函数在各个象限的取值

第一象限 第二象限 第三象限 第四象限 x轴 y轴
sin α >0 >0 <0 <0 0 ±1
cos α >0 <0 <0 >0 ±1 0
tan α >0 <0 >0 <0 0 /

# 正弦曲线

  • y = sin x, x∈R, y∈[–1,1],周期为2π,函数图像以 x = (π/2) + kπ 为对称轴
  • y = arcsin x, x∈[–1,1], y∈[–π/2,π/2]
  • sin x = 0 ←→ arcsin x = 0
  • sin x = 1/2 ←→ arcsin x = π/6
  • sin x = √2/2 ←→ arcsin x = π/4
  • sin x = 1 ←→ arcsin x = π/2

# 余弦曲线

  • y = cos x, x∈R, y∈[–1,1],周期为2π,函数图像以 x = kπ 为对称轴
  • y = arccos x, x∈[–1,1], y∈[0,π]
  • cos x = 0 ←→ arccos x = π/2
  • cos x = 1/2 ←→ arccos x = π/3
  • cos x = √2/2 ←→ arccos x = π/4
  • cos x = 1 ←→ arccos x = 0

# 三角函数线

图中的三条彩色线段 MP、OM、AT,分别叫正弦线、余弦线、正切线,统称为三角函数线

# 曲线视频

# 一些公式

# 平方

# 任意角α与-α的三角函数值之间的关系

# 两角和与差

# 常见问题

# 一个点是否在三角形中?

我们可以简单的观察下面两种情况:

  • P点在△ABC外:
  • P点在△ABC内:

可以看得出如果P点在三角形内的话,P点都在三角形边向量的左侧。我们是如何来判断一点在一个向量的某一边呢?我们知道两个向量的叉乘的结果可以判断这个两个向量是否同向,我们这里计算出每条边与边的起始点与P点连接的线段的叉乘,来判断点P是否与每条边同向,可以列出式子:

  • Corss(AB,AP)
  • Corss(BC,BP)
  • Corss(CA,CP)

如果说这三个结果都为正,那么说明P点都在三角形的三边的一侧。简单的实现:

static bool insideTriangle(int x, int y, const Vector3f* _v)
{
    // Implement this function to check if the point (x, y) 
    // is inside the triangle represented by _v[0], _v[1], _v[2]
    Vector3f point(x + 0.5f, y + 0.5f, 1);
    for (int i = 0; i < 3; i++)
    {
        Vector3f triangle2point = point - _v[i];
        int index = (i + 1) % 3;
        Vector3f triangleP2P = _v[index] - _v[i];
        // case x , y cross equal z 
        if (triangleP2P.cross(triangle2point).z() < 0)
        {
            return false;
        }
    }

    return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

使用重心求法 (opens new window)

# 三角形重心

设P点的坐标(α, β, γ),为三角形的重心坐标。

我们这里简单的推导一下,:

  1. 根据向量的线性相关:AP = βAB + γAC
  2. 拆分上面式子:A - P = β(A - B) + γ(A - C)
  3. 整理得到:P = (1-β-γ)A + βB + γC = αA + βB + γC
  4. α = 1 - γ - β
  5. 0 < α < 1, 0 < β < 1, 0 < γ < 1

从上面可以看出这里的重心点P可以有很多值,只需要满足以上列举出来的规则。

我们使用距离比例算法来简单的推导实现,我们知道当α = 0 时,点p在BC线上,当α = 1 时,点p就是点A。我们可以简单认为 α 的值就是A点到BC线距离的比例,不过是反比例。因为一个点带入一个直线方程求到的解就是该点到方程的近似距离,然后就可以列出计算方式:(这里的0、1、2表示的是三角形的三个顶点的索引,也就是A、B、C点)

  • α = f12(x, y)/f12(x0, y0) :点 PBC 线的距离与点 ABC 线的距离的比例
  • β = f20(x, y)/f20(x1, y1) :点 PCA 线的距离与点 BCA 线的距离的比例
  • γ = f01(x, y)/f01(x2, y2) :点 PAB 线的距离与点 CAB 线的距离的比例

我们可以根据直线公式获得:

  • f01(x, y)=(y0 − y1)x + (x1 − x0)y + x0y1 − x1y0,
  • f12(x, y)=(y1 − y2)x + (x2 − x1)y + x1y2 − x2y1,
  • f20(x, y)=(y2 − y0)x + (x0 − x2)y + x2y0 − x0y2.

最终就可以求解出这个坐标,简单实现:

static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector4f *v)
{
    float c1 = (x * (v[1].y() - v[2].y()) + (v[2].x() - v[1].x()) * y + v[1].x() * v[2].y() - v[2].x() * v[1].y()) / (v[0].x() * (v[1].y() - v[2].y()) + (v[2].x() - v[1].x()) * v[0].y() + v[1].x() * v[2].y() - v[2].x() * v[1].y());
    float c2 = (x * (v[2].y() - v[0].y()) + (v[0].x() - v[2].x()) * y + v[2].x() * v[0].y() - v[0].x() * v[2].y()) / (v[1].x() * (v[2].y() - v[0].y()) + (v[0].x() - v[2].x()) * v[1].y() + v[2].x() * v[0].y() - v[0].x() * v[2].y());
    float c3 = (x * (v[0].y() - v[1].y()) + (v[1].x() - v[0].x()) * y + v[0].x() * v[1].y() - v[1].x() * v[0].y()) / (v[2].x() * (v[0].y() - v[1].y()) + (v[1].x() - v[0].x()) * v[2].y() + v[0].x() * v[1].y() - v[1].x() * v[0].y());
    return {c1, c2, c3};
}
1
2
3
4
5
6
7

重心讲解1 (opens new window) 重心讲解2 (opens new window)

上次更新: 1/12/2021, 11:21:04 PM