计算几何摸黑(1)

作为一个刚学完向量的OJ看天选手,看了点计算几何,打算来记两笔。

首先先定义一下π的值:

// 法1:直接define
#define pi 3.14159265358979323846264338327950288
// 这样……可以说好处是直观吧
// 法2:∵cos π == -1 ∴π == arccos -1
const double pi = std::acos(-1);

最基本的构造

定义、输入输出、加法减法赋值和比较的重载和取向量的模

struct Vector // 向量类
{
    double x, y;
    // 构造方法
    Vector(const double a = 0.0, const double b = 0.0)
        : x(a), y(b) { }
    friend std::istream &operator>>(std::istream &Scanner, Vector &t)
    {
        Scanner >> t.x >> t.y;
        return Scanner;
    } // 重定义cin和ifstream
    friend std::ostream &operator<<(std::ostream &Printer, const Vector &t)
    {
        Printer << "(" << t.x << ", " << t.y << ")";
        return Printer;
    } // 重定义cout和ofstream
    inline double getNorm()
    {
        return std::sqrt(x * x + y * y);
    } // 求该向量的模
    /* 下面是加法减法和赋值什么的 */
    inline Vector operator+(const Vector &t)
    {
        return Vector(x + t.x, y + t.y);
    }
    Vector operator+=(const Vector &t)
    {
        x += t.x;
        y += t.y;
        return *this;
    }
    inline Vector operator-(const Vector &t)
    {
        return Vector(x - t.x, y - t.y);
    }
    Vector operator-=(const Vector &t)
    {
        x -= t.x;
        y -= t.y;
        return *this;
    }
    Vector operator<(const Vector &t)
    {
        return x < t.x || (x == t.x && y < t.y);    
    }
};
typedef Vector Point;

向量的点乘和叉乘

啊就这样,按照点乘和叉乘的定义写,以成员x和y来表示横纵坐标。

double mulDot(const Vector &x, const Vector &y)
{
    return x.x * y.x + x.y * y.y;
}
// 向量的点乘

double mulCross(const Vector &x, const Vector &y)
{
    return x.x * y.y - x.y * y.x;
}
// 向量的叉乘

向量的夹角

以下是向量点乘的定义,这个可以用求角

a⃗ b⃗ =|a⃗ ||b⃗ |cosa⃗ ,b⃗ 

通过这个公式,我们可以求ab的夹角的余弦,进而通过arccos求夹角的值。

double getAngle(Vector &x, Vector &y)
{
    return std::acos(mulDot(x, y) / x.getNorm() / y.getNorm());
}

向量的旋转

通过和角公式,我们可以求将α旋转θ度后得到的向量β

α⃗ =(x,y),β⃗ =(xcosθxsinθ,ysinθ+ycosθ)

所以,我们可以这样实现向量的旋转

Vector Rotate(const Vector &x, const double theta)
{
    return Vector(x.x * std::cos(theta) - x.y * std::sin(theta),
                  x.x * std::sin(theta) + x.y * std::cos(theta));
}

单位法向量

单位法向量就是把模长归一化的法向量,其中法向量就是过此向量起点,并与该向量垂直的向量。

Vector getNormal(const Vector &t)
{
    double L = t.getNorm();
    return Vector(-t.y / L, t.x / L);
      // 这里的原理就是把向量逆时针旋转π / 2,cos (π / 2) == 0, sin(π / 2) == 1代入Rotate(x, theta)的原理可得
}
posted @ 2017-04-21 17:55  Edward_Tsui  阅读(257)  评论(0编辑  收藏  举报