function ahrsRenderer(locationId) { this.width = -1; this.height = -1; this.locationId = locationId; this.canvas = document.getElementById(locationId); this.resize(); // State variables this.pitch = 0; this.roll = 0; this.heading = 0; this.slipSkid = 0; this.altitude = 0; var ai = SVG(locationId).viewbox(-200, -200, 400, 400).group().addClass('ai'), defs = ai.defs(), earthClip = defs.rect(2400, 1200).x(-1200).y(0), screenClip = defs.rect(400, 400).cx(0).cy(0); this.pitchClip = defs.circle(320).cx(0).cy(0); this.rollClip = defs.polygon('0,0 -200,-200 200,-200'); ai = ai.clipWith(screenClip).group(); // card is the earth+sky+pitch marks, moves with both pitch and roll. this.card = ai.group(); this.card.circle(2400).cx(0).cy(0).addClass('sky'); // Sky this.card.line(-1200, 0, 1200, 0).addClass('marks'); // Horizon line this.card.circle(2400).cx(0).cy(0).addClass('earth').clipWith(earthClip); // Earth var pitchMarks = this.card.group().addClass('marks').clipWith(this.pitchClip); for (i = -1050; i <= 1050; i+=25) { switch (i%100) { case 0: pitchMarks.line(-40, i, 40, i); if (i!=0) { pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(-55).cy(i).addClass('markText'); pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(+55).cy(i).addClass('markText'); } break; case 50: pitchMarks.line(-20, i, 20, i); break; default: pitchMarks.line(-10, i, 10, i); } } this.rollMarks = ai.group().addClass('marks').clipWith(this.rollClip); for (i=-180; i<180; i+=10) { if (i == 0) { this.rollMarks.polygon('-10,-189 0,-175 10,-189').style('stroke-width', 0); } else if (i % 30 == 0) { this.rollMarks.line(0, -175, 0, -195).rotate(i, 0, 0); } else { this.rollMarks.line(0, -175, 0, -189).rotate(i, 0, 0); } } var rollPointer = ai.group().addClass('marks'); rollPointer.polygon('-10,-160 0,-174 10,-160').style('stroke-width', 0); rollPointer.polygon('-10,+160 0,+174 10,+160').style('stroke-width', 0); this.skidBar = ai.rect(20, 6).cx(0).y(-158).style('stroke-width', 0).addClass('marks'); var pointer = ai.group().addClass('pointer'); pointer.polygon('-150,-3 -78,-3 -75,0 -78,3 -150,3'); pointer.polygon('+150,-3 +78,-3 +75,0 +78,3 +150,3'); pointer.polygon('-75,25 0,0 75,25 25,25 25,20 -25,20 -25,25').addClass('pointerBG'); pointer.polygon('-75,25 0,0 75,25 0,10'); pointer.line(0, 0, 0, 10); this.headingMarks = ai.group().addClass('marks'); for (i=-200; i<=920; i+=20) { if (i%60==0) { this.headingMarks.line(i, 175, i, 178); this.headingMarks.text((i<0 ? (i/2+360) : i/2).toString()).x(i).cy(185).addClass('markText'); this.headingMarks.line(i, 192, i, 195); } else { this.headingMarks.line(i, 175, i, 195).style('stroke-width', 1); } } } ahrsRenderer.prototype = { constructor: ahrsRenderer, resize: function () { var canvasWidth = this.canvas.parentElement.offsetWidth - 12; if (canvasWidth !== this.width) { this.width = canvasWidth; this.height = canvasWidth * 0.5; this.canvas.width = this.width; this.canvas.height = this.height; } }, update: function (pitch, roll, heading, slipSkid) { this.pitch = pitch; this.roll = roll; this.heading = heading; this.slipSkid = slipSkid; this.pitchClip.translate(0, -10 * this.pitch); this.rollClip.rotate(this.roll, 0, 0); this.card.rotate(0, 0, 0).translate(0, 10 * this.pitch); this.card.rotate(-this.roll, 0, -10 * this.pitch); this.rollMarks.rotate(-this.roll, 0, 0); this.headingMarks.translate(-2 * (this.heading % 360), 0); this.skidBar.translate(-2 * this.slipSkid, 0); } }; function gMeterRenderer(locationId, plim, nlim) { this.plim = plim; this.nlim = nlim; this.nticks = Math.floor(plim+1) - Math.floor(nlim) + 1; this.width = -1; this.height = -1; this.locationId = locationId; this.canvas = document.getElementById(locationId); this.resize(); // State variables this.g = 1; this.min = 1; this.max = 1; // Draw the G Meter using the svg.js library var gMeter = SVG(locationId).viewbox(-200, -200, 400, 400).group().addClass('gMeter'); var el, card = gMeter.group().addClass('card'); card.circle(390).cx(0).cy(0); card.line(-150, 0, -190, 0) .addClass('marks one'); for (i=Math.floor(nlim); i<=Math.floor(plim+1); i++) { if (i%2 == 0) { el = card.line(-150, 0, -190, 0).addClass('big'); card.text(i.toString()) .addClass('text') .cx(-105).cy(0) .transform({ rotation: (i-1)/this.nticks*360, cx: 0, cy: 0, relative: true }) .transform({ rotation: -(i-1)/this.nticks*360, relative: true }); } else { el = card.line(-165, 0, -190, 0); } el.addClass('marks') .rotate((i-1)/this.nticks*360, 0, 0); } card.line(-140, 0, -190, 0).addClass('marks limit').rotate((plim-1)/this.nticks*360, 0, 0); card.line(-140, 0, -190, 0).addClass('marks limit').rotate((nlim-1)/this.nticks*360, 0, 0); var ax = -Math.cos(2*Math.PI/this.nticks), ay = -Math.sin(2*Math.PI/this.nticks); card.path('M -170 0, A 170 170 0 0 1 ' + 170*ax + ' ' + 170*ay) .rotate(-Math.floor(plim)/this.nticks*360, 0, 0) .addClass('marks') .style('fill-opacity', '0'); card.path('M -175 0, A 175 175 0 0 1 ' + 175*ax + ' ' + 175*ay) .rotate(-Math.floor(plim)/this.nticks*360, 0, 0) .addClass('marks') .style('fill-opacity', '0'); this.min_el = gMeter.group().addClass('min'); this.min_el.polygon('0,0 -170,0 -160,-5 0,-5').addClass('pointer'); this.min_el.polygon('0,0 -170,0 -160,+5 0,+5').addClass('pointerBG'); this.pointer_el = gMeter.group().addClass('g'); this.pointer_el.polygon('0,0 -170,0 -150,-10 0,-10').addClass('pointer'); this.pointer_el.polygon('0,0 -170,0 -150,+10 0,+10').addClass('pointerBG'); this.max_el = gMeter.group().addClass('max'); this.max_el.polygon('0,0 -170,0 -150,-5 0,-5').addClass('pointer'); this.max_el.polygon('0,0 -170,0 -150,+5 0,+5').addClass('pointerBG'); gMeter.circle(40).cx(0).cy(0).addClass('center'); var reset = gMeter.group().cx(-165).cy(165).addClass('reset'); reset.circle(60).cx(0).cy(0).addClass('reset'); reset.text('RESET').cx(0).cy(0).addClass('text'); reset.on('click', function() { reset.animate(200).rotate(20, 0, 0); this.reset(); reset.animate(200).rotate(0, 0, 0); }, this); } gMeterRenderer.prototype = { constructor: gMeterRenderer, resize: function () { var canvasWidth = this.canvas.parentElement.offsetWidth - 12; if (canvasWidth !== this.width) { this.width = canvasWidth; this.height = canvasWidth * 0.5; this.canvas.width = this.width; this.canvas.height = this.height; } }, update: function (g) { this.g = g; this.max = g > this.max ? g : this.max; this.min = g < this.min ? g : this.min; this.pointer_el.animate(50).rotate((g-1)/this.nticks*360, 0, 0); this.max_el.animate(50).rotate((this.max-1)/this.nticks*360, 0, 0); this.min_el.animate(50).rotate((this.min-1)/this.nticks*360, 0, 0); }, reset: function() { this.g = 1; this.max = 1; this.min = 1; } };