Friday 12 April 2019

openlayers 2 - Using Geodesic Measurements for Circle Radii?


I am currently developing an OpenLayers mapping site. Measurements can be made using a line tool, and an area tool. Both of these are currently set to calculate geodesic measurements as outlined in the OpenLayers API.


I use geodesic measurements rather than planar measurements as during user testing people questioned the tool's measurements for distances they already knew (such as driving between towns).


A new feature of the site is for a user to be able to draw a circle on the map of a set radius. OpenLayers only allows for drawing circles using planar distances, so when a user measures the circle with the geodesic measurement tool the values do not match. In the image below the circle planar radius is 10km, but the geodesic line measurement for the diameter is 12km.



Clearly this will leave a user (and myself) wondering which is correct.


alt text


Looking at this answer it is seems most desktop GIS systems "ignore" this issue, and return planar measurements and distances. So what is the best practice in terms of user interface and accuracy to deal with planar and geodesic measurements?


Update


I found this Google example which illustrates the issue of radii and the Mercator projection:


http://maps.forum.nu/gm_sensitive_circle2.html


The JavaScript code to draw the circle is as follows:


    var lat1 = (PI/180)* center.lat(); // radians
var lng1 = (PI/180)* center.lng(); // radians


for (var a = 0 ; a < 361 ; a++ ) {
var tc = (PI/180)*a;
var y = asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc));
var dlng = atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(y));
var x = ((lng1-dlng+PI) % (2*PI)) - PI ; // MOD function
var point = new GLatLng(parseFloat(y*(180/PI)),parseFloat(x*(180/PI)));
circlePoints.push(point);
bounds.extend(point);
}


Does this circle take the curvature of the earth into account?


Final Update


Working code posted at http://geographika.co.uk/creating-a-geodesic-circle-in-openlayers



Answer



If you're home-brewing in the browser, you can get a "circle" (it will not be round on the screen due to your projection; rather approximated by a polygon w/ as many points as you care to draw), use a the direct form of geodesic calculations: given a point, a direction (azimuth), and a distance it gives you the resulting point. Gory details: http://en.wikipedia.org/wiki/Vincenty%27s_formulae#Direct_Method


Looks like someone has done a translation to javascript already: http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html. Lucky you!


To finish things off:



  • Decide how chunky (# of vertices, call it n) you are willing to have the end result be.

  • Divide 360 degrees into n pieces.


  • Build a polygon by (for i in range(n): polygon.add(vincenty_direct(start_point, i * 360/n, distance)))

  • After-the-fact, possibly fix up some projection and planarisation irritations:

    • If you're using the typical web map projection, which you almost certainly are, the resulting polygon will be hugely stretched vertically if it nears a pole.

    • Similarly, if the result polygon crosses the international date line, it'll be really borked.




Cheers!


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...