检查多边形是否在视口中

时间:2016-01-26 07:22:12

标签: javascript google-maps google-maps-api-3

我有250个多边形,每个100-300个点。 如何检查哪些多边形在视口中?

要做的逻辑事情是检查每个多边形的每个点,如果它们在视口中,但这看起来非常昂贵和愚蠢。 我还有其他选择,如果有,有哪些选择?

我的其他想法:

  • 使用边界框 - 缺点是它只有4个点,可能会出现漏报
  • 使用较少的点制作不可见的简化多边形 - 过多的额外工作,数据和资源使用

以下代码遍历所有250个多边形,每个多边形的100-300个点并在视口中检查它。我认为自己是编程的初学者,但这似乎并不是一个好主意,特别是如果我需要在每次更改边界/地图被拖动时发生这种情况。

google.maps.event.addListener( map, 'bounds_changed', function( ) {

    var viewport = map.getBounds();

    var polygons = [array of polygons];
    var polygonsCount = polygons.length;

    // Polygons
    for(a = 0; a < polygonsCount; a++) {

        var polygonPoints = polygons[a].getPath(); // Array of points
        var inBounds = false;

        var pointsCount = polygonPoints.length;

        // Points
        for(b = 0; b < pointsCount; b++) {

            if(viewport.contains(polygonPoints[b])) { 

                inBounds = true; 
                return false;  // No need to continue loop if we found one 
            } 
        } 
    }
});

2 个答案:

答案 0 :(得分:3)

您可以使用以下函数来确定多边形是否位于地图视口内:

function containsPolygon(map,polygon) {
    return polygon.getPaths().getArray().every(function (path) {
        return path.getArray().every(function(coord) {
            return map.getBounds().contains(coord);
        });
    });
}

示例

var g_polygongs = [];
function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 3,
        center: { lat: 24.886, lng: -70.268 },
        mapTypeId: google.maps.MapTypeId.TERRAIN
    });

    //generate polygons
    for (var i = 0; i < 100; i++) {
        var startLng = getRandomArbitrary(-90.0, 0.0);
        var startLat = getRandomArbitrary(0.0, 60.0);
        var coords = [
            { lat: startLat, lng: startLng },
            { lat: startLat - 6.0, lng: startLng + 4.0 },
            { lat: startLat + 6.0, lng: startLng + 8.0 },
            { lat: startLat, lng: startLng }
        ];
        g_polygongs.push(createPolygon(map,coords));
    }


    google.maps.event.addListener(map, 'bounds_changed', function () {

      g_polygongs.forEach(function(p) {
          if (containsPolygon(map, p)) {
              p.setOptions({ strokeWeight: 2.0, fillColor: 'green' });
          } else {
              p.setOptions({ fillColor: 'orange' });
          }

      });
    });

}


function containsPolygon(map,polygon) {
    return polygon.getPaths().getArray().every(function (path) {
        return path.getArray().every(function(coord) {
            return map.getBounds().contains(coord);
        });
    });
}





function createPolygon(map,coords) {
    // Construct the polygon.
    var poly = new google.maps.Polygon({
        paths: coords,
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.35
    });
    poly.setMap(map);
    return poly;
}


function getRandomArbitrary(min, max) {
    return Math.random() * (max - min) + min;
}
html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#map {
    height: 100%;
}
<div id="map"></div>
<script async defer
            src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>

JSFiddle

答案 1 :(得分:0)

使用边界框应该是一个简单的过程,并且可以很好地减少比较。如果通过,那么你仍然可以检查每个点是否有明确的结果。

google.maps.LatLngBounds有一个你可以使用的交叉函数。

您希望预先计算每个多边形的边界,但这只需要发生一次或更新时。 Google地图不提供边界功能,但您可以创建它。

多边形的GetBounds

if (!google.maps.Polygon.prototype.getBounds) {

    google.maps.Polygon.prototype.getBounds=function(){
        var bounds = new google.maps.LatLngBounds()
        this.getPath().forEach(function(element,index)  {bounds.extend(element)})
        return bounds
    }
}

每个的Precalc界限;

function calcBounds(){
    for(a = 0; a < polygonsCount; a++) {
            polygons[a].bounds = polygons[a].getBounds(); //precalculated
    }
}

在您的事件处理程序中添加额外的测试。

google.maps.event.addListener( map, 'bounds_changed', function( ) {

    var viewport = map.getBounds();

    var polygons = [array of polygons];
    var polygonsCount = polygons.length;

    // Polygons
    for(a = 0; a < polygonsCount; a++) {
        var bounds = polygons[a].bounds; //precalculated
        if(viewport.intersects(bounds)){ //only continue if basic test passes
            var polygonPoints = polygons[a].getPath(); // Array of points
            var inBounds = false;

            var pointsCount = polygonPoints.length;

            // Points
            for(b = 0; b < pointsCount; b++) {

                if(viewport.contains(polygonPoints[b])) { 

                    inBounds = true; 
                    return false;  // No need to continue loop if we     found one 
                } 
            }
        } 
    }
});