Ticket #20345: 20345.patch

File 20345.patch, 5.0 KB (added by GerdP, 4 years ago)

possible solution, needs cleanup if OK

  • src/org/openstreetmap/josm/tools/GeoPropertyIndex.java

     
    5858        return geoProp;
    5959    }
    6060
    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 
    7461    protected static class GPLevel<T> {
    7562        private final T val;
    7663        private final int level;
     
    117104                this.children = tmp;
    118105            }
    119106
    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());
    142136                }
    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                }
    147144            }
    148             return children[idx].getBounded(ll);
     145            throw new AssertionError("Point "+ll+" should be inside one of the children of "+bbox);
    149146        }
    150147
    151148        /**
     
    162159                    (ll.lat() < bbox.getTopLeftLat() || (ll.lat() == 90.0 && bbox.getTopLeftLat() == 90.0));
    163160        }
    164161
     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
    165177        @Override
    166178        public String toString() {
    167179            return "GPLevel [val=" + val + ", level=" + level + ", bbox=" + bbox + ']';