我也算是刚入门计算几何吧,想写一篇入门的模板,让那些和我一样刚入门的人都能看懂就好。
首先要有一些理论知识,这可以百度,我就不多说了,通过百度,你要知道:
①叉积可以判断3个点共线,还可以判断2个点构成直线,第3个点在直线的左边还是右边。
②判断两条线段相交要有2个条件:
(1)快速排斥试验
设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。
(2)跨立试验
如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 )
< 0。上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 )
> 0。当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 -
Q1 ) >= 0。同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 )
>= 0。
之后就可以看下我收集的简单的模板了(代码来自kuangbin)。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <string> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; typedef long long ll; #define prN printf(" ") #define SI(N) scanf("%d",&(N)) #define SII(N,M) scanf("%d%d",&(N),&(M)) #define SIII(N,M,K) scanf("%d%d%d",&(N),&(M),&(K)) #define cle(a,val) memset(a,(val),sizeof(a)) #define rep(i,b) for(int i=0;i<(b);i++) #define Rep(i,a,b) for(int i=(a);i<=(b);i++) #define reRep(i,a,b) for(int i=(a);i>=(b);i--) const double eps = 1e-8; //判断doubule型的正负或0 int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0) return -1; else return 1; } //构建点,且重载运算符 struct Point { double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } //重载减号 因为在求两个点相减构成一个向量时候会用到 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; } };
//构建线, struct Line { Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; } }; //判断线段相交 bool inter(Line l1,Line 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) && //跨立试验 sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) <= 0 && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0; } //求距离 double dist(Point a,Point b) { return sqrt((b-a)*(b-a)); } int main() { //主函数调用就好了 return 0; }
现在我入门也就用了这些,做出了十几道题,等再刷刷题,我就更。