叉积是计算几何中运用最多的运算,所以简单说一下叉积。
设 向量 A =(x1,y1) B = (x2, y2)
则A和B的叉积为:
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;
}