计算几何基础模板 例 POJ - 1269 Intersecting Lines 求两直线位置关系

叉积是计算几何中运用最多的运算,所以简单说一下叉积。

设 向量 A =(x1,y1) B = (x2, y2) 

则A和B的叉积为:  x1*y2- x2*y1 == |A| * |B| * sin \Theta

A和B的叉积在数值上等于 A和B围成的平行四边行的面积, 用X代表叉积   若  A X B >0  则  B X  A < 0 , 这是因为如果当A X 时B, A在B的不超过180度的顺时针方向,则AXB>0   换成 B X A 则 B在A的不超过180度的逆时针方向所以 B X A < 0

详见https://baike.baidu.com/item/%E5%90%91%E9%87%8F%E7%A7%AF

相关函数:

floor(x); :向下取整

ceil(x); : 向下取整

round(x); : 四舍五入

pi = acos(-1.0); 

double eps = 1e-9;

double inf = 1e100;

点的定义:

typedef struct Point{
    int x,y;
    Point(int x=0, int y=0):x(x),y(y){}
}Point;

Point (int x = 0, int y = 0):x(x),y(y){}   是构造函数  作用是给 x 和 y进行初始化 初始化的值就是Point函数里形参的值, :, 和{}是固定格式,必须要有。

常用函数模板:

struct Point {
	double x, y;
	Point(double x = 0, double y = 0) : x(x) , y(y) { }
};
typedef Point Vector; 

//向量 + 向量 = 向量 ,点 + 向量 = 点
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); } 

bool operator < (const Point& a, const Point& b) {
	return a.x < b.x || (a.x == b.x && a.y < b.y);
} 
 
const double eps = 1e-10;
int dcmp(double x) {
	if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
}
 
bool operator == (const Point& a, const Point& b) {
	return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

//点积 
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } //求点积 
double Length(Vector A) { return sqrt(Dot(A, A)); }			 //求向量模
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }//求向量之间的夹角 

//叉积 
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }//求叉积 
double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A); }//根据叉积求面积 


//旋转 
Vector Rotate(Vector A, double rad) {//rad是弧度 
	return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad) );
} 

//点到直线距离  
double DistanceToLine(Point P, Point A, Point B) {  
    Vector v1 = B-A, v2 = P - A;  
    return fabs(Cross(v1,v2) / Length(v1));  //如果不取绝对值,得到的是有向距离 
}  

//点到线段距离  
double DistanceToSegment(Point P, Point A, Point B) {  
    if(A==B) return Length(P-A);  
    Vector v1 = B - A, v2 = P - A, v3 = P - B;  
    if(dcmp(Dot(v1, v2)) < 0) return Length(v2);  
    else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);  
    else return fabs(Cross(v1, v2)) / Length(v1);  
}  

AC代码:

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <string>
#include <queue>
using namespace std;
//定义点的类型 
struct Point {
	double x, y;
	Point(double x = 0, double y = 0) : x(x) , y(y) { }
};
typedef Point Vector; 

//向量 + 向量 = 向量 ,点 + 向量 = 点
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); } 

bool operator < (const Point& a, const Point& b) {
	return a.x < b.x || (a.x == b.x && a.y < b.y);
} 
 
const double eps = 1e-10;
int dcmp(double x) {
	if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
}
 
bool operator == (const Point& a, const Point& b) {
	return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

//点积 
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } //求点积 
double Length(Vector A) { return sqrt(Dot(A, A)); }			 //求向量模
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }//求向量之间的夹角 

//叉积 
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }//求叉积 
double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A); }//根据叉积求面积 


//旋转 
Vector Rotate(Vector A, double rad) {//rad是弧度 
	return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad) );
} 

//点到直线距离  
double DistanceToLine(Point P, Point A, Point B) {  
    Vector v1 = B-A, v2 = P - A;  
    return fabs(Cross(v1,v2) / Length(v1));  //如果不取绝对值,得到的是有向距离 
}  

//点到线段距离  
double DistanceToSegment(Point P, Point A, Point B) {  
    if(A==B) return Length(P-A);  
    Vector v1 = B - A, v2 = P - A, v3 = P - B;  
    if(dcmp(Dot(v1, v2)) < 0) return Length(v2);  
    else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);  
    else return fabs(Cross(v1, v2)) / Length(v1);  
}  
int pan(Point A, Point B, Point C, Point D){
	
	if(Area2(A,B,C)==0&&Area2(A,B,D)==0)
		return 1;
	else if((B.x-A.x)*(D.y-C.y)-(D.x-C.x)*(B.y-A.y)==0)
		return 2;
	else return 0;	
}
Point jd(Point A, Point B, Point C, Point D){    //求交点,设交点为p0 则 (p1-p0)X(p2-p0)=0, (p3-p0)X(p2-p0)=0,  叉乘 
	double a1, a2 ,b1 ,b2, c1, c2;              //              展开后 (y1-y2)x0+(x2-x1)y0+x1y2-x2y1=0,  (y3-y4)x0+(x4-x3)y0+x3y4-x4y3=0 
	Point e;
	a1 = A.y-B.y;                  // 令 a1 = y1 - y2   a2 = y3 - y4; 
	a2 = C.y-D.y; 
	b1 = B.x-A.x;                  //  b1 = x2 - x1     b2 = x4 - x3; 
	b2 = D.x-C.x;
	c1 = A.x*B.y-B.x*A.y;          //  c1 = x1y2 - x2y1    c2 = x3y4 - x4y3   ,则求解 二元一次方程组 a1*x+b1*y+c1=0,a2*x+b2*y+c2=0 
	c2 = C.x*D.y-D.x*C.y;
	e.x = (c2*b1 - c1*b2)/(a1*b2 - a2*b1);    //联立方程求得 x =  (c2*b1 - c1*b2)/(a1*b2 - a2*b1)
	e.y = (a2*c1 - a1*c2)/(a1*b2 - a2*b1);    //             y =  (a1*c2 - a2*c1)/(a2*b1 - a1*b2)
	return e;
}
/*int Kspc(Point A, Point B, Point C, Point D){  //快速排斥 
	if(min(p1x,p2x) <= max(q1x,q2x) &&	min(q1x,q2x) <= max(p1x,p2x) &&	min(p1y,p2y) <= max(q1y,q2y) &&	min(q1y,q2y) <= max(p1y,p2y))
		return 1;
	else return 0;				
}*/
int main()
{
	int T;
	cin>>T;
	cout<<"INTERSECTING LINES OUTPUT"<<endl;
	while(T--){
		Point a,b,c,d,e;
		cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y;
		if(pan(a,b,c,d)==2)
			cout<<"NONE"<<endl;
		else if(pan(a,b,c,d)==1)
			cout<<"LINE"<<endl; 
		else{
			e = jd(a,b,c,d);
		    printf("POINT %.2lf %.2lf\n",e.x,e.y); 
		}
	}
	cout<<"END OF OUTPUT"<<endl;
	return 0;
}

 

 

 

 

发布了52 篇原创文章 · 获赞 114 · 访问量 6023

猜你喜欢

转载自blog.csdn.net/GD_ONE/article/details/95916164