计算几何模板(1):最最基本的东西

这里是最基本,

有多基本?


1.头文件:

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
应该够了

2.几个常量

eps:正的极小值。

由于c艹里$double$运算的误差,我们人为设定一个$eps$,认为绝对值不比他大的都是零。

Pi:即π(圆周率)。

直接$acos(-1.0)$,或者装x手打。

const double eps = 1e-8;
const double Pi = acos(-1.0);
int dcmp(const double x)
{
    if(fabs(x)<=eps)return 0;
    return x>0?1:-1;
}
常量们

3.(二维平面上的)点与向量

正常都会用横纵坐标$(x,y)$表示一个点,还有一个向量。

然后

向量加、减向量:横纵坐标相加、减。

向量乘、除常数:横纵坐标乘、除常数。

向量点积:$x_1*x_2+y_1*y_2$,同时也有$a*b=|a|*|b|*cos<a,b>$;

和物理学中计算功的方法一样。

向量叉积:$x_1*y_2-x_2*y_1$,同时$a$^$b=|a|*|b|*sin<a,b>$;

两个向量叉积就是围成的平行四边形的有向面积

级角排序:先$x$递增后$y$递增。

struct Point
{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (const Point&a)const{return Point(x+a.x,y+a.y);}
    Point operator - (const Point&a)const{return Point(x-a.x,y-a.y);}
    Point operator * (const double&a)const{return Point(x*a,y*a);}
    Point operator / (const double&a)const{return Point(x/a,y/a);}
    double operator * (const Point&a)const{return x*a.x+y*a.y;}
    double operator ^ (const Point&a)const{return x*a.y-y*a.x;}
    bool operator < (const Point&a)const{return (x!=a.x)?x<a.x:y<a.y;}
    bool operator == (const Point&a)const{return !dcmp(x-a.x)&&!dcmp(y-a.y);}
};
typedef Point Vector;
点和向量

 4.相关基本操作

向量的模:本来是$\sqrt{x^2+y^2}$,有点积之后可以自乘开根号。

double lth(const Vector a){return sqrt(a*a);}
%

点、向量级角:直接$y/x$之后直接$atan2$一下,具体关于$atan2$戳

向量夹角:借助强大的$cmath$直接点积或叉积都能求出来。

double ang(const Vector a){return atan2(a.y,a.x);}
double ang(const Vector a,const Vector b){return acos(a*b/lth(a)/lth(b));}

三角形面积:搞出来两个向量之后叉积再$/2$即可。

用海伦公式需要开根号,误差会偏大。

double S_(const Point a,const Point b,const Point c){return ((b-a)^(c-a))/2;}
叉积求三角形面积

 向量逆时针转:

可以理解成向量相乘(得到向量的那种乘),也可以理解为先拆成两个向量$(x,0)$和$(0,y)$,转完了再加回去。

Vector rot(const Vector a,const double d){return Vector(a.x*cos(d)-a.y*sin(d),a.y*cos(d)+a.x*sin(d));}
向量旋转

upd:三维向量旋转(可能有锅)

struct Point
{
    double x,y,z;
    Point(){}
    Point(double x,double y,double z):x(x),y(y),z(z){}
    Point operator + (const Point&p)const{return Point(x+p.x,y+p.y,z+p.z);}
    Point operator - (const Point&p)const{return Point(x-p.x,y-p.y,z-p.z);}
    Point operator * (const double&p)const{return Point(x*p,y*p,z*p);}
    Point operator / (const double&p)const{return Point(x/p,y/p,z/p);}
    double operator * (const Point&p)const{return x*p.x+y*p.y+z*p.z;}
    Point operator ^ (const Point&p)const{return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);}
};
double lth(Point p){return sqrt(p*p);}
Point stdrd(Point p){return p/lth(p);}
Point rotate(Point p,Point v,int r)//dian faxiangliang jiaodu
{
    double D = -(p*v);
    double k = -D/(v*v);
    Point p0 = v*k;
    Point nx = stdrd(p-p0);
    Point ny = stdrd(p0^(p-p0));
    Point ans0 = nx*cos(r)+ny*sin(r);
    return p0+ans0*lth(p-p0);
}
三维向量旋转

法向量:

转$90$度再让长度变成一。

Vector Nol(const Vector a){return Vector(-a.y,a.x)/lth(a);}
法向量

 

posted @ 2019-06-01 22:11  LiGuanlin  阅读(734)  评论(2编辑  收藏  举报