Inputting/Drawing Circles in Virtual Earth
Link: http://totusterra.com/VESamples/InputtingACircle.htm
One notable gap in Virtual Earth's set of tools is the ability to draw circles. Points, lines, polygons -- they have those covered, but circles remain on the 'to do' list. That might seem odd - given that VE uses SVG to render the shapes, and SVG supports circles - but remember that we're not dealing with a flat surface here, and circles can end up being distinctly ellipsish after projection. So just exposing 'circle' as an SVG shape type wouldn't really solve the problem.
A reasonable work-around is to treat circles like a polygon, with points along the circumference calculated individually. This way any weirdness in shape is automatically calculated and accounted for. Today, then, I'm going to step through the logic behind it and build a fun little demo that not just draws a circle, but lets you use a 'click and drag' to interactively create one on the map. With SQL Server 2008 offering spatial queries, I can see this becoming a popular way of interacting with data.

So, let's get started.
Follow up:
Calculating a new latitude & longitude given a starting position, a direction, and a distance:
In order to find points along the circumference of the circle, we need a way to calculate them. Luckily, there's a relatively easy function to calculate a new point given a starting point and a vector away from it.

Ok, maybe it doesn't look that easy, but it turns into javascript pretty easily. We're going to use Virtual Earth's VELatLong class to manage latitude & longitude, and then given R is the radius of the earth, d is the distance you are interested in, and θ (theta) is the direction from the starting point, we get some javascript that looks like this:
function FindDestinationByStartAndVector( startPoint, direction, distance )
{
// Convert lat & lng from degrees into radians
var lat1 = startPoint.Latitude / 180 * Math.PI;
var lng1 = startPoint.Longitude / 180 * Math.PI;
direction = direction / 180 * Math.PI;
var angDist = distance/3963.21; // 3963.21 = radius of earth in miles
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(angDist) +
Math.cos(lat1)*Math.sin(angDist)*Math.cos(direction) );
var lng2 = lng1 + Math.atan2(Math.sin(direction)*Math.sin(angDist)*Math.cos(lat1),
Math.cos(angDist)-Math.sin(lat1)*Math.sin(lat2));
// Convert the new position back into degrees and create a LatLong
var destPoint = new VELatLong( lat2 / Math.PI * 180, lng2 / Math.PI * 180 );
return destPoint;
}
Notice that we used the radius of the earth in miles, but you wanted to work in kilometers, just use 6,378.135. Just make sure that whatever unit you use here, you use the same units when passing in the distance.
Drawing a Circle:
I just showed how to find a point on the circumference of a circle – and since a circle is, pretty much by definition, just a set of those points, we’re really very close to being able to draw a circle on a map. Let’s take it in two steps.
First, we need to generate a set of points on the circumference. In order to make everything look nice and easy, we want those points to be evenly spaced. The code below will just go in a loop, dividing a circle up into evenly sized chunks, and will create an array of the points necessary:
function GetCirclePoints( center, radius, numPoints )
{
var points = new Array();
for (var theta = 0; theta < 360; theta += 360/numPoints)
{
points.push( FindDestinationByStartAndVector(center, theta, radius) );
}
return points;
}
And once we have the points, we simply create a polygon with those points. I’m going to enclose that in a function that wraps everything up nicely for us – you’ll see why in the next section.
function CreateCircle( center, distance, points )
{
return new VEShape( VEShapeType.Polygon, GetCirclePoints(center, distance, points) );
}
Because it is just a VEShape, you can set colors, transparencies, events, etc., just like you would with any point, line or polygon in Virtual Earth. For example:
var circle = CreateCircle(map.GetCenter(), 250, 60);
circle.HideIcon();
circle.SetFillColor(new VEColor(128, 16, 16, 0.5));
circle.SetLineColor(new VEColor(255, 0, 0, 0.3));
map.AddShape(circle);
And the results look like this:

Of course, the fewer points you use, the less it will look like a perfect circle, especially as it gets larger, but the more points you use the more complex the shape VE has to render. In my demo, I am trading off at 40 points which looks reasonable at most sizes, but does definitely end up looking chunky on really large circles.
Creating/Inputting a Circle:
Following up on a previous blog entry on how to input/create a polygon in Virtual Earth, I’m going to expand on what we’ve just done by showing how to create a circle by clicking on the map.
We’ll start the same way, by right-clicking on the map to set a start point – or in this case a center point. Then as the use moves the mouse, we’ll track where it is, find the distance from the current location to the center, and then draw a circle at that distance. When the user clicks, the drawing ends, and we ‘fix’ the circle in place.
So we’re going to need a little bit more math here. Often I turn to my old friend Haversine when I’m doing these calculations, but it’s more complex than (and not much more precise than) the Spherical Law of Cosines:

It turns pretty easily into javascript:
function DistanceBetweenPoints( point1, point2 )
{
var R = 3963.21; // Radius of the earth in miles
// Convert lat/long from degrees to radians
var lat1 = point1.Latitude / 180 * Math.PI;
var lng1 = point1.Longitude / 180 * Math.PI;
var lat2 = point2.Latitude / 180 * Math.PI;
var lng2 = point2.Longitude / 180 * Math.PI;
// Calculate the distance between the points
return R * Math.acos( Math.sin(lat1)*Math.sin(lat2) +
Math.cos(lat1)*Math.cos(lat2)*Math.cos(lng2-lng1));
}
With this we can jump in and start working with the mouse handlers, and it’ll come together fast. I am not actually going to go into all the details here because it follows very closely what I did in the polygon-related entry from a week or so ago, and because it's all there in the source code.
So there you go. Mind-numbing detail about circles in Virtual Earth, I hope it comes in handy!
10/08/08 12:10:49 am,