Измерение площадей — одна из наиболее востребованных функций веб-картографических приложений. Она используется в кадастровых системах, геоинформационных платформах, инженерных проектах, экологическом мониторинге, сельском хозяйстве и логистике. Библиотека OpenLayers предоставляет инструменты для построения полигонов на карте и вычисления их площади как в процессе рисования, так и после завершения редактирования.
Основой измерения площади является создание геометрии типа
Polygon, состоящей из замкнутого набора координат. После
построения полигона его площадь может быть вычислена различными
способами в зависимости от требований к точности.
Для определения площади используется геометрия
Polygon.
Пример создания полигона вручную:
import Polygon from 'ol/geom/Polygon.js';
const polygon = new Polygon([
[
[0, 0],
[1000, 0],
[1000, 1000],
[0, 1000],
[0, 0]
]
]);
Каждый полигон содержит один или несколько линейных колец.
Структура координат:
[
[
[x1, y1],
[x2, y2],
[x3, y3],
...
]
]
Первое и последнее значения должны совпадать, образуя замкнутую область.
Самый простой способ вычисления площади — использование метода
getArea().
const area = polygon.getArea();
console.log(area);
Метод возвращает площадь в квадратных единицах текущей проекции.
Например, если координаты представлены в метрах, результат будет выражен в квадратных метрах.
const area = polygon.getArea();
console.log(`${area} м²`);
Большинство карт OpenLayers работают в проекции EPSG:3857 (Web Mercator).
const view = new View({
center: [0, 0],
zoom: 5
});
В этой проекции координаты выражены в метрах, однако значения площади не являются полностью корректными для больших территорий из-за искажений карты.
Например:
const area = polygon.getArea();
Для небольших участков ошибка обычно незначительна.
Для измерения земельных участков, зданий, парковок и других локальных объектов такого вычисления зачастую достаточно.
При работе с большими территориями предпочтительно использовать геодезические расчёты.
OpenLayers предоставляет функцию getArea() из модуля
сферической геометрии.
import {getArea} from 'ol/sphere.js';
Пример:
const area = getArea(polygon);
console.log(area);
В этом случае вычисление выполняется с учётом кривизны Земли.
Такой подход обеспечивает значительно более высокую точность при измерении:
polygon.getArea();
Особенности:
import {getArea} from 'ol/sphere.js';
getArea(polygon);
Особенности:
Перед началом измерения обычно создаётся отдельный векторный слой.
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
const source = new VectorSource();
const vectorLayer = new VectorLayer({
source: source
});
map.addLayer(vectorLayer);
Все создаваемые пользователем полигоны будут храниться в данном источнике данных.
Для измерения площади пользователь должен иметь возможность нарисовать контур объекта.
Используется взаимодействие Draw.
import Draw from 'ol/interaction/Draw.js';
const draw = new Draw({
source: source,
type: 'Polygon'
});
map.addInteraction(draw);
После активации режима пользователь последовательно указывает вершины полигона.
Событие drawend позволяет обработать завершение
построения фигуры.
draw.on('drawend', function(event) {
const polygon = event.feature.getGeometry();
const area = polygon.getArea();
console.log(area);
});
После замыкания контура вычисляется площадь созданной области.
Для повышения точности:
import {getArea} from 'ol/sphere.js';
draw.on('drawend', function(event) {
const geometry = event.feature.getGeometry();
const area = getArea(geometry);
console.log(area);
});
Полученное значение будет выражено в квадратных метрах.
Неудобно отображать большие числа без преобразования единиц измерения.
Пример функции форматирования:
function formatArea(area) {
if (area > 1000000) {
return (area / 1000000).toFixed(2) + ' км²';
}
return area.toFixed(2) + ' м²';
}
Использование:
const areaText = formatArea(area);
console.log(areaText);
Результаты:
542.12 м²
или
14.57 км²
Во многих приложениях площадь отображается ещё до завершения построения полигона.
Для этого отслеживаются изменения геометрии.
draw.on('drawstart', function(event) {
const geometry = event.feature.getGeometry();
geometry.on('change', function(e) {
const polygon = e.target;
const area = polygon.getArea();
console.log(area);
});
});
После добавления каждой новой вершины значение автоматически пересчитывается.
Для вывода площади непосредственно на карте используется объект
Overlay.
Создание HTML-элемента:
const measureElement =
document.createElement('div');
measureElement.className = 'measure';
Создание оверлея:
import Overlay from 'ol/Overlay.js';
const measureOverlay = new Overlay({
element: measureElement
});
map.addOverlay(measureOverlay);
Обновление текста:
measureElement.innerHTML =
formatArea(area);
Изменение позиции:
measureOverlay.setPosition(
polygon.getInteriorPoint().getCoordinates()
);
Подпись будет отображаться внутри измеряемой области.
Для корректного размещения подписи применяется метод:
polygon.getInteriorPoint()
Пример:
const point =
polygon.getInteriorPoint();
const coordinates =
point.getCoordinates();
Полученные координаты практически всегда находятся внутри фигуры независимо от её формы.
Необязательно рисовать полигон вручную.
Если объект уже находится на карте:
const feature =
source.getFeatures()[0];
const polygon =
feature.getGeometry();
const area =
polygon.getArea();
Подход широко применяется при загрузке данных из внешних источников.
После загрузки GeoJSON можно вычислять площади всех объектов.
source.getFeatures().forEach(feature => {
const geometry =
feature.getGeometry();
const area =
geometry.getArea();
console.log(area);
});
Пример использования:
Иногда необходимо получить общую площадь набора полигонов.
let totalArea = 0;
source.getFeatures().forEach(feature => {
totalArea +=
feature.getGeometry().getArea();
});
console.log(totalArea);
Результат:
1254300
После форматирования:
console.log(
formatArea(totalArea)
);
Если полигон можно изменять, площадь должна обновляться автоматически.
Для этого используется взаимодействие Modify.
import Modify from 'ol/interaction/Modify.js';
const modify = new Modify({
source: source
});
map.addInteraction(modify);
После изменения геометрии:
modify.on('modifyend', function(event) {
event.features.forEach(feature => {
const area =
feature.getGeometry().getArea();
console.log(area);
});
});
Удаление всех измеренных объектов:
source.clear();
Удаление отдельных объектов:
source.removeFeature(feature);
После удаления рекомендуется очищать подписи площади:
measureElement.innerHTML = '';
Для лучшей визуализации измеряемые области обычно выделяются специальным стилем.
import Style from 'ol/style/Style.js';
import Stroke from 'ol/style/Stroke.js';
import Fill from 'ol/style/Fill.js';
const style = new Style({
stroke: new Stroke({
color: '#ff6600',
width: 2
}),
fill: new Fill({
color: 'rgba(255,102,0,0.2)'
})
});
Применение:
vectorLayer.setStyle(style);
Такой стиль делает контур хорошо заметным и одновременно сохраняет видимость картографической подложки.
При работе с тысячами полигонов рекомендуется:
import Draw from 'ol/interaction/Draw.js';
import {getArea} from 'ol/sphere.js';
const draw = new Draw({
source: source,
type: 'Polygon'
});
map.addInteraction(draw);
draw.on('drawend', function(event) {
const polygon =
event.feature.getGeometry();
const area =
getArea(polygon);
alert(
formatArea(area)
);
});
Последовательность работы:
Polygon.drawend.Такой механизм лежит в основе большинства инструментов измерения площадей в приложениях, построенных на OpenLayers.