Mapping large circular features
Posted by Opk on 10 August 2010 in English. Last updated on 23 August 2010.I recently looked at improving the very basic map data for the Waldfriedhof in Darmstadt - a large circular cemetery.
When creating a circle using JOSM, you get an octagon. This is fine for roundabouts but for anything larger the wiki tells you to to put a few extra nodes in and then select align nodes in circle. This isn't very precise - start with a 600 metre line, turn it into an octagonal "circle", add another 8 nodes, align in a circle and then measure the diameter. It comes out as about 578 metres. I needed it to be precise because there are paths closely following both sides of the perimeter fence.
So to get a much better circle, I first created an octagon, did a copy and paste to get a second octagon. I placed this exactly over the first octagon and rotated it. Adding lines across the octagon can help with accurate positioning. I then repeated the process again, copying both octagons together to get 32 nodes total. It is then possible to draw a 32 sided "circle" manually through these nodes and delete the four octagons.
At this point, I discovered that the cemetery is actually very slightly egg shaped. This is hard to spot because the lower half tapers into a rectangle. I was about to start on some calculations to work out how much I would need to move each node down by to massage my circle into an egg shape when it occurred to me that it might be easier to simply write a script to draw me the appropriate shape and save it to a .osm file that I could load with josm. This approach also made it easy to accurately map the path along the perimeter.
The script below is a simplified example for drawing an ellipse. A few constants define the size and position of the ellipse and the number of nodes (use a multiple of 4). The calculations look a bit complicated but basically it just uses cos and sin to get the position in metres from the angle (in radians) and then converts metres to latitude/longitude degrees. This is more complicated for the longitude because it depends on the latitude.
#!/bin/zsh
zmodload zsh/mathfunc
typeset -F midlat midlon angle metre
steps=32
width=588
height=590
midlon=8.61193
midlat=49.87309
(( circum = 40041455 ))
(( latmetre = 360.0/circum ))
node=0
for step in {1..$steps}; do
(( angle=(step-1) * 8*atan(1) / steps ))
lat[$step]=$(( midlat+latmetre*height*cos(angle)/2 ))
lon[$step]=$(( midlon+latmetre/cos(atan(1)*lat[$step]/45)*width*sin(angle)/2 ))
done
cat - <
echo " <way id='$((--node))' action='modify' visible='true'>"
for step in {1..$steps} 1; do
echo " <nd ref='$((-step))'/>"
done
cat - <<END
</way>
</osm>
END
I'm inclined to extend this approach to create something more general that can be used for things like mapping buildings based on measurements.
Discussion
Comment from Sundance on 10 August 2010 at 18:35
The Potlatch algoritm does a certain number of default nodes for a circle, you can add more nodes and will smooth the circle out a bit more. Of course your's is somewhat eggshaped so Potlatch wouldn't exactly fit your problme.