如何在Leaflet中绘制天梭的椭圆(Tissot's indicatrix)
How to draw Tissot's ellipse (Tissot's indicatrix) in Leaflet
OpenLayers supports tissot's ellipses natively by adding a sphere to the circular() method.
很遗憾 Leaflet L.circle() 不支持此功能。
如何使用 Leaflet 绘制天梭的椭圆?
编辑 3:
使用 leaflet-geodesy 的新命题似乎非常适合您的需要。它免除了 Turf 的错误(请参阅下面的编辑 2)。
API很简单:
LGeo.circle([51.441767, 5.470247], 500000).addTo(map);
(以 [latitude, longitude] 度为单位的中心位置,以米为单位的半径)
演示:http://jsfiddle.net/ve2huzxw/61/
与 nathansnider 的解决方案进行快速比较:http://fiddle.jshell.net/58ud0ttk/2/
(表明两个代码产生相同的结果面积,唯一的区别在于用于近似面积的段数)
编辑:一个很好的页面,将 Leaflet-geodesy 与标准 L.Circle 进行比较:https://www.mapbox.com/mapbox.js/example/v1.0.0/leaflet-geodesy/
编辑 2:
不幸的是 Turf 使用 JSTS Topology Suite 构建缓冲区。貌似JSTS中的这个操作不适合像地球表面这样的非平面几何。
错误已报告 here,截至今天,主要的 Turf 库还没有完整的解决方法。
所以下面的答案(编辑 1)产生了错误的结果。
请参阅 了解围绕某个点构建缓冲区的解决方法。
编辑 1:
您可以使用 Turf 轻松构建所描述的多边形。它提供了 turf.buffer
方法,该方法在给定要素(可以是一个简单的点)周围创建具有指定距离的多边形。
所以你可以简单地做例如:
var pt = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [5.470247, 51.441767]
}
};
var buffered = turf.buffer(pt, 500, 'kilometers');
L.geoJson(pt).addTo(map);
L.geoJson(buffered).addTo(map);
演示:http://jsfiddle.net/ve2huzxw/41/
原回答:
不幸的是,目前似乎没有 Leaflet 插件可以这样做。
也不太清楚Tissot indicatrix应该代表什么:
- 表示无限小圆变形(即单点变形)的真椭圆,或
- 一个类似圆形的形状,代表地球表面上有限大小的圆的变形,就像您 link 到的 OpenLayers 演示一样?
在该演示中,EPSG:4326 中的形状不是椭圆,与形状的另一半相比,垂直轴的长度在较高纬度处减小。
如果您正在寻找第二个选项,那么您将不得不手动构建一个多边形来表示球体和地球表面的交点。如果我的理解是正确的,这就是OL demo所做的。如果这是你的选择,也许你可以在那里生成你的多边形并将它们作为 GeoJSON 特征导入 Leaflet? :-)
因为 turf.buffer 目前似乎有一个错误,这里有一个与 turf.js 不同的方法,这次使用 turf.destination 在一定范围内旋转来创建一个真实的圈子:
//creates a true circle from a center point using turf.destination
//arguments are the same as in turf.destination, except using number of steps
//around the circle instead of fixed bearing. Returns a GeoJSON Polygon as output.
function tissotish(center, radius, steps, units) {
var step_angle = 360/steps;
var bearing = -180;
var tissot = { "type": "Polygon",
"coordinates": [[]]
};
for (var i = 0; i < steps + 1; ++i) {
var target = turf.destination(center, radius, bearing, units);
var coords = target.geometry.coordinates;
tissot.coordinates[0].push(coords);
bearing = bearing + step_angle;
}
return tissot;
}
这不会产生真正的 Tissot 指示线(应该测量单个点的失真),但它确实会产生一个真正的圆,从您的其他评论来看,这似乎正是您要找的东西.这是一个例子 fiddle:
http://fiddle.jshell.net/nathansnider/58ud0ttk/
为了比较,我在此处添加了与上面 相同的测量线。 (点线的时候确实说高纬度的水平距离大于500km,但那是因为我画出来的线稍微延伸到圆圈外,懒得裁剪了他们。)
OpenLayers supports tissot's ellipses natively by adding a sphere to the circular() method.
很遗憾 Leaflet L.circle() 不支持此功能。
如何使用 Leaflet 绘制天梭的椭圆?
编辑 3:
使用 leaflet-geodesy 的新命题似乎非常适合您的需要。它免除了 Turf 的错误(请参阅下面的编辑 2)。
API很简单:
LGeo.circle([51.441767, 5.470247], 500000).addTo(map);
(以 [latitude, longitude] 度为单位的中心位置,以米为单位的半径)
演示:http://jsfiddle.net/ve2huzxw/61/
与 nathansnider 的解决方案进行快速比较:http://fiddle.jshell.net/58ud0ttk/2/
(表明两个代码产生相同的结果面积,唯一的区别在于用于近似面积的段数)
编辑:一个很好的页面,将 Leaflet-geodesy 与标准 L.Circle 进行比较:https://www.mapbox.com/mapbox.js/example/v1.0.0/leaflet-geodesy/
编辑 2:
不幸的是 Turf 使用 JSTS Topology Suite 构建缓冲区。貌似JSTS中的这个操作不适合像地球表面这样的非平面几何。
错误已报告 here,截至今天,主要的 Turf 库还没有完整的解决方法。
所以下面的答案(编辑 1)产生了错误的结果。
请参阅
编辑 1:
您可以使用 Turf 轻松构建所描述的多边形。它提供了 turf.buffer
方法,该方法在给定要素(可以是一个简单的点)周围创建具有指定距离的多边形。
所以你可以简单地做例如:
var pt = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [5.470247, 51.441767]
}
};
var buffered = turf.buffer(pt, 500, 'kilometers');
L.geoJson(pt).addTo(map);
L.geoJson(buffered).addTo(map);
演示:http://jsfiddle.net/ve2huzxw/41/
原回答:
不幸的是,目前似乎没有 Leaflet 插件可以这样做。
也不太清楚Tissot indicatrix应该代表什么:
- 表示无限小圆变形(即单点变形)的真椭圆,或
- 一个类似圆形的形状,代表地球表面上有限大小的圆的变形,就像您 link 到的 OpenLayers 演示一样?
在该演示中,EPSG:4326 中的形状不是椭圆,与形状的另一半相比,垂直轴的长度在较高纬度处减小。
如果您正在寻找第二个选项,那么您将不得不手动构建一个多边形来表示球体和地球表面的交点。如果我的理解是正确的,这就是OL demo所做的。如果这是你的选择,也许你可以在那里生成你的多边形并将它们作为 GeoJSON 特征导入 Leaflet? :-)
因为 turf.buffer 目前似乎有一个错误,这里有一个与 turf.js 不同的方法,这次使用 turf.destination 在一定范围内旋转来创建一个真实的圈子:
//creates a true circle from a center point using turf.destination
//arguments are the same as in turf.destination, except using number of steps
//around the circle instead of fixed bearing. Returns a GeoJSON Polygon as output.
function tissotish(center, radius, steps, units) {
var step_angle = 360/steps;
var bearing = -180;
var tissot = { "type": "Polygon",
"coordinates": [[]]
};
for (var i = 0; i < steps + 1; ++i) {
var target = turf.destination(center, radius, bearing, units);
var coords = target.geometry.coordinates;
tissot.coordinates[0].push(coords);
bearing = bearing + step_angle;
}
return tissot;
}
这不会产生真正的 Tissot 指示线(应该测量单个点的失真),但它确实会产生一个真正的圆,从您的其他评论来看,这似乎正是您要找的东西.这是一个例子 fiddle:
http://fiddle.jshell.net/nathansnider/58ud0ttk/
为了比较,我在此处添加了与上面