61 | | /** |
62 | | * Gets the index of the given coordinate. Only used internally |
63 | | * @param ll The lat/lon coordinate |
64 | | * @param level The scale level |
65 | | * @return The index for that position |
66 | | */ |
67 | | public static int index(LatLon ll, int level) { |
68 | | long noParts = 1L << level; |
69 | | long x = ((long) ((ll.lon() + 180.0) * noParts / 360.0)) & 1; |
70 | | long y = ((long) ((ll.lat() + 90.0) * noParts / 180.0)) & 1; |
71 | | return (int) (2 * x + y); |
72 | | } |
73 | | |
120 | | int idx = index(ll, level+1); |
121 | | if (children[idx] == null) { |
122 | | double lon1, lat1; |
123 | | switch (idx) { |
124 | | case 0: |
125 | | lon1 = bbox.getTopLeftLon(); |
126 | | lat1 = bbox.getBottomRightLat(); |
127 | | break; |
128 | | case 1: |
129 | | lon1 = bbox.getTopLeftLon(); |
130 | | lat1 = bbox.getTopLeftLat(); |
131 | | break; |
132 | | case 2: |
133 | | lon1 = bbox.getBottomRightLon(); |
134 | | lat1 = bbox.getBottomRightLat(); |
135 | | break; |
136 | | case 3: |
137 | | lon1 = bbox.getBottomRightLon(); |
138 | | lat1 = bbox.getTopLeftLat(); |
139 | | break; |
140 | | default: |
141 | | throw new AssertionError(); |
| 107 | LatLon center = bbox.getCenter(); |
| 108 | for (int idx = 0; idx < 4; idx++) { |
| 109 | BBox testBBox = null; |
| 110 | if (children[idx] != null) |
| 111 | testBBox = children[idx].bbox; |
| 112 | |
| 113 | if (testBBox == null) { |
| 114 | double lon1, lat1; |
| 115 | switch (idx) { |
| 116 | case 0: |
| 117 | lon1 = bbox.getTopLeftLon(); |
| 118 | lat1 = bbox.getBottomRightLat(); |
| 119 | break; |
| 120 | case 1: |
| 121 | lon1 = bbox.getTopLeftLon(); |
| 122 | lat1 = bbox.getTopLeftLat(); |
| 123 | break; |
| 124 | case 2: |
| 125 | lon1 = bbox.getBottomRightLon(); |
| 126 | lat1 = bbox.getBottomRightLat(); |
| 127 | break; |
| 128 | case 3: |
| 129 | lon1 = bbox.getBottomRightLon(); |
| 130 | lat1 = bbox.getTopLeftLat(); |
| 131 | break; |
| 132 | default: |
| 133 | throw new AssertionError(); |
| 134 | } |
| 135 | testBBox = new BBox(lon1, lat1, center.lon(), center.lat()); |
143 | | if (DEBUG) System.err.println(" - new with idx "+idx); |
144 | | LatLon center = bbox.getCenter(); |
145 | | BBox b = new BBox(lon1, lat1, center.lon(), center.lat()); |
146 | | children[idx] = new GPLevel<>(level + 1, b, this, owner); |
| 137 | if (isInside(testBBox, ll)) { |
| 138 | if (children[idx] == null) { |
| 139 | if (DEBUG) System.err.println(" - new with idx "+idx); |
| 140 | children[idx] = new GPLevel<>(level + 1, testBBox, this, owner); |
| 141 | } |
| 142 | return children[idx].getBounded(ll); |
| 143 | } |
| 162 | /** |
| 163 | * Checks, if a point is inside this tile. |
| 164 | * Makes sure, that neighboring tiles do not overlap, i.e. a point exactly |
| 165 | * on the border of two tiles must be inside exactly one of the tiles. |
| 166 | * @param bbox the tile |
| 167 | * @param ll the coordinates of the point |
| 168 | * @return true, if it is inside of the box |
| 169 | */ |
| 170 | boolean isInside(BBox bbox, LatLon ll) { |
| 171 | return bbox.getTopLeftLon() <= ll.lon() && |
| 172 | (ll.lon() < bbox.getBottomRightLon() || (ll.lon() == 180.0 && bbox.getBottomRightLon() == 180.0)) && |
| 173 | bbox.getBottomRightLat() <= ll.lat() && |
| 174 | (ll.lat() < bbox.getTopLeftLat() || (ll.lat() == 90.0 && bbox.getTopLeftLat() == 90.0)); |
| 175 | } |
| 176 | |