zoukankan      html  css  js  c++  java
  • 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)));
    }
    
  • 相关阅读:
    Jzoj4822 完美标号
    Jzoj4822 完美标号
    Jzoj4792 整除
    Jzoj4792 整除
    Educational Codeforces Round 79 A. New Year Garland
    Good Bye 2019 C. Make Good
    ?Good Bye 2019 B. Interesting Subarray
    Good Bye 2019 A. Card Game
    力扣算法题—088扰乱字符串【二叉树】
    力扣算法题—086分隔链表
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/20201012day33-002.html
Copyright © 2011-2022 走看看