计算几何总结

1 计算几何基础

1.1 向量

(1)零向量

长度为零的向量称为零向量,记作0。 零向量的方向不确定,也是唯一方向不定的向量。

(2) 向量点积

两向量ab的点积(或称为标记)为一个标量,大小为:

a.b = |a|*|b|*cos<a,b>

其中,<a, b>为两向量ab的夹角,也可计算两向量的夹角:

<a,b> = arccos(a.b/(|a|*|b|))

若设向量P=(x1, y1), Q=(x2, y2), 则:

P.Q = x1*x2 + y1*y2

(3)向量叉积

两个向量ab的叉积写作a×b(有时也被写成a∧b,避免和字母x混淆)。向量积可以被定义为:

|向量向量b|=|a||b|sinθ在这里θ表示两向量之间的角夹角(0° ≤ θ ≤ 180°),它位于这两个矢量所定义的平面上。

一个简单的确定满足“右手定则”的结果向量的方向的方法是这样的:

若坐标系是满足右手定则的,当右手的四指从a以不超过180度的转角转向b时,竖起的大拇指指向是c的方向。向量积:

|c|=|a×b|=|a| |b|sin<a,b>
c的长度在数值上等于以ab,夹角为θ组成的平行四边形的面积;

c的方向垂直于ab所决定的平面,c的指向按右手规则从a转向b来确定。

几何意义:
叉积的长度 |a×b| 可以解释成以a和b为邻边的平行四边形的面积。
混合积 [a b c] = (a×b)·c可以得到以a,b,c为棱的平行六面体的体积。

设向量P = (x1, y1), Q = (x2, y2), 则向量P与向量Q的叉积任是一个向量,它的长度规定为:

|P×Q| = x1*y2 - x2*y1

它的方向规定为:与向量P, Q均垂直,并且使(P, Q, P×Q)成右手系,即当右手四指从P弯向Q(转角小于pi)时,拇指的指向就是P×Q的方向。

显然有性质:

P×Q = - (P×Q),P×(-Q)= - (P×Q

通过叉积的符号来判断两向量相互之间的顺逆时针的关系:

若P×Q > 0, 则P在Q的顺时针方向,如图(a);

若P×Q < 0, 则P在Q的逆时针方向,如图(b);

若P×Q = 0, 则P与Q共线,但可能同向也可能反向,如图(c)。

 

(4)Determining whether consecutive segments turns left or right:



1.2 点定位

(1)判断点是否在线段上:

设点Q及线段P1P2,判断点Q在线段P1P2上的包括两条依据:

1> (Q - P1)×(P2 - P1) = 0;

2> Q在以P1, P2为对角顶点的矩形内。

(2)判断点在三角形内外:

ABC,判断点Q是否在三角形内(包括在某条边上),则当:

S(PAB)  + S(PAC) + S(PBC) = S(ABC)

即可判断点Q在△ABC之内。

三角形ABC的面积 = 1/2*|AB × AC| = 1/2*|AB × BC| = 1/2*|AC×BC|

(3)判断点在矩形中:

设点Q及矩形P1P2P3P4,若判断点Q在矩形P1P2P3P4中,

只需判断该点的横、纵坐标是否夹在矩形的左、右边和上、下边之间。

(4)判断点在多边形的内外:

角度和的判断法(适用于任意多边形)

对于平面多边形来说,连接多边形内点与多边形所有顶点所形成的所有角的角度和在要求精度范围内应该等于360度;

如果小于360度或大于360度,则证明点不在多边形中。


1.3 线段

(1)判断两条线段是否相交:

1>快速排斥实验。

设以线段A1A2为对角线的矩形为R,设以线段B1B2为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。

判断矩形相交,只需判断某一矩形是否有顶点在另一矩形内即可。

2>跨立实验。

如果两线段相交,则两线段必然相互跨立对方。设向量P1 = 向量OA1, 向量P2 = 向量OA2,向量Q1 = 向量OB1,向量Q2= 向量OB2,

若线段A1A2跨立线段B1B2,则向量(P1 - Q1) 和(P2 - Q1)位于向量(Q2 - Q1)的两侧,即

((P1 - Q1)×(Q2 - Q1)).((P2 - Q1)×(Q2 - Q1)) < 0

上式可改写成:

((P1 - Q1)×(Q2 - Q1)).((Q1 - P2)×(Q2 - Q1)) > 0

当(P1 - Q1)×(Q2 - Q1) = 0时,说明(P1 - Q1)和(Q2 - Q1) 共线,但是因为已经通过快速排斥实验,所以点A1一定在线段B1B2上;

同理,(P2 - Q1)×(Q2 - Q1) = 0,说明点A2一定在线段B1B2上。所以:

判断线段A1A2跨立线段B1B2的依据是:

((P1 - Q1)×(Q2 - Q1)).((Q1 - P2)×(Q2 - Q1)) >= 0

判断线段B1B2跨立线段A1A2的依据是:

((Q1 - P1)×(P2 - P1)).((P1 -Q2)×(P2 -P1)) >= 0

(2)求线段交点

若已确定两线段相交, 求两线段交点的坐标。

可以通过解析几何中的直线方程求解,也可通过向量方法来求解。

向量法:

定义叉积multi(p1, p2, p0)可看作是由点p1, p2, p0p1+p2这四个点围成的平行四边形的阴影面积,及S(△p0p1p2) = 1/2*multi(p1, p2, p0)。  

struct Point{
    double x, y;
};

double multi(Point p1, Point p2, Point p0){
	return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
}
设线段AB和CD交于点P,所以:



2 解析几何

2.1 三角形面积的计算

设a, b, c为三角形三条边的长度,则三角形面积的公式有如下几类:

S△ = 1/2*h*c(其中,h为高,c为对应的底边)

S△ = 1/2*a*b*sinC = 1/2*a*c*sinB = 1/2*b*c*sinA

S△ = a*b*c/(4*R) (其中R是三角形外接圆半径)

S△ = (a + b + c)*r/2 (r是三角形的内切圆半径)
S△ = 1/2*a*b*sin<a, b>

S△ = sqrt(p*(p-a)*(p-b)*(p-c)) (其中p = 1/2*(a + b + c))

还可利用向量的叉积来求三角形的面积,任意两边的叉积的绝对值的1/2即为三角形的面积。

设三角形ABC,其顶点坐标分别为(A.x, A.y), (B.x, B.y), (C.x, C.y), 则面积为:

S△ = ((B.x - A.x)*(C.y - A.y) - (C.x - A.x)*(B.y - A.y)) / 2

具体实现代码如下:

double triangleArea(Point A, Point B, Point C){
    return fabs((B.x - A.x)*(C.y - A.y) - (C.x - A.x)*(B.y - A.y))/2;
}
2.2 多边形面积的计算

这里的多边形指简单多边形,即不会出现自交的多边形,计算时采用剖分的思想,将其转化成求多个三角形面积的子问题的集合。

如下图:


面积的计算公式为:



若所选取的点既不是在多边形内,也不是多边形的顶点,而是原点时,多边形面积公式为:


2.3 三角形的外接圆

三角形外接圆是三条边上垂直平分线的交点,而外接圆的半径是外心到定点的距离。

设三角形三点坐标分别为(x1, y1), (x2, y2), (x3, y3),则三角形的外心坐标为:

X = ((x1 - x2)*(x1 + x2)/(2*y1 - 2*y2) - (x3 - x2)*(x3 + x2)/(2*y3 - 2*y2) + (y1 + y2)/2 - (y3 + y2))/((x1 - x2)/(y1 - y2) - (x3 - x2)/(y3 - y2))

Y = ((y1 - y2)*(y1 + y2)/(2*x1 - 2*x2) - (y3 - y2)*(y3 + y2)/(2*x3 - 2*x2) + (x1 + x2)/2 - (x3 + x2))/((y1 - y2)/(x1 - x2) - (y3 - y2)/(x3 - x2))

2.4 三角形的内切圆

三角形的内切圆的圆心是三角形内角平分线的交点。

设三角形三点坐标分别为(x1, y1), (x2, y2), (x3, y3),则三角形的内心坐标(X, Y)为:

a = sqrt((x2 - x3)*(x2 - x3) + (y2 - y3)*(y2 - y3));  
b = sqrt((x1 - x3)*(x1 - x3) + (y1 - y3)*(y1 - y3));  
c = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)); 

X = (a*x1 + b*x2 + c*x3)/(a + b + c)

Y = (a*y1 + b*y2 + c*y3)/(a + b + c)


3 立体几何

3.1 叉积

设有u(u1, u2, u3),v(v1, v2, v3),则三维叉积计算公式为

u×v= [u2*v3 - u3*v2, u3*v1 - u1*v3, u1*v2 - u2*v1]

叉积方向和uv都垂直,方向由右手定则确定,长度是以uv为为边组成的平行四边形的面积。叉积公式如下:

|u×v| = |u|*|v|*sin<u,v>

3.2 点积

点积的计算公式为:

u×v = u1*v1 + u2*v2 + u3*v3

点积的结果并非一个向量,而是一个实数,其大小为|u|*|v|*cos<u,v>

3.3 判断四点共面

设空间中有四点a, b, c, d,取a,b,c三点求其叉积v

若叉积v为0向量(向量长度为0),则a, b, c三点共线,故a, b , c, d四点必共面;

若叉积v不为0向量,则v为a, b, c三点构成平面的法向量,此时可利用点积判断法向量v与直线ad是否垂直(垂直点积为0)。

3.4 平行和垂直

利用叉积判断两向量是否平行:

u×v = 0(向量长度为0),则u、v平行;

利用点积判断两向量是否垂直:

u.v =0(标量),则u、v垂直;

3.4 欧拉四面体体积公式


(1)

如上图(1)所示的四面体OABC,由立体几何知识知道V = 1/3*h*S△ABO,其中,h是点C到平面ABO的距离。

又S△ABO = 1/2*(OA×OB),故有:V = 1/6*OC*(OA×OB)OA、OBOC为向量,构成右手系时为正,

其中OC*(OA×OB)称为向量的混合积。

四面体还可以用其六条棱长来表示体积,具体的解决方法是将四面体放入直角坐标系内,利用向量混合积的几何意义及

坐标运算公式,结合向量数量积的坐标运算公式、定义及余弦定理得到用六条棱长表示的四面体体积公式。

欧拉四面体公式的推导及证明过程。

下面我直接给出结论及计算机表达式:

如上图(1)所示,O为顶点;ABC为底面三角形;|OA| = p, |OB| = q, |OC| = r, |AB| = n, |BC| = l, |CA| = m.

结论:


计算机表达式:

v=(double)sqrt((4.0*p*p*q*q*r*r-p*p*(q*q+r*r-l*l)*(q*q+r*r-l*l)-
      q*q*(r*r+p*p-m*m)*(r*r+p*p-m*m)-r*r*(p*p+q*q-n*n)*
      (p*p+q*q-n*n)+(p*p+q*q-n*n)*(q*q+r*r-l*l)*
      (r*r+p*p-m*m)))/12.0;

此公式注意题目中的边和图(1)中的边要对应,否则会wa. 

参看poj 2208 欧拉四面体公式的运用一个比较好的解法

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int main()
{
	double a,b,c,d,e,f;
	double tr1,tr2,tr3,tr4,temp,ans;
	while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)
	{
	tr1=acos((c*c+b*b-f*f)/(2.0*b*c));
	tr2=acos((a*a+c*c-e*e)/(2.0*a*c));
	tr3=acos((a*a+b*b-d*d)/(2.0*a*b));
	tr4=(tr1+tr2+tr3)/2.0;
	temp=sqrt(sin(tr4)*sin(tr4-tr1)*sin(tr4-tr2)*sin(tr4-tr3));
	ans=a*b*c*temp/3.0;
	printf("%.4lf\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值