• 20201012day33 复习6:计算几何


    计算几何的一些东西(入门)

    矢量表示

    class CVector{
          double x,y;
    };
    

    表示从0到((x,y))的矢量。对矢量只关心方向和长度,不关心起点和终点
    2.

    CVector operator +(CVector p,CVector q){
          return CVector(p.x+q.x,p.y+q.y);
    }
    

    用法:c=a+b
    3.

    CVector operator -(CVector p, CVector q) {
          return CVector(p.x - q.x, p.y - q.y);
    }
    

    用法:c=a-b
    4.

    CVector operator *(double k, CVector p) {
    return CVector(k * p.x, k * p.y);
    }
    

    (oldsymbol{c}=foldsymbol{a}),f是double
    5.矢量的点积

    double operator *(Cvector p,CVector q){
          return p.x*q.x+p.y*q.y;
    }
    

    功能:求同向还是异向;求投影;求投影后用勾股定理求点到直线距离
    6.矢量模长

    double length(CVector p){
          return sqrt(p*p);
    }
    

    7.向量单位化
    将矢量除以自身的长度来得到同方向的单位矢量

    CVector unit(CVector p){
          return 1/length(p)*p;
    }
    

    8.矢量的投影长度
    矢量与该方向单位向量的点积
    注意:负数表示反方向

    double project(CVector p,CVector n){
          return dot(p,unit(n));
    }
    double dot(CVector p,CVector q){
          return p.x*q.x+p.y*q.y;
    }
    

    表示向量p在向量n上的投影p'

    b在a上的投影的模是(dfrac{oldsymbol{a} cdot oldsymbol{b}}{|oldsymbol{a}|})
    所以b在a上的投影即为(dfrac{oldsymbol{a} cdot oldsymbol{b}}{|oldsymbol{a}|} dfrac{oldsymbol{a}}{|oldsymbol{a}|}=oldsymbol{a}dfrac{oldsymbol{a} cdot oldsymbol{b}}{oldsymbol{a}^2})
    9.矢量的对称
    记b在a上的投影为(oldsymbol{S}=oldsymbol{a}dfrac{oldsymbol{a} cdot oldsymbol{b}}{oldsymbol{a}^2})
    则b关于a的对称为(oldsymbol{b-2(b-S)=2S-b=2adfrac{acdot b}{a^2}-b})
    10.向量的叉乘
    性质:在二维情况中,(oldsymbol{|p imes q|=|p||q|sin<p,q>})
    功能:求面积;求顺时针方向还是逆时针方向;判断是否在半平面上

    double operator ^(CVector p,CVector q){
          return p.x*q.y-q.x*p.y;
    }
    c=a^b;//a,b,c all is CVector type
    

    (oldsymbol{a imes b})为有向面积,可正可负,若a逆时针旋转小于180°可到b,则结果为正,否则结果为负

    11.叉积排序

    #include <iostream>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    struct Vector
    {
    double x, y;
    Vector(int xx, int yy) :x(xx), y(yy) { }
    Vector() { }
    double operator ^ (const Vector & v) const {
    return x*v.y - v.x*y;
    }
    };
    #define Point Vector
    Vector operator - (const Point & p1, const Point & p2)
    { //从A点指向B点的矢量AB可用B-A来表示
    return Vector(p1.x - p2.x, p1.y - p2.y); 
    //矢量从 p2指向p1 
    }
    bool operator < (const Point & p1, const Point & p2)
    {
    //如果p1^p2 〉0,说明p1经逆时针旋转<180度可以到p2,则 p1 < p2
    if ((Vector(p2 - Point(0, 0)) ^ 
    Vector(p1 - Point(0, 0))) > 0)
    return true;
    return false;
    }
    Point ps[60];
    int main()
    {
    int x, y;
    int n = 0;
    while (cin >> ps[n].x >> ps[n].y)
    ++n;
    sort(ps + 1, ps + n);
    cout << "(0,0)" << endl;
    for (int i = n - 1; i > 0; --i)
    cout << "(" << ps[i].x << ",“<< ps[i].y << ")" << endl;
    return 0;
    }
    

    12.矢量围成的三角形面积
    叉积的一半

    double area(CVector p, CVector q) {
          return p^q / 2; 
    }
    

    13.求多边形的面积
    基本思路是进行三角剖分。
    指定逆时针方向,枚举(vec{AB}),累加(dfrac{vec{A} imesvec{B}}{2})
    14.点、线的表示

    #define CPoint CVector
    class CPoint {
    double x, y;
    }
    class CLine {
    CPoint a, b;
    }
    

    15.常用函数与常数

    double PI = acos(-1);
    double INF = 1e20;
    double EPS = 1e-6; //精度不是越高
    bool IsZero(double x) {
          return –EPS < x && x < EPS;
    }
    bool FLarger(double a, double b) {
          return a - b > EPS;
    }
    bool FLess(double a, double b) {
          return b - a > EPS;
    }
    

    16.点与矢量

    CVector operator -(CPoint b, CPoint a) 
    {
          return CVector(b.x – a.x, b.y – a.y);
    } // c = a – b;
    CPoint operator +(CPoint a, CVector p) {
          return CPoint(a.x + p.x, a.y + p.y);
    } // p = p + v; p是点,v是向量
    

    17.点与点距离
    利用两点之间模长

    double dist(CPoint p, CPoint q) {
          return length(p – q);
    } //从A点指向B点的矢量AB可用来
    

    点与线距离
    利用叉积求面积,然后除以底边即为高

    double dist(CPoint p, CLine l) {
          return fabs((p – l.a) ^ (l.b – l.a)) / length(l.b – l.a);
    }
    

    19.点绕点旋转(二维)
    旋转矢量AB到AC注:
    在xy平面上逆时针旋转α角(弧度制)

    CPoint rotate(CPoint b, CPoint a,double alpha) {//返回点C坐标
    CVector p = b – a;
    return CPoint(a.x + (p.x * cos(alpha)- p.y * sin(alpha)), a.y + (p.x * sin(alpha)+ p.y * cos(alpha));
    }
    

    20.点在直线左侧还右侧
    直线用两个点A,B表示,是有方向的,假设方向是A->B

    int sideOfLine(Point p, Point a, Point b)
    { //判断p在直线 a->b的哪一侧
          double result = (b - a) ^ (p - a);
          if (IsZero(result))
          return 0; //p 在 a->b上
          else if (result > 0)
          return 1; //p在a->b左侧
          else
          return -1; //p在a->b右侧
    }
    

    21.过点作线的垂线(二维)

    CLine Vertical(CPoint p, CLine l) {
     return CLine(p,p + (rotate(l.b, l.a, PI / 2) – l.a));
    }
    

    22.点到线的垂足
    利用点积求投影,进而求出垂足
    应用:求对称点
    注:在平面上也可作垂线,利用线与线交点(后面会提到)

    CPoint foot(CPoint p, CLine l) {
     return l.a + project(p – l.a, l.b – l.a)* unit(l.b – l.a);
    } 
    

    23.线与线夹角
    利用投影(也可以利用叉积或余弦定理)
    应用:两直线的位置关系,射线夹角(注意方向即可)

    double angle(CLine l, CLine m) {
     return acos(fabs(project(l.b – l.a, m.b – m.a)/ length(l.b – l.a)));
    }
    
  • 相关阅读:
    RN 各种小问题
    迷宫问题的求解(回溯法、深度优先遍历、广度优先遍历)
    java 对象的初始化流程(静态成员、静态代码块、普通代码块、构造方法)
    java四种访问权限
    八大排序之归并排序
    八大排序之堆排序
    八大排序之选择排序
    八大排序之快速排序
    Java动态代理和cglib动态代理
    类加载器 ClassLoder详解
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/20201012day33-002.html
Copyright © 2020-2023  润新知