Openlayers 3 圆半径(以米为单位)
Openlayers 3 Circle radius in meters
如何获得 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));
但两者并不覆盖同一区域。任何人都可以让我知道我哪里做错了。
基本上我的 input/output to/from 圆将仅以米为单位。
ol.geom.Circle可能不代表圆
OpenLayers 圆形几何体在投影平面上定义。这意味着它们在地图上始终是圆形的,但所覆盖的区域可能并不代表地球上的实际圆圈。圆圈覆盖区域的实际形状和大小将取决于使用的投影。
这可以通过 Tissot 的 indicatrix 进行可视化,它显示了地球上的圆形区域在投影到平面上时是如何变换的。使用投影 EPSG:3857,这看起来像:
图像来自 OpenLayer 3's Tissot example 并显示半径均为 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 只是米和其他一些单位之间的转换 table。 ol.proj.METERS_PER_UNIT['m']
将始终 return 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。
我的回答是对 Alvin 出色回答的补充。
假设您想围绕一个点要素绘制一个给定半径(以米为单位)的圆。在我的特殊情况下,围绕移动车辆的 200 米圆圈。
如果这个圆的直径很小(<几公里),你可以忽略地球的圆度。然后,您可以在点要素的样式函数中使用标记“圆”。
这是我的样式函数:
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 示例中观察到的失真效果。
如何获得 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));
但两者并不覆盖同一区域。任何人都可以让我知道我哪里做错了。
基本上我的 input/output to/from 圆将仅以米为单位。
ol.geom.Circle可能不代表圆
OpenLayers 圆形几何体在投影平面上定义。这意味着它们在地图上始终是圆形的,但所覆盖的区域可能并不代表地球上的实际圆圈。圆圈覆盖区域的实际形状和大小将取决于使用的投影。
这可以通过 Tissot 的 indicatrix 进行可视化,它显示了地球上的圆形区域在投影到平面上时是如何变换的。使用投影 EPSG:3857,这看起来像:
图像来自 OpenLayer 3's Tissot example 并显示半径均为 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 只是米和其他一些单位之间的转换 table。 ol.proj.METERS_PER_UNIT['m']
将始终 return 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。
我的回答是对 Alvin 出色回答的补充。
假设您想围绕一个点要素绘制一个给定半径(以米为单位)的圆。在我的特殊情况下,围绕移动车辆的 200 米圆圈。
如果这个圆的直径很小(<几公里),你可以忽略地球的圆度。然后,您可以在点要素的样式函数中使用标记“圆”。
这是我的样式函数:
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 示例中观察到的失真效果。