@@ -28,7 +28,7 @@ func (oct Octree) DecomposeDFS(dst []Vec, cubes []i3.Cube) ([]Vec, []i3.Cube) {
2828 for len (cubes ) > 0 {
2929 lastIdx := len (cubes ) - 1
3030 cube := cubes [lastIdx ]
31- if cube .Lvl == 0 {
31+ if cube .Level == 0 {
3232 // Cube has been moved to prune queue. Discard and keep going.
3333 cubes = cubes [:lastIdx ]
3434 continue
@@ -69,7 +69,7 @@ func (oct Octree) DecomposeBFS(dst []i3.Cube, start i3.Cube, minimumDecomposedLv
6969 }
7070 if cap (dst ) < 8 {
7171 return dst , false // No space to decompose new cubes.
72- } else if start .Lvl <= minimumDecomposedLvl {
72+ } else if start .Level <= minimumDecomposedLvl {
7373 return dst , false // Cube already fully decomposed.
7474 }
7575
@@ -80,7 +80,7 @@ func (oct Octree) DecomposeBFS(dst []i3.Cube, start i3.Cube, minimumDecomposedLv
8080 for cap (dst )- len (dst ) >= 8 {
8181 // Decompose and append cubes.
8282 cube := dst [firstIdx ]
83- if cube .Lvl <= minimumDecomposedLvl {
83+ if cube .Level <= minimumDecomposedLvl {
8484 // Reached cube of minimum prunable level.
8585 break
8686 }
@@ -104,15 +104,15 @@ func (oct Octree) SafeMove(dst, src []i3.Cube) (newDst, newSrc []i3.Cube) {
104104 return dst , src
105105 }
106106 // Calculate amount of cubes that would be generated in DFS
107- srcGenCubes := 8 * (src [0 ].Lvl + 1 ) // TODO(soypat): Checking the first cube is very (read as "too") conservative.
108- neededSpace := 1 + srcGenCubes // plus one for appended cube.
107+ srcGenCubes := 8 * (src [0 ].Level + 1 ) // TODO(soypat): Checking the first cube is very (read as "too") conservative.
108+ neededSpace := 1 + srcGenCubes // plus one for appended cube.
109109 // Calculate free space in dst after cubes generated by 1 decomposition+append.
110110 free := cap (dst ) - neededSpace
111111 trimIdx := max (0 , len (src )- free )
112112 prevCap := cap (dst )
113113 dst = append (dst , src [trimIdx :]... )
114114 if cap (dst ) != prevCap {
115- panic ("heapless assumption broken" )
115+ panic ("heapless promise broken" )
116116 }
117117 src = src [:trimIdx ]
118118 return dst , src
@@ -121,22 +121,23 @@ func (oct Octree) SafeMove(dst, src []i3.Cube) (newDst, newSrc []i3.Cube) {
121121// SafeSpread takes cube swith Lvl>0 from end of src and "spreads" them over dstWithLvl0 cube buffer taking special care so that the buffer can still be decomposed to smallest cubes.
122122// The buffer dstWithLvl0 is considered to have exactly numLvl0 cubes with Lvl==0 anywhere within. These Lvl==0 cubes will be replaced
123123// with src cubes first.
124+ // src must not contain zero leveled cubes.
124125func (oct Octree ) SafeSpread (dstWithLvl0 , src []i3.Cube , numLvl0 int ) (newDst , newSrc []i3.Cube , newNumLvl0 int ) {
125126 if len (src ) == 0 || numLvl0 == 0 || len (dstWithLvl0 ) == 0 {
126127 return dstWithLvl0 , src , numLvl0 // No work to do.
127128 }
128129 srcIdx := len (src ) - 1 // Start appending from end of src.
129130 cube := src [srcIdx ]
130- neededSpace := 8 * cube .Lvl + 1
131+ neededSpace := 8 * cube .Level + 1
131132 for i := 0 ; numLvl0 > 0 && i < len (dstWithLvl0 ); i ++ {
132133 free := cap (dstWithLvl0 ) - i
133134 if free < neededSpace {
134135 break // If we add this cube we'd overflow the target buffer upon DFS decomposition, so don't.
135136 }
136137 // Look for zero level cubes (invalid/empty/discarded).
137- if dstWithLvl0 [i ].Lvl != 0 {
138+ if dstWithLvl0 [i ].Level != 0 {
138139 continue
139- } else if cube .Lvl == 0 {
140+ } else if cube .Level == 0 {
140141 panic ("bad src cube in octreeSafeSpread" )
141142 }
142143 // Calculate free space.
@@ -147,7 +148,7 @@ func (oct Octree) SafeSpread(dstWithLvl0, src []i3.Cube, numLvl0 int) (newDst, n
147148 break // Done processing cubes.
148149 }
149150 cube = src [srcIdx ]
150- neededSpace = 8 * cube .Lvl + 1
151+ neededSpace = 8 * cube .Level + 1
151152 }
152153 return dstWithLvl0 , src [:srcIdx + 1 ], numLvl0
153154}
@@ -175,6 +176,13 @@ func (oct Octree) CubeOrigin(c i3.Cube, cubeSize float32) Vec {
175176 return Add (oct .Origin , Scale (cubeSize , Vec {X : float32 (idx .X ), Y : float32 (idx .Y ), Z : float32 (idx .Z )}))
176177}
177178
179+ // CubeCenter returns center of cube.
180+ // cubeSize should be the result of [Octree.CubeSize] called on c. It is left to the user for performance reasons.
181+ func (oct Octree ) CubeCenter (c i3.Cube , cubeSize float32 ) Vec {
182+ halfSize := 0.5 * cubeSize
183+ return Add (oct .CubeOrigin (c , cubeSize ), Vec {X : halfSize , Y : halfSize , Z : halfSize })
184+ }
185+
178186// Box returns the bounding box of the cube argument.
179187// cubeSize should be the result of [Octree.CubeSize] called on c. It is left to the user for performance reasons.
180188func (oct Octree ) CubeBox (c i3.Cube , cubeSize float32 ) Box {
@@ -187,7 +195,7 @@ func (oct Octree) CubeBox(c i3.Cube, cubeSize float32) Box {
187195
188196// CubeSize returns the length of the sides of the cube.
189197func (oct Octree ) CubeSize (c i3.Cube ) float32 {
190- dim := 1 << (c .Lvl - 1 )
198+ dim := 1 << (c .Level - 1 )
191199 return float32 (dim ) * oct .Resolution
192200}
193201
0 commit comments