Cyrus-Beck算法的计算方法

运算步骤

  1. 表示出P(t)=P0+t⋅DP(t) = P_0 + t \cdot DP(t)=P0+tD,求解其中的D=P1−P0D = P_1 - P_0D=P1P0
  2. 计算每一条边指向多边形内部的法向量NiN_iNi
  3. 对每一条边都进行分组,Ni⋅D>0N_i \cdot D > 0NiD>0为Enter (PEP_EPE),反之Ni⋅D<0N_i \cdot D < 0NiD<0则为Exit (PLP_LPL)
  4. 根据t=−Ni⋅(P0−Ai)Ni⋅Dt = -\frac{N_i \cdot (P_0 - A_i)}{N_i \cdot D}t=NiDNi(P0Ai)ttt进行求解。
  5. PEP_EPE中寻找最大值,若全为负数则设为0;在PLP_LPL中寻找最小值,若全为大于1的数则设为1。
  6. 将求到的texitt_{exit}texittentert_{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)(从左下到右上)。

Alt

(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+tD,D=P1P0=(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)BA=(2,1),法向量 N1=(−1,2)N_1=(-1,2)N1=(1,2)
  • BCBCBC:向量 C−B=(1,2)C-B=(1,2)CB=(1,2),法向量 N2=(−2,1)N_2=(-2,1)N2=(2,1)
  • CDCDCD:向量 D−C=(−2,1)D-C=(-2,1)DC=(2,1),法向量 N3=(−1,−2)N_3=(-1,-2)N3=(1,2)
  • DEDEDE:向量 E−D=(−2,−2)E-D=(-2,-2)ED=(2,2),法向量 N4=(2,−2)N_4=(2,-2)N4=(2,2)
  • EAEAEA:向量 A−E=(1,−2)A-E=(1,-2)AE=(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=NiDNi(P0Ai)t=NiDNi(AiP0)
注意:AiA_iAi 为每条边的起点。

并分类为PE(进入)PL(离开)

法向量NiN_iNiNi⋅DN_i \cdot DNiDW=P0−AiW=P_0-A_iW=P0AiNi⋅WN_i \cdot WNiWttt分类
AB(−1,2)(-1,2)(1,2)−1⋅6+2⋅2=−2-1 \cdot 6 + 2 \cdot 2 = -216+22=2(0−2,2−1)=(−2,1)(0-2,2-1)=(-2,1)(02,21)=(2,1)−1⋅(−2)+2⋅1=4-1 \cdot (-2) + 2 \cdot 1 = 41(2)+21=4t=2t=2t=2PL
BC(−2,1)(-2,1)(2,1)−2⋅6+1⋅2=−10-2 \cdot 6 + 1 \cdot 2 = -1026+12=10(0−4,2−2)=(−4,0)(0-4,2-2)=(-4,0)(04,22)=(4,0)−2⋅(−4)+1⋅0=8-2 \cdot (-4) + 1 \cdot 0 = 82(4)+10=8t=0.8t=0.8t=0.8PL
CD(−1,−2)(-1,-2)(1,2)−1⋅6+(−2)⋅2=−10-1 \cdot 6 + (-2) \cdot 2 = -1016+(2)2=10(0−5,2−4)=(−5,−2)(0-5,2-4)=(-5,-2)(05,24)=(5,2)−1⋅(−5)+(−2)⋅(−2)=9-1 \cdot (-5) + (-2) \cdot (-2) = 91(5)+(2)(2)=9t=0.9t=0.9t=0.9PL
DE(2,−2)(2,-2)(2,2)2⋅6+(−2)⋅2=−82 \cdot 6 + (-2) \cdot 2 = -826+(2)2=8(0−3,2−5)=(−3,−3)(0-3,2-5)=(-3,-3)(03,25)=(3,3)2⋅(−3)+(−2)⋅(−3)=02 \cdot (-3) + (-2) \cdot (-3) = 02(3)+(2)(3)=0t=0t=0t=0PE
EA(2,1)(2,1)(2,1)2⋅6+1⋅2=142 \cdot 6 + 1 \cdot 2 = 1426+12=14(0−1,2−3)=(−1,−1)(0-1,2-3)=(-1,-1)(01,23)=(1,1)2⋅(−1)+1⋅(−1)=−32 \cdot (-1) + 1 \cdot (-1) = -32(1)+1(1)=3t=314≈0.214t = \frac{3}{14} \approx 0.214t=1430.214PE
(4) 分类并确定tentert_{\text{enter}}tentertexitt_{\text{exit}}texit
  • PE组(进入)t=0t=0t=0(DE边)、t≈0.214t\approx0.214t0.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.214texit=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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸠菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值