[模板]计算几何-二维Point

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38013346/article/details/82218556

浮点精度

const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
int sgn(double x) {
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}

s g n sgn三态函数用于减少浮点的精度问题


叉积

// 叉积
double operator ^ (const Point &b)const {
	return x*b.y - y*b.x;
}

定义
向量叉积 a × b = a b s i n ( θ ) a × b = absin(\theta)
模长 a × b = a b s i n ( θ ) |a × b| = |a||b|sin(\theta)
方向 θ a b \theta 的方向是从a \to b方向的夹角。
a b a , b 叉积的方向满足a\to b的右手法则,即与a,b构成的平面垂直。
这里写图片描述
性质
1. a × b = a b 1.|a × b| = a和b构成的平行四边形面积
a × b = a b s i n ( θ ) ; a s i n ( θ ) = h 如上图因为|a × b| = |a||b|sin(\theta) ;|a|sin(\theta) = h
a × b = h b = S A B C D |a × b| = h|b| = S_{ABCD}
2. 线 2.叉积判断线段拐向
a × b = = 0 : a b a × b ==0 : a和b平行
a × b &gt; 0 : b a ( 0 &lt; θ 10 8 ) a × b &gt; 0 : b在a的逆时针方向(0&lt; \theta \leq 108^。)
a × b &lt; 0 : b a ( 0 &lt; θ 10 8 ) a × b &lt; 0 : b在a的顺时针方向(0&lt; \theta \leq 108^。)
3. 3.判断点在多边形内
4. 线 ( ) 4.判断两直线相交(跨立实验)
5. 5.极角排序


点积

// 点积
double operator * (const Point &b)const {
	return x*b.x + y*b.y;
}

定义
a b = a b c o s ( θ ) a \bullet b = |a||b|cos(\theta)
这里写图片描述
a b = a b c o s ( θ ) = d a ; d b a a \bullet b = |a||b|cos(\theta) = d|a|;d是b在a上的投影

计算 pa 和 pb 的夹角

// 测试LightOJ1203
double rad(Point a,Point b) {
	Point p = *this;
	return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
}

x = p a ; y = p b x = p \to a;y = p \to b
x × y = x y s i n ( θ ) x × y = |x||y|sin(\theta)
x y = x y c o s ( θ ) x\bullet y = |x||y|cos(\theta)
t a n ( θ ) = x × y x y tan(\theta) = \frac{x × y}{x \bullet y}


化为长度为r的向量

Point trunc(double r) {
	double l = len();
	if(!sgn(l)) return *this;
	r /= l;
	return Point(x*r,y*r);
}

用途
已知直线向量。求出直线上任意一点
这里写图片描述
A ( x 1 , y 1 ) , C ( x 2 , y 2 ) A r B 如图已知点A(x1,y1),C(x2,y2)。想要计算出距离点A长度为r的B点坐标
B = A + ( C A ) . t r u n c ( r ) B = A + (C-A).trunc(r)


向量绕点P旋转angle

A ( x , y ) , P ( a , b ) θ B ( x 1 , y 1 ) 公式已知点A(x,y),绕点P(a,b)逆时针转\theta 得到B(x1,y1)
x 1 = a + x c o s ( θ ) y s i n ( θ ) x1 = a + x*cos(\theta)-y*sin(\theta)
y 1 = b + x s i n ( θ ) + y c o s ( θ ) y1 = b + x*sin(\theta)+y*cos(\theta)

Point rotate(Point p,double angle) {
	Point v = (*this) - p;
	double c = cos(angle),s = sin(angle);
	return Point(p.x + v.x*c - v.y*s,p.y+v.x*s + v.y*c);
}

Code

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
int sgn(double x) {
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}
inline double sqr(double x) {return x*x;}
struct Point {
    double x,y;
    Point() {}
    Point(double _x,double _y) {
        x = _x;
        y = _y;
    }
    void input() {
        scanf("%lf%lf",&x,&y);
    }
    void output() {
        printf("%.2f %.2f\n",x,y);
    }
    bool operator == (Point b)const {
        return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
    }
    bool operator < (Point b)const {
        return sgn(x-b.x) == 0 ? sgn(y-b.y)<0 : sgn(x-b.x)<0;
    }
    Point operator - (const Point &b)const {
        return Point(x-b.x,y-b.y);
    }
    // 叉积
    double operator ^ (const Point &b)const {
        return x*b.y - y*b.x;
    }
    // 点积
    double operator * (const Point &b)const {
        return x*b.x + y*b.y;
    }
    // 返回长度
    double len() {
        return hypot(x,y); // 库函数
    }
    // 
    double len2() {
        return x*x + y*y;
    }
    double distance(Point p) {
        return hypot(x-p.x,y-p.y);
    }
    Point operator + (const Point &b)const {
        return Point(x+b.x,y+b.y);
    }
    Point operator * (const double &k)const {
        return Point(x*k,y*k);
    }
    Point operator / (const double &k)const {
        return Point(x/k,y/k);
    }
    // 计算 pa 和 pb 的夹角
    // 测试LightOJ1203
    double rad(Point a,Point b) {
        Point p = *this;
        return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
    }
    // 化为长度为r的向量
    Point trunc(double r) {
        double l = len();
        if(!sgn(l)) return *this;
        r /= l;
        return Point(x*r,y*r);
    }
    // 逆时针旋转90度(绕原点)
    Point rotleft() {
        return Point(-y,x);
    }
    // 顺时针旋转90度(绕原点)
    Point rotright() {
        return Point(y,-x);
    }
    // 绕着p点逆时针旋转angle
    Point rotate(Point p,double angle) {
        Point v = (*this) - p;
        double c = cos(angle),s = sin(angle);
        return Point(p.x + v.x*c - v.y*s,p.y+v.x*s + v.y*c);
    }
};
int main()
{

}

猜你喜欢

转载自blog.csdn.net/m0_38013346/article/details/82218556
今日推荐