33
44import java .util .ArrayList ;
55
6- // TODO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7- //
8- // [ ] NestedGrid
9- // [ ] validation in constructor
10- // [ ] test for that validation
11- // [ ] javadoc
12- //
13- // [ ] NestedPosition interface
14- // [+] LazyNestedPosition class
15- // [+] fields: NestedGrid, long[] position, int level
16- // [+] construct with source level 0
17- // [+] minimal abs/rel access methods
18- // [+] toString()
19- // [-] extract NestedPosition interface
20- // ==> postpone until necessary
21- // [ ] equals / hashcode
22- // [ ] should we have prefix()? suffix()? head()? tail()?
23- // [+] Implement Comparable so that we can sort and aggregate for N5Reader.readBlocks(...).
24- // For nested = {X,Y,Z} compare by Z, then Y, then X.
25- // For X = {x,y,z} compare by z, then y, then x. (flattening order)
26- //
27- // TODO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28-
296import java .util .Arrays ;
307import java .util .List ;
318
329import org .janelia .saalfeldlab .n5 .util .GridIterator ;
3310
3411public class Nesting {
3512
36- public static void main (String [] args ) {
37- final int [][] blockSizes = {{1 ,1 ,1 }, {3 ,2 ,2 }, {6 ,4 ,4 }, {24 ,24 ,24 }};
38- final NestedGrid grid = new NestedGrid (blockSizes );
39- final NestedPosition pos = new NestedPosition (grid , new long [] {38 , 7 , 129 });
40- System .out .println ("pos = " + pos );
41- System .out .println ("key = " + Arrays .toString (pos .key ()));
42- }
43-
4413 public static class NestedPosition implements Comparable <NestedPosition > {
4514
4615 private final NestedGrid grid ;
4716 private final long [] position ;
4817 private final int level ;
4918
50- public NestedPosition (final NestedGrid grid , final long [] position , final int level ) {
19+ protected NestedPosition (final NestedGrid grid , final long [] position , final int level ) {
5120 this .grid = grid ;
5221 this .position = position ;
5322 this .level = level ;
5423 }
5524
56- public NestedPosition (final NestedGrid grid , final long [] position ) {
57- this (grid , position , 0 );
58- }
59-
6025 /**
6126 * Get the nesting level of this position.
6227 * <p>
@@ -84,7 +49,18 @@ public int numDimensions() {
8449 * @return relative grid position
8550 */
8651 public long [] relative (final int level ) {
87- return grid .relativePosition (position , level );
52+ return grid .relativePosition (position , this .level , level );
53+ }
54+
55+ /**
56+ * Get the relative grid position at this positions {@link #level()},
57+ * that is, relative offset within containing the {@code (level+1)}
58+ * element.
59+ *
60+ * @return relative grid position
61+ */
62+ public long [] relative () {
63+ return relative (level ());
8864 }
8965
9066 /**
@@ -96,13 +72,17 @@ public long[] relative(final int level) {
9672 * @return absolute grid position
9773 */
9874 public long [] absolute (final int level ) {
99- return grid .absolutePosition (position , level );
75+ return grid .absolutePosition (position , this . level , level );
10076 }
10177
10278 public long [] key () {
10379 return relative (grid .numLevels () - 1 );
10480 }
10581
82+ public long [] pixelPosition () {
83+ return grid .pixelPosition (position , level );
84+ }
85+
10686 @ Override
10787 public String toString () {
10888 StringBuilder sb = new StringBuilder ();
@@ -117,7 +97,8 @@ public String toString() {
11797 return sb .toString ();
11898 }
11999
120- @ Override public int compareTo (NestedPosition o ) {
100+ @ Override
101+ public int compareTo (NestedPosition o ) {
121102
122103 final int dimensionInequality = Integer .compare (numDimensions (), o .numDimensions ());
123104 if (dimensionInequality != 0 )
@@ -127,13 +108,10 @@ public String toString() {
127108 if (levelInequality != 0 )
128109 return levelInequality ;
129110
130- final long [] otherAbsPos = o .absolute (level );
131- final long [] absPos = absolute (level );
132-
133- for (int i = absPos .length - 1 ; i >= 0 ; --i ) {
134- final long diff = absPos [i ] - otherAbsPos [i ];
111+ for (int i = position .length - 1 ; i >= 0 ; --i ) {
112+ final long diff = position [i ] - o .position [i ];
135113 if (diff != 0 )
136- return (int )diff ;
114+ return (int ) diff ;
137115 }
138116
139117 return 0 ;
@@ -156,6 +134,52 @@ public String toString() {
156134 */
157135 public static class NestedGrid {
158136
137+ /**
138+ * Create a {@code NestedPosition} at the specified nesting {@code
139+ * level} grid {@code position}.
140+ * <p>
141+ * Note that {@code position} is in units of grid elements at {@code
142+ * level}. Positions with {@code level=0} refer to the DataBlock grid,
143+ * positions with {@code level=1} refer to first-level Shard grid, and
144+ * so on.
145+ * <p>
146+ * The returned {@code NestedPosition} will have
147+ * {@link NestedPosition#level() level()==level}.
148+ *
149+ * @param position
150+ * position at {@code level}
151+ * @param level
152+ * nesting level of {@code position}
153+ *
154+ * @return a NestedPosition representation of the specified grid position and nesting level
155+ */
156+ public NestedPosition nestedPosition (final long [] position , final int level ) {
157+ return new NestedPosition (this , position , level );
158+ }
159+
160+ /**
161+ * Create a {@code NestedPosition} at the specified block grid {@code
162+ * position} (that is, at nesting level 0).
163+ * <p>
164+ * Note that {@code position} is in units of DataBlocks.
165+ * <p>
166+ * The returned {@code NestedPosition} will have
167+ * {@link NestedPosition#level() level()==0}.
168+ *
169+ * @param position
170+ * position at level 0 (block grid)
171+ *
172+ * @return a NestedPosition representation of the specified block grid position
173+ */
174+ public NestedPosition nestedPosition (final long [] position ) {
175+ return nestedPosition (position , 0 );
176+ }
177+
178+
179+
180+
181+
182+
159183 private final int numLevels ;
160184
161185 private final int numDimensions ;
@@ -249,6 +273,46 @@ public int[] getBlockSize(final int level) {
249273 return blockSizes [level ];
250274 }
251275
276+ /**
277+ * Computes the pixel position for the given {@code sourcePos} grid
278+ * position at {@code sourceLevel}.
279+ *
280+ * @param sourcePos
281+ * a grid position at {@code sourceLevel}
282+ * @param sourceLevel
283+ * nesting level of {@code sourcePos}
284+ * @param targetPos
285+ * the pixel position will be stored here
286+ */
287+ public void pixelPosition (
288+ final long [] sourcePos ,
289+ final int sourceLevel ,
290+ final long [] targetPos ) {
291+ final int [] s = blockSizes [sourceLevel ];
292+ for (int d = 0 ; d < numDimensions ; ++d ) {
293+ targetPos [d ] = sourcePos [d ] * s [d ];
294+ }
295+ }
296+
297+ /**
298+ * Get the pixel position for the given {@code sourcePos} grid position
299+ * at {@code sourceLevel}.
300+ *
301+ * @param sourcePos
302+ * a grid position at {@code sourceLevel}
303+ * @param sourceLevel
304+ * nesting level of {@code sourcePos}
305+ *
306+ * @return the pixel position
307+ */
308+ public long [] pixelPosition (
309+ final long [] sourcePos ,
310+ final int sourceLevel ) {
311+ final long [] targetPos = new long [numDimensions ];
312+ pixelPosition (sourcePos , sourceLevel , targetPos );
313+ return targetPos ;
314+ }
315+
252316 /**
253317 * Computes the absolute {@code targetPos} grid position at {@code
254318 * targetLevel} for the given {@code sourcePos} grid position at {@code
@@ -296,6 +360,9 @@ public long[] absolutePosition(
296360 final long [] sourcePos ,
297361 final int sourceLevel ,
298362 final int targetLevel ) {
363+ if (sourceLevel == targetLevel ) {
364+ return sourcePos ;
365+ }
299366 final long [] targetPos = new long [numDimensions ];
300367 absolutePosition (sourcePos , sourceLevel , targetPos , targetLevel );
301368 return targetPos ;
@@ -381,10 +448,6 @@ public int[] relativeBlockSize(final int level) {
381448 return relativeToAdjacent [level ];
382449 }
383450
384- public int [] absoluteBlockSize (final int level ) {
385- return relativeToBase [level ];
386- }
387-
388451 /**
389452 * Given a block position at a particular level, returns a list of
390453 * positions of all sub-blocks at a particular subLevel.
@@ -400,22 +463,24 @@ public int[] absoluteBlockSize(final int level) {
400463 * the nesting sub-level of positions to return
401464 * @return the sub-block positions
402465 */
466+ // TODO: rename to positionsInSubGrid
403467 public List <long []> positionInSubGrid (long [] position , int level , int subLevel ) {
404468
405- final long [] subPosition = new long [numDimensions ()];
406- absolutePosition (position , level , subPosition , subLevel );
469+ // find the starting (subLevel grid) coordinates corresponding to the
470+ // first subLevel block in the element at the given level and position
471+ final long [] subPosition = absolutePosition (position , level , subLevel );
407472
408- final int [] numElementsInSubGrid = absoluteBlockSize (numLevels () - 1 );
409- final GridIterator git = new GridIterator (GridIterator .int2long (numElementsInSubGrid ), subPosition );
473+ // find the dimensions (number of subLevel blocks in one level block, along each dimension)
474+ final long [] one = new long [numDimensions ];
475+ Arrays .fill (one , 1 );
476+ final long [] dimensions = absolutePosition (one , level , subLevel );
410477
411- // TODO return NestedPositions instead?
478+ final GridIterator git = new GridIterator ( dimensions , subPosition );
412479 final ArrayList <long []> positions = new ArrayList <>();
413480 while (git .hasNext ())
414481 positions .add (git .next ().clone ());
415482
416483 return positions ;
417484 }
418-
419485 }
420-
421486}
0 commit comments