本文涉及知识点
预备知识
半平面
ax+by+c=0是直线,直线将整个平面分成两个半平面,ax+by+c ≤ 0 \le 0 ≤0是其中一个半平面。
ax+by+c=0的方向,如果直线不垂直于x轴,我们不妨令方向为 ( 0 , y 0 ) 到 ( 1 , y 1 ) 即( 1 , − a − c b − − c b ) = ( 1 , − a b ) = ( b , − a ) (0,y_0)到(1,y_1)即(1,\frac{-a-c}b-\frac{-c}b)=(1,\frac{-a}b)=(b,-a) (0,y0)到(1,y1)即(1,b−a−c−b−c)=(1,b−a)=(b,−a)。b=0时,也是此方向。
逆时针旋转 90 ∘ , ( b cos 90 ∘ − a sin 90 ∘ , − b sin 90 ∘ − a cos 90 ∘ ) = ( − a , − b ) 90^\circ,(b\cos 90^\circ-a\sin90^\circ,-b\sin90^\circ-a\cos90^\circ)=(-a,-b) 90∘,(bcos90∘−asin90∘,−bsin90∘−acos90∘)=(−a,−b)
在旋转 180 ∘ , 就变成 ( a , b ) 在旋转180^\circ,就变成(a,b) 在旋转180∘,就变成(a,b)
我们直接顺时针旋转 90 ∘ 90^\circ 90∘就变成了法向量,数学没规定直线的方向,只规定了直线法线的方向(a,b),执向ax+by ≥ 0 \ge 0 ≥0所在半平面。
ax+by 可以看成(a,b)和(x,y)的点乘。直线 ax+by=0 平移 M ( 0 , − c b ) M(0,\frac {-c}b) M(0,b−c), ax+by+c。
任意向量(x,y)和(a,b)夹角为 0 , 或 180 ∘ 0,或180^\circ 0,或180∘,ax+by上,平移M后ax+by+c上。
任意向量(x,y)和(a,b)夹角 大于 0 , 小于 90 ∘ 大于0,小于90^\circ 大于0,小于90∘,ax+by的左侧,平移M后ax+by+c的左侧。
任意向量(x,y)和(a,b)夹角 大于 90 , 小于 180 ∘ 大于90,小于180^\circ 大于90,小于180∘,ax+by的右侧,平移M后ax+by+c的右侧。
排除三点共线,凸多边形不会有两条边在同一直线上
令这两条边和直线的交点为 p 1 , p 2 , p 3 , p 4 p_1,p_2,p_3,p_4 p1,p2,p3,p4,对这四个点按直线的任意方向排序。则 p 1 p 2 和 p 3 p 4 在多边线上 , 线段 p 2 p 3 非端点不在多边形上,与凸多边形定义矛盾 p1p2和p3p4在多边线上,线段p2p3非端点不在多边形上,与凸多边形定义矛盾 p1p2和p3p4在多边线上,线段p2p3非端点不在多边形上,与凸多边形定义矛盾。
1 铸造中的几何
铸造的过程:液态金属被倒金铸模中,待凝固之后将形成的物体从中抽取出来。有时,成型的物品会卡在铸模中,比如球体无论从那个面都无法取出。我们将做如下限定。首先,假设需要制造的物体都是多面体形状的。其次,联通为一体的铸模。最后,只通过一次平移。
关于物品的摆放:物品必须具有一张水平的顶面(top facet),物品与铸模不相接触的面仅限一张。因此,物体有多少个面,就有多少种摆放。给定物品,在对应于这些方向的铸模中,至少有一个可以使形成的物品从中顺利取出,则称为可铸造的。
设P为一个三维的多面体--即由多张二维小平面(facet)围成的三维体。除顶面外,都是普通平面f。
是否存在 d ⃗ \vec d d ,使得沿改方向将P平移至无穷远的过程中,P与铸模的任何部分都不相交。只有顶面不和铸模接触,故移出方向必然是向上的,就是z方向的分量必然是正的。
任取P的一张普通面f,相对于铸模上与之对应的小平面 f ^ \hat f f^,f能移动的方向两种:远离 f ^ ,帖着 f ^ 滑动 \hat f,帖着\hat f滑动 f^,帖着f^滑动。
即: d ⃗ 在 f ^ 外方向的法线投影 ≤ 0 \vec d在\hat f外方向的法线投影 \le 0 d 在f^外方向的法线投影≤0,则可以移动。
三维空间中任意两个向量所构成的角度做出定义,假定两个向量起源于坐标原点。这两个向量可以确定两个角度,其和为 2 π 2\pi 2π,其中较小的那个,被定义为这两个向量所称的角度。
引理4.1 :沿着某个方向 d ⃗ \vec d d 通过一次平移,多面体P能够从其铸模中取出,当且仅当相对于P的每张普通面的外法矢, d ⃗ \vec d d 与之形成的角度至少 90 ∘ 90^\circ 90∘。
由于 d ⃗ . z > 0 ,不妨设 d . z = 1 \vec d.z >0,不妨设d.z=1 d .z>0,不妨设d.z=1, d ⃗ \vec d d 与之形成的角度至少 90 ∘ 90^\circ 90∘即点乘法 ≤ 0 \le 0 ≤0。
令某个面的外法线量为: η \eta η,则
d . x η . x + d . y η . y + η . z ≤ 0 d.x \eta.x+d.y\eta.y+\eta.z \le 0 d.xη.x+d.yη.y+η.z≤0
于是铸造问题,便转换成了平面几何的问题:半平面求交,如果交集非空,返回任意一点。
2 半平面求交
任何双变量线性约束条件集H={ h 1 , h 2 , ∼ h n h_1,h_2,\sim h_n h1,h2,∼hn},其中约束条件形式如下:
a i x + b i y ≤ c i , 其中 a i , b i , c i 是常数, a i 和 b i 不同时为零 a_ix+b_iy \le c_i,其中a_i,b_i,c_i是常数,a_i和b_i不同时为零 aix+biy≤ci,其中ai,bi,ci是常数,ai和bi不同时为零。从几何角度看,每个约束条件可以理解为 R 2 R^2 R2空间的半平面。由于半平面是凸集,故半平面的交也是凸集。
半平面的交集有如下几种情况:
一,凸多边形。
二,线段。l的下半平面和三角形ABC求交。

三,点。l的上半平面和三角形ABC求交。

四,空集。三角形ABC和l的下半平面。

五,无界多边形。l1的下半平面,l2的上半平面。

半平面的交集如果是凸多边形,最多n条边。无边界多边形,可以通过加4个半平面约束,转成多边形,即 x < X 0 , x > X 1 , y < Y 0 , y > Y 1 x < X0,x >X1,y <Y0,y>Y1 x<X0,x>X1,y<Y0,y>Y1。
两个凸多边形求交的平面扫描线算法,可以简化。因为任意线段和凸多边只有两个交点,故可用左右两个指针记录和扫描线相交的边。
水平线的处理:如果属于左链,算左边界,如果属于右链,算右边界。
定理4.3 :任意两个凸多边形区域的交集,可以在O(n)时间内计算出来。
定理4.4 :给定平面上的一组n张半平面,可以使用线性的空间,在 O ( n l o g n ) 时间 O(nlogn)时间 O(nlogn)时间内计算出其公共的交集。
3 递增式线性规划
找出满足一组线性约束条件的一个解,与运筹学(operations research)中的一个著名问题密切相关,这就是所谓的线性优化(linear optimization)或线性规划(Linear Programming)问题。线性规划的目标,在可行解域中,找出一个特定的解。这个解将使一个定义在有关变量上的函数极大化。每个线性规划问题,都可以描述成如下形式:
在满足约束条件: a 1 , 1 x 1 + ⋯ a 1 , d X d ≤ b 1 a 2 , 1 x 1 + ⋯ a 2 , d X d ≤ b 2 ⋮ a n , 1 x 1 + ⋯ a n , d X d ≤ b n 的前提下,使函数 c 1 x 1 + c 2 x 2 + ⋯ c d X d 极大花 在满足约束条件:\\ a_{1,1}x_1+\cdots a_{1,d}X_d \le b_1\\ a_{2,1}x_1+\cdots a_{2,d}X_d \le b_2\\ \vdots \\ a_{n,1}x_1+\cdots a_{n,d}X_d \le b_n\\ 的前提下,使函数c_1x_1+c_2x_2+\cdots c_dX_d 极大花\\ 在满足约束条件:a1,1x1+⋯a1,dXd≤b1a2,1x1+⋯a2,dXd≤b2⋮an,1x1+⋯an,dXd≤bn的前提下,使函数c1x1+c2x2+⋯cdXd极大花
待极大化的那个函数称为目标函数(objective function),而约束条件集与目标函数合在一起,就是一个线性规划问题。其中d是线性规划问题的维数。
目标函数可以 X ( x 1 , x 2 ⋯ x d ) 和 C ( c 1 , c 2 ⋯ c d ) X(x_1,x_2\cdots x_d)和C(c_1,c_2\cdots c_d) X(x1,x2⋯xd)和C(c1,c2⋯cd)的点乘,由于C的长度已知且为正,且X在C的投影最大时,点乘最大。
解决二维线性规划时,计算几何的方法比线性规划的方法更有效。
如果结果是无界多边形,加一个矩形包围盒就可以,实际上加两条边就可以了。
如果最优解有多个,取字典序最小的。相当于C逆时针旋转无限小度。
任取一个线性规划问题 ( H , C ⃗ ) 。我们将其中的半平面依次编号为 h 1 , h 2 ⋯ h n (H,\vec C)。我们将其中的半平面依次编号为h_1,h_2\cdots h_n (H,C )。我们将其中的半平面依次编号为h1,h2⋯hn。其中前i个约束条件,加上专门附加的两个约束条件,就构成集合 H i H_i Hi,令 H i 所对应的可行解域为 C i H_i所对应的可行解域为C_i Hi所对应的可行解域为Ci。
H i : = m 1 , m 2 , h 1 , h 2 , ⋯ , h i C i : = m 1 ∩ m 2 ∩ h 1 ∩ h 2 ∩ ⋯ ∩ h i H_i := {m_1,m_2,h_1,h_2,\cdots ,h_i}\\ C_i:=m_1 \cap m_2 \cap h_1 \cap h_2 \cap \cdots \cap h_i Hi:=m1,m2,h1,h2,⋯,hiCi:=m1∩m2∩h1∩h2∩⋯∩hi
∀ i , C i = ∅ , 则 ∀ j > i , C j = ∅ \forall i,C_i=\empty,则\forall j>i,C_j=\empty ∀i,Ci=∅,则∀j>i,Cj=∅即改线性规划问题是不可行的。因此线性规划问题一旦不可行,就立即终止算法。
引理4.5 :设 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n,而且 c i 和 v i c_i和v_i ci和vi的定义如上。则有:
一,若 v i − 1 ∈ h i ,则 v i = v n − 1 二,若 v i − 1 ∉ h i , 则要么 C i = ∅ , 要么 v i ln l i ,其中 l i 是 h i 的边界线 一,若v_{i-1} \in h_i,则v_i=v_{n-1}\\ 二,若v_{i-1}\notin h_i,则要么C_i=\empty,要么v_i \ln l_i,其中l_i是h_i的边界线 一,若vi−1∈hi,则vi=vn−1二,若vi−1∈/hi,则要么Ci=∅,要么vilnli,其中li是hi的边界线。
情况二,二维线性规划可以转化为一位线性规划。令 h i 的边界线是 c x + d y + e = 0 h_i的边界线是cx+dy+e=0 hi的边界线是cx+dy+e=0。
如果 d 为 0 ,则解的 x ≡ − e c 如果d为0,则解的x \equiv -\frac e c 如果d为0,则解的x≡−ce,消除x后,二维线性规划就降为一维。
如果 d ≠ 0 , 则 y = − c x − e d 如果d \neq 0,则y=\frac{-cx-e}d 如果d=0,则y=d−cx−e。消除y后,二维线性规划将为一维。
引理4.6 :每个一维线性规划问题都可在线性时间内求解。若出现引理4.5的情况二,在可以在O(i)的时间内,要么可以计算出更新后的最优解顶点,要么可以判断出这个线性规划问题是不可行的。
引理4.7 :算法2DBoundedLinearLP可以使用线性的空间,在O( n 2 n^2 n2)时间内,求解一个含n个约束的双变量有界线性规划问题。
4 随机线性规划
处理之前,对H采取随机排序。
引理4.8:任一包含n个约束条件的二维线性规划问题,都可以在O(n)的期望运行时间内得到解答;而且,所需要的空间在最坏情况下也不会超过线性规模。
5 无界线性规划问题
如何判断线性规划问题 ( H , c ⃗ ) (H,\vec c) (H,c )是否无界。如果结果无界,则存在某条射线 ρ = p + λ d ⃗ : λ > 0 \rho={p+\lambda \vec d: \lambda >0 } ρ=p+λd :λ>0全部是解。p是射线起点。
目标函数的值可以任意增长,当且仅当 d ⃗ ⋅ c ⃗ > 0 \vec d \cdot \vec c > 0 d ⋅c >0,即两个向量的夹角< 90 ∘ 。 90^\circ。 90∘。
任意 h ∈ H 都对应于两条法矢,它们以边界线为准,分别指向两侧,若将其中指向可行域一侧的那条法向量记作 η , 则有 d ⃗ ⋅ η ⃗ ( h ) ≥ 0 任意h\in H都对应于两条法矢,它们以边界线为准,分别指向两侧,若将其中指向可行域一侧的那条法向量记作\eta,则有\vec d \cdot \vec \eta(h) \ge 0 任意h∈H都对应于两条法矢,它们以边界线为准,分别指向两侧,若将其中指向可行域一侧的那条法向量记作η,则有d ⋅η (h)≥0。
引理4.9 :一个线性规划问题是无界的,当且仅当存在某个矢量 d ⃗ 满足 d ⃗ ⋅ > ⃗ 0 的,同时使得对于任何 h ∈ H , 不仅有 d ⃗ ⋅ η ⃗ ( h ) ≥ 0 , 而且若令 H ′ = h ∈ H : η ⃗ ( h ) . d ⃗ = 0 , 则线性规划问题 ( H ′ , c ⃗ ) 总是可行的 \vec d满足\vec d \cdot \vec > 0的,同时使得对于任何h\in H,不仅有\vec d \cdot \vec\eta(h) \ge 0,而且若令H'={h\in H: \vec \eta(h).\vec d=0},则线性规划问题(H',\vec c)总是可行的 d 满足d ⋅> 0的,同时使得对于任何h∈H,不仅有d ⋅η (h)≥0,而且若令H′=h∈H:η (h).d =0,则线性规划问题(H′,c )总是可行的。
隐含的假定是有解,任意解对应的点p。则射线 p + λ d ⃗ , λ > 0 p+\lambda \vec d,\lambda>0 p+λd ,λ>0都是H'的解。
由于 c ⃗ , d ⃗ \vec c,\vec d c ,d 夹角小于90度,故当 λ \lambda λ增加时, c ⃗ \vec c c 的投影也增加。
H'之外,H之内的 η i 和 d ⃗ 的夹角小于 90 度 \eta_i和\vec d的夹角小于90度 ηi和d 的夹角小于90度
如果射线所在直线和h_i交点的 λ 是 λ 0 ,则 λ > λ 0 \lambda是\lambda_0,则\lambda > \lambda_0 λ是λ0,则λ>λ0都是解。
6 最小外接圆(选修)
如果点数大于等于2,至少两个点在最小外接圆上。如果没有点在圆上,移动圆到点上。令只有p在圆上,以p为中心旋转圆,直到另外一个点在圆上。
令点i的坐标是(a_i,b_i),令最小外接圆的圆心是(x,y),半径是r。则第i个条件是:
( x − a i ) 2 + ( y − b i ) 2 ≤ r 2 即 x 2 − 2 a i x + a i 2 + y 2 − 2 b i y + b i 2 − r 2 ≤ 0 (x-a_i)^2+(y-b_i)^2 \le r^2即x^2-2a_ix+a_i^2+y^2-2b_iy+b_i^2-r^2 \le 0 (x−ai)2+(y−bi)2≤r2即x2−2aix+ai2+y2−2biy+bi2−r2≤0
令 z = x 2 + y 2 − r 2 z=x^2+y^2-r^2 z=x2+y2−r2则第i个条件是 − 2 a i x − 2 b i y + z + a i 2 + b i 2 ≤ 0 -2a_ix-2b_iy+z+a_i^2+b_i^2 \le 0 −2aix−2biy+z+ai2+bi2≤0。
转化成三维线性规划,暂时不知道如何定目标函数。感觉目标函数对应的矢量是(0,0,1)。
扩展阅读
| 算法为骨,CAD为魂 |
|---|
| 亲士工具箱:支持中望CAD2024、AutoCad2013及以上,多年承接CAD项目的精华 |
| 工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》《数学》。 |
| 学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
| 活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。