Клуб API Карт

Определение принадлежности точки многоугольнику (для xml)

Пост в архиве.

Есть замечательный код, который позволяет определить принадлежит ли точка заданной области.

Вот сама функция:

 

function inPolygon (polygon, point) {
var c = 0;

for (var i = 0, points = polygon.getPoints(), j = points.length - 1; i < points.length; j = i++) {
if ((((points[i].getLat() <= point.getLat()) && (point.getLat() < points[j].getLat())) || ((points[j].getLat() <= point.getLat()) && (point.getLat() < points[i].getLat()))) &&
(point.getLng() > (points[j].getLng() - points[i].getLng()) * (point.getLat() - points[i].getLat()) / (points[j].getLat() - points[i].getLat()) + points[i].getLng())
) {
c = !c;
}
}
return c;
}

 

У меня есть YMapsML-файл в котором содержится описание зон на карте полигонами:

  <ymaps:GeoObjectCollection>

        <ymaps:GeoObject>

                <gml:Polygon>

Ну и так далее.

Загружаю я этот файл как обычно:

var zoneh = new YMaps.YMapsML('http://мой сайт/zone.xml');

map.addOverlay(zoneh);

 Но выполнить следующий код не удается:

 

if (inPolygon(zoneh.get(0).get(1), obj4.getGeoPoint())) {
YMaps.jQuery(".ClDataCold").append("<p>Зона влажности: Влажная</p>");
alert("Зона найдена.");
}

Пример кода тут - http://ovvk-info.narod.ru/maps-climatrr.html

10 комментариев

Не надо подключать три раза API. Для подключения двух дополнительных модулей достаточно при первом подключении api к строке подключения добавить "modules=regions~plainstyle".


<script src="http://api-maps.yandex.ru/1.1/index.xml?key=API-ключ&modules=regions~plainstyle" type="text/javascript">script>

Определить принадлежность многоугольнику можно вот так:



var zoneh = new YMaps.YMapsML("http://ovvk-info.narod.ru/zone.xml");
map.addOverlay(zoneh);

// С объектами можно работать только после успешной загрузки YMapsML
var flagLoad = false;
YMaps.Events.observe(zoneh, zoneh.Events.Load, function (ml) {
    flagLoad = true;
});

function getPolygons (point) {
    if (flagLoad) {
        return zoneh.get(0).filter(function (obj) {
            return inPolygon(obj, point);
        });
    } else {
        return false;
    }
}

Немного поясню. Пока YMapsML с зонами не загрузился функция getPolygons будет возвращать false. После того, как YMapsML загрузился, сработает обработчики события Load и флаг flagLoad установится в значение true. Это поменяет поведение функции getPolygons и она станет возвращать массив отфильтрованных многоугольников. Если у вас многоугольники не пересекаются, то можно возвращать только первый найденный многоугольник.


Использовать функцию можно вот так:



var polygons = getPolygons(obj4.getGeoPoint());

А можно получить имя этого полигона, которое записано в поле файла zone.xml ?

Мне нужно получить только имя зоны.

Типа obj.name .

Имя первого многоугольника:


alert(polygons[0].name);

Отладчик выдает ошибку на строке:

    return zoneh.get(0).filter(function (obj) {  

 

Судя ао всему почему-то не срабатывает строка:

inPolygon(obj, point);
 

 

Приведите фрагмент кода или страница с минимальным количеством кода, на которой можно наблюдать ошибку.

Внес в код следующие изменения:

//Флаг окончания загрузки климатических зон
var flagLoad = false;

....

// Если кнопка "Зоны влажности" активна, добавлям зоны на карту
YMaps.Events.observe(buttonZone, buttonZone.Events.Select, function () {
map.addOverlay(zoneh);
YMaps.Events.observe(zoneh, zoneh.Events.Load, function () {
flagLoad = true;
});
});

// Если кнопка "Зоны влажности" неактивна, то удаляем зоны с карты
YMaps.Events.observe(buttonZone, buttonZone.Events.Deselect, function () {
map.removeOverlay(zoneh);
flagLoad = false;
});   

....

//Функция поиска зоны
function getPolygons (point) {
if (flagLoad) {
return zoneh.get(0).filter(function (obj) {
return inPolygon(obj, point);});
} else {
return false;
}
}

....

//Делаю вызов
var polygons = getPolygons(obj4.getGeoPoint());
alert(polygons[0].name);
Обновил код - http://ovvk-info.narod.ru/maps-climatrr.html

 

Необходимо только предварительно отобразить зоны влажности кнопкой "Влажность".

Ошибка появляется даже если просто выполнить:

var zdd = zoneh.get(0); 

 

Прошу прощенья.

Все оказалось просто - забыл про область видимости переменных.