计算几何--二维几何基础练习

Posted 125418a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算几何--二维几何基础练习相关的知识,希望对你有一定的参考价值。

内容参考书籍——《算法竞赛入门经典训练指南》

例题1 题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2119

  莫利定理(Morley‘s theorem),也称为莫雷角三分线定理。将三角形的三个内角三等分,靠近某边的两条三分角线相交得到一个交点,则这样的三个交点可以构成一个正三角形。这个三角形常被称作莫利正三角形。

本题无算法可言,暴力求解即可(根据夹角根据旋转三角形的边,求出交点即为答案)。

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 struct Point
  4 {
  5     double x,y;
  6     Point(double x=0, double y=0):x(x),y(y) {}//构造函数,方便编写代码
  7 };
  8 typedef Point Vector;//别名
  9 //向量+向量=向量,点+向量=点
 10 Vector operator + (Vector A, Vector B){return Vector(A.x+B.x,A.y+B.y);}
 11 //点-点=向量
 12 Vector operator - (Vector A, Vector B){return Vector(A.x-B.x,A.y-B.y);}
 13 //向量*数=向量
 14 Vector operator * (Vector A, double p){return Vector(A.x*p,A.y*p);}
 15 //向量/数=向量
 16 Vector operator / (Vector A, double p){return Vector(A.x/p,A.y/p);}
 17 
 18 bool operator < (const Point& a, const Point& b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
 19 
 20 const double eps = 1e-10;
 21 int dcmp(double x)
 22 {
 23     if (fabs(x) < eps) return 0;
 24     else return x < 0 ? -1 : 1;
 25 }
 26 
 27 bool operator == (const Point& a, const Point &b){return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}
 28 
 29 //计算点积、向量长度、夹角函数
 30 double Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y;}
 31 double Length(Vector A){return sqrt(Dot(A,A));}
 32 double Angle(Vector A, Vector B){return acos(Dot(A,B)/Length(A)/Length(B));}
 33 
 34 //计算叉积
 35 double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
 36 double Area2(Point A, Point B, Point C){return Cross(B-A,C-A);}
 37 
 38 //计算旋转和单位法向量
 39 //rad为弧度
 40 Vector Rotate(Vector A, double rad){return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
 41 Vector Normal(Vector A)
 42 {
 43     double L =Length(A);
 44     return Vector(-A.y/L,A.x/L);
 45 }
 46 
 47 //交点,注意精度问题
 48 //调用该函数前请确保两条直线P+tv和Q+tw有唯一交点。当且仅当Cross(v,w)非0
 49 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
 50 {
 51     Vector u = P-Q;
 52     double t = Cross(w,u) / Cross(v,w);
 53     return P+v*t;
 54 }
 55 //点到直线的距离。用叉积计算。平行四边形的面积除以底
 56 double DistanceToLine(Point P, Point A, Point B)
 57 {
 58     Vector v1 = B-A,v2= P-A;
 59     return fabs(Cross(v1,v2)) / Length(v1);
 60 }
 61 //点到线段的距离
 62 double DistanceToSegment(Point P, Point A, Point B)
 63 {
 64     if (A==B) return Length(P-A);
 65     Vector v1 = B-A,v2 = P-A,v3=P-B;
 66     if (dcmp(Dot(v1,v2))<0) return Length(v2);
 67     else if (dcmp(Dot(v1,v3))>0) return Length(v3);
 68     else return fabs(Cross(v1,v2)) / Length(v1);
 69 }
 70 //计算投影点
 71 Point GetLineProjection(Point P, Point A, Point B)
 72 {
 73     Vector v = B-A;
 74     return A+v*(Dot(v,P-A) / Dot(v,v));
 75 }
 76 //按“相交规范”判断相交
 77 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
 78 {
 79     double c1 = Cross(a2-a1,b1-a1),c2 = Cross(a2-a1,b2-a1),
 80     c3 = Cross(b2-b1,a1-b1),c4 = Cross(b2-b1,a2-b1);
 81     return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
 82 }
 83 //允许在端点处相交,判断是否发生加入下面一段判断一个点是否在一条线段上的代码
 84 bool OnSegment(Point P,Point a1, Point a2)
 85 {
 86     return dcmp(Cross(a1-P,a2-P)) == 0 && dcmp(Dot(a1-P,a2-P))<0; 
 87 }
 88 //多边形的有向面积
 89 double PolygonArea(Point* p, int n)
 90 {
 91     double area = 0;
 92     for (int i = 1; i < n-1; ++i)
 93     {
 94         area +=Cross(p[i]-p[0],p[i+1]-p[0]);
 95     }
 96     return area/2;
 97 }
 98 Point GetDaan(Point A,Point B,Point C)
 99 {
100     //bc逆时针转
101     Vector v1 = C-B;//直线方向向量
102     double a1=Angle(A-B,v1);
103     v1 = Rotate(v1,a1/3);
104     //bc顺时针转
105     Vector v2 = B-C;
106     double a2=Angle(A-C,v2);
107     v2 = Rotate(v2,-a2/3);//负数表示顺时针旋转
108 
109     return GetLineIntersection(B,v1,C,v2);
110 }
111 int main(int argc, char const *argv[])
112 {
113     int t;
114     cin>>t;
115     while(t--)
116     {
117         Vector a,b,c;
118         Vector d,e,f;//答案
119         cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y;
120         d=GetDaan(a,b,c);
121         e=GetDaan(b,c,a);
122         f=GetDaan(c,a,b);
123         printf("%.6f %.6f %.6f %.6f %.6f %.6f
",d.x,d.y,e.x,e.y,f.x,f.y);
124     }
125     return 0;
126 }

例题2题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=submit_problem&problemid=2896&category=0

  已知两狗以恒定速度奔跑但速度未知,同时出发同时达到,已知各自起点折线跑过程中的拐点和终点,求狗距。狗距=(奔跑过程中的最大距离减去最小距离)。

  首先,我们考虑两条狗直线奔跑,那么我们可以认为一条狗不动,另外一条狗相对于这条狗奔跑。即问题转化为,求一个点到一条线段的最短距离和最大距离。

  现在我们来模拟整个过程,用pa和pb来记录当前两条狗的位置,sa和sb为各自拐点的编号,每一次我们计算这两条狗谁先到达下一个拐点,那么在他到达下一个拐点的这段时间里便是上面说的直线奔跑的情况,不断跟新pa,pb,sa,sb,以及狗距最后的的结果便是答案。

代码如下(待更新)

 

以上是关于计算几何--二维几何基础练习的主要内容,如果未能解决你的问题,请参考以下文章

算法学习:计算几何基础

《计算机视觉中的多视图几何》笔记有限射影摄像机

计算几何模板中的代码

二维几何基础

计算几何--二维几何常用算法

二维空间计算几何