How to draw a circle with Bing Maps Ajax Control 6.3? - javascript

I've been searching for a solution for this and haven't been successful, what I want to do is that by specifying a radius and a center, to draw a circle on a map. The documentation for Bing Maps Ajax Control 6.3 for shapes doesn't cover circles. Is there a way to draw circles on a map?
Any help would be appreciated.

You should check Mike Garza's blog (Garzilla) that created really interesting examples around your needs: http://www.garzilla.net/vemaps/CircleDragHandle.aspx
Here is a sample code to generate the circle locations:
function buildCircle(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+=10) {
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;
}
And here the code to add it on the map and use the previous method:
//Build circle
circle = new VEShape(VEShapeType.Polygon, circlePoints);
circle.HideIcon();
circle.SetLineWidth(2);
map.AddShape(circle);

Related

Calculate driving distance between two points

I want to measure the distance by road between two places provided the latitude and longitude of the places.
My JavaScript/Java based custom application is going to be used by offline users.
I think Google map API can't be used in this case. I need free service. arcgis provide this facility??
Any help or guide will be appreciated..
I think this will work for you assuming you have the latitude and longitude for both points:
var rad = function(x) {
return x * Math.PI / 180;
};
var getDistance = function(p1, p2) {
var R = 6371; // Earth’s mean radius in meter
var dLat = rad(p2.lat() - p1.lat());
var dLong = rad(p2.lng() - p1.lng());
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) *
Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return parseInt(d); // returns the distance in km
};

I cannot get the same accuracy as Google maps when it comes to distance?

I am developing an app which calculate the distance between 2 points. I cannot use the Google Maps API.
I have found the coordinates for each of the markers in the map below.
I am then using the haversine formula to calculate the distance between each points.
e.g. 1 -> 2, 2 -> 3, 3 -> 4... etc up to the final point.
I add up these distances to retrieve the total distance for the route.
The problem is Google maps says it is 950-1000 meters, but my app says the length is 1150-1200 meters. I have tried adding in more coordinates, removing coordinates, but I am still getting approximately 200 meters longer route.
Out of curiosity I calculated the distance between the start and end point (the 2 green stars) and this matched the Google Maps distance (998 metres to be exact).
Does this mean Google Maps calculates its distances without the consideration of roads / paths etc.
Here is my code:
var coordinates = [
[1,51.465097,-3.170893,1,0],
[2,51.465526,-3.170714,0,0],
[3,51.465853,-3.170526,0,0],
[4,51.466168,-3.170338,0,0],
[5,51.466305,-3.170236,0,0],
[6,51.466534,-3.170157,0,0],
[7,51.466798,-3.170159,0,0],
[8,51.467042,-3.170232,0,0],
[9,51.467506,-3.170580,0,0],
[10,51.468076,-3.171532,0,0],
[11,51.468863,-3.172170,0,0],
[12,51.469284,-3.172841,0,0],
[13,51.469910,-3.174732,0,0],
[14,51.470037,-3.174930,0,0],
[15,51.470350,-3.175091,0,0],
[16,51.472447,-3.176151,1,0]
];
function distanceBetweenCoordinates() //calculates the distance between each of the coordinates
{
for (var i=0; i<coordinates.length-1; i++)
{
var firstClosestPoint = [0,0,6371];
var secondClosestPoint = [0,0,6371];
var lng1 = (coordinates[i][1]);
var lat1 = (coordinates[i][2]);
var lng2 = (coordinates[i+1][2]);
var lat2 = (coordinates[i+1][2]);
var d = haversine(lat1, lng1, lat2, lng2);
routeLength = routeLength + d;
}
return distanceBetweenCoordinatesArray; //returns the array which stores the 2 points and the distance between the 2 points
}
EDIT
Here is my haversine forumla to calculate the distance between 2 points:
Source: here
Number.prototype.toRad = function() //to rad function which is used by the haversine formula
{
return this * Math.PI / 180;
}
function haversine(lat1, lng1, lat2, lng2) { //haversine foruma which is used to calculate the distance between 2 coordinates
lon1 = lng1;
lon2 = lng2;
var R = 6371000; // metres
var a = lat1.toRad();
var b = lat2.toRad();
var c = (lat2-lat1).toRad();
var d = (lon2-lon1).toRad();
var a = Math.sin(c/2) * Math.sin(c/2) +
Math.cos(a) * Math.cos(b) *
Math.sin(d/2) * Math.sin(d/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
If I have correctly entered your start and end points, this implementation of the haversine formula (which I have tested in the real world) produces a distance of 895m (straight line).
var lt = 51.472447;
var lt1 = 51.465097;
var ln = -3.176151;
var ln1 = -3.170893;
var dLat = (lt - lt1) * Math.PI / 180;
var dLon = (ln - ln1) * Math.PI / 180;
var a = 0.5 - Math.cos(dLat) / 2 + Math.cos(lt1 * Math.PI / 180) * Math.cos(lt * Math.PI / 180) * (1 - Math.cos(dLon)) / 2;
d = Math.round(6371000 * 2 * Math.asin(Math.sqrt(a)));
$('#distance').html(d);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="distance"></div>

Variables impossibly set as "undefined"

This is very odd behavior (which appears only to happen on Chrome on a Mac) where much of the code appears to be skipped entirely and variables that should have values are set as "undefined".
Here is a screenshot from Chrome's developer tools. Note that line 817 was never hit! However 833 was hit and what we are looking at is an exception that was hit and I looked up the call stack to find this mess. Also note that the variables "loc", "lon" and "tc" are all undefined, which should not be possible as they have each have been evaluated on lines 822, 823/824, and 827/831. If there was an error in the calculations the values of these variables should be NaN from my understanding.
Here is the actual code:
function getCircle2(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;
}
Can anyone shine some light on this wizardry? Why would a breakpoint be ignored and variables have incorrect values only in Chrome on a Mac!?
EDIT:
It appears that I have fixed the bug. All I did was isolate the breaking code in its own function, call the function once, if it threw an exception I called it again and it seems to work 100% of the time. I am still very curious at what was the root cause of the issue.
//new function to isolate the exception
function getCirclePointOnRadius(deg, lat1, lon1, d, attempt) {
attempt = attempt || 1;
var maxAttempts = 2;
try {
var tc = (deg / 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);
return loc;
}
catch (e) {
console.log2('Error when gathering circle point "' + e + '", trying again', deg, lat1, lon1);
if (attempt < maxAttempts) {
return getCirclePointOnRadius(deg, lat1, lon1, ++attempt);
}
else {
return 0;
}
}
}
And then I replace the loop that originally held the logic (in getCircle2) with:
for (x = 0; x <= 360; x++) {
locs.push(getCirclePointOnRadius(x, lat1, lon1, d));
}
It looks like you might be a victim of variable hoisting http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
Line 833 is probably being hoisted as its a variable name declaration within the function scope. Refactoring your variable declarations may fix the problem.

Circle radius on Lat/Lng map

I am trying to draw a circle on a CloudMade map. The center of the circle is expressed in Lat/Lng, while the radius is in meters. Here following is the JavaScript I use, but some tests seem to indictae that the conversion I'm using for the radius gives me a too short radius. Does somebody understand what I', doing wrong?
function DrawCircle (center, radius)
{
var circlePoints = Array();
with (Math)
{
var d = radius/6371000; // radians
var lat1 = (PI/180) * center.lat(); // radians
var lng1 = (PI/180) * center.lng(); // radians
for (var a = 0; a <= 360; 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 CM.LatLng(parseFloat(y * (180/PI)), parseFloat(x * (180/PI)));
circlePoints.push(point);
}
circle = new CM.Polygon(circlePoints, circleBorderColor, circleBorderWidth, circleBorderOpacity, circleFillColor, circleFillOpacity);
map.addOverlay(circle);
}
}

Get Degrees (0-360) from One LatLng to Another in JavaScript

Can someone help me fill in the blanks with native JavaScript?
function getHeading(lat1, lon1, lat2, lon2) {
// Do cool things with math here
return heading; // Should be a number between 0 and 360
}
I've been messing around with this for a long time and can't seem to get my code to work right.
There is a very good JavaScript implementation by Chris Veness at Calculate distance, bearing and more between Latitude/Longitude points under the Bearings heading.
You may prefer augmenting Google's LatLng prototype with a getHeading method, as follows (using the v3 API):
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
Number.prototype.toDeg = function() {
return this * 180 / Math.PI;
}
google.maps.LatLng.prototype.getHeading = function(point) {
var lat1 = this.lat().toRad(), lat2 = point.lat().toRad();
var dLon = (point.lng() - this.lng()).toRad();
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
var brng = Math.atan2(y, x);
return ((brng.toDeg() + 360) % 360);
}
Which then can be used like this:
var pointA = new google.maps.LatLng(40.70, -74.00);
var pointB = new google.maps.LatLng(40.70, -75.00);
pointA.getHeading(pointB); // Returns 270 degrees
Otherwise if you prefer a global function instead of augmenting Google's LatLng, you can do it as follows:
function getHeading(lat1, lon1, lat2, lon2) {
var lat1 = lat1 * Math.PI / 180;
var lat2 = lat2 * Math.PI / 180;
var dLon = (lon2 - lon1) * Math.PI / 180;
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
var brng = Math.atan2(y, x);
return (((brng * 180 / Math.PI) + 360) % 360);
}
Usage:
getHeading(40.70, -74.00, 40.70, -75.00); // Returns 270 degrees

Categories