运算步骤
- 表示出P(t)=P0+t⋅DP(t) = P_0 + t \cdot DP(t)=P0+t⋅D,求解其中的D=P1−P0D = P_1 - P_0D=P1−P0
- 计算每一条边指向多边形内部的法向量NiN_iNi
- 对每一条边都进行分组,Ni⋅D>0N_i \cdot D > 0Ni⋅D>0为Enter (PEP_EPE),反之Ni⋅D<0N_i \cdot D < 0Ni⋅D<0则为Exit (PLP_LPL)
- 根据t=−Ni⋅(P0−Ai)Ni⋅Dt = -\frac{N_i \cdot (P_0 - A_i)}{N_i \cdot D}t=−Ni⋅DNi⋅(P0−Ai)对ttt进行求解。
- 在PEP_EPE中寻找最大值,若全为负数则设为0;在PLP_LPL中寻找最小值,若全为大于1的数则设为1。
- 将求到的texitt_{exit}texit 和 tentert_{enter}tenter带入1中的式子得到裁剪的线段的起点和终点。
例题
- 裁剪窗口:凸五边形,顶点按逆时针顺序为A(2,1)A(2,1)A(2,1)、B(4,2)B(4,2)B(4,2)、C(5,4)C(5,4)C(5,4)、D(3,5)D(3,5)D(3,5)、E(1,3)E(1,3)E(1,3)。
- 待裁剪线段:P0(0,2)→P1(6,4)P_0(0,2) \to P_1(6,4)P0(0,2)→P1(6,4)(从左下到右上)。

(1) 参数化线段
P(t)=P0+t⋅D,D=P1−P0=(6,4)−(0,2)=(6,2) P(t) = P_0 + t \cdot D, \\ D = P_1 - P_0 = (6, 4) - (0, 2) = (6, 2) P(t)=P0+t⋅D,D=P1−P0=(6,4)−(0,2)=(6,2)
其中t∈[0,1]t\in[0,1]t∈[0,1]。
(2) 五边形各边的法向量(内法向)
对每条边 EiE_iEi,计算内法向量 Ni=(Eiy,−Eix)N_i=(E_{iy},-E_{ix})Ni=(Eiy,−Eix)(垂直于边并指向内部):
- 边ABABAB:向量 B−A=(2,1)B-A=(2,1)B−A=(2,1),法向量 N1=(−1,2)N_1=(-1,2)N1=(−1,2)。
- 边BCBCBC:向量 C−B=(1,2)C-B=(1,2)C−B=(1,2),法向量 N2=(−2,1)N_2=(-2,1)N2=(−2,1)。
- 边CDCDCD:向量 D−C=(−2,1)D-C=(-2,1)D−C=(−2,1),法向量 N3=(−1,−2)N_3=(-1,-2)N3=(−1,−2)。
- 边DEDEDE:向量 E−D=(−2,−2)E-D=(-2,-2)E−D=(−2,−2),法向量 N4=(2,−2)N_4=(2,-2)N4=(2,−2)。
- 边EAEAEA:向量 A−E=(1,−2)A-E=(1,-2)A−E=(1,−2),法向量 N5=(2,1)N_5=(2,1)N5=(2,1)。
(3) 计算每条边的交点参数 ttt
对每条边EiE_iEi,计算:
t=−Ni⋅(P0−Ai)Ni⋅D或t=Ni⋅(Ai−P0)Ni⋅D
t = -\frac{N_i \cdot (P_0 - A_i)}{N_i \cdot D} \\
或 \quad t = \frac{N_i \cdot (A_i - P_0)}{N_i \cdot D} \\
t=−Ni⋅DNi⋅(P0−Ai)或t=Ni⋅DNi⋅(Ai−P0)
注意:AiA_iAi 为每条边的起点。
并分类为PE(进入)或PL(离开)。
| 边 | 法向量NiN_iNi | Ni⋅DN_i \cdot DNi⋅D | W=P0−AiW=P_0-A_iW=P0−Ai | Ni⋅WN_i \cdot WNi⋅W | ttt | 分类 |
|---|---|---|---|---|---|---|
| AB | (−1,2)(-1,2)(−1,2) | −1⋅6+2⋅2=−2-1 \cdot 6 + 2 \cdot 2 = -2−1⋅6+2⋅2=−2 | (0−2,2−1)=(−2,1)(0-2,2-1)=(-2,1)(0−2,2−1)=(−2,1) | −1⋅(−2)+2⋅1=4-1 \cdot (-2) + 2 \cdot 1 = 4−1⋅(−2)+2⋅1=4 | t=2t=2t=2 | PL |
| BC | (−2,1)(-2,1)(−2,1) | −2⋅6+1⋅2=−10-2 \cdot 6 + 1 \cdot 2 = -10−2⋅6+1⋅2=−10 | (0−4,2−2)=(−4,0)(0-4,2-2)=(-4,0)(0−4,2−2)=(−4,0) | −2⋅(−4)+1⋅0=8-2 \cdot (-4) + 1 \cdot 0 = 8−2⋅(−4)+1⋅0=8 | t=0.8t=0.8t=0.8 | PL |
| CD | (−1,−2)(-1,-2)(−1,−2) | −1⋅6+(−2)⋅2=−10-1 \cdot 6 + (-2) \cdot 2 = -10−1⋅6+(−2)⋅2=−10 | (0−5,2−4)=(−5,−2)(0-5,2-4)=(-5,-2)(0−5,2−4)=(−5,−2) | −1⋅(−5)+(−2)⋅(−2)=9-1 \cdot (-5) + (-2) \cdot (-2) = 9−1⋅(−5)+(−2)⋅(−2)=9 | t=0.9t=0.9t=0.9 | PL |
| DE | (2,−2)(2,-2)(2,−2) | 2⋅6+(−2)⋅2=−82 \cdot 6 + (-2) \cdot 2 = -82⋅6+(−2)⋅2=−8 | (0−3,2−5)=(−3,−3)(0-3,2-5)=(-3,-3)(0−3,2−5)=(−3,−3) | 2⋅(−3)+(−2)⋅(−3)=02 \cdot (-3) + (-2) \cdot (-3) = 02⋅(−3)+(−2)⋅(−3)=0 | t=0t=0t=0 | PE |
| EA | (2,1)(2,1)(2,1) | 2⋅6+1⋅2=142 \cdot 6 + 1 \cdot 2 = 142⋅6+1⋅2=14 | (0−1,2−3)=(−1,−1)(0-1,2-3)=(-1,-1)(0−1,2−3)=(−1,−1) | 2⋅(−1)+1⋅(−1)=−32 \cdot (-1) + 1 \cdot (-1) = -32⋅(−1)+1⋅(−1)=−3 | t=314≈0.214t = \frac{3}{14} \approx 0.214t=143≈0.214 | PE |
(4) 分类并确定tentert_{\text{enter}}tenter和texitt_{\text{exit}}texit
- PE组(进入):t=0t=0t=0(DE边)、t≈0.214t\approx0.214t≈0.214(EA边)。
tenter=max(0,0.214)=0.214t_{\text{enter}}=\max(0,0.214)=0.214tenter=max(0,0.214)=0.214。 - PL组(离开):t=0.8t=0.8t=0.8(BC边)、t=0.9t=0.9t=0.9(CD边)、t=2t=2t=2(AB边)。
texit=min(0.8,0.9,2)=0.8t_{\text{exit}}=\min(0.8,0.9,2)=0.8texit=min(0.8,0.9,2)=0.8。
(5) 裁剪结果
- 因为tenter=0.214≤texit=0.8t_{\text{enter}}=0.214 \leq t_{\text{exit}}=0.8tenter=0.214≤texit=0.8,线段部分可见。
- 可见部分:
P(0.214)=(0+0.214×6,2+0.214×2)≈(1.28,2.43)P(0.214)=(0+0.214 \times 6, 2+0.214\times2)\approx(1.28,2.43)P(0.214)=(0+0.214×6,2+0.214×2)≈(1.28,2.43)。
P(0.8)=(0+0.8×6,2+0.8×2)=(4.8,3.6)P(0.8)=(0+0.8 \times 6, 2+0.8\times2)=(4.8,3.6)P(0.8)=(0+0.8×6,2+0.8×2)=(4.8,3.6)。 - 裁剪后线段:(1.28,2.43)→(4.8,3.6)(1.28,2.43)\to(4.8,3.6)(1.28,2.43)→(4.8,3.6)。

1224

被折叠的 条评论
为什么被折叠?



