20201012day33 复习6:计算几何

计算几何的一些东西(入门)

矢量表示

class CVector{
      double x,y;
};

表示从0到((x,y))的矢量。对矢量只关心方向和长度,不关心起点和终点
2.

CVector operator +(CVector p,CVector q){
      return CVector(p.x+q.x,p.y+q.y);
}

用法:c=a+b
3.

CVector operator -(CVector p, CVector q) {
      return CVector(p.x - q.x, p.y - q.y);
}

用法:c=a-b
4.

CVector operator *(double k, CVector p) {
return CVector(k * p.x, k * p.y);
}

(oldsymbol{c}=foldsymbol{a}),f是double
5.矢量的点积

double operator *(Cvector p,CVector q){
      return p.x*q.x+p.y*q.y;
}

功能:求同向还是异向;求投影;求投影后用勾股定理求点到直线距离
6.矢量模长

double length(CVector p){
      return sqrt(p*p);
}

7.向量单位化
将矢量除以自身的长度来得到同方向的单位矢量

CVector unit(CVector p){
      return 1/length(p)*p;
}

8.矢量的投影长度
矢量与该方向单位向量的点积
注意:负数表示反方向

double project(CVector p,CVector n){
      return dot(p,unit(n));
}
double dot(CVector p,CVector q){
      return p.x*q.x+p.y*q.y;
}

表示向量p在向量n上的投影p'

b在a上的投影的模是(dfrac{oldsymbol{a} cdot oldsymbol{b}}{|oldsymbol{a}|})
所以b在a上的投影即为(dfrac{oldsymbol{a} cdot oldsymbol{b}}{|oldsymbol{a}|} dfrac{oldsymbol{a}}{|oldsymbol{a}|}=oldsymbol{a}dfrac{oldsymbol{a} cdot oldsymbol{b}}{oldsymbol{a}^2})
9.矢量的对称
记b在a上的投影为(oldsymbol{S}=oldsymbol{a}dfrac{oldsymbol{a} cdot oldsymbol{b}}{oldsymbol{a}^2})
则b关于a的对称为(oldsymbol{b-2(b-S)=2S-b=2adfrac{acdot b}{a^2}-b})
10.向量的叉乘
性质:在二维情况中,(oldsymbol{|p imes q|=|p||q|sin<p,q>})
功能:求面积;求顺时针方向还是逆时针方向;判断是否在半平面上

double operator ^(CVector p,CVector q){
      return p.x*q.y-q.x*p.y;
}
c=a^b;//a,b,c all is CVector type

(oldsymbol{a imes b})为有向面积,可正可负,若a逆时针旋转小于180°可到b,则结果为正,否则结果为负

11.叉积排序

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
struct Vector
{
double x, y;
Vector(int xx, int yy) :x(xx), y(yy) { }
Vector() { }
double operator ^ (const Vector & v) const {
return x*v.y - v.x*y;
}
};
#define Point Vector
Vector operator - (const Point & p1, const Point & p2)
{ //从A点指向B点的矢量AB可用B-A来表示
return Vector(p1.x - p2.x, p1.y - p2.y); 
//矢量从 p2指向p1 
}
bool operator < (const Point & p1, const Point & p2)
{
//如果p1^p2 〉0,说明p1经逆时针旋转<180度可以到p2,则 p1 < p2
if ((Vector(p2 - Point(0, 0)) ^ 
Vector(p1 - Point(0, 0))) > 0)
return true;
return false;
}
Point ps[60];
int main()
{
int x, y;
int n = 0;
while (cin >> ps[n].x >> ps[n].y)
++n;
sort(ps + 1, ps + n);
cout << "(0,0)" << endl;
for (int i = n - 1; i > 0; --i)
cout << "(" << ps[i].x << ",“<< ps[i].y << ")" << endl;
return 0;
}

12.矢量围成的三角形面积
叉积的一半

double area(CVector p, CVector q) {
      return p^q / 2; 
}

13.求多边形的面积
基本思路是进行三角剖分。
指定逆时针方向,枚举(vec{AB}),累加(dfrac{vec{A} imesvec{B}}{2})
14.点、线的表示

#define CPoint CVector
class CPoint {
double x, y;
}
class CLine {
CPoint a, b;
}

15.常用函数与常数

double PI = acos(-1);
double INF = 1e20;
double EPS = 1e-6; //精度不是越高
bool IsZero(double x) {
      return –EPS < x && x < EPS;
}
bool FLarger(double a, double b) {
      return a - b > EPS;
}
bool FLess(double a, double b) {
      return b - a > EPS;
}

16.点与矢量

CVector operator -(CPoint b, CPoint a) 
{
      return CVector(b.x – a.x, b.y – a.y);
} // c = a – b;
CPoint operator +(CPoint a, CVector p) {
      return CPoint(a.x + p.x, a.y + p.y);
} // p = p + v; p是点,v是向量

17.点与点距离
利用两点之间模长

double dist(CPoint p, CPoint q) {
      return length(p – q);
} //从A点指向B点的矢量AB可用来

点与线距离
利用叉积求面积,然后除以底边即为高

double dist(CPoint p, CLine l) {
      return fabs((p – l.a) ^ (l.b – l.a)) / length(l.b – l.a);
}

19.点绕点旋转(二维)
旋转矢量AB到AC注:
在xy平面上逆时针旋转α角(弧度制)

CPoint rotate(CPoint b, CPoint a,double alpha) {//返回点C坐标
CVector p = b – a;
return CPoint(a.x + (p.x * cos(alpha)- p.y * sin(alpha)), a.y + (p.x * sin(alpha)+ p.y * cos(alpha));
}

20.点在直线左侧还右侧
直线用两个点A,B表示,是有方向的,假设方向是A->B

int sideOfLine(Point p, Point a, Point b)
{ //判断p在直线 a->b的哪一侧
      double result = (b - a) ^ (p - a);
      if (IsZero(result))
      return 0; //p 在 a->b上
      else if (result > 0)
      return 1; //p在a->b左侧
      else
      return -1; //p在a->b右侧
}

21.过点作线的垂线(二维)

CLine Vertical(CPoint p, CLine l) {
 return CLine(p,p + (rotate(l.b, l.a, PI / 2) – l.a));
}

22.点到线的垂足
利用点积求投影,进而求出垂足
应用:求对称点
注:在平面上也可作垂线,利用线与线交点(后面会提到)

CPoint foot(CPoint p, CLine l) {
 return l.a + project(p – l.a, l.b – l.a)* unit(l.b – l.a);
} 

23.线与线夹角
利用投影(也可以利用叉积或余弦定理)
应用:两直线的位置关系,射线夹角(注意方向即可)

double angle(CLine l, CLine m) {
 return acos(fabs(project(l.b – l.a, m.b – m.a)/ length(l.b – l.a)));
}
原文地址:https://www.cnblogs.com/liuziwen0224/p/20201012day33-002.html