2016-01-26 2 views
1

У меня есть 250 полигонов каждый со 100-300 очками. Как проверить, какие полигоны находятся в окне просмотра?Проверьте, есть ли многоугольник в окне просмотра

Логической задачей было бы проверить каждую точку для каждого полигона, если они находятся в окне просмотра, но это кажется чрезвычайно дорогим и глупым. Есть ли у меня какие-либо другие варианты, и если да, то какие варианты?

Мои другие мысли:

  • Использование ограничивающего параллелепипеда - недостаток заключается в том, что он имеет только 4 очка, и это может дать ложные негативов
  • сделать невидимыми Simplifiled многоугольники с меньшим количеством очков - слишком много дополнительной работы данные, использование ресурсов

После кода перебирает все 250 многоугольник s и 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 
      } 
     } 
    } 
}); 
+0

Вы можете отслеживать точки полигонов, наиболее близкие к границе границ, но НЕ внутри границ для каждой стороны карты, а затем при изменении границ вам нужно только обновить, какие полигоны находятся внутри карты IFF any из 4 пунктов, которые вы отслеживали, теперь внутри, в отличие от проверки всех 250 * n точек каждый раз, когда обновляется оценка. Сделайте то же самое с ближайшими точками на внутренней стороне, они сжимают границы. –

+0

Вы также можете проверить только 1 точку на каждом полигоне и посмотреть, находится ли она в пределах «n» края границ, где n - это диаметр круга, который ограничивал бы многоугольник, IFF, который верно, затем перебирает все точки, иначе перемещается на следующий полигон –

+0

Эти две тактики должны резко сократить время вычислений, например, 1% от того, что было. Удачи! –

ответ

2

Вы можете использовать следующую функцию, чтобы определить, является ли полигон, расположенный внутри карта видового экрана или нет:

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

+0

Это, кажется, проверяет каждую точку и может привести к некоторым проблемам с производительностью, когда мои полигоны содержат сотни баллов или я неправильно понимаю ваш код? Кроме того, есть ли способ добавить _padding_, чтобы даже полигоны вблизи границ и немного за пределами границ считались _visible_? – Solo

+0

, это может повлиять на производительность, поскольку в функции 'map.getBounds() .''''''' мы проверяем, содержит ли карта координату всех вершин многоугольника –

0

Использование ограничивающих прямоугольников должно быть прямым процессом и обеспечивать хорошее сокращение сравнений. Если это пройдет, вы все равно можете проверить каждую точку на определенный результат.

google.maps.LatLngBounds имеет функцию пересечения, которую вы могли бы использовать.

Вы хотели бы предварительно рассчитать границы каждого многоугольника, но это должно произойти только один раз или когда они обновляются. Карты Google не предлагают функцию границ, но вы можете ее создать.

GetBounds Для Polygon

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 
       } 
      } 
     } 
    } 
}); 
+0

Хорошо .. Но как решить проблему, когда карта увеличена, а мы - в середине полигона или _ в средней или граничной рамке border_? Ни один из пунктов не показан, как все еще знать, отображается ли этот этот многоугольник? – Solo

+0

Ну, исходный ограничивающий прямоугольник пересекает тест, который должен работать для этого. Вам просто нужно усовершенствовать функцию пересечения многоугольников с чем-то более продвинутым, чем просто сравнение точек. Для этого нужны ресурсы. Посмотрите на этот ответ http://stackoverflow.com/a/10838831/1522857 –

Смежные вопросы