Получить ограничивающую рамку многоугольника

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

решение должно быть в в JavaScript или, может быть, есть функция Google Maps API v3, которую я пропустил.


или я должен жестко закодировать координаты ограничивающей рамки и использовать их для уменьшения нагрузки на клиент?

enter image description here

Как создаются полигоны:

//Coordinates
var coordinates = [ 
    new google.maps.LatLng(11,22),
    new google.maps.LatLng(11,22),
    new google.maps.LatLng(11,22),

    //etc up to 200, 500 or even 800 points
]

//Options
var options = {
    path: coordinates,
    strokeColor: "#222",
    strokeOpacity: 1,
    strokeWeight: 2,
    fillColor: "#000",
    fillOpacity: 0,
    zIndex: 0
}

//Create polygon
var polygon = new google.maps.Polygon( options );

//Show it on map
polygon.setMap( map );

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

Мне нужна как можно более простая форма, потому что мне нужно проверить, находится ли мой многоугольник в окне просмотра, и это будет наверное, будет кошмар с 800 очками, потому что я не знаю другого способа, кроме как перебирать все точки.

4 ответов


Polygon не имеет метода getBounds на Google Maps API v3. Вы можете реализовать его вручную. Но он содержит Форса. Кстати. Я реализовал метод, метод getbounds. Это жестко закодированная версия. Ссылку демо.

обновление

чтобы получить одну рамку для нескольких полигонов, используйте union метод getBounds метод.

var coordinates = [ 
   new google.maps.LatLng(10,15),
   new google.maps.LatLng(12,16),
   new google.maps.LatLng(11,18),
   new google.maps.LatLng(11,19),
   new google.maps.LatLng(13,21),
   new google.maps.LatLng(12,22),
   new google.maps.LatLng(13,24),
   new google.maps.LatLng(11,25),
   new google.maps.LatLng(8,23),
   new google.maps.LatLng(7,23),
   new google.maps.LatLng(8,21),
   new google.maps.LatLng(6,17),
   new google.maps.LatLng(9,16)
]

var coordinates_1 = [ 
   new google.maps.LatLng(15,28),
   new google.maps.LatLng(16,30),
   new google.maps.LatLng(17,30),
   new google.maps.LatLng(16,31),
   new google.maps.LatLng(16,32),
   new google.maps.LatLng(14,29),
]

var options = {
   path: coordinates,
   strokeColor: "#222",
   strokeOpacity: 1,
   strokeWeight: 2,
   fillColor: "#000",
   fillOpacity: 0,
   zIndex: 0,
   map: map
}

var options_1 = {
   path: coordinates_1,
   strokeColor: "#222",
   strokeOpacity: 1,
   strokeWeight: 2,
   fillColor: "#000",
   fillOpacity: 0,
   zIndex: 0
}

var polygon = new google.maps.Polygon(options);
var polygon_1 = new google.maps.Polygon(options_1);

if(!google.maps.Polygon.prototype.getBounds)
google.maps.Polygon.prototype.getBounds = function() {
    var bounds = new google.maps.LatLngBounds();
    var paths = this.getPaths();    
    for (var i = 0; i < paths.getLength(); i++) {
        var path = paths.getAt(i);
        for (var j = 0; j < path.getLength(); j++) {
            bounds.extend(path.getAt(j));
        }
    }
    return bounds;
}

var rectangle = new google.maps.Rectangle({
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35,
    map: map,
    bounds: polygon.getBounds()
  });

var rectangle_1 = new google.maps.Rectangle({
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35,
    map: map,
    bounds: polygon_1.getBounds()
  });

var rectangle_single = new google.maps.Rectangle({
    strokeColor: '#FFC000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FFF000',
    fillOpacity: 0.35,
    map: map,
    bounds: polygon.getBounds().union(polygon_1.getBounds())
  });

более простая и компактная версия кода:

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

координаты X и Y в массиве, затем X и y массив min и max. Хотя нам нужно больше, чем изображение, чтобы знать, что именно вы хотите и как.


Если очки Даны, мы не априори конструкции нет более эффективного способа чем итерация по точкам и расширение ограничивающей рамки. Поскольку вы ничего не знаете заранее, любая точка может быть на углу (или edge point) и поэтому вы должны принять это во внимание. Ни один алгоритм не может сделать это более эффективно.

Если у вас есть контроль над сервером, который предоставляет координаты, вы можете хранить точки заранее в datastructure как К-Д Дерево. Скажем, например, все точки статичны, вы можете хранить их в таком дереве k-d, а затем вы можете определенно ускорить вещи (хотя, насколько я знаю, проблема все еще O (n), но вы не должны принимать во внимание все пункты).

проблема в том, что вы не предоставляете никакой информации о стороне сервера.