Reputation: 5964
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));
}
Upvotes: 9
Views: 668
Reputation: 3788
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.
Upvotes: 3