How to draw Tissot's ellipse (Tissot's ind

2019-03-04 06:11发布

OpenLayers supports tissot's ellipses natively by adding a sphere to the circular() method.

Unfortunately the Leaflet L.circle() does not support such feature.

How do I draw tissot's ellipses with Leaflet?

2条回答
可以哭但决不认输i
2楼-- · 2019-03-04 06:53

EDIT 3:

New proposition using leaflet-geodesy which seems a perfect fit for your need. It is exempt from Turf's bug (see Edit 2 below).

The API is quite simple:

LGeo.circle([51.441767, 5.470247], 500000).addTo(map);

(center position in [latitude, longitude] degrees, radius in meters)

Demo: http://jsfiddle.net/ve2huzxw/61/

Quick comparison with nathansnider's solution: http://fiddle.jshell.net/58ud0ttk/2/

(shows that both codes produce the same resulting area, the only difference being in the number of segments used for approximating the area)

EDIT: a nice page that compares Leaflet-geodesy with the standard L.Circle: https://www.mapbox.com/mapbox.js/example/v1.0.0/leaflet-geodesy/


EDIT 2:

Unfortunately Turf uses JSTS Topology Suite to build the buffer. It looks like this operation in JSTS does not fit a non-plane geometry like the Earth surface.

The bug is reported here and as of today the main Turf library does not have a full workaround.

So the below answer (edit 1) produces WRONG results.

See nathansnider's answer for a workaround for building a buffer around a point.


EDIT 1:

You can easily build the described polygon by using Turf. It offers the turf.buffer method which creates a polygon with a specified distance around a given feature (could be a simple point).

So you can simply do for example:

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

Demo: http://jsfiddle.net/ve2huzxw/41/


Original answer:

Unfortunately it seems that there is currently no Leaflet plugin to do so.

It is also unclear what the Tissot indicatrix should represent:

  1. A true ellipse that represents the deformation of an infinitely small circle (i.e. distortion at a single point), or
  2. A circular-like shape that represents the deformation of a finite-size circle when on the Earth surface, like the OpenLayers demo you link to?

In that demo, the shape in EPSG:4326 is not an ellipse, the length in the vertical axis decreases at higher latitude compared to the other half of the shape.

If you are looking for that 2nd option, then you would have to manually build a polygon that represents the intersection of a sphere and of the Earth surface. If my understanding is correct, this is what the OL demo does. If that is an option for you, maybe you can generate your polygons there and import them as GeoJSON features into Leaflet? :-)

查看更多
在下西门庆
3楼-- · 2019-03-04 06:58

Because turf.buffer appears to have a bug at the moment, here is a different approach with turf.js, this time using turf.destination rotated over a range of bearings to create a true circle:

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

This doesn't produce a true Tissot's indicatrix (which is supposed to measure distortion at a single point), but it does produce a true circle, which from your other comments seems to be what you're looking for anyway. Here it is at work in an example fiddle:

http://fiddle.jshell.net/nathansnider/58ud0ttk/

For comparison, I added the same measurement lines here as I applied to ghybs's answer above. (When you click on the lines, they do say that the horizontal distance is greater than 500km at higher latitudes, but that is because, the way I created them, they end up extending slightly outside the circle, and I was too lazy to crop them.)

查看更多
登录 后发表回答