| 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 | |