こちらの続きです。
端点一致を探る、組み合わせテスト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で作っているのですが・・・。