Fix the radius when drawing a circle.

81 Views Asked by At

I found this function and it draws an oval rather than a circle. What do I need to do to fix the calculations to make a circle? Thanks.

enter image description here

Dim seg As Double = Math.PI * 2 / segments
For i As Integer = 0 To segments - 1
  Dim theta As Double = seg * i
  Dim lat As Double = _point.Lat + Math.Cos(theta) * radius
  Dim lng As Double = _point.Lng + Math.Sin(theta) * radius
  points.Add(New PointLatLng(lat, lng))
Next
2

There are 2 best solutions below

1
On BEST ANSWER

You code will work if you are displaying a region near the equator.

Assume the earth is a sphere of radius $R$. If you choose the coordinate system so that

  • The origin is the center of earth.
  • The $x$-axis is pointing at the intersection of equator and the prime meridian (i.e. longitude = $0^\circ$)
  • The $z$-axis is pointing towards north pole.

Then for a point on earth's surface with latitude $\theta$ and longitude $\phi$, the spatial position of the point will be given by

$$(x,y,z) = R(\cos\theta\cos\phi,\cos\theta\sin\phi,\sin\theta)$$

If you work out the distance $\Delta s$ between two nearby points corresponds to latitude/longitude $(\theta,\phi)$ and $(\theta+\Delta\theta,\phi+\Delta\phi)$. You will find

$$\Delta s^2 \approx R^2 ( \Delta \theta^2 + \cos\theta^2 \Delta\phi^2 )$$

What this means is for same amount of small change in longitude and latitude, if you are not on the equator, the 'length' along the longitude direction will be shrinked by a factor $\cos\theta$. To compensate that, you need to expand along the longitude direction by a factor $\frac{1}{\cos\theta}$.

This means your code should become something like

 Dim lng As Double = _point.Lng + Math.Sin(theta) * radius / Math.Cos(_point.Lat*Math.PI/180)

(Note: I'm assuming your longitude is stored in degree).

For example, from the picture you have, you are displaying a region near Laporte, Colorado, US whose latitude is around $40^\circ 37'$N. The corresponding scaling factor is $\cos(40^\circ 37') \approx 0.7591$. That's why a hard coding aspect ratio $0.75$ works around there. The same aspect ratio will not work for other latitudes.

8
On

There are two main ways. The first is to change how you display the data, which is not part of the code you showed. This is almost certainly the best way to handle this problem, but I can't help you much with that.

If you really want to keep the display the same and have your figure look like a circle, choose the appropriate "aspect ratio," a positive real number that give the ratio of the $x$ and $y$ coordinates to show a circle, square, and so on. Let's call that constant "Aspect." In the drawing you gave it looks like Aspect is around $0.75$.

Then change one line in your code to

Dim lng As Double = _point.Lng + Math.Sin(theta) * radius * Aspect