|BD| = BA * BC / |BC|
BD = |BD| * BC / |BC| = BA * BC * BC / (|BC| * |BC|)
D = B + BD
#include
#include
#include
using namespace std;
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
int n;
int main()
{
Point p1, p2;
scanf("%lf%lf%lf%lf", &p1.x, &p1.y, &p2.x, &p2.y);
scanf("%d", &n);
while(n--)
{
Point ans;
scanf("%lf%lf", &ans.x, &ans.y);
double k1 = dot(ans - p1, p2 - p1);
double k2 = (p2 - p1).abs();
k1 /= k2;
ans = (p2 - p1) * (k1 / k2);
printf("%.10f %.10f\n", ans.x + p1.x, ans.y + p1.y);
}
return 0;
}
分析:用(1)中的方法求垂足后扩深两倍后即可。
#include
#include
#include
using namespace std;
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
int n;
int main()
{
Point p1, p2;
scanf("%lf%lf%lf%lf", &p1.x, &p1.y, &p2.x, &p2.y);
scanf("%d", &n);
while(n--)
{
Point p, ans;
scanf("%lf%lf", &p.x, &p.y);
double k1 = dot(p - p1, p2 - p1);
double k2 = (p2 - p1).abs();
k1 /= k2;
ans = (p2 - p1) * (k1 / k2);
ans = ans + p1; /// 垂足
printf("%.10f %.10f\n", 2 * ans.x - p.x, 2 * ans.y - p.y);
}
return 0;
}
点积为0垂直,叉积为0平行。
#include
#include
#include
using namespace std;
const double eps = 1e-8;
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
double cross(Vector a, Vector b)
{
return a.x * b.y - a.y * b.x;
}
bool isParallel(Vector a, Vector b)
{
return fabs(cross(a, b)) <= eps;
}
bool isOrthogonal(Vector a, Vector b)
{
return fabs(dot(a, b)) <= eps;
}
Point p1, p2, p3, p4, ans;
int n;
int main()
{
scanf("%d", &n);
while(n--)
{
scanf("%lf%lf%lf%lf", &p1.x, &p1.y, &p2.x, &p2.y);
scanf("%lf%lf%lf%lf", &p3.x, &p3.y, &p4.x, &p4.y);
if(isParallel(p1 - p2, p3 - p4)) puts("2");
else if(isOrthogonal(p1 - p2, p3 - p4)) puts("1");
else puts("0");
}
return 0;
}
#include
#include
#include
using namespace std;
const double eps = 1e-8;
int sgn(double x){
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
else return -1;
}
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
double cross(Vector a, Vector b)
{
return a.x * b.y - a.y * b.x;
}
Point p1, p2, p3, p4, ans;
int n;
/*
Point a=p1-p0;
Point b=p2-p0;
1.外积大小cross(a,b)为正时,可确定b在a的逆时针方向
sin(Y)(Y在0-180)所以是正数
2. 外积大小cross(a,b)为负时,可确定b在a的顺时针方向
3.(1,2)不符合 表示p2在直线p0p1上(注意是直线),cos(Y)大于90或小于-90
度时为负,因此a与b的内积dot(a,b)负时,可确定p2位于线段p0p1后方
即p2->p0->p1
4.不是3时,有俩种p0->p1-p2或者p0->p2->p1如果b的大小大于a的大小,即为
p0->p1->p2;
5.不符合4,可以确定p2位于线段p0p1上
*/
int ccw(Point p0,Point p1,Point p2)//判断三个点相对位置
{
Point a=p1-p0;
Point b=p2-p0;
if(cross(a,b)>eps) return 1;//p0,p1,p2成逆时针方向
if(cross(a,b)<-eps) return -1;//p0,p1,p2成顺时针方向
if(dot(a,b)<-eps) return 2;//p2 p0 p1一次排列在同一直线上
if(a.norm()
#include
#include
using namespace std;
const double eps = 1e-8;
int sgn(double x){
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
else return -1;
}
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
double cross(Vector a, Vector b)
{
return a.x * b.y - a.y * b.x;
}
Point p1, p2, p3, p4, ans;
int n;
/*
Point a=p1-p0;
Point b=p2-p0;
1.外积大小cross(a,b)为正时,可确定b在a的逆时针方向
sin(Y)(Y在0-180)所以是正数
2. 外积大小cross(a,b)为负时,可确定b在a的顺时针方向
3.(1,2)不符合 表示p2在直线p0p1上(注意是直线),cos(Y)大于90或小于-90
度时为负,因此a与b的内积dot(a,b)负时,可确定p2位于线段p0p1后方
即p2->p0->p1
4.不是3时,有俩种p0->p1-p2或者p0->p2->p1如果b的大小大于a的大小,即为
p0->p1->p2;
5.不符合4,可以确定p2位于线段p0p1上
*/
int ccw(Point p0,Point p1,Point p2)//判断三个点相对位置
{
Point a=p1-p0;
Point b=p2-p0;
if(cross(a,b)>eps) return 1;//p0,p1,p2成逆时针方向
if(cross(a,b)<-eps) return -1;//p0,p1,p2成顺时针方向
if(dot(a,b)<-eps) return 2;//p2 p0 p1一次排列在同一直线上
if(a.norm()
#include
#include
#include
using namespace std;
const double eps = 1e-8;
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
double cross(Vector a, Vector b)
{
return a.x * b.y - a.y * b.x;
}
struct Segment{
Point p1,p2;
};
Point getCrossPoint(Segment a,Segment b)
{
Vector base=b.p2-b.p1;
double d1=fabs(cross(a.p1-b.p1,base));
double d2=fabs(cross(a.p2-b.p1,base));
double t=d1 / (d1 + d2);
Point ans=a.p1 + (a.p2 - a.p1) * t;
return ans;
}
Point p1, p2, p3, p4, ans;
int n;
int main()
{
scanf("%d", &n);
while(n--)
{
scanf("%lf%lf%lf%lf", &p1.x, &p1.y, &p2.x, &p2.y);
scanf("%lf%lf%lf%lf", &p3.x, &p3.y, &p4.x, &p4.y);
Segment a, b;
a.p1 = p1, a.p2 = p2, b.p1 = p3, b.p2 = p4;
ans = getCrossPoint(a, b);
printf("%.10f %.10f\n", ans.x, ans.y);
}
return 0;
}
先判断第1和第2个边的位置如果是逆时针方向,则每次判断下个点的位置,是在顺时针方向还是在逆时针方向,在遍历过程中有一个向量向顺时针方向了,是凹多边形
#include
#include
#include
using namespace std;
const double eps = 1e-8;
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
double cross(Vector a, Vector b)
{
return a.x * b.y - a.y * b.x;
}
const int COUNTER_CLOCKWISE = -1;
const int CLOCKWISE = 1;
const int ON_SEGMENT = 0;
const int ONLINE_BACK = 2;
const int ONLINE_FRONT = -2;
int ccw(Point p0,Point p1,Point p2){
Vector a=p1-p0;
Vector b=p2-p0;
if(cross(a,b)>eps) return COUNTER_CLOCKWISE;
if(cross(a,b)<-eps) return CLOCKWISE;
if(dot(a,b)<-eps) return ONLINE_BACK;
if(a.norm()
两个向量同一起点的叉乘积再乘1/2就是三角形的面积(哦哦哦,我知道,把多边形分成三角形就可以了)
#include
#include
#include
using namespace std;
const double eps = 1e-8;
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double k){return Point(k*x,k*y);}
Point operator / (double k){return Point(x/k,y/k);}
double norm(){return x*x+y*y;};
double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a, Vector b)
{
return a.x * b.x + a.y * b.y;
}
double cross(Vector a, Vector b)
{
return a.x * b.y - a.y * b.x;
}
double getS(Point a,Point b,Point c) //返回三角形面积
{
return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y)*(c.x - a.x))/2;
}
double getPS(Point p[],int n) //返回多边形面积。必须确保 n>=3,且多边形是凸多 边形
{
double sumS=0;
for(int i=1;i<=n-1;i++)
sumS+=getS(p[1],p[i],p[i+1]);
return sumS;
}
Point p[110];
int n;
int main()
{
while(~scanf("%d", &n) && n)
{
for(int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
double ans = getPS(p, n);
printf("%.1f\n", ans);
}
return 0;
}
模板解释博客
#include
#include
#include
#include
using namespace std;
typedef struct node
{
double x, y;
}NODE;
double cross(NODE A, NODE B, NODE P) //向量AB与向量AP的外积
{
NODE AB = { B.x - A.x, B.y - A.y };
NODE AP = { P.x - A.x, P.y - A.y };
return AB.x*AP.y - AB.y*AP.x;
}
double dot(NODE A, NODE B, NODE P) //向量AB与向量AP的外积
{
NODE AB = { B.x - A.x, B.y - A.y };
NODE AP = { P.x - A.x, P.y - A.y };
return AB.x*AP.x + AB.y*AP.y;
}
double dis2(NODE a, NODE b) //点a、b距离的平方
{
return (a.x - b.x)*(a.x - b.x) + (a.y-b.y)*(a.y-b.y);
}
int dir(NODE A, NODE B, NODE P) //点P与线段AB位置关系
{
if (cross(A, B, P) < 0) return -1; //逆时针
else if (cross(A, B, P)>0) return 1; //顺时针
else if (dot(A, B, P) < 0) return -2; //反延长线
else if (dot(A, B, P) >= 0&&dis2(A,B)>=dis2(A,P))
{
if (dis2(A, B) < dis2(A, P)) return 2; //延长线
return 0; //在线上
}
}
double disMin(NODE A, NODE B, NODE P) //点P到线段AB的最短距离
{
double r = ((P.x-A.x)*(B.x-A.x) + (P.y-A.y)*(B.y-A.y)) / dis2(A, B);
if (r <= 0) return sqrt(dis2(A, P));
else if (r >= 1) return sqrt(dis2(B, P));
else
{
double AC = r*sqrt(dis2(A,B));
return sqrt(dis2(A,P)-AC*AC);
}
}
int main()
{
NODE A1, A2, B1, B2;
int n;
scanf("%d", &n);
while(n--)
{
cin >> A1.x >> A1.y;
cin >> A2.x >> A2.y;
cin >> B1.x >> B1.y;
cin >> B2.x >> B2.y;
if (dir(A1, A2, B1)*dir(A1, A2, B2) <= 0 && dir(B1, B2, A1)*dir(B1, B2, A2) <= 0) //两线段相交, 距离为0
printf("%.10f\n", 0);
else printf("%.10f\n", min(min(min(disMin(A1, A2, B1), disMin(A1, A2, B2)), disMin(B1, B2, A1)),disMin(B1,B2,A2)));
//如不相交, 则最短距离为每个端点到另一条线段距离的最小值
}
return 0;
}