I am currently implementing the ve api in such a way that we are plotting points on a map and drawing a circle (polygon) around that point on a map based on a provided radius. The point in question is in the Fiji Islands which would be on the rightmost part of the map (approx. Lat: -16.694078, Lon: 179.835205). The radius of the circle is large and there are points which lie outside the map boundaries. The circle gets plotted correctly which would be on both sides of the map. However, there are lines between the top and the bottom of each circle part and the outside of the circle is shaded in. I can't include an image in the post, so i have included a link here (yahoo for lack of a better place to put them): http://new.photos.yahoo.com/dad26087/album/576460762387851094.

Most of my problem comes from the circle points code not being commented. I still have yet to find good comments on this code. I will however post a solution if i do figure it out in the mean time.

Here is a fully reproducable html example:

<html>

<head>

<script language="javascript" src="http://dev.virtualearth.net/mapcontrol/v4/mapcontrol.js"></script>

<script language="javascript">

var map = null;

function onBodyLoad()

{

/**************************************/

/*Firefox Issue*/

var ffv = 0;

var ffn = "Firefox/"

var ffp = navigator.userAgent.indexOf(ffn);

if (ffp != -1) ffv = parseFloat( navigator.userAgent.substring(ffp + ffn.length));

// If we're using Firefox 1.5 or above override

// the Virtual Earth drawing functions to use SVG

if (ffv >= 1.5)

{

Msn.Drawing.Graphic.CreateGraphic=function(f,b){ return new Msn.Drawing.SVGGraphic(f,b) }

}

/**************************************/

map = new VEMap("MyMapDiv");

map.LoadMap(new VELatLong(20, 0), 2 , 'r', false, VEMapMode.Mode2D, true);

var points = GetCirclePoints( -16.694078, 179.835205, 2000);

map.AddPolygon(GetFilledPolygon(points));

map.SetMapView(points);

}

//generates 360 points so a approx circle

//can be drawn around a latitude and longitude

function GetCirclePoints(latin, lonin, radius)

{

var locs = new Array();

var lat1 = latin * Math.PI/180.0;

var lon1 = lonin * Math.PI/180.0;

var d = radius/3956;

var x;

for (x = 0; x <= 360; x++)

{

var tc = (x / 90)* Math.PI / 2;

var lat = Math.asin(Math.sin(lat1) * Math.cos(d) + Math.cos(lat1) * Math.sin(d) * Math.cos(tc));

lat = 180.0 * lat / Math.PI;

var lon;

if (Math.cos(lat1)==0)

{

lon=lonin; // endpoint a pole

}

else

{

lon = ((lon1 - Math.asin(Math.sin(tc) * Math.sin(d)/Math.cos(lat1)) + Math.PI) % (2 * Math.PI)) - Math.PI;

}

lon = 180.0 * lon / Math.PI;

var loc = new VELatLong(lat,lon);

locs.push(loc);

}

return locs;

}

var polygonID = 0;

//generates a filled in polygon based

//on passed in points

function GetFilledPolygon(points)

{

var poly = new VEPolygon(polygonID, points);

polygonID++;

poly.SetOutlineWidth(1);

poly.SetOutlineColor(new VEColor(0,150,100,1.0));

poly.SetFillColor(new VEColor(0,150,100,0.5));

return poly;

}

</script>

</head>

<body onload="onBodyLoad();">

<div id="MyMapDiv" style="width: 500px; height:500px;"></div>

</body>

</html>

dad26087

This is my post above. Forgot to finish my thought. Does anyone have any ideas about how to fix this Any help would be appreciated. Thanks.

This is my post above. Forgot to finish my thought. Does anyone have any ideas about how to fix this Any help would be appreciated. Thanks.

Derek Chan

I think you need an algorithm which factors in curvature of the earth.

I think you need an algorithm which factors in curvature of the earth.

Ruprect8696

I was the one who wrote the code to draw the circle and it is commentless because for the most part I have no idea what it is doing. I "borrowed" an algorithm for determining the a latitude and longitude based on a starting point and distance in miles and adapted it to plot 360 points. Some of it has to do with translating degrees to radians.

That being said it looks like that part of the code is working correctly. The problem appears to be with the VEAPI function that fills in a polyline. I'm not sure how it decides what side of a polyline to fill in but it looks to be guessing wrong.

I was the one who wrote the code to draw the circle and it is commentless because for the most part I have no idea what it is doing. I "borrowed" an algorithm for determining the a latitude and longitude based on a starting point and distance in miles and adapted it to plot 360 points. Some of it has to do with translating degrees to radians.

That being said it looks like that part of the code is working correctly. The problem appears to be with the VEAPI function that fills in a polyline. I'm not sure how it decides what side of a polyline to fill in but it looks to be guessing wrong.

Ruprect8696

I think it does that. Although from what I understand it is only accurate up to a certain range. It works good for my purposes so I haven't done any additional research into it.

Derek Chan wrote:

I think you need an algorithm which factors in curvature of the earth.

I think it does that. Although from what I understand it is only accurate up to a certain range. It works good for my purposes so I haven't done any additional research into it.

Derek Chan

no I think it has to do with the points. If you change the fill color lets say to black you'll notice that its the actual plotted points that are causing that huge line. Code attached below:

<html>

<head>

<script language="javascript" src="http://dev.virtualearth.net/mapcontrol/v4/mapcontrol.js"></script>

<script language="javascript">

var map = null;

function onBodyLoad()

{

/**************************************/

/*Firefox Issue*/

var ffv = 0;

var ffn = "Firefox/"

var ffp = navigator.userAgent.indexOf(ffn);

if (ffp != -1) ffv = parseFloat( navigator.userAgent.substring(ffp + ffn.length));

// If we're using Firefox 1.5 or above override

// the Virtual Earth drawing functions to use SVG

if (ffv >= 1.5)

{

Msn.Drawing.Graphic.CreateGraphic=function(f,b){ return new Msn.Drawing.SVGGraphic(f,b) }

}

/**************************************/

map = new VEMap("MyMapDiv");

map.LoadMap(new VELatLong(20, 0), 2 , 'r', false, VEMapMode.Mode2D, true);

var points = GetCirclePoints( -16.694078, 179.835205, 2000);

map.AddPolygon(GetFilledPolygon(points));

map.SetMapView(points);

}

//generates 360 points so a approx circle

//can be drawn around a latitude and longitude

function GetCirclePoints(latin, lonin, radius)

{

var locs = new Array();

var lat1 = latin * Math.PI/180.0;

var lon1 = lonin * Math.PI/180.0;

var d = radius/3956;

var x;

for (x = 0; x <= 360; x++)

{

var tc = (x / 90)* Math.PI / 2;

var lat = Math.asin(Math.sin(lat1) * Math.cos(d) + Math.cos(lat1) * Math.sin(d) * Math.cos(tc));

lat = 180.0 * lat / Math.PI;

var lon;

if (Math.cos(lat1)==0)

{

lon=lonin; // endpoint a pole

}

else

{

lon = ((lon1 - Math.asin(Math.sin(tc) * Math.sin(d)/Math.cos(lat1)) + Math.PI) % (2 * Math.PI)) - Math.PI;

}

lon = 180.0 * lon / Math.PI;

var loc = new VELatLong(lat,lon);

locs.push(loc);

}

return locs;

}

var polygonID = 0;

//generates a filled in polygon based

//on passed in points

function GetFilledPolygon(points)

{

var poly = new VEPolygon(polygonID, points);

polygonID++;

//poly.SetOutlineWidth(1);

//poly.SetOutlineColor(new VEColor(0,150,100,1.0));

poly.SetFillColor(new VEColor(0,0,0,0.5));

return poly;

}

</script>

</head>

<body onload="onBodyLoad();">

<div id="MyMapDiv" style="width: 500px; height:500px;"></div>

</body>

</html>

Ruprect8696

But doesn't the problem have more to do with the map.

The algorithm just produces lats and longs to plot as the border of the polygon. The fact that it "wraps" around the edges of the map is what causes the fill to be incorrect. The line is drawn in the order it is added so when it gets to the edge of the map the next point is all the way across the other side. To render it correctly you would have to create 2 polygons that each stop at the end of the map.

But doesn't the problem have more to do with the map.

The algorithm just produces lats and longs to plot as the border of the polygon. The fact that it "wraps" around the edges of the map is what causes the fill to be incorrect. The line is drawn in the order it is added so when it gets to the edge of the map the next point is all the way across the other side. To render it correctly you would have to create 2 polygons that each stop at the end of the map.

dad26087

Yes, this code works correctly if the circle points are within the map boundaries. So what I am looking for is to somehow separate out the points that lie outside the map boundaries, and draw two separate polygons. Ruprect, where did you find that algorithm Any info would be appreciated.

Yes, this code works correctly if the circle points are within the map boundaries. So what I am looking for is to somehow separate out the points that lie outside the map boundaries, and draw two separate polygons. Ruprect, where did you find that algorithm Any info would be appreciated.

Ruprect8696

I don't have the algorithm anymore so I can't help you there. John (SoulSolutions) has fixed the circle accuracy beyond 200km issue. See the other post about drawing a circle efficiency for the link.

If you know the boundries of the map (lats and longs) which should be easy to figure out you can modify the algorithm to draw separate polylines based on their lat and long.

Basically have 2 arrays of VELatLong objects and use the lat/longs to determine which array to add it to.

I don't have the algorithm anymore so I can't help you there. John (SoulSolutions) has fixed the circle accuracy beyond 200km issue. See the other post about drawing a circle efficiency for the link.

If you know the boundries of the map (lats and longs) which should be easy to figure out you can modify the algorithm to draw separate polylines based on their lat and long.

Basically have 2 arrays of VELatLong objects and use the lat/longs to determine which array to add it to.

SoulSolutions

Wow, thats a pretty cool effect!

I would upgrade to the more accurate version here:

http://viavirtualearth.com/wiki/Draw+a+filled+Circle.ashx

What i need you to do is build in some bounds logic specifically for VE so if the circle goes past -180 or 180 it splits it into two circles to be drawn, i would actually put a slight tolerance on it so it would draw at 179.9995 or something.

Feel free to update the wiki, that is what it is for.

John.

dad26087

Alright, so I came up with a hack around this problem and I posted to the Wiki. Here is the http://viavirtualearth.com/wiki/Map+Boundary+Problem.ashx

There are some issues with this algorithm, but it works for my purposes. Any improvements to this, please let me know. Thanks.

Alright, so I came up with a hack around this problem and I posted to the Wiki. Here is the http://viavirtualearth.com/wiki/Map+Boundary+Problem.ashx

There are some issues with this algorithm, but it works for my purposes. Any improvements to this, please let me know. Thanks.

SoulSolutions

Very good!

I just updated a few typos that were stopping the example code from working.

The only improvement i see is to force a 89.9995 and 0.0005 points so that the circle appears in 3D mode to close, currently there is a big gap due to the points being some random amount less then this.

John.