模板 2018-01-26 计算几何 基础定义 点 直线 点积与叉积

计算几何的模板实在是太臭太长了....

直接粘代码, 大部分需要解释的都已经注释好了, 所以应该没什么问题.....本来很多东西就是高中知识嘛(并不)

包含有如下函数(和定义):

1.数字的符号判断(别问我为啥计算几何有这么个东西)

2.点与向量的结构体定义与部分符号的重载

3.直线与线段的结构体定义

4.点是否在直线上 与 直线上距离给定点最近的点

5.点是否在线段上 与 线段上距离给定点最近的点

6.两条线段是否相交 与 一条线段和一条直线是否相交

7.求两直线交点

p.s 这都啥玩意儿......这么长是要抄多久啊

int sign(double x)
{//一个很不起眼但是很重要的函数
    if(x==0) return 0;
    return x>0?1:-1;
}

struct dot{
    double x,y;
    dot(double xx=0,double yy=0){//默认初始化为原点  (0,0)
        x=xx;y=yy;
    }
    dot operator - (const dot &p){//可以直接当成两个点形成一个向量
        return dot(x-p.x,y-p.y);
    }
    dot operator + (const dot &p){//两点(向量)相加
        return dot(x+p.x,y+p.y);
    }
    dot operator * (const double &p){//向量扩大p倍
        return dot(x*p,y*p);
    }
    dot operator / (const double &p){//向量缩小p倍
        return dot(x/p,y/p);
    }
    int operator *(const dot &p){//点积
        //通常用于向量之间的计算
        //注意左右(不满足交换律)
        return x*p.x+y*p.y;
    }
    int operator ^(const dot &p){//叉积
        //在二维平面上面,叉积相乘只能有模,因为两个二维向量作叉积后新向量方向是垂直于原平面的,即直接跳到了三维空间
        //res=0 则a和b平行,但是可能同向也可能反向
        //res>0 则向量a方向在b的顺时针那一边,否则就是逆时针那边
        //res的绝对值意义是两向量共起点后组成的平行四边形的面积
        return x*p.y-y*p.x;
    }
    double length(){//向量的模或者点距离
        return sqrt(x*x+y*y);
    }
};
typedef dot vec;//向量的表示跟点一样,都是有序实数对

struct line{//直线
    double a,b,c;//Ax+By+C=0;
    //ABC不唯一!
    dot s,e;//直线上两个点,或者直接当成线段来用
    line()
    {
    }
    line(dot start,dot end){//两点式
        s=start; e=end;
        a=e.y-s.y; b=s.x-e.x; c=e^s;
    }
};
typedef line segment;

bool dot_on_line(dot d,line l){//点是否在直线上
    if((l.a*d.x+l.b*d.y+l.c)==0) return true;
    else return false;
}

dot dot_to_line(dot p,line l){//直线上离给顶点最近的点
    double t=((p-l.s)*(l.e-l.s))/((l.e-l.s)*(l.e-l.s));
    return dot(l.s.x+(l.e.x-l.s.x)*t,l.s.y+(l.e.y-l.s.y));
}

bool dot_on_segment(dot p,line l){//点是否在线段上
    return
    sign((l.s-p)^(l.e-p))==0&&
    sign((p.x-l.s.x)*(p.x-l.e.x))<=0&&
    sign((p.y-l.s.y)*(p.y-l.e.y))<=0;
}

dot dot_to_segment(dot p,line l){//线段上离给顶点最近的点
    double t=((p-l.s)*(l.e-l.s))/((l.e-l.s)*(l.e-l.s));
    if(t>=0&&t<=1)
        return dot(l.s.x+(l.e.x-l.s.x)*t,l.s.y+(l.e.y-l.s.y)*t);
    else if(dot(l.s-p).length()<dot(l.e-p).length()) return l.s;
    else return l.e;
}

bool segment_inter(segment l1,segment l2){//线段是否相交
    return
    max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&
    max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&
    max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&
    max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&
    sign((l2.s-l1.e)^(l1.s-l1.e))*sign((l2.e-l1.e)^(l1.s-l1.e))<=0&&
    sign((l1.s-l2.e)^(l2.s-l2.e))*sign((l1.e-l2.e)^(l2.s-l2.e))<=0;
}

bool line_segment_inter(line l1,segment l2){//直线l1与线段l2是否相交
    return sign((l2.s-l1.e)^(l1.s-l1.e))*sign((l2.e-l1.e)^(l1.s-l1.e))<=0;
}

dot intersection(line l1,line l2)
{//求两直线交点(线段亦可,如果线段相交了的话)
    dot ret = l1.s;
    double t = ((l1.s.x-l2.s.x)*(l2.s.y-l2.e.y)-(l1.s.y-l2.s.y)*(l2.s.x-l2.e.x))/((l1.s.x-l1.e.x)*(l2.s.y-l2.e.y)-(l1.s.y-l1.e.y)*(l2.s.x-l2.e.x));
    ret.x += (l1.e.x-l1.s.x)*t;
    ret.y += (l1.e.y-l1.s.y)*t;
    return ret;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值