Openlayers 3圆半径(米)

时间:2015-08-25 11:35:23

标签: postgis openlayers-3

如何以米为单位获得Circle半径 可能这是现有的问题,但我没有得到正确的结果。我试图在postgis创建具有相同半径和&的多边形。中心来自openlayers圈。

为了得到以米为单位的半径,我跟着this。 运行示例link

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));

但两者都没有涵盖相同的区域。任何人都可以告诉我我在哪里做错了。

基本上我的圆圈输入/输出仅以米为单位。

2 个答案:

答案 0 :(得分:15)

ol.geom.Circle可能不代表圆圈

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

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

Tissot's indicatrix using EPSG:3857

图像来自OpenLayer 3's Tissot example,显示半径均为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')
);

更多选项

如果要在地球上添加表示圆形区域的几何图形,则应考虑使用上述天梭示例中使用的方法。也就是说,定义具有足够点的正多边形以显得平滑。这将使它可以在投影之间转换,并且看起来就像你在做服务器端。 OpenLayers 3通过ol.geom.Polygon.circular启用此功能:

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

还有ol.geom.Polygon.fromCircle,它接受​​ol.geom.Circle并将其转换为代表相同区域的多边形。

答案 1 :(得分:1)

我的回答是对 Alvin 的精彩回答的补充。

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

如果这个圆的直径很小(<几公里),你可以忽略地球的粗糙度。然后,您可以在点要素的样式功能中使用标记“圆”。

这是我的样式函数:

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

诀窍是按纬度余弦缩放半径。这将“局部”禁用我们在天梭示例中可以观察到的失真效果。