基础二维计算几何板子[预备知识]

1. 向量的基本运算


1.1点和向量的表示
在平面直角坐标系中,任意一点的坐标可以用一个有序数对 (x,y) 表示,向量也是如此

struct Point//点或向量
{
    double x, y;
    Point() {}
    Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;

1.2基本向量运算
设向量 v1=(x1,y1),v2=(x2,y2) ,定义如下运算
1.2.1 向量四则运算以及向量的模长

int dcmp(double x)//精度三态函数(>0,<0,=0)
{
    if (fabs(x) < eps)return 0;
    else if (x > 0)return 1;
    return -1;
}
Vector operator + (Vector a, Vector b)//向量加法
{
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b)//向量减法
{
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p)//向量数乘
{
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p)//向量数除
{
    return Vector(a.x / p, a.y / p);
}
double Distance(Point a, Point b)//两点间距离
{
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
bool operator == (const Point &a, const Point &b)//向量相等
{
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

2.向量的叉积的运用

叉积的方向
在这里插入图片描述

2.1.叉积的几何意义:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

double Cross(Vector a, Vector b)//外积
{
    return a.x*b.y - a.y*b.x;
}

2.2叉积的运用:
2.2.1计算多边形的面积
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

2.2.2判断凹凸多边形
在这里插入图片描述
在这里插入图片描述


2.2.3折线的拐向的方向
在这里插入图片描述
在这里插入图片描述
2.2.4:判断点是否在线段上
在这里插入图片描述
代码模板

struct line//线段
{
   Point s;
   Point e;
   line(Point s, Point e){s = a, e = b;}
   line(){}
}
//直线方程
struct Lineequ
{
   double a, b, c;
   Lineequ(double a1, double b1, double c1)
   {a = a1; b = b1; c = c1;}
   Lineequ(){}
}
double Cross(Vector a, Vector b)//外积
{
    return a.x*b.y - a.y*b.x;
}

double Dot(Vector a, Vector b)//内积
{
    return a.x*b.x + a.y*b.y;
}
//判断是否在线段上
bool InSegment(Point P,Point A,Point B)
{
    return dcmp(Cross(A-B,P-A))==0 && dcmp(Dot(A-P,B-P))<=0;
}

2.2.5:判断两个线段是否相交
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

bool StrictIntersect(Point A, Point B, Point C, Point D) //线段相交(包括端点)
{
    return
        dcmp(max(A.x, B.x) - min(C.x, D.x)) >= 0
        && dcmp(max(C.x, D.x) - min(A.x, B.x)) >= 0
        && dcmp(max(A.y, B.y) - min(C.y, D.y)) >= 0
        && dcmp(max(C.y, D.y) - min(A.y, B.y)) >= 0
        && dcmp(Cross(C - A, D - A)*Cross(C - B, D - B)) <= 0
        && dcmp(Cross(A - C, B - C)*Cross(A - D, B - D)) <= 0;
}

2.2.6判断点是否在多边形中
在这里插入图片描述
在这里插入图片描述
HDU1756;

#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define f first
#define s second
using namespace std;
const int N = 500 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
struct Point//点或向量
{
    double x, y;
    Point() {}
    Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;
int dcmp(double x)//精度三态函数(>0,<0,=0)
{
    if (fabs(x) < eps)return 0;
    else if (x > 0)return 1;
    return -1;
}
double Dot(Vector a, Vector b)//内积
{
    return a.x*b.x + a.y*b.y;
}
Vector operator + (Vector a, Vector b)//向量加法
{
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b)//向量减法
{
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p)//向量数乘
{
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p)//向量数除
{
    return Vector(a.x / p, a.y / p);
}
double Distance(Point a, Point b)//两点间距离
{
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
bool operator == (const Point &a, const Point &b)//向量相等
{
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Cross(Vector a, Vector b)//外积
{
    return a.x*b.y - a.y*b.x;
}

bool InSegment(Point P,Point A,Point B)
{
    return dcmp(Cross(A-B,P-A))==0 && dcmp(Dot(A-P,B-P))<=0;
}

int IsPointInPolygon(Point p,Point *poly,int n)
{
    int wn=0;
    for(int i=0;i<n;++i)
    {
        if(InSegment(p, poly[(i+1)%n], poly[i]) ) return 1;
        int k=dcmp( Cross(poly[(i+1)%n]-poly[i], p-poly[i] ) );
        int d1=dcmp( poly[i].y-p.y );
        int d2=dcmp( poly[(i+1)%n].y-p.y );
        if(k>0 && d1<=0 && d2>0) ++wn;
        if(k<0 && d2<=0 && d1>0) --wn;
    }
    if(wn != 0) return 1;
    return 0;
}

int npoi, nploy;
Point ploy[1100];
int main()
{
    IOS;
    while(cin >> nploy)
    {
        _for(i,0,nploy) 
        {
            double x,y;
            cin >> x >> y;
            ploy[i] = {x,y};
        }
        cin >> npoi;
        while(npoi --)
        {
            double x, y;
            cin >> x >> y;
            if(IsPointInPolygon({x,y},ploy,nploy)) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

3.向量的点积


向量点积的几何意义:就是 a ∗ b = b 在 a 方 向 上 投 影 的 大 小 a*b=b在a方向上投影的大小 ab=ba


3.1定义:r = AP/AB
则r = ac dot(点乘) ab / |ab|^2
在这里插入图片描述
下面A,B是线段两个端点

double relation(Point A, Point B, Point C)
{
    return Dot(B - A, C - A) / Distance(A,B) / Distance(A,B);
}

求C在AB所在直线的垂足P坐标

Point pedal(Point A, Point B, Point C)
{
    double r = relation(A,B,C);
    Point res;
    res.x = A.x + r * (B.x - A.x);
    res.y = A.y + r * (B.y - A.y);
    return res;
}

求直线外一点距离直线线段最近距离
在这里插入图片描述
在这里插入图片描述

double pedaldist(Point A, Point B, Point C)
{
    double r = relation(A,B,C);
    if(r < 0) return Distance(A,C);
    else if(r > 1) return Distance(B,C);
    else 
    {
        Point np = pedal(A,B,C);
        return Distance(np,C);
    }
}

在这里插入图片描述

double DistanceToLine(Point A, Point M, Point N)//点A到直线MN的距离,Error:MN=0
{
    return fabs(Cross(A - M, A - N) / Distance(M, N));
}

在这里插入图片描述

Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)//两直线的交点
{
    Vector u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值