天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 158|回复: 0

计算几何笔记

[复制链接]
  • TA的每日心情
    开心
    半小时前
  • 签到天数: 20 天

    [LV.4]偶尔看看III

    115

    主题

    11

    回帖

    1393

    积分

    管理员

    积分
    1393
    QQ
    发表于 2024-3-16 09:08:26 | 显示全部楼层 |阅读模式
    1. 向量
    2. 常规操作
    3. struct Vector {
    4.     double x, y;
    5.     Vector(double x = 0, double y = 0) : x(x), y(y) {};
    6.     Vector operator + (const Vector &A) const {
    7.         return Vector(x + A.x, y + A.y);
    8.     }//向量的加法
    9.     Vector operator - (const Vector &A) const {
    10.         return Vector(x - A.x, y - A.y);
    11.     }//减法
    12.     Vector operator * (const double &A) const {
    13.         return Vector(x * A, y * A);
    14.     }//数乘
    15.     Vector operator / (const double &A) const {
    16.         return Vector(x / A, y / A);
    17.     }//数除
    18.     bool operator == (const Vector &A) const  {
    19.         return dcmp(x - A.x) == 0 && dcmp(y - A.y) == 0;
    20.     }//相等
    21. };
    22. 复制
    23. 向量的极角
    24. 极角:这里指从$x$轴旋转到向量方向的弧度
    25. double PolarAngle(Vector A) {
    26.     return atan2(A.y, A.x);
    27. }//向量的极角
    28. 复制
    29. 向量的旋转
    30. 若向量$(x, y)$旋转角度为$a$,则旋转后的向量为$(xcosa - ysina, y cosa + xsina)$
    31. 证明:
    32. 设旋转之前的向量的极角为$t$,半径为$r$
    33. 那么
    34. $$x = rcost$$
    35. $$y = rsint$$
    36. 旋转时候的向量为
    37. $$x' = rcos(t + a) = r(costcosa - sintsina) = xcosa - ysina$$
    38. $$y' = rsin(t + a) = r(sintcosa + costsina) = ycosa + xsina$$
    39. Vector rotate(Vector &A, double a) {
    40.     return A = Vector(A.x * cos(a) - A.y * sin(a), A.x * sin(a) + A.y * cos(a));
    41. }//向量旋转,a为弧度
    42. 复制
    43. 向量的点积
    44. $a \cdot b = |a||b|cos<a,b>$
    45. 两向量的点积得到的是标量,即一个向量的模长乘另一个向量在该向量上正投影的数量
    46. double Dot(Vector A, Vector B) {
    47.     return A.x * B.x +  A.y * B.y;
    48. }//两向量点积
    49. 复制
    50. 向量的叉积
    51. $a \times b = |a||b| sin<a,b>$
    52. 两向量叉积得到的是向量,在二维平面中得到的是三维空间中与这两个向量垂直的向量
    53. 在平面中,向量$v$和$w$的叉积等于$v$和$w$组成的三角形的有向面积的两倍
    54. 记$cross(v,w)$表示两向量的叉积,若$cross(v,w) > 0 $则说明$w$在$v$的左侧,否则$w$在$v$的右侧
    55. double Cross(Vector A, Vector B) {
    56.     return A.x * B.y - A.y * B.x;
    57. }//两向量叉积
    58. 复制
    59. 计算三角形面积
    60. 直接利用叉积的定义
    61. double Area(Point A, Point B, Point C) {
    62.     return fabs(Cross(B - A, C - A) / 2);
    63. }//计算三角形的面积
    64. 复制
    65. 计算向量的长度
    66. 直接利用点积的定义
    67. double Length(Vector A) {
    68.     return sqrt(Dot(A, A));
    69. }//计算向量的长度
    70. 复制
    71. 计算向量的夹角
    72. 同样直接利用点积的定义
    73. double Angle(Vector A, Vector B) {
    74.     return acos(Dot(A, B) / Length(A) / Length(B));
    75. }//计算向量的夹角
    76. 复制
    77. 线段
    78. 判断两直线的相对位置
    79. 判断$P采用1P采用0$与$P采用1P采用2$的相对位置关系,可以转化为判断$P采用1P采用0$与$P采用2P采用0$叉积的正负性
    80. int Direction(Vector P1, Vector P2, Vector P0) {
    81.     int opt = Cross(P1 - P0, P2 - P0);
    82.     return dcmp(opt);
    83. }//判断P1-P0,P1-P2的相对位置关系,-1为逆时针,1为顺时针(P1P0顺时针旋转到P1P2),0为共线
    84. 复制
    85. 判断两直线的交点
    86. 尼玛看不懂
    87. Point GetLineIntersection(Point P, Vector V, Point Q, Vector W) {
    88.     Vector u = P - Q;
    89.     double t = Cross(W, u) / Cross(V, W);
    90.     return P + V * t;
    91. }//判断两直线(P + tv,Q + tW)的交点(看不懂直接上y = kx + b吧)
    92. 复制
    93. 计算点到直线的距离
    94. 利用叉积算出他们围城的平行四边形的面积,再除以底,高即为距离
    95. double DistanceToLine(Point P, Point A, Point B) {
    96.     Vector v1 = B - A, v2 = P - A;
    97.     return fabs(Cross(v1, v2)) / Length(v1);
    98. }//计算点P到直线AB的距离(平行四边形面积 / 底)
    99. 复制
    100. 计算点到线段的距离
    101. 这个要分三种情况讨论
    102. double DistanceToSegment(Point P, Point A, Point B) {
    103.     if(A == B) return Length(P - A);
    104.     if(dcmp(Dot(P - A, B - A)) < 0) return Length(P - A);
    105.     if(dcmp(Dot(P - B, A - B)) < 0) return Length(P - B);
    106.     return DistanceToLine(P, A, B);
    107. }//计算点P到线段AB的距离
    108. 复制
    109. 多边形
    110. 计算多边形的有向面积
    111. 将$n$边形拆成三角形
    112. double PolygonAread(Point *P, int N) {
    113.     double area = 0;
    114.     for(int i = 1; i <= N - 1; i++)
    115.         area += Cross(P[i] - P[0], P[i + 1] - P[0]);
    116.     return area / 2;
    117. }//计算多边形的有向面积
    118. 复制
    119. 判断点是否在多边形内部
    120. 基本思想:从点$P$向右做一条射线,判断从无限远处到点$P$,射线穿过了几条边
    121. 有两种需要特判的情况
    122. 1.射线与某条边重合,该边不统计入答案
    123. 2.射线与端点重合
    124. 此时,我们钦定边是由编号小的连向编号大的
    125. 若边从上到下穿过了射线,包含终点不包含起点
    126. 若边从下到上穿过了射线,包含起点不包含重点
    127. int isPointInPolygon(Point P, Point Poly[], int N) {
    128.     int wn = 0, k, d1, d2;
    129.     for(int i = 0; i < N; i++) {
    130.         if(!dcmp(DistanceToSegment(P, Poly[i], Poly[(i + 1) % N]))) return -1;
    131.     //点在线段的边界上
    132.         k = dcmp(Cross(Poly[(i + 1) % N] - Poly[i], P - Poly[i]));
    133.         d1 = dcmp(Poly[i].y - P.y);
    134.         d2 = dcmp(Poly[(i + 1) % N].y - P.y);
    135.         if(k > 0 && d1 <= 0 && d2 > 0) wn++;//点在左,下上穿
    136.         if(k > 0 && d2 <= 0 && d1 > 0) wn++;//点在右,上下穿
    137.         return wn & 1; // 1:内 2:外   
    138.     }   
    139. }//判断点是否在多边形内部
    140. 复制
    141. 对踵点
    142. 定义:若点对$(a, b)$均为多边形上的点且存在过$a$点的切线与过$b$点的切线平行,则成$(a, b)$为多边形上的对踵点
    143. 计算方法:
    144. 设$p采用{ymin}$表示$y$最小的点,$q采用{ymax}$表示$y$最大的点,显然它们是一对对踵点
    145. 接下来以相同的角速度逆时针旋转两条射线,当其中的一条穿过多边形的下一个端点$p采用{next}$时,用$p采用{next}$作为新的端点,同时与$q采用{pre}$构成新的对踵点。
    146. 在这个算法中,我们快速的找出两条射线究竟是哪条先穿过下一个端点,我们可以用叉积来优化这一过程。
    147. 求凸多边形的直径
    148. 定义:凸多边形的直径为多边形的上最远的点对的距离
    149. 很显然,直径一定是在对踵点处取得,直接枚举对踵点即可
    150. double RotatingCaliper采用diameter(Point Poly[], int N) {
    151.     int p = 0, q = N - 1, fl;
    152.     double ret = 0;
    153.     for(int i = 0; i < N; i++) {
    154.         if(Poly[i].y > Poly[q].y) q = i;
    155.         if(Poly[i].y < Poly[p].y) p = i;
    156.     }
    157.     for(int i = 0; i < N * 3; i++) {
    158.         ret = max(ret, Length(Poly[p % N] - Poly[q % N]));
    159.         fl = dcmp(Cross(Poly[(p + 1) % N] - Poly[p % N], Poly[q % N] - Poly[(q + 1) % N]));
    160.         if(!fl) {
    161.             ret = max(ret, Length(Poly[p % N] - Poly[(q + 1) % N]));
    162.             ret = max(ret, Length(Poly[q % N] - Poly[(p + 1) % N]));
    163.             p++, q++;
    164.         } else {
    165.             if(fl > 0) p++;
    166.             else q++;
    167.         }
    168.     }
    169. }//计算多边形直径
    170. 复制
    171. 凸多边形的宽度
    172. 凸多边形最小面积外接矩形
    173. 凸包-Andrew算法
    174. 首先按照$x$为第一关键字,$y$为第二关键字从小到大排序,并删除重复的点
    175. 用栈维护凸包内的点
    176. 1、把$p采用1, p采用2$放入栈中
    177. 2、若$p采用{i{(i > 3)}}$在直线$p采用{i - 1}, p采用{i - 2}$的右侧,则不断的弹出栈顶,直到该点在直线左侧
    178. 3、此时我们已经得到了下凸包,那么反过来从$p采用n$再做一次即可得到下凸包
    179. 题目链接
    180. // luogu-judger-enable-o2
    181. #include<cstdio>
    182. #include<cmath>
    183. #include<algorithm>
    184. using namespace std;
    185. const int eps = 1e-10;
    186. int dcmp(double x) {
    187.     if(fabs(x) < eps) return 0;
    188.     return x < 0 ? -1 : 1;
    189. }
    190. #define Point Vector
    191. struct Vector {
    192.     double x, y;
    193.     Vector(double x = 0, double y = 0) : x(x), y(y) {};
    194.     bool operator < (const Vector &rhs) const {
    195.         return dcmp(x - rhs.x) == 0 ? y < rhs.y : x < rhs.x;
    196.     }
    197.     Vector operator - (const Vector &rhs) const {
    198.         return Vector(x - rhs.x, y - rhs.y);
    199.     }
    200. };
    201. double Cross(Vector A, Vector B) {
    202.     return A.x * B.y - A.y * B.x;
    203. }
    204. double dis(Point a, Point b) {
    205.     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    206. }
    207. int N;
    208. Point p[10001], q[10001];
    209. int top;
    210. void Push(Point p) {
    211.     while(Cross(q[top] - q[top - 1], p - q[top - 1]) < 0) top--;
    212.     q[++top] = p;
    213. }
    214. void Andrew() {
    215.     q[0] = q[top = 1] = p[1];
    216.     for(int i = 2; i <= N; i++) Push(p[i]);
    217.     for(int i = N - 1; i; --i)  Push(p[i]);
    218. }
    219. int main() {   
    220.     scanf("%d", &N);
    221.     for(int i = 1; i <= N; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
    222.     sort(p + 1, p + N + 1);
    223.     Andrew();
    224.     double ans = 0;
    225.     for(int i = 1; i < top; i++)
    226.         ans += dis(q[i], q[i + 1]);
    227.     printf("%.2lf", ans);
    228.     return 0;
    229. }
    230. 复制
    231. 要做的题
    232. POJ 2187 凸多边形直径
    233. #include<cstdio>
    234. #include<cmath>
    235. using namespace std;
    236. const int eps = 1e-10;
    237. int dcmp(double x) {
    238.     if(fabs(x) < eps) return 0;
    239.     return x < 0 ? -1 : 1;
    240. }
    241. #define Point Vector
    242. struct Vector {
    243.     double x, y;
    244.     Vector(double x = 0, double y = 0) : x(x), y(y) {};
    245.     Vector operator + (const Vector &A) const {
    246.         return Vector(x + A.x, y + A.y);
    247.     }//向量的加法
    248.     Vector operator - (const Vector &A) const {
    249.         return Vector(x - A.x, y - A.y);
    250.     }//减法
    251.     Vector operator * (const double &A) const {
    252.         return Vector(x * A, y * A);
    253.     }//数乘
    254.     Vector operator / (const double &A) const {
    255.         return Vector(x / A, y / A);
    256.     }//数除
    257.     bool operator == (const Vector &A) const  {
    258.         return dcmp(x - A.x) == 0 && dcmp(y - A.y) == 0;
    259.     }//相等
    260. };
    261. double PolarAngle(Vector A) {
    262.     return atan2(A.y, A.x);
    263. }//向量的极角
    264. Vector rotate(Vector &A, double a) {
    265.     return A = Vector(A.x * cos(a) - A.y * sin(a), A.x * sin(a) + A.y * cos(a));
    266. }//向量旋转,a为弧度
    267. double Dot(Vector A, Vector B) {
    268.     return A.x * B.x +  A.y * B.y;
    269. }//两向量点积
    270. double Cross(Vector A, Vector B) {
    271.     return A.x * B.y - A.y * B.x;
    272. }//两向量叉积
    273. double Area(Point A, Point B, Point C) {
    274.     return fabs(Cross(B - A, C - A) / 2);
    275. }//计算三角形的面积
    276. double Length(Vector A) {
    277.     return sqrt(Dot(A, A));
    278. }//计算向量的长度
    279. double Angle(Vector A, Vector B) {
    280.     return acos(Dot(A, B) / Length(A) / Length(B));
    281. }//计算向量的夹角
    282. int Direction(Vector P1, Vector P2, Vector P0) {
    283.     int opt = Cross(P1 - P0, P2 - P0);
    284.     return dcmp(opt);
    285. }//判断P1-P0,P1-P2的相对位置关系,-1为逆时针,1为顺时针(P1P0顺时针旋转到P1P2),0为共线
    286. Point GetLineIntersection(Point P, Vector V, Point Q, Vector W) {
    287.     Vector u = P - Q;
    288.     double t = Cross(W, u) / Cross(V, W);
    289.     return P + V * t;
    290. }//判断两直线(P + tv,Q + tW)的交点(看不懂直接上y = kx + b吧)
    291. double DistanceToLine(Point P, Point A, Point B) {
    292.     Vector v1 = B - A, v2 = P - A;
    293.     return fabs(Cross(v1, v2)) / Length(v1);
    294. }//计算点P到直线AB的距离(平行四边形面积 / 底)
    295. double DistanceToSegment(Point P, Point A, Point B) {
    296.     if(A == B) return Length(P - A);
    297.     if(dcmp(Dot(P - A, B - A)) < 0) return Length(P - A);
    298.     if(dcmp(Dot(P - B, A - B)) < 0) return Length(P - B);
    299.     return DistanceToLine(P, A, B);
    300. }//计算点P到线段AB的距离
    301. double PolygonAread(Point *P, int N) {
    302.     double area = 0;
    303.     for(int i = 1; i <= N - 1; i++)
    304.         area += Cross(P[i] - P[0], P[i + 1] - P[0]);
    305.     return area / 2;
    306. }//计算多边形的有向面积
    307. int isPointInPolygon(Point P, Point Poly[], int N) {
    308.     int wn = 0, k, d1, d2;
    309.     for(int i = 0; i < N; i++) {
    310.         if(!dcmp(DistanceToSegment(P, Poly[i], Poly[(i + 1) % N]))) return -1;
    311.     //点在线段的边界上
    312.         k = dcmp(Cross(Poly[(i + 1) % N] - Poly[i], P - Poly[i]));
    313.         d1 = dcmp(Poly[i].y - P.y);
    314.         d2 = dcmp(Poly[(i + 1) % N].y - P.y);
    315.         if(k > 0 && d1 <= 0 && d2 > 0) wn++;//点在左,下上穿
    316.         if(k > 0 && d2 <= 0 && d1 > 0) wn++;//点在右,上下穿
    317.         return wn & 1; // 1:内 2:外   
    318.     }   
    319. }//判断点是否在多边形内部
    320. int main() {   
    321.         
    322.     return 0;
    323. }
    324. https://cloud.tencent.com/developer/article/1172724?areaId=106001
    复制代码

     

     

     

     

    计算几何笔记
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

    GMT+8, 2024-11-5 06:04 , Processed in 0.194667 second(s), 26 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表