Openlayers 3 圆半径(以米为单位)

问题描述 投票:0回答:2

如何获得半径(以米为单位) 也许这是现有的问题,但我没有得到正确的结果。我正在尝试在 postgis 中创建一个具有与 openlayers 圆相同的半径和中心的多边形。

为了获得以米为单位的半径,我遵循了this。 运行示例链接

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

获得中心、半径(以米为单位)后,我尝试使用 postgis (服务器作业)生成多边形(WKT)并在像 this 这样的地图中绘制该特征。

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

但是两者并不覆盖同一区域。有人可以告诉我我做错了什么吗?

基本上,我对 Circle 的输入/输出仅以米为单位。

postgis openlayers-3
2个回答
21
投票

ol.geom.Circle 可能不代表圆

OpenLayers 圆几何形状在投影平面上定义。这意味着它们在地图上始终是圆形的,但所覆盖的区域可能并不代表地球上的实际圆形。圆所覆盖区域的实际形状和大小将取决于所使用的投影。

这可以通过天梭的指示线来可视化,它显示了地球上的圆形区域在投影到平面上时如何变换。使用投影 EPSG:3857,这看起来像:

该图像来自OpenLayer 3 的 Tissot 示例,显示半径均为 800 000 米的区域。如果这些圆圈被绘制为半径为 800000 的

ol.geom.Circle
(使用 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
并将其转换为表示同一区域的 Polygon。


4
投票

我的答案是对阿尔文精彩答案的补充。

假设您想要围绕点要素绘制给定半径(以米为单位)的圆。在我的具体情况中,围绕移动车辆 200m 的圆圈。

如果这个圆的直径很小(< some kilometers), you can ignore earth roudness. Then, you can use the marker "Circle" in the style function of your point feature.

这是我的风格功能:

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];
}

技巧是按纬度余弦缩放半径。这将“局部”禁用我们在天梭示例中观察到的扭曲效应。

© www.soinside.com 2019 - 2024. All rights reserved.