Работа с зонами избегания в приложениях на основе HERE Maps API for JavaScript строится вокруг управления пространственными ограничениями: полигонами, географическими областями и правилами маршрутизации, которые исключают определённые участки карты из расчётов или пользовательского взаимодействия. В реальных задачах это используется для обхода опасных территорий, частных зон, зон с ограниченным доступом, экологических территорий, строительных площадок или просто нежелательных маршрутов.
Избегание зон в картографических приложениях — это не просто фильтрация маршрутов, а наложение дополнительной логики поверх геоданных.
Основные типы ограничений:
Каждый из этих типов реализуется на разных уровнях: от клиентского JavaScript до серверного расчёта маршрутов через Routing API.
Базовая сущность любой зоны избегания — полигон. В JavaScript SDK он строится через геометрические примитивы.
const points = [
{ lat: 52.51, lng: 13.40 },
{ lat: 52.52, lng: 13.41 },
{ lat: 52.51, lng: 13.42 }
];
const polygon = new H.map.Polygon(new H.geo.Polygon(
new H.geo.LineString(points.map(p => ({ lat: p.lat, lng: p.lng })))
), {
style: {
strokeColor: 'red',
lineWidth: 2,
fillColor: 'rgba(255,0,0,0.2)'
}
});
map.addObject(polygon);
Ключевой момент: визуализация зоны не означает её автоматическое влияние на маршруты — это разные слои логики.
Для реального избегания зон используется Routing API v8, который
поддерживает параметр avoid[areas]. Он позволяет передавать
географические области, которые должны быть исключены из маршрута.
Пример логики формирования запроса:
const routingParameters = {
transportMode: 'car',
origin: '52.5200,13.4050',
destination: '52.5300,13.4200',
'avoid[areas]': '52.515,13.405;52.515,13.415;52.525,13.415'
};
Здесь координаты задают полигональную область, которую маршрут должен обойти.
Важно:
Частый сценарий — пользователь сам выделяет область на карте, которую нужно избегать.
const drawingTool = new H.map.Rect(new H.geo.Rect());
map.addEventListener('tap', function (evt) {
const coord = map.screenToGeo(evt.currentPointer.viewportX, evt.currentPointer.viewportY);
drawingTool.getGeometry().pushPoint(coord);
if (drawingTool.getGeometry().getPointCount() > 2) {
const polygon = new H.map.Polygon(drawingTool.getGeometry(), {
style: {
fillColor: 'rgba(0,0,255,0.2)',
strokeColor: '#0000ff'
}
});
map.addObject(polygon);
}
});
После завершения редактирования координаты полигона обычно:
Избегание зон часто расширяется до геофенсинга — реакции на вход/выход из области.
function isPointInPolygon(point, polygon) {
return H.geo.Point.prototype.withinPolygon.call(point, polygon);
}
map.addEventListener('pointermove', function (evt) {
const coord = map.screenToGeo(evt.currentPointer.viewportX, evt.currentPointer.viewportY);
if (isPointInPolygon(coord, restrictedZone)) {
console.warn('Пользователь в запрещённой зоне');
}
});
Практическое применение:
Помимо географических зон, Routing API поддерживает параметрические ограничения:
avoid[features]=tollRoadsavoid[features]=highwaysavoid[features]=ferriesКомбинирование с полигонами позволяет строить сложную модель:
const params = {
transportMode: 'truck',
origin: '52.52,13.40',
destination: '52.60,13.50',
'avoid[areas]': encodedPolygon,
'avoid[features]': 'tollRoads,highways'
};
Так формируется многоуровневая система ограничений:
Для масштабируемых систем зоны избегания почти всегда хранятся в GeoJSON.
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[13.40, 52.51],
[13.41, 52.52],
[13.42, 52.51],
[13.40, 52.51]
]
]
},
"properties": {
"type": "restricted",
"name": "construction_zone"
}
}
Причины использования GeoJSON:
В реальных сценариях зоны избегания редко бывают простыми.
Типичные сложности:
Пример мультиполигона:
const multiPolygon = new H.geo.MultiPolygon([
polygon1,
polygon2
]);
При маршрутизации такие структуры часто требуют предварительной нормализации:
Когда количество зон растёт, возникают проблемы вычислительной сложности.
Оптимизационные подходы:
На клиенте не рекомендуется выполнять проверку десятков тысяч точек полигона без упрощения — это приводит к деградации UI.
Для административных интерфейсов часто используется режим редактирования:
polygon.enableEditing();
polygon.addEventListener('geometrychange', function () {
const updatedCoords = polygon.getGeometry().getExterior().getLatLngAltArray();
console.log(updatedCoords);
});
Это позволяет динамически обновлять зоны без перезагрузки карты и пересчёта всей сцены.
Критическая архитектурная деталь: клиентская карта и сервер маршрутизации должны использовать одинаковые зоны.
Типичная схема:
Несинхронизированные данные приводят к расхождению:
Иногда требуется не просто избегать зоны, а детектировать пересечение.
function routeIntersectsPolygon(routeLineString, polygon) {
return H.geo.Polyline.prototype.intersects.call(routeLineString, polygon);
}
Используется для:
При интеграции с потоковыми данными (например, пробки или аварии) зоны избегания могут становиться временными:
Это превращает систему в адаптивную гео-модель, где ограничения меняются в реальном времени без ручного вмешательства.