0

I am using a QuadTree to find all the markers that are within the viewport of a google map object. The problem is none of points are being retrieved from the tree using the google maps boundaries as the query rectangle. I also think there is a problem when the map has boundaries that cross over the international dateline but I don't know of a general solution for this.

function QuadTree (points) {
    this.root = null;
    this.size =0;
    for(var i = 0; i < points.length; i++)
         this.add(points[i]);
}
function withinBounds(p, r) {
    return  p.x > r.x1 && p.x < r.x2 && p.y > r.y1 && p.y < r.y2;
}
QuadTree.prototype.queryRectangle = function(bounds) {
    console.log("Root:"+this.root.value[0].getPosition());
    var points = [];
    this.query2D(this.root, bounds, points);
    return points;
};
// This is the problem function
QuadTree.prototype.query2D = function( h,  r, points) {
    if(h==null) return ;
    var ne = r.getNorthEast();
    var sw = r.getSouthWest();

    var xmin = sw.lng();
    var xmax = ne.lng();
    var ymin = ne.lat();
    var ymax = sw.lat();

    var rect = {x1: xmin, x2: xmax, y1: ymax, y2: ymin};
    if(withinBounds(h, rect)) {
        console.log("Found "+h.x+" "+h.y);
        for(var i = 0; i < h.value.length; i++) {
            var p = h.value[i];
            points.push(p);
        }
     }
     if ( (xmin < h.x) &&  (ymin < h.y)){this.query2D(h.SW, r, points);};
     if ( (xmin < h.x) && !(ymax < h.y)){this.query2D(h.NW, r, points);};
     if (!(xmax < h.x) &&  (ymin < h.y)){this.query2D(h.SE, r, points);};
     if (!(xmax < h.x) && !(ymax < h.y)){this.query2D(h.NE, r, points);};
};
// Other functions to make the quadtree work
QuadTree.prototype.add = function(p) {
    this.size++;
    console.log("adding node"+p.getPosition());
    this.root = this.insert(this.root,p);
};
QuadTree.prototype.insert = function insert(h, p) {
    if(h== null) return new QuadTreeNode(p);
    else if ( eq(p,h)) h.value.push(p);
    else if ( lessX(p,h) &&  lessY(p,h)) h.SW = this.insert(h.SW, p);
    else if ( lessX(p,h) && !lessY(p,h)) h.NW = this.insert(h.NW, p);
    else if (!lessX(p,h) &&  lessY(p,h)) h.SE = this.insert(h.SE, p);
    else if (!lessX(p,h) && !lessY(p,h)) h.NE = this.insert(h.NE, p);
    return h;
};
function  lessX( p,  h) {
    return p.getPosition().lat() < h.x;
}
function  lessY( p,  h) {
    return p.getPosition().lng() < h.y;
}
function eq( p,  h) {
    return p.getPosition().lat() == h.x && p.getPosition().lng() == h.y;
}

function QuadTreeNode(point) {
    this.value = [point];
    this.NW = null;
    this.NE = null;
    this.SW = null;
    this.SE = null;
    this.x = point.getPosition().lat();
    this.y = point.getPosition().lng();
}

I am adding Google marker objects to the map in this manner:

var points = [{latitude:-34.9876, longitude: 138.574}]; // there are a few thousand more points to show
var markers = [];
for(var i = 0;i < points.length; i++) {
    var p = points[i];
    markers.push(new google.maps.Marker( {
        position: new google.maps.LatLng(points[i].latitude,points[i].longitude),
        map: null,
    });
}
var oldBounds = null;
var quadTree = new QuadTree(markers);
console.log("Built quadtree with size "+quadTree.size);
google.maps.event.addListener(map,'idle', function() {
    if(oldBounds !== null) {
        quadTree.queryRectangle(oldBounds).map(function(x){x.setMap(null);});
        console.log("Old bounds:"+oldBounds);
    }
    var bounds = map.getBounds();
    quadTree.queryRectangle(bounds).map(function(x){x.setMap(map);});
    oldBounds = bounds;
});
Jonno_FTW
  • 8,601
  • 7
  • 58
  • 90

1 Answers1

0

You've mixed up x and y in QuadTreeNode, it has to be:

this.x = point.getPosition().lng();
this.y = point.getPosition().lat();
Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • This only shows the root node now. The other points are definitely in there, they just aren't being retrieved. – Jonno_FTW Mar 11 '14 at 05:54