Openlayers 3 Радиус окружности в метрах

Как получить радиус окружности в метрах Может быть так существует вопрос, но я не получаю должного результата. Я пытаюсь создать Polygon в postgis с таким же радиусом и центром, полученным из круга openlayers.

Чтобы получить радиус в метрах, я выполнил этот . Пример выполнения ссылка.

var radiusInMeters = circleRadius * ol.proj.METERS_PER_UNIT['m'];

После получения центра, радиуса (в метрах) я пытаюсь создать полигон (WKT) с помощью postgis (задание сервера) и нарисовать эту функцию на карте, например это.

select st_astext(st_buffer('POINT(79.25887485937808 17.036647682474722 0)'::geography, 365.70644956827164));

Но оба не покрывают одну и ту же область. Может ли кто-нибудь сообщить мне, где я делаю неправильно.

В основном мой ввод/вывод в/из Circle будет только в метрах.


person Dyapa Srikanth    schedule 25.08.2015    source источник


Ответы (2)


ol.geom.Circle может не представлять собой круг

Геометрия OpenLayers Circle определяется на плоскости проекции. Это означает, что они всегда круглые на карте, но покрываемая область может не представлять собой настоящий круг на земле. Фактическая форма и размер области, покрытой кругом, будут зависеть от используемой проекции.

Это можно визуализировать с помощью индикатрисы Тиссо, которая показывает, как круглые области на земном шаре трансформируются при проецировании на плоскость. Используя проекцию EPSG:3857, это будет выглядеть так:

Индикатриса Tissot с использованием EPSG:3857

Изображение взято из примера Tissot для OpenLayer 3 и показывает области, которые все имеют радиус 800 000 метров. Если бы эти круги были нарисованы как ol.geom.Circle с радиусом 800000 (используя EPSG:3857), все они были бы одинакового размера на карте, но те, что ближе к полюсам, представляли бы гораздо меньшую площадь земного шара.

Это верно для большинства вещей с геометрией OpenLayers. Радиус, длина или площадь геометрии сообщаются в плоскости проекции.

Таким образом, если у вас есть ol.geom.Circle, получение фактического радиуса поверхности будет зависеть от проекции и расположения элементов. Для некоторых проекций (таких как EPSG:4326) точного ответа быть не может, поскольку геометрия может даже не представлять круглую область.

Однако если вы используете EPSG:3857 и не рисуете очень большие круги или очень близко к полюсам, круг будет хорошим представлением круглой области.

ol.proj.METERS_PER_UNIT

ol.proj.METERS_PER_UNIT — это просто таблица преобразования между метрами и некоторыми другими единицами измерения. ol.proj.METERS_PER_UNIT['m'] всегда будет возвращать 1, поскольку единицей измерения 'm' являются метры. В EPSG:3857 в качестве единиц измерения используются метры, но, как уже отмечалось, они искажены по направлению к полюсам.

Решение (используйте после прочтения и понимания вышеизложенного)

Чтобы получить фактический радиус ol.geom.Circle на земле, вы должны найти расстояние между центром круга и точкой на его краю. Это можно сделать с помощью ol.Sphere:

var center = geometry.getCenter()
var radius = geometry.getRadius()
var edgeCoordinate = [center[0] + radius, center[1]];
var wgs84Sphere = new ol.Sphere(6378137);
var groundRadius = wgs84Sphere.haversineDistance(
    ol.proj.transform(center, 'EPSG:3857', 'EPSG:4326'), 
    ol.proj.transform(edgeCoordinate, 'EPSG:3857', 'EPSG:4326')
);

Дополнительные параметры

Если вы хотите добавить геометрию, представляющую круглую область на земном шаре, вам следует рассмотреть возможность использования метода, использованного в приведенном выше примере Tissot. То есть определение правильного многоугольника с достаточным количеством точек, чтобы он выглядел гладким. Это сделало бы его переносимым между проекциями, и, похоже, это то, что вы делаете на стороне сервера. OpenLayers 3 обеспечивает это с помощью ol.geom.Polygon.circular< /а>:

var circularPolygon = ol.geom.Polygon.circular(wgs84Sphere, center, radius, 64);

Существует также ol.geom.Polygon.fromCircle, который берет ol.geom.Circle и преобразует его в полигон, представляющий ту же область.

person Alvin Lindstam    schedule 27.08.2015

Мой ответ является дополнением к отличному ответу Элвина.

Представьте, что вы хотите нарисовать окружность заданного радиуса (в метрах) вокруг точечного объекта. В моем конкретном случае это 200-метровый круг вокруг движущегося автомобиля.

Если этот круг имеет небольшой диаметр (‹ нескольких километров), то шероховатостью земли можно пренебречь. Затем вы можете использовать маркер Circle в функции стиля вашего точечного объекта.

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

private pointStyle(feature: Feature, resolution: number): Array<Style> {
  const viewProjection = map.getView().getProjection();      
  const coordsInViewProjection = (<Point>(feature.getGeometry())).getCoordinates();
  const longLat = toLonLat(coordsInViewProjection, viewProjection);
  const latitude_rad = longLat[1] * Math.PI / 180.;
  const circle = new Style({
     image: new CircleStyle({
          stroke: new Stroke({color: '#7c8692'});,
          radius: this._circleRadius_m / (resolution / viewProjection.getMetersPerUnit() * Math.cos(latitude_rad)),
        }),
      });
   
  return [circle];
}

Хитрость заключается в масштабировании радиуса по косинусу широты. Это локально отключит эффект искажения, который мы можем наблюдать в примере Tissot.

person Adrien BARRAL    schedule 18.05.2021