检测方框碰撞的分区策略

371 阅读3分钟

模型:

一个较大的平面空间里,面积为S,相对均匀的随机分布着边长为1的正方形。

其分布密度为m【即平均单位面积有m个小正方形】。

现需用程序检测这些小正方形两两碰撞的次数。

方案1:直接小正方形两两判断碰撞。

则检测次数约为:

(Sm) * (Sm-1) / 2

单位面积的检测次数约为:

m * (S*m -1) /2

从这里可以看出,按此方法,S越大,单位面积的检测次数越多。

故尝试优化:优化方案:细分成较小区域

方案2:将其细分成面积为 x*x 的方形区域【共 S/x^2 个方形区域】

先小正方形与方形区域碰撞,与同一区域产生碰撞的小正方形,再两两检测碰撞。【需考虑由于小正方形与多个区域碰撞的可能】

故检测次数为:

A 小正方形与区域碰碰撞检测:(Sm) * (S/x^2) ,事实上区域是规律分布,分区可以优化至约 Sm*(x+1)^2*x^-2 次检测。

B 与每个小区域相关的正方形数目:(x+1)^2m,这些两两碰撞检测次数: (x+1)^2m * ((x+1)^2*m-1) / 2

C 所以总的检测次数为:A + B * (S/x^2)

D 得到单位面积的检测次数为 m*(x+1)^2x^-2 + (x+1)^2m * ((x+1)^2*m-1) * x^-2 / 2

= m*(x+1)^{2} * (x^{-2}+((x+1)^{2}*m-1)*x^{-2}/2)

= m*(x+1)^{2} * ( m/2 + mx^{-1} + (1+m)/2x^{-2})

求导得: m(x+1)(2*( m/2 + mx^{-1} + (1+m)/2x^{-2}) + (x+1) * ( -m*x^{-2} - (1+m)*x^{-3}))

导数为0时是极值。其中一个根是-1,求正半轴上的根,即解方程:

(2*( m/2 + mx^{-1} + (1+m)/2x^{-2}) + (x+1) * ( -m*x^{-2} - (1+m)*x^{-3})) = 0

即:

m + (2m-m-m-1) *x^{-1} + (1+m -1-m -m)*x^{-2} + (-m-1)*x^{-3} = 0

即:

m+mx^{-1}-mx^{-2}+(-m-1)*x^{-3} = 0

即:

x^{3} + x^{2} -x -1-1/m = 0;

即: (x+1/3)^{3} - 4/3*(x+1/3) -1/m-2/3 = 0;

此为典型 x^3 + p*x + q = 0 式。

可用以下方法求实根:

(-q/2+((q/2)^{2}- (-p/3)^{3})^{0.5})^{1/3} + (-(q/2+((q/2)^{2}-(-p/3)^{3})^{0.5}))^{1/3} - 1/3

其中:

p = (-4/3)

(-1/m-2/3)

得:

(-(-1/m-2/3)/2+(((-1/m-2/3)/2)^{2}- (-(-4/3)/3)^{3})^{0.5})^{1/3} + (-((-1/m-2/3)/2+(((-1/m-2/3)/2)^{2}-(-(-4/3)/3)^{3})^{0.5}))^{1/3} - 1/3

以上过程,部分曲线如下:

www.desmos.com/calculator/…

最佳分区宽度,与小方框的密度曲线如下:【x轴代表方框密度,Y轴代表最佳分区宽度】

www.desmos.com/calculator/…

y = (-(-1/x-2/3)/2+(((-1/x-2/3)/2)^{2}- (-(-4/3)/3)^{3})^{0.5})^{1/3} + (-((-1/x-2/3)/2+(((-1/x-2/3)/2)^{2}-(-(-4/3)/3)^{3})^{0.5}))^{1/3} - 1/3

image.png

对应Javascript函数:

function getBestSize(m){
	var p = -4/3;
	var q = -1/m-2/3;
	var ret = Math.pow(-q/2+Math.pow(Math.pow(q/2,2)- Math.pow(-p/3,3),0.5),1/3) 
		+ Math.pow(-(q/2+Math.pow(Math.pow(q/2,2)-Math.pow(-p/3,3),0.5)),1/3);
	return ret-1/3;
}
getBestSize(0.01)

例:

getBestSize(0.01) = 4.414

getBestSize(0.1) = 2.069

getBestSize(1) = 1.218

getBestSize(2) = 1.127

getBestSize(10) = 1.042

getBestSize(100) = 1.021

getBestSize(1000) = 1.018

待办项:

待编码验证。。