var CIRCLE_RADIUS = 0.75, REAR_ARROW_WIDTH = 0.18,
FRONT_ARROW_WIDTH = 0.15, BEARING_ARROW_WIDTH = 0.08,
BEARING_ARROW_LENGTH = 0.65, LETTER_SIZE = 0.1,
LETTER_RADIUS = 0.88, global_angle = 200, COOKIE = "ressie_angle",
spin_initialized = 0, dragging = 0, start_drag_angle = 0, old_global_angle = 0,
WIND_STEPS = 20, WIND_TIME = 1,
wind_start = 0, wind_end = 0, wind_step = 0, wind_timer = null,
last_angle = null, cache_ctx = null, cache_canvas = null, minWidthHeight = 1, current_angle = null;
function getContext() {
if (cache_ctx) {
return cache_ctx;
}
if (!cache_canvas) {
cache_canvas = document.getElementById("compass");
if (typeof G_vmlCanvasManager != "undefined") {
cache_canvas = G_vmlCanvasManager.initElement(cache_canvas);
}
minWidthHeight = Math.min(cache_canvas.width, cache_canvas.height);
}
if (cache_canvas) {
cache_ctx = cache_canvas.getContext("2d");
}
return cache_ctx;
}
function svgPathMap(svg_path, move_fun, line_fun, curve_fun, close_fun) {
var i = 0;
while (i < svg_path.length) {
if (svg_path[i] == "M") {
var move_xy = svg_path[i+1].split(",");
move_fun(move_xy[0], move_xy[1]);
i = i + 2;
} else if (svg_path[i] == "L") {
var line_xy = svg_path[i+1].split(",");
line_fun(line_xy[0], line_xy[1]);
i = i + 2;
} else if (svg_path[i] == "C") {
var xy1 = svg_path[i+1].split(","), xy2 = svg_path[i+2].split(","), xy3 = svg_path[i+3].split(",");
curve_fun(xy1[0], xy1[1], xy2[0], xy2[1], xy3[0], xy3[1]);
i = i + 4;
} else if (svg_path[i] == "z") {
close_fun();
i++;
} else {
alert("Unknown path element: " + svg_path[i]);
}
}
}
function drawPath(svg_path, ctx, fill, scale) {
if (fill) {
ctx.beginPath();
svgPathMap(svg_path, function(x, y) {ctx.moveTo(x*scale, y*scale);},
function(x, y) {ctx.lineTo(x*scale, y*scale);},
function(x1, y1, x2, y2, x, y) {ctx.bezierCurveTo(x1*scale, y1*scale, x2*scale,
y2*scale, x*scale, y*scale);},
function() {ctx.fill();});
} else {
ctx.beginPath();
svgPathMap(svg_path, function(x, y) {ctx.moveTo(x*scale, y*scale);},
function(x, y) {ctx.lineTo(x*scale, y*scale);},
function(x1, y1, x2, y2, x, y) {ctx.bezierCurveTo(x1*scale, y1*scale, x2*scale,
y2*scale, x*scale, y*scale);},
function() {ctx.stroke();});
}
}
function drawCompass(ctx, scale) {
// draw a compass, centred at (0, 0), bounded by (-scale, -scale), (scale, scale)
ctx.save();
// draw background semi transparent filled circle
//ctx.lineWidth = 0.75;
ctx.strokeStyle = "rgb(136,136,136)";
ctx.fillStyle="rgba(255,255,255,0.5)";
ctx.beginPath();
ctx.arc(0, 0, CIRCLE_RADIUS * scale, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, CIRCLE_RADIUS * scale, 0, Math.PI * 2, true);
ctx.closePath();
ctx.stroke();
// draw background N, S, E, W arrows in blue
var QUART = Math.sqrt(2)/2 * CIRCLE_RADIUS,
SVG_BACK_ARROWS = ("M 0,-" + REAR_ARROW_WIDTH + " L " + QUART + ",-" + QUART +
" L " + REAR_ARROW_WIDTH + ",0 L " + QUART + "," + QUART +
" L 0," + REAR_ARROW_WIDTH + " L -" + QUART + "," + QUART +
" L -" + REAR_ARROW_WIDTH + ",0 L -" + QUART + ",-" + QUART +
" L 0,-" + REAR_ARROW_WIDTH + " z").split(" ");
ctx.fillStyle = "rgb(0, 0, 255)";
drawPath(SVG_BACK_ARROWS, ctx, 1, scale);
drawPath(SVG_BACK_ARROWS, ctx, 0, scale);
var FRONT_45 = QUART * FRONT_ARROW_WIDTH * scale;
for (var i = 0; i < 2; i++) {
ctx.save();
for(var j=0; j<4; j++) {
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(FRONT_45, -FRONT_45);
ctx.lineTo(0, -scale);
ctx.lineTo(0, 0);
ctx.closePath();
if (i === 0) {
ctx.fillStyle = "rgb(255,0,0)";
ctx.fill();
} else {
ctx.stroke();
}
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(-FRONT_45, -FRONT_45);
ctx.lineTo(0, -scale);
ctx.lineTo(0, 0);
ctx.closePath();
if (i === 0) {
ctx.fillStyle = "rgb(255,255,255)";
ctx.fill();
} else {
ctx.stroke();
}
ctx.rotate(Math.PI / 2);
}
ctx.restore();
}
var NORTH_PATH = ("M -" + (LETTER_SIZE / 1.4) + ",-" + (LETTER_RADIUS - LETTER_SIZE) +
" L -" + (LETTER_SIZE / 1.4) + ",-" + (LETTER_RADIUS + LETTER_SIZE) +
" L " + (LETTER_SIZE / 1.4) + ",-" + (LETTER_RADIUS - LETTER_SIZE) +
" L " + (LETTER_SIZE / 1.4) + ",-" + (LETTER_RADIUS + LETTER_SIZE) +
" z").split(" ");
ctx.lineWidth = 3.0;
ctx.lineJoin = 'round';
ctx.strokeStyle = "rgba(255,255,255,0.9)";
drawPath(NORTH_PATH, ctx, 0, scale);
ctx.lineWidth = 1.0;
ctx.strokeStyle = "rgb(0,0,0)";
drawPath(NORTH_PATH, ctx, 0, scale);
ctx.restore();
}
function drawArrow(ctx, scale) {
ctx.save();
var ARROW_PATH = ("M -0.05,-0.15 L 0.05,-0.15 L 0.05,0.25 L 0.1,0.25 " +
"L 0,0.4 L -0.1,0.25 L -0.05,0.25 L -0.05,-0.15 z").split(" ");
ctx.lineWidth = 1.0;
ctx.strokeStyle = "rgb(0,0,0)";
ctx.fillStyle = "rgb(238, 238, 0)";
ctx.lineJoin = "round";
drawPath(ARROW_PATH, ctx, 1, scale);
drawPath(ARROW_PATH, ctx, 0, scale);
ctx.restore();
}
function drawRessie(ctx, scale) {
var SVG_PATH=("M 242.14286,620.93361 C 242.14286,620.93361 307.14286,540.93361 318.57143,526.6479 "+
"C 330,512.36218 309.28571,498.07647 309.28571,498.07647 C 309.28571,498.07647 291.19688,481.65613 287.85714,477.36218 "+
"C 282.85715,470.93361 290.78801,462.50108 298.57143,463.79075 C 310.72728,465.80491 334.28571,463.79075 347.85714,456.6479 "+
"C 361.42857,449.50504 360.71429,440.21933 370,435.21933 C 379.28571,430.21933 390,425.93361 407.14286,423.07647 "+
"C 424.05247,420.2582 430.71429,413.07647 437.14286,409.50504 C 443.57143,405.93361 450,398.07647 451.42857,405.21933 "+
"C 452.85714,412.36218 480,520.93361 480,520.93361 C 480,520.93361 447.14286,551.6479 440,555.93361 "+
"C 432.85714,560.21933 427.85714,567.36218 423.57143,567.36218 C 419.28571,567.36218 409.28571,574.50504 409.28571,574.50504 "+
"L 408.57143,594.50504 C 408.57143,594.50504 407.85714,615.21933 405,615.93361 "+
"C 402.14286,616.6479 392.14286,625.93361 375,613.79075 C 357.85714,601.6479 337.14286,593.07647 327.14286,595.93361 "+
"C 317.14286,598.79075 298.57143,603.07647 298.57143,603.07647 C 298.57143,603.07647 265,641.6479 259.28571,641.6479 "+
"C 253.57143,641.6479 243.57143,643.07647 240.71429,635.93361 C 237.85714,628.79076 242.14286,621.6479 242.14286,620.93361 z").split(" ");
var max_x = 0, max_y = 0, min_x = 2000, min_y = 2000;
function bound(x, y) {
max_x = Math.max(max_x, x);
max_y = Math.max(max_y, y);
min_x = Math.min(min_x, x);
min_y = Math.min(min_y, y);
}
svgPathMap(SVG_PATH, bound, bound, function(cx1, cy1, cx2, cy2, x, y) {bound(x, y);}, function() {});
ctx.save();
//ctx.translate(minWidthHeight / 2, minWidthHeight / 2);
// cCtx.rotate(Math.PI / 180 * ressie_angle);
var thisScale = scale / Math.max(max_x - min_x, max_y - min_y) * 2 / Math.sqrt(2);
ctx.scale(thisScale, thisScale);
ctx.translate(-(min_x + max_x) / 2, -(min_y + max_y) / 2);
ctx.beginPath();
ctx.strokeStyle = "rgb(136, 136, 136)";
ctx.fillStyle = "rgb(34, 170, 238)";
svgPathMap(SVG_PATH, function(x, y) {ctx.moveTo(x, y);},
function(x, y) {ctx.lineTo(x, y);},
function(x1, y1, x2, y2, x, y) {ctx.bezierCurveTo(x1, y1, x2, y2, x, y);},
function() {ctx.closePath(); ctx.fill();});
svgPathMap(SVG_PATH, function(x, y) {ctx.moveTo(x, y);},
function(x, y) {ctx.lineTo(x, y);},
function(x1, y1, x2, y2, x, y) {ctx.bezierCurveTo(x1, y1, x2, y2, x, y);},
function() {ctx.closePath(); ctx.stroke();});
ctx.restore();
}
function drawAll(ctx, wind_angle) {
ctx.clearRect(0, 0, cache_canvas.width, cache_canvas.height);
ctx.save();
ctx.translate(minWidthHeight / 2, minWidthHeight / 2);
ctx.rotate(Math.PI * global_angle / 180);
drawRessie(ctx, minWidthHeight / 2);
ctx.restore();
ctx.save();
ctx.translate(minWidthHeight / 4, minWidthHeight / 4);
ctx.rotate(Math.PI * global_angle / 180);
drawCompass(ctx, minWidthHeight / 4);
ctx.restore();
ctx.save();
ctx.translate(minWidthHeight / 2, minWidthHeight / 2);
ctx.rotate(Math.PI * (global_angle) / 180 + wind_angle);
drawArrow(ctx, minWidthHeight / 2);
ctx.restore();
}
function initSpin(canvas) {
var start, end, value;
if (document.cookie.length > 0) {
start = document.cookie.indexOf(COOKIE + "=");
if ((start != -1) && (document.cookie.length >= start + COOKIE.length + 1)) {
end = document.cookie.indexOf(";", start + COOKIE.length + 1);
if (end == -1) {
end = document.cookie.length;
}
global_angle = parseInt(unescape(document.cookie.substring(start + COOKIE.length + 1, end)), 10);
}
}
$('#compass').mousedown(function(event){
if (dragging === 0) {
var x = event.clientX - (canvas.width / 2),
y = event.clientY - (canvas.height / 2),
elem = canvas;
while (elem) {
x -= elem.offsetLeft;
y -= elem.offsetTop;
elem = elem.offsetParent;
}
start_drag_angle = Math.atan2(y, x);
old_global_angle = global_angle;
dragging = 1;
}
}).mousemove(function(event){
if (dragging == 1) {
var x = event.clientX - (canvas.width / 2),
y = event.clientY - (canvas.height / 2),
elem = canvas;
while (elem) {
x -= elem.offsetLeft;
y -= elem.offsetTop;
elem = elem.offsetParent;
}
var current = Math.atan2(y, x);
global_angle = old_global_angle + (current - start_drag_angle) * 180 / Math.PI;
drawAll(cache_ctx, current_angle);
}
}).mouseup(function(event){
if (dragging == 1) {
dragging = 0;
if (global_angle != old_global_angle) {
drawAll(cache_ctx, current_angle);
var date = new Date();
date.setTime(date.getTime() + (10*365.25*60*60*1000));
var expires = "; expires="+date.toGMTString();
document.cookie = COOKIE + "=" + Math.floor(global_angle) + expires + "path=/";
}
}
}).mouseout(function(event){
if (dragging == 1) {
dragging = 0;
global_angle = old_global_angle;
drawAll(cache_ctx, current_angle);
}
});
spin_initialized = 1;
}
function drawStep() {
var ctx = getContext();
if (ctx) {
if (spin_initialized === 0) {
initSpin(cache_canvas);
}
var ratio = (1-Math.cos(wind_step / WIND_STEPS * Math.PI))/2;
current_angle = wind_start + (wind_end - wind_start) * ratio;
drawAll(ctx, current_angle);
}
if (wind_step < WIND_STEPS) {
wind_step = wind_step + 1;
} else {
clearInterval(wind_timer);
wind_timer = null;
wind_start = wind_end;
}
}
function drawWind(angle) {
if (last_angle && (last_angle === angle)) {
return;
}
last_angle = angle;
wind_end = angle / 180 * Math.PI;
if ((wind_end - wind_start) > Math.PI) {
wind_end = wind_end - 2 * Math.PI;
}
wind_step = 0;
if (wind_timer !== null) {
clearInterval(wind_timer);
wind_start = current_angle;
}
wind_timer = setInterval(drawStep, WIND_TIME * 1000 / WIND_STEPS);
}