MortonList.java 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * To change this template, choose Tools | Templates
  3. * and open the template in the editor.
  4. */
  5. package com.cloudsoft.utils;
  6. import java.awt.Point;
  7. import java.util.Vector;
  8. // **************************************************************************************************
  9. /** Stores a one-dimensional ordered list of objects that can represent a two-dimensional arrangement
  10. * using Morton ordering. The order of objects stored in this collection is assumed to be Morton.
  11. * Ordering can be <code>VERTICAL</code> (mirror 'N' shaped) or <code>HORIZONTAL</code> ('Z' shaped).
  12. * @author Jo Wood, giCentre.
  13. * @version 3.0, 24th February, 2011.
  14. * @param <E> Type of object stored in the Morton ordered collection.
  15. */
  16. // **************************************************************************************************
  17. /* This file is part of the giCentre treeMappa library. treeMappa is free software: you can
  18. * redistribute it and/or modify it under the terms of the GNU Lesser General Public License
  19. * as published by the Free Software Foundation, either version 3 of the License, or (at your
  20. * option) any later version.
  21. *
  22. * treeMappa is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  23. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  24. * See the GNU Lesser General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU Lesser General Public License along with this
  27. * source code (see COPYING.LESSER included with this source code). If not, see
  28. * http://www.gnu.org/licenses/.
  29. */
  30. public class MortonList<E> extends Vector<E>
  31. {
  32. // -------------------- Object and class variables -------------------
  33. private static final long serialVersionUID = 1464385625231719807L;
  34. /** Indicates that Morton ordering is mirror 'N' shaped. */
  35. public static final int VERTICAL = 1;
  36. /** Indicates that Morton ordering is 'Z' shaped. */
  37. public static final int HORIZONTAL = 2;
  38. private int direction;
  39. // --------------------------- Constructor ---------------------------
  40. /** Creates the collection assuming a vertical Morton layout.
  41. */
  42. public MortonList()
  43. {
  44. this(VERTICAL);
  45. }
  46. /** Creates the collection with a Morton layout in the given direction.
  47. * @param direction Direction of layout. Should be one of <code>VERTICAL</code>
  48. * (mirrored 'N' shaped) or <code>HORIZONTAL</code> ('Z' shaped).
  49. */
  50. public MortonList(int direction)
  51. {
  52. super();
  53. this.direction = direction;
  54. }
  55. // ----------------------------- Methods -----------------------------
  56. /** Clears this collection and sets the given direction for Morton ordering.
  57. * @param mDirection New direction for Morton ordering. Should be one of <code>VERTICAL</code>
  58. * (mirrored 'N' shaped) or <code>HORIZONTAL</code> ('Z' shaped).
  59. */
  60. public void resetDirection(int mDirection)
  61. {
  62. clear();
  63. this.direction = mDirection;
  64. }
  65. /** Returns the x,y position of the first occurrence of the given object in this collection,
  66. * or null if the collection does not contain the object.
  67. * @param obj Object whose position will be reported.
  68. * @return 2-dimensional position of the object.
  69. */
  70. public Point positionOf(Object obj)
  71. {
  72. int index = indexOf(obj);
  73. if (index < 0)
  74. {
  75. return null;
  76. }
  77. return new Point(getX(index),getY(index));
  78. }
  79. /** Returns the object at the given x,y position or null if no object at the given position.
  80. * Note that it is not possible to distinguish between a null object at a given position
  81. * and position that it out of bounds of the current collection.
  82. * @param x x coordinate of the position from which to retrieve the object.
  83. * @param y x coordinate of the position from which to retrieve the object.
  84. * @return Object at the given position or null if out of bounds or no object.
  85. */
  86. public E get(int x, int y)
  87. {
  88. int morton = getMorton(x, y);
  89. if (morton >= size())
  90. {
  91. //System.err.println("Position out of bounds: Morton number for "+x+","+y+" is "+morton+" but collection only has "+size()+" elements.");
  92. return null;
  93. }
  94. return get(morton);
  95. }
  96. /** Returns the object that is to the 'right' (x+1) of the first instance of the given reference object
  97. * or null if no object to the right or if the given reference object not found.
  98. * @param obj Reference object from which to find its neighbour.
  99. * @return Object to the right of the given reference object.
  100. */
  101. public E getNextX(Object obj)
  102. {
  103. Point position = positionOf(obj);
  104. if (position == null)
  105. {
  106. //System.err.println("getNextX(): Object "+obj+" not found in collection.");
  107. return null;
  108. }
  109. return get(position.x+1,position.y);
  110. }
  111. /** Returns the object that is 'below' (y+1) the first instance of the given reference object
  112. * or null if no object below or if the given reference object not found.
  113. * @param obj Reference object from which to find its neighbour.
  114. * @return Object below the given reference object.
  115. */
  116. public E getNextY(Object obj)
  117. {
  118. Point position = positionOf(obj);
  119. if (position == null)
  120. {
  121. //System.err.println("getNextY(): Object "+obj+" not found in collection.");
  122. return null;
  123. }
  124. return get(position.x,position.y+1);
  125. }
  126. /** Reports the x coordinate of the position represented by the given Morton number.
  127. * @param mortonNumber Number to process.
  128. * @return x coordinate represented by the Morton number.
  129. */
  130. public int getX(int mortonNumber)
  131. {
  132. int x=0;
  133. if (direction == HORIZONTAL)
  134. {
  135. for (int i=0; i<32; i+=2)
  136. {
  137. int mask = 1 << (i);
  138. x += (mortonNumber&mask)>>(i/2);
  139. }
  140. }
  141. else
  142. {
  143. for (int i=1; i<32; i+=2)
  144. {
  145. int mask = 1 << (i);
  146. x += (mortonNumber&mask)>>((i+1)/2);
  147. }
  148. }
  149. return x;
  150. }
  151. /** Reports the y coordinate of the position represented by the given Morton number.
  152. * @param mortonNumber Number to process.
  153. * @return y coordinate represented by the Morton number.
  154. */
  155. public int getY(int mortonNumber)
  156. {
  157. int y=0;
  158. if (direction == HORIZONTAL)
  159. {
  160. for (int i=1; i<32; i+=2)
  161. {
  162. int mask = 1 << (i);
  163. y += (mortonNumber&mask)>>((i+1)/2);
  164. }
  165. }
  166. else
  167. {
  168. for (int i=0; i<32; i+=2)
  169. {
  170. int mask = 1 << (i);
  171. y += (mortonNumber&mask)>>(i/2);
  172. }
  173. }
  174. return y;
  175. }
  176. /** Reports the Morton number representing the given x,y coordinate pair.
  177. * @param x x coordinate of position to calculate.
  178. * @param y y coordinate of position to calculate.
  179. * @return Morton number representing the given position.
  180. */
  181. public int getMorton(int x, int y)
  182. {
  183. int newX = x;
  184. int newY = y;
  185. int morton = 0;
  186. if (direction == HORIZONTAL)
  187. {
  188. // Swap x and y coordinates for horizontal ordering.
  189. newX = y;
  190. newY = x;
  191. }
  192. for (int i=0; i<16; i++)
  193. {
  194. int mask = 1 << (i);
  195. morton += (newX&mask)<<(i+1);
  196. morton += (newY&mask)<<i;
  197. }
  198. return morton;
  199. }
  200. }