C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

端点一致を探る、組み合わせテスト5

こちらの続きです。
端点一致を探る、組み合わせテスト4 - C#ATIA

最初は対象が端点なので、点で考えれば良いと思っていたのですが、
点ではなくボリューム(立方体)として空間分割し、登録しなければ
ならない気がしてます。 上手く行かなく苦しんでます。

ボリュームから空間番号を求める関数が、正しく処理出来ていない・・・。
オリジナルがこちら

	// 座標から空間番号を算出
	DWORD GetMortonNumber( D3DXVECTOR3 *Min, D3DXVECTOR3 *Max )
	{
		// 最小レベルにおける各軸位置を算出
		DWORD LT = GetPointElem(*Min);
		DWORD RB = GetPointElem(*Max);

		// 空間番号を引き算して
		// 最上位区切りから所属レベルを算出
		DWORD Def = RB ^ LT;
		unsigned int HiLevel = 1;
		unsigned int i;
		for(i=0; i<m_uiLevel; i++)
		{
			DWORD Check = (Def>>(i*3)) & 0x7;
			if( Check != 0 )
				HiLevel = i+1;
		}
		DWORD SpaceNum = RB>>(HiLevel*3);
		DWORD AddNum = (m_iPow[m_uiLevel-HiLevel]-1)/7;
		SpaceNum += AddNum;

		if(SpaceNum > m_dwCellNum)
			return 0xffffffff;

		return SpaceNum;
	}

コメント部分 "空間番号を引き算して" となっていましたが、処理的に
排他的論理和の間違いと思われます。

あまりに酷いコードですが、VBA化しているのがこちら

'座標から空間番号を算出
Private Function GetMortonNumber(ByVal p1, ByVal p2, ByVal Min, ByVal Max, ByVal Level)
    '最小レベルにおける各軸位置を算出
    Dim LT&: LT = GetPointElem(p1, Min, Max)
    Dim RB&: RB = GetPointElem(p2, Min, Max)
    
    '空間番号を排他的論理和して
    '最上位区切りから所属レベルを算出
    Dim Def&: Def = RB Xor LT
    Dim HiLevel&: HiLevel = 1
    Dim i&, Check&
    For i = 0 To Level
        Check = (sr(Def, (i * 3))) And &H7
        If Check <> 0 Then HiLevel = i + 1
    Next
    Dim SpaceNum&: SpaceNum = sr(RB, (HiLevel * 3))
    Dim AddNum&: AddNum = (m_iPow(Level - HiLevel) - 1) / 7
    SpaceNum = SpaceNum + AddNum
    
    If SpaceNum > m_dwCellNum Then
        GetMortonNumber = &HFFFFFFFF
    End If
    GetMortonNumber = SpaceNum
End Function

これを例としてされている "分割レベルL=2 最小を16番 最大を23番" では
"親空間の2番" なのですが、実行すると "親空間の3番" に・・・。

何となく原因は、変数 "HiLevel" が、オリジナルは 符号なしInt ですが
VBAには符号なしが無い為、Long型で代用している事と、先日の右ビットシフト関数が
">>" ではなく ">>>" になっている事だろうとは思うのですが。

こんなのまでExcelで作っているのですが・・・。
f:id:kandennti:20161214200148p:plain