需要注意的细节
1.判断点在直线上
• 利用三点共线的等价条件 α×β==0
•
常用头文件
#include<
math.h
>
•
计算几何中一般来说使用
double
型比较频繁,请注意数据类型的选择,该用实数的时候就用
double
,而
float
容易失去精度。
•
判断
double
型的
x
是否为
0
,应当用
x<
eps
&& x>-
eps
(或者
fabs
(x)<
eps
),其中
eps
代表某个精度,常常取
eps
=0.000001
,还有其他类似情况也要注意
double
类型的精度问题,
int
(
x+eps
)
,避免
x=4.999999999
•
圆周率取
3.141592654
或者更精确,或者用
acos
(-1)
•
角度制和弧度制的转换,
C/C++
中的三角函数均为弧度制
•
尽量少用除法,开方,三角函数,容易失去精度。用除法时注意除数不为
0
•
输出的时候要小心
-0.00000
,比如
•
a=-0.0000001
,
printf
(“%.5lf”,a);
1.判断点在直线上
• 利用三点共线的等价条件 α×β==0
•
直线上取两不同点
P1,P2
,若点
P
在直线上,则
fabs
((P1- P) × (P2 - P )) <
eps
•
如果该题目需要编写求三角形面积的函数,那直接判断这三个点形成的三角形面积是否
<
eps
2.判断点在线段上
•
判断点
P(
x,y
)
是否在线段
P1P2
上,其中
P1(x1,y1),P2(x2,y2)
•
需要验证两条
•
(
1
)点
P
在
P1P2
所在直线上,即三点共线
•
(
2
)点
P
在
P1P2
为对角线的矩形内
•
其中(
2
)利用
min(x1,x2)<=x<=max(x1,x2)&&
min(y1,y2)<=y<=max(y1,y2)
min(x1,x2)<=x<=max(x1,x2)&&
min(y1,y2)<=y<=max(y1,y2)
如何判断是否同线?由叉积的原理知道如果p1,p2,p3共线的话那么(p2-p1)X(p3-p1)=0。因此如果p1,p2,p3共线,p1,p2,p4共线,那么两条直线共线。direction()求叉积,叉积为0说明共线。
如何判断是否平行?由向量可以判断出两直线是否平行。如果两直线平行,那么向量p1p2、p3p4也是平等的。即((p1.x-p2.x)*(p3.y-p4.y)-(p1.y-p2.y)*(p3.x-p4.x))==0说明向量平等。
如何求出交点?这里也用到叉积的原理。假设交点为p0(x0,y0)。则有:
(p1-p0)X(p2-p0)=0
(p3-p0)X(p2-p0)=0
展开后即是
(y1-y2)x0+(x2-x1)y0+x1y2-x2y1=0
(y3-y4)x0+(x4-x3)y0+x3y4-x4y3=0
将x0,y0作为变量求解二元一次方程组。
假设有二元一次方程组
a1x+b1y+c1=0;
a2x+b2y+c2=0
那么
x=(c1*b2-c2*b1)/(a2*b1-a1*b2);
y=(a2*c1-a1*c2)/(a1*b2-a2*b1);
因为此处两直线不会平行,所以分母不会为0。
•
struct
point{ //
构造点的数据类型,也可作向量使用
•
doublex;
•
double y;
•
point operator+(point p2);
•
double operator*(point p2);
•
}v1,v2;
线段判交
•
判断
P1P2
是否和
P3P4
相交,其中
Pi
坐标为
(
xi,yi
)
,同样需要满足两个条件
•
(
1
)快速排斥试验:
以 P1P2 为对角线的矩形 S1 是否和以 P3P4 为对角线的矩形 S2 相交,即
min(x1,x2)<=max(x3,x4)&&
min(x3,x4)<=max(x1,x2) &&
min(y1,y2)<=max(y3,y4) &&
min(y3,y4)<=max(y1,y2)
此代码中有很多模板,特转一下
以 P1P2 为对角线的矩形 S1 是否和以 P3P4 为对角线的矩形 S2 相交,即
min(x1,x2)<=max(x3,x4)&&
min(x3,x4)<=max(x1,x2) &&
min(y1,y2)<=max(y3,y4) &&
min(y3,y4)<=max(y1,y2)
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using std::swap;
#define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps)
struct Point{double x,y;};
struct Line{Point a,b;};
//计算cross product (P1-P0)x(P2-P0)
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 xmult(double x1,double y1,double x2,double y2,double x0,double y0){
return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
}
//计算dot product (P1-P0).(P2-P0)
double dmult(Point p1,Point p2,Point p0){
return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
double dmult(double x1,double y1,double x2,double y2,double x0,double y0){
return (x1-x0)*(x2-x0)+(y1-y0)*(y2-y0);
}
//两点距离
double distance(Point p1,Point p2){
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double distance(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
//判三点共线
int dots_inline(Point p1,Point p2,Point p3){
return zero(xmult(p1,p2,p3));
}
int dots_inline(double x1,double y1,double x2,double y2,double x3,double y3){
return zero(xmult(x1,y1,x2,y2,x3,y3));
}
//判点是否在线段上,包括端点
int dot_online_in(Point p,Line l){
return zero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps;
}
int dot_online_in(Point p,Point l1,Point l2){
return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;
}
int dot_online_in(double x,double y,double x1,double y1,double x2,double y2){
return zero(xmult(x,y,x1,y1,x2,y2))&&(x1-x)*(x2-x)<eps&&(y1-y)*(y2-y)<eps;
}
//判点是否在线段上,不包括端点
int dot_online_ex(Point p,Line l){
return dot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y));
}
int dot_online_ex(Point p,Point l1,Point l2){
return dot_online_in(p,l1,l2)&&(!zero(p.x-l1.x)||!zero(p.y-l1.y))&&(!zero(p.x-l2.x)||!zero(p.y-l2.y));
}
int dot_online_ex(double x,double y,double x1,double y1,double x2,double y2){
return dot_online_in(x,y,x1,y1,x2,y2)&&(!zero(x-x1)||!zero(y-y1))&&(!zero(x-x2)||!zero(y-y2));
}
//判两点在线段同侧,点在线段上返回0
int same_side(Point p1,Point p2,Line l){
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;
}
int same_side(Point p1,Point p2,Point l1,Point l2){
return xmult(l1,p1,l2)*xmult(l1,p2,l2)>eps;
}
//判两点在线段异侧,点在线段上返回0
int opposite_side(Point p1,Point p2,Line l){
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps;
}
int opposite_side(Point p1,Point p2,Point l1,Point l2){
return xmult(l1,p1,l2)*xmult(l1,p2,l2)<-eps;
}
//判两直线平行
int parallel(Line u,Line v){
return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y));
}
int parallel(Point u1,Point u2, Point v1,Point v2){
return zero((u1.x-u2.x)*(v1.y-v2.y)-(v1.x-v2.x)*(u1.y-u2.y));
}
//判两直线垂直
int perpendicular(Line u,Line v){
return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));
}
int perpendicular(Point u1,Point u2,Point v1,Point v2){
return zero((u1.x-u2.x)*(v1.x-v2.x)+(u1.y-u2.y)*(v1.y-v2.y));
}
//判两线段相交,包括端点和部分重合
int intersect_in(Line u,Line v){
if (!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);
}
int intersect_in(Point u1,Point u2,Point v1,Point v2){
if (!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))
return !same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);
return dot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
}
//判两线段相交,不包括端点和部分重合
int intersect_ex(Line u,Line v){
return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);
}
int intersect_ex(Point u1,Point u2,Point v1,Point v2){
return opposite_side(u1,u2,v1,v2)&&opposite_side(v1,v2,u1,u2);
}
//计算两直线交点,注意事先判断直线是否平行!
//线段交点请另外判线段相交(同时还是要判断是否平行!)
Point intersection(Line u,Line v){
Point ret=u.a;
double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))
/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
return ret;
}
Point intersection(Point u1,Point u2,Point v1,Point v2){
Point ret=u1;
double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
return ret;
}
//点到直线上的最近点
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);
}
Point ptoline(Point p,Point l1,Point l2){
Point t=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
return intersection(p,t,l1,l2);
}
//点到直线距离
double disptoline(Point p,Line l){
return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);
}
double disptoline(Point p,Point l1,Point l2){
return fabs(xmult(p,l1,l2))/distance(l1,l2);
}
double disptoline(double x,double y,double x1,double y1,double x2,double y2){
return fabs(xmult(x,y,x1,y1,x2,y2))/distance(x1,y1,x2,y2);
}
//点到线段上的最近点
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 distance(p,l.a)<distance(p,l.b)?l.a:l.b;
return intersection(p,t,l.a,l.b);
}
Point ptoseg(Point p,Point l1,Point l2){
Point t=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
if (xmult(l1,t,p)*xmult(l2,t,p)>eps)
return distance(p,l1)<distance(p,l2)?l1:l2;
return intersection(p,t,l1,l2);
}
//点到线段距离
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 distance(p,l.a)<distance(p,l.b)?distance(p,l.a):distance(p,l.b);
return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);
}
double disptoseg(Point p,Point l1,Point l2){
Point t=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
if (xmult(l1,t,p)*xmult(l2,t,p)>eps)
return distance(p,l1)<distance(p,l2)?distance(p,l1):distance(p,l2);
return fabs(xmult(p,l1,l2))/distance(l1,l2);
}
//矢量V以P为顶点逆时针旋转angle并放大scale倍
Point rotate(Point v,Point p,double angle,double scale){
Point ret=p;
v.x-=p.x,v.y-=p.y;
p.x=scale*cos(angle);
p.y=scale*sin(angle);
ret.x+=v.x*p.x-v.y*p.y;
ret.y+=v.x*p.y+v.y*p.x;
return ret;
}
int main()
{
int t, i;
//freopen("a.txt","r",stdin);
double x1, y1, x2, y2;
Line l0, l[5];
scanf("%d",&t);
while ( t-- )
{
scanf("%lf%lf%lf%lf",&l0.a.x, &l0.a.y, &l0.b.x, &l0.b.y);
scanf("%lf%lf%lf%lf",&x1, &y1, &x2, &y2);
if ( x1 > x2 ) swap (x1, x2);
if ( y1 > y2 ) swap (y1, y2);
l[1].a.x = x1; l[1].a.y = y1; l[1].b.x = x2; l[1].b.y = y1;
l[2].a.x = x2; l[2].a.y = y1; l[2].b.x = x2; l[2].b.y = y2;
l[3].a.x = x2; l[3].a.y = y2; l[3].b.x = x1; l[3].b.y = y2;
l[4].a.x = x1; l[4].a.y = y2; l[4].b.x = x1; l[4].b.y = y1;
bool flag = false;
for ( i = 1; i <= 4; i++ )
if ( intersect_in (l[i],l0) ) flag = true;
if ( flag == false )
{
for ( i = 1; i <= 4; i++ )
if ( xmult(l[i].b, l0.a, l[i].a) < -eps || xmult(l[i].b, l0.b, l[i].a) < -eps )
break;
if ( i > 4 ) flag = true;
}
if ( flag ) printf("T\n");
else printf("F\n");
}
return 0;
}
待补充。。。。