C++笔记-学习算法与实现-计算几何-二维向量和线段运算
判斷正負(fù)號(hào)
??給定一個(gè)double類(lèi)型的數(shù),判斷它的符號(hào);
const double eps = 1e-8; int cmp(double x) {if (fabs(x) < eps) return 0;if (x > 0) return 1;return -1; }??通過(guò)acos計(jì)算PI的值;計(jì)算sqr平方值;
const double pi = acos(-1.0); inline double sqr(double x) {return x * x; }計(jì)算幾何點(diǎn)類(lèi)
??設(shè)計(jì)了一個(gè)二維點(diǎn)類(lèi),可以進(jìn)行一些向量運(yùn)算。
????det:計(jì)算兩個(gè)向量的叉積;
????dot:計(jì)算兩個(gè)向量的點(diǎn)積;
????dist:計(jì)算兩個(gè)點(diǎn)的距離;
????rotate_point: o p ? \vec{op} op?繞原點(diǎn)逆時(shí)針旋轉(zhuǎn)A(弧度);
??點(diǎn)積(也叫內(nèi)積)結(jié)果 為 x1 * x2 + y1 * y2 = | a ? \vec{a} a|| b ? \vec{b} b| cos< a ? \vec{a} a, b ? \vec{b} b>,可以理解為向量a在向量b上投影的長(zhǎng)度乘以向量b的長(zhǎng)度。
??叉積(也叫外積)的模為 x1 * y2 - x2 * y1 = | a ? \vec{a} a|| b ? \vec{b} b| sin< a ? \vec{a} a, b ? \vec{b} b>,可以理解為平行四邊形的有向面積(三維以上為體積)。外積的方向垂直于這兩個(gè)方向。
計(jì)算幾何線(xiàn)段類(lèi)
??線(xiàn)段類(lèi)使用一個(gè)有向線(xiàn)段表示,線(xiàn)段類(lèi)的運(yùn)算使用向量運(yùn)算;內(nèi)部使用線(xiàn)段的兩個(gè)點(diǎn)記錄,用a->b表示有向線(xiàn)段;
struct line {point a;// beginpoint b;// endline() {}line(point x, point y) :a(x), b(y) {} }; // 用兩個(gè)點(diǎn) line point_make_line(const point a, const point b) {return line(a, b); } // 計(jì)算p點(diǎn)到線(xiàn)段st的距離 double dis_point_segment(const point p, const point s, const point t) {if (cmp(dot(p - s, t - s)) == 0) return (p - s).norm();if (cmp(dot(p - t, s - t)) == 0) return (p - t).norm();return fabs(det(s - p, t - p) / dist(s, t)); } // 計(jì)算p點(diǎn)在線(xiàn)段st上的投影點(diǎn)cp void PointProjLine(const point p, const point s, const point t, point& cp) {double r = dot((t - s), (p - s)) / dot(t - s, t - s);cp = s + r * (t - s); } // 判斷p點(diǎn)是否在線(xiàn)段st上(包括端點(diǎn)) bool PointOnSegment(point p, point s, point t) {return cmp(det(p - s, t - s)) == 0 && cmp(dot(p - s, p - t)) <= 0; } // 判斷線(xiàn)段a和線(xiàn)段b是否平行; bool parallel(line a, line b) {return !cmp(det(a.a - a.b, b.a - b.b)); } // 判斷線(xiàn)段a和線(xiàn)段b是否相交,如果相交則返回true且交點(diǎn)保存在res中; bool line_make_point(line a, line b, point& res) {if (parallel(a, b)) return false;double s1 = det(a.a - b.a, b.b - b.a);double s2 = det(a.b - b.a, b.b - b.a);res = (s1 * a.b - s2 * a.a) / (s1 - s2);return true; } // 將線(xiàn)段a沿著法線(xiàn)方向平移距離len得到的線(xiàn)段 line move_d(line a, const double& len) {point d = a.b - a.a;d = d / d.norm();d = rotate_point(d, pi / 2);return line(a.a + d * len, a.b + d * len); }計(jì)算p點(diǎn)到線(xiàn)段st的距離
??計(jì)算距離的特殊情況是p點(diǎn)與s點(diǎn)的連線(xiàn)垂直于st向量或者p點(diǎn)與t點(diǎn)的連線(xiàn)垂直于st向量時(shí),直接使用ps或者pt向量的模;
??一般情況下,使用面積法計(jì)算p點(diǎn)到st段上的投影,即使用ps向量和st向量的叉積表示兩個(gè)向量形成的平行四邊形的面積,除以st的線(xiàn)段長(zhǎng)度,就是p點(diǎn)到st向量的距離;
??具體代碼,參照之前代碼的dis_point_segment函數(shù);
總結(jié)
以上是生活随笔為你收集整理的C++笔记-学习算法与实现-计算几何-二维向量和线段运算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 第九章——规范数据库设计
- 下一篇: 拼手气红包算法_线段切割法