得鹿梦鱼 得鹿梦鱼

梁友栋-barsky线段裁剪算法

它基于分析线段的参数化方程

对端点为x0,y0,x1,y1x_0,y_0,x_1,y_1的直线段,可使用参数形式描述为
{x=x0+ux1x0y=y0+uy1y0\begin{cases}x = x_0 + ux_1 - x_0 \\y = y_0 + uy_1 - y_0\end{cases}
与点裁剪的条件结合则有

{xwminx0+ux1x0xwmaxywminy0+uy1y0ywmax\begin{cases}xw_{min} \leq x_0 + ux_1 - x_0 \leq xw_{max} \\yw_{min} \leq y_0 + uy_1 - y_0 \leq yw_{max}\end{cases}

展开上式,表示为upkqk1up_k \leq q_k \tag{1}

{xwminx0+ux1x0xwminx0uΔxuΔxx0xwminx0+ux1x0xwmaxuΔxxwmaxx0uΔxxwmaxx0ywminy0+uy1y0ywminy0uΔyuΔyy0ywminy0+uy1y0ywmaxuΔyywmaxy0uΔyywmaxy0\begin{cases}xw_{min} \leq x_0 + ux_1 - x_0 \Rightarrow xw_{min} - x_0 \leq u \Delta x \Rightarrow u -\Delta x \leq x_0 - xw_{min} \\x_0 + ux_1 - x_0 \leq xw_{max} \Rightarrow u \Delta x \leq xw_{max} - x_0 \Rightarrow u \Delta x \leq xw_{max} - x_0 \\yw_{min} \leq y_0 + uy_1 - y_0 \Rightarrow yw_{min} - y_0 \leq u \Delta y \Rightarrow u -\Delta y \leq y_0 - yw_{min} \\y_0 + uy_1 - y_0 \leq yw_{max} \Rightarrow u \Delta y \leq yw_{max} - y_0 \Rightarrow u \Delta y \leq yw_{max} - y_0\end{cases}

pk=0p_k = 0

线段平行于裁剪窗口的边界中的任意一条

满足qk<0q_k < 0

则线段完全在裁剪窗口外如下图所示
线段完全在裁剪窗口外

如果qk0q_k \geq 0

线段不完全在裁剪窗口外

pk0p_k \neq 0

pk<0p_k < 0线段从裁剪边延长线的外部延伸到内部,是入边交点
pk>0p_k > 0线段从裁剪边延长线的内部延伸到外部,是出边交点

线段和窗口一共有4个交点,根据pk的符号,就可以知道那个入点,那个是出点,如下图中的ul,ur,ut,ubu_l,u_r,u_t,u_b,在加上两个端点的u=0,1u=0,1,一共6个u值

示意图

根据1式的得出

u=qkpku = \frac{q_k}{p_k}

6个u值分别为

{us=0ue=1ul=x0xwminΔxur=xwmaxx0Δxut=ywmaxy0Δyub=y0ywminΔy\begin{cases}u_s = 0 \\u_e = 1\\u_l = \frac{x_0 - xw_{min}}{-\Delta x} \\u_r = \frac{xw_{max} - x_0}{\Delta x} \\u_t = \frac{yw_{max} - y_0}{\Delta y} \\u_b = \frac{y0 - yw_{min}}{-\Delta y}\end{cases}

pk<0p_k < 0的两个u值和0比较去找大的

Δx>0\Delta x > 0 && Δy>0\Delta y > 0ul,ubu_l, u_b
Δx>0\Delta x > 0 && Δy<0\Delta y < 0ul,utu_l, u_t
Δx<0\Delta x < 0 && Δy>0\Delta y > 0ur,ubu_r, u_b
Δx<0\Delta x < 0 && Δy<0\Delta y < 0ur,utu_r, u_t

pk>0p_k > 0的两个u值和1比较去找小的

Δx>0\Delta x > 0 && Δy>0\Delta y > 0ur,utu_r, u_t
Δx>0\Delta x > 0 && Δy<0\Delta y < 0ur,ubu_r, u_b
Δx<0\Delta x < 0 && Δy>0\Delta y > 0ul,utu_l, u_t
Δx<0\Delta x < 0 && Δy<0\Delta y < 0ul,ubu_l, u_b

条件pk<0p_k < 0[umaxu_{max}]pk>0[p_k > 0[u_{min}]]
Δx>0\Delta x > 0 && Δy>0\Delta y > 0maxul,ub,0u_l, u_b, 0minur,ut,1u_r, u_t, 1
Δx>0\Delta x > 0 && Δy<0\Delta y < 0maxul,ut,0u_l, u_t, 0minur,ub,1u_r, u_b, 1
Δx<0\Delta x < 0 && Δy>0\Delta y > 0maxur,ub,0u_r, u_b, 0minul,ut,1u_l, u_t, 1
Δx<0\Delta x < 0 && Δy<0\Delta y < 0maxur,ut,0u_r, u_t, 0minul,ub,1u_l, u_b, 1

如果umax>uminu_{max} > u_{min} 则直线段在窗口外面删除
如果umaxuminu_{max} \leq u_{min} 求出交点坐标

注意u的有效范围是[0,1]

请参考梁友栋-barsky线段裁剪算法