计算几何模板

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define EPS 1e-8

struct Point{
    double x,y;
    Point(){}
    Point(double xx, double yy):x(xx), y(yy){}
};

struct Line{
    Point a,b;
};

/*
    向量p0p1与p0p2的叉积
    =0说明三点共线
    >0则p0p2在p0p1的逆时针方向
    <0则p0p2在p0p1的顺时针方向
*/
double xmult(Point p1, Point p2, Point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

//两点距离
double dis(Point p1, Point p2)
{
    double x = p1.x-p2.x;
    double y = p1.y-p2.y;
    return sqrt(x*x+y*y);
}

//p点到直线ab的距离
double disptoline(Point p, Point a, Point b)
{
    //fabs(xmult(p,a,b))是以pa,pb为邻边的平行四边形面积
    return fabs(xmult(p,a,b))/dis(a,b);
}
//两条直线的交点,注意判断直线是否平行或重合
Point intersection(Point A, Point B, Point C, Point D)
{
    //a1*x+b1*y=c1;a2*x+b2*y=c2;
    //得到直线的3个系数
    double a1 = A.y-B.y;
    double b1 = B.x-A.x;
    double c1 = A.x*B.y-B.x*A.y;
    double a2 = C.y-D.y;
    double b2 = D.x-C.x;
    double c2 = C.x*D.y-D.x*C.y;
    double x = (b1*c2-b2*c1)/(a1*b2-a2*b1);
    double y = (a2*c1-a1*c2)/(a1*b2-a2*b1);
    return Point(x,y);
}

//点到直线上的最近点
Point ptoline(Point p,Line l)
{
    Point t=p;
    t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
    return intersection(p,t,l.a,l.b);
}
//点是否在线段l上
bool pisonline(Line l,Point p)
{
    return( (xmult(l.a,l.b,p)==0) &&( ( (p.x-l.a.x)*(p.x-l.b.x)<=0 )&&( (p.y-l.a.y)*(p.y-l.b.y)<=0 ) ) );
}
//点到线段上的最近点
Point ptoseg(Point p,Line l)
{
     Point t=p;
     t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
     if(xmult(l.a,t,p)*xmult(l.b,t,p)>EPS)
         return dis(p,l.a)<dis(p,l.b)?l.a:l.b;
     return intersection(p,t,l.a,l.b);
}
//点到线段距离
double disptoseg(Point p,Line l)
{
     Point t=p;
     t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
     if(xmult(l.a,t,p)*xmult(l.b,t,p)>EPS)
         return dis(p,l.a)<dis(p,l.b)?dis(p,l.a):dis(p,l.b);
    return fabs(xmult(p,l.a,l.b))/dis(l.a,l.b);
 }


//判断直线是否重合
bool isSame(Point A,Point B,Point C,Point D)
{
    if(fabs(xmult(A,B,C))<=EPS&&fabs(xmult(A,B,D))<=EPS)
        return true;
    return false;
}
//判断直线是否平行,判断平行之前先判断是否重合
bool isParallel(Point A,Point B,Point C,Point D)
{
    if((A.y-B.y)*(D.x-C.x)==(B.x-A.x)*(C.y-D.y))
        return true;
    return false;
}
//根据圆周上的三点,求出圆心
Point getCir(Point a,Point b,Point c)
{
    Line u,v;
    u.a.x = (a.x+b.x)/2;
    u.a.y = (a.y+b.y)/2;
    u.b.x = u.a.x-a.y+b.y;
    u.b.y = u.a.y+a.x-b.x;
    v.a.x = (a.x+c.x)/2;
    v.a.y = (a.y+c.y)/2;
    v.b.x = v.a.x-a.y+c.y;
    v.b.y = v.a.y+a.x-c.x;
    return intersection(u.a, u.b, v.a, v.b);
}

//判断线段ab与线段cd是否相交
bool SegIntersection(Point a, Point b, Point c, Point d)  //判断线段相交
{
	if (min(a.x, b.x) <= max(c.x, d.x) &&
		min(a.y, b.y) <= max(c.y, d.y) &&
		min(c.x, d.x) <= max(a.x, b.x) &&
		min(c.y, d.y) <= max(a.y, b.y) &&
		xmult(a, b, c) * xmult(a, b, d) <= EPS &&
		xmult(c, d, a) * xmult(c, d, b) <= EPS)
		return true;
	return false;
}

 

posted on 2016-08-24 14:39  wastonl  阅读(155)  评论(0编辑  收藏  举报