| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- <!--
- layout: false
- -->
- <!DOCTYPE html>
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <!--
- Useful websites:
- Comparison of Canvas and SVG
- http://people.mozilla.com/~vladimir/xtech2006/
- Canvas Tutorial
- https://developer.mozilla.org/en/Canvas_tutorial/
- Animating with Javascript + Canvas
- http://dev.opera.com/articles/view/blob-sallad-canvas-tag-and-javascrip/
- -->
- <title>CNC Simulator</title>
- <script type="text/javascript">
- // Global variables
- var temp = "";
- var start_second = 0;
- var intervalID = 0;
- var running = true;
- var seconds = 0; // 6 degrees
- var time_inc = 1; // in seconds
- var sec_hand_length = 70;
- var min_hand_length = 65;
- var hour_hand_length = 35;
- var clock_radius = 75;
- // Function to run as soon as page loads
- function init()
- {
- var d = new Date();
- var curr_hour = d.getHours();
- var curr_min = d.getMinutes();
- start_second = d.getSeconds();
- seconds = start_second + 60*curr_min + 60*60*((curr_hour) % 12);
- intervalID = window.setInterval(animate,1000);
-
- // Initialize the canvas.
-
- }
- // Animate one frame of the animation
- function animate()
- {
- var canvas = document.getElementById("cnc_canvas");
- var ctx = canvas.getContext("2d");
- var sec_angle = 0;
- var min_angle = 0;
- var hour_angle = 0;
- //alert("Breakpoint animate");
- // Always put the terminating code near the top in case there is an error later on and the function exits before it can stop the interval timer.
- seconds = seconds + time_inc;
- //if (seconds % 60 > (3+start_second) % 60) {
- // stop();
- //}
-
- with (ctx) {
- // What? No "clear canvas" command?
- clearRect(0,0,400,600);
-
- // Draw clock face
- strokeStyle = "black";
- lineWidth = 1;
- beginPath();
- arc(100, 100, clock_radius, 0.001, 2*Math.PI, false);
- //alert("Breakpoint arc");
- stroke();
- //alert("Breakpoint stroke");
-
- // Draw second hand.
- lineWidth = 1;
- strokeStyle = "green";
- beginPath();
- moveTo(100,100);
- sec_angle = 180-360/60*seconds;
- //alert("Breakpoint sec_angle = " + String(sec_angle));
- temp = "x = " + String(100+sec_hand_length*Sin(sec_angle)) + " y = " + String(100+sec_hand_length*Cos(sec_angle));
- //alert("Breakpoint " + temp);
- lineTo(100+sec_hand_length*Sin(sec_angle), 100+sec_hand_length*Cos(sec_angle));
- //alert("Breakpoint lineTo");
- stroke();
-
- // Draw minute hand.
- beginPath();
- strokeStyle = "red";
- lineWidth = 2;
- moveTo(100,100);
- min_angle = 180-360/60*seconds/60;
- lineTo(100+min_hand_length*Sin(min_angle), 100+min_hand_length*Cos(min_angle));
- stroke();
-
- // Draw hour hand.
- lineWidth = 3;
- strokeStyle = "blue";
- beginPath();
- moveTo(100,100);
- hour_angle = 180-360/12*seconds/60/60;
- lineTo(100+hour_hand_length*Sin(hour_angle), 100+hour_hand_length*Cos(hour_angle));
- stroke();
- }
- }
- function stop() {
- window.clearInterval(intervalID);
- running = false;
- }
- function start() {
- time_inc = 1;
- // Only start if we're not already running an animation.
- if (!running) {
- running = true;
- intervalID = window.setInterval(animate,1000);
- }
- }
- function start_high_speed() {
- // If we're not already running an animation.
- if (running) {
- // Kill previous interval
- stop();
- }
- time_inc = 15;
- running = true;
- intervalID = window.setInterval(animate,10);
- }
- function d2r(degrees) {
- return degrees*Math.PI/180;
- }
- function Sin(degrees) {
- return Math.sin(d2r(degrees));
- }
- function Cos(degrees) {
- return Math.cos(d2r(degrees));
- }
- </script>
- <style type="text/css">
- td {
- padding-top: 10px;
- }
- </style>
- </head>
- <body onload="init()">
- <h2 style="margin-bottom: 0">CNC Simulator</h2>
- <table>
- <tr>
- <td style="vertical-align: top" >
- <div style="border-width: 5px; border-style: ridge;">
- <p style="font-weight: bold; margin: 10px">
- <span id="x_disp">X:</span>
- <br />
- <span id="y_disp">Y:</span>
- <br />
- <span id="z_disp">Z:</span>
- <br />
- <span id="time_disp">Time:</span>
- </p>
- </div>
- <form action="">
- <table>
- <tr>
- <td>
- <label for="ppi_input">Pixels per inch:</label>
- <br />
- <input id="ppi_input" type="text" value="127" style="width: 5em" />
- </td>
- <td>
- <label for="time_step_input">Time step:</label>
- <br />
- <input id="time_step_input" type="text" value="1" style="width: 5em" />
- </td>
- </tr>
- <tr>
- <td>
- <label for="speed_input">Speed factor:</label>
- <br />
- <input id="speed_input" type="text" value="5" style="width: 5em; margin-right: 5em;" />
- </td>
- <td>
- <label for="blitz_input">Blitz mode:</label>
- <input type="checkbox" id="blitz_input" checked="checked" />
- </td>
- </tr>
- <tr>
- <td>
- <label for="offset_x">Offset X:</label>
- <br />
- <input id="offset_x" type="text" value="50" style="width: 5em; margin-right: 5em;" />
- </td>
- <td>
- <label for="offset_y">Offset Y:</label>
- <br />
- <input id="offset_y" type="text" value="50" style="width: 5em; margin-right: 5em;" />
- </td>
- </tr>
- <tr>
- <td colspan="2">
- <label for="code_input">Enter CNC code here:<br/></label>
- <textarea rows="20" cols="50" id="code_input">START MM 01 // Use millimeters, program ID 01
- TD= 3.175 // Tool diameter: 1/8 in = 3.175 mm
- FR XY =03.7 // Divided the suggested feedrate by two, because tool was flexing.
- FR Z =01.2 // Feedrate based on 1 cutting edge, instead of 4, then slightly reduced.
- SETUP >zcxyu // Allow user to position tool above 1st hole.
- REPEAT 02 // Second traverse gets the edges better
- GOfX 0.000 // Go to 1st hole
- GOfY 0.000 //
- GO Z- 6.000 // Drill 1st hole
- Z>C // Raise tool
- CALL SUB 10 // Cut left side...
- ZERO AT // (Set origin to right hole)
- X 47.000 // * Change depending on connector *
- Y 0.000 //
- CALL SUB 11 // ...Cut right side...
- ZERO AT // (Reset origin to left hole)
- X- 47.000 // * Change depending on connector *
- Y 0.000 //
- GO X 6.920 // ...And return to Point 1.
- Y 3.410 //
- Z>C // Raise tool
- GOfX 47.000 // Go to 2nd hole * Change depending on connector *
- Y 0.000 //
- GO Z -6.000 // Drill 2nd hole
- Z>C // Raise tool
- REPEAT END //
- END NEW PART //
- SUB 10 // Left Side (located on line 050)
- GO X 6.920 // Point 1
- Y 3.410 //
- GO Z- 9.000 // Insert tool
- ARC // Point 2
- XC= 6.920 //
- YC= 1.500 //
- a= 101.470 //
- GO X 5.740 // Point 3
- Y- 2.280 //
- ARC // Point 4
- XC= 7.120 //
- YC=- 2.000 //
- a= 79.530 //
- SUB RETURN //
- SUB 11 // Right Side (located on line 100)
- GO X- 7.120 // Point 5
- Y- 3.410 //
- ARC // Point 6
- XC=- 7.120 //
- YC=- 2.000 //
- a= 79.530 //
- GO X- 5.050 // Point 7
- Y 1.120 //
- ARC // Point 8
- XC=- 6.920 //
- YC= 1.500 //
- a= 101.470 //
- SUB RETURN //
- </textarea>
- <br/>
- <input name="submit" type="button" value="Click To Run Simulator" onclick="startSimulation();"/>
- <input id="pause_input" type="button" value="Pause" onclick="pause();" />
- </td>
- </tr>
- </table>
- </form>
- </td>
- <td style="vertical-align:top">
- <canvas id="cnc_canvas" width="780" height="650" style="border:1px solid black"></canvas>
- </td>
- </tr>
- </table>
- <hr />
- <div class="output_wrapper" >
- <b>Output:</b>
- <pre id="output"></pre>
- </div>
- <script type="text/javascript">
- // The so-called Prototype Dollar function, a shortcut for document.getElementById()
- function $() {
- var elements = new Array();
- for (var i = 0; i < arguments.length; i++) {
- var element = arguments[i];
- if (typeof element == "string")
- element = document.getElementById(element);
- if (arguments.length == 1)
- return element;
- elements.push(element);
- }
- return elements;
- }
- ctx = null;
- canvas = null;
- function clear_vars() {// Global variables
- unit = "MM"; // or "IN"
- time_step = 1; // update every half second.
- ppi = 96; // Pixels per inch
- cf = 1; // Pixel to unit ratio
- td = 1; // Tool diameter
- max_frx = 1; // Maximum feed rate X
- max_fry = 1; // Maximum feed rate Y
- max_frz = 1; // Maximum feed rate Z
- x_inc = 1; // Distance to move per tick
- y_inc = 1; // Distance to move per tick
- z_inc = 1; // Distance to move per tick
- a_inc = 1; // Distance to move per tick
- mar_x = 10; // Horizontal margin of origin
- mar_y = 10; // Vertical margin of origin
- tool_c = 2; // Clearance height.
- tool_x = 0; // Tool position X
- tool_y = 0; // Tool position Y
- tool_z = 0; // Tool position Z
- tool_a = 0; // Tool angle (used for arcs)
- arc_r = 0; // Radius of currently drawn arc.
- arc_dir = false; // Counter-clockwise
- old_x = 0; // Previous tool position X
- old_y = 0; // Previous tool position Y
- old_z = 0; // Previous tool position Z
- old_a = 0; // Previous tool angle (used for arcs)
- goal_x = 0; // Destination coordinate
- goal_y = 0; // Destination coordinate
- goal_z = 0; // Destination coordinate
- xc = 0; // Used for drawing arcs
- yc = 0; // Used for drawing arcs
- ac = 0; // Used for drawing arcs
- time = 0; // Time needed to execute cut.
- time_x = 0;
- time_y = 0;
- time_z = 0;
- time_a = 0; // Used for arcs
- time_elapsed = 0;
- n = 0; // Line index
- lines = []; // Array of each line of code
- line = ""; // Current line
- moving = false; // Set to true when the tool is moving from one point to another.
- arcing = false; // Set to true when the tool is arcing.
- interval_id = 0; // Variable needed to stop the timer during real-time mode
- blitz_done = false; // Variable used to stop the timer in blitz mode.
- paused = false; // Pause/unpaused state
- speed = 1;
- stack = []; // Line numbers to return to
- canvas_stack = 0; // How many times restore() the canvas
- canvas = $("cnc_canvas");
- ctx = canvas.getContext("2d");
- }
- function startSimulation() {
- // Clean up variables from the last run.
- clear_vars();
- // Clear debug output
- $("output").innerHTML = "";
- // Because the previous run might not have finished
- for (var i = 0; i < 50; i++) {
- ctx.restore();
- }
- // Stop the clock
- stop();
- // Since there is no "clear canvas" command.
- ctx.fillStyle = "white"
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.strokeStyle = "black";
- /*
- The canvas has it's origin in the top-left corner, but the CNC
- Machine has it's origin in the bottom-left corner. Therefore,
- we translate the origin and apply a transformation matrix to
- flip the Y direction.
- */
- ctx.save();
- canvas_stack = canvas_stack + 1;
- ctx.transform(1, 0, 0, -1, 0, 0);
- mar_x = parseFloat($("offset_x").value);
- mar_y = parseFloat($("offset_y").value);
- ctx.translate(mar_x, mar_y-canvas.height);
- ctx.save();
- canvas_stack = canvas_stack + 1;
-
- lines = $("code_input").value.split("\n"); //str.split("\n");
- ppi = parseFloat($("ppi_input").value);
- // Start the animation sequence
- n = -1;
- debugn("There are " + lines.length + " lines");
- // Stop all animations
- window.clearInterval(interval_id);
- paused = true;
- pause();
- }
- function pause() {
- if (paused) {
- paused = false;
- // Set the speed
- speed = parseFloat($("speed_input").value);
- time_step = parseFloat($("time_step_input").value);
- // Start the CNC simulation.
- if ($("blitz_input").checked) {
- while (blitz_done == false) {
- tick();
- }
- } else {
- interval_id = window.setInterval(tick,1000*time_step/speed);
- }
- $("pause_input").value = "Pause";
- } else {
- paused = true;
- window.clearInterval(interval_id);
- $("pause_input").value = "Resume";
- }
- }
- function nextLine() {
- n = n + 1;
- if (n >= lines.length) {
- return false;
- } else {
- line = lines[n];
- return true;
- }
- }
- function startsWith(s1, s2) {
- if (s1.substr(0,s2.length) == s2) {
- return true;
- } else {
- return false;
- }
- }
- function deg2rad(d) {
- return (Math.PI/180)*d;
- }
- function rad2deg(r) {
- return (180/Math.PI)*r;
- }
- function tick() {
- if (moving) {
- // Store previous position
- old_x = tool_x;
- old_y = tool_y;
- old_z = tool_z;
- old_a = tool_a;
- // Figure out new position
- if (time < time_step) {
- if (arcing) {
- tool_a = goal_a;
- tool_x = xc + Math.cos(tool_a)*arc_r;
- tool_y = yc + Math.sin(tool_a)*arc_r;
- } else {
- tool_x = goal_x;
- tool_y = goal_y;
- tool_z = goal_z;
- }
- time_elapsed = time_elapsed + time;
- } else {
- if (arcing) {
- tool_a = tool_a + a_inc;
- tool_x = xc + Math.cos(tool_a)*arc_r;
- tool_y = yc + Math.sin(tool_a)*arc_r;
- } else {
- tool_x = tool_x + x_inc;
- tool_y = tool_y + y_inc;
- tool_z = tool_z + z_inc;
- }
- time_elapsed = time_elapsed + time_step;
- }
- // Update display
- $("x_disp").innerHTML = "X: " + tool_x;
- $("y_disp").innerHTML = "Y: " + tool_y;
- $("z_disp").innerHTML = "Z: " + tool_z;
- $("time_disp").innerHTML = "Time: " + time_elapsed;
-
- // Draw line if tool is below surface.
- if (tool_z < 0) {
- with (ctx) {
- // Draw hole
- beginPath();
- fillStyle = "black";
- arc(tool_x, tool_y, td/2.0, 0, Math.PI*2.0, true);
- fill();
- // Draw line
- lineCap = "round";
- lineWidth = td;
- beginPath();
- strokeStyle = "black";
- if (arcing) {
- arc(xc, yc, arc_r, old_a, tool_a, arc_dir);
- } else {
- moveTo(old_x, old_y);
- lineTo((tool_x), (tool_y));
- }
- stroke();
- }
- } else {
- // Draw hollow dot (so we can see the path of the tool)
- with (ctx) {
- lineWidth = 1/cf;
- strokeStyle = "blue";
- strokeRect((tool_x)-1/cf, (tool_y) -1/cf, 3/cf, 3/cf);
- }
- }
- // Decrease time
- time = time - time_step;
- // Finish line
- if (time < 0) {
- time = 0;
- moving = false;
- arcing = false;
- }
- debug(".");
- } else {
- // Always safest to put this first, in case of unhandled syntax
- // errors later on in the code.
- if (nextLine()) {
- ndebug("Line " + n + ": ");
- } else {
- ndebug("Ended because there are no more lines.");
- n = -1;
- ndebug("canvas_stack = " + canvas_stack);
- for (var i = 0; i < canvas_stack; i++) {
- ndebug("ctx.restore()");
- ctx.restore();
- }
- blitz_done = true;
- window.clearInterval(interval_id);
- return;
- }
- //debug(line);
- if (startsWith(line, "START")) {
- // Set unit
- unit = line.substr(6,2);
- debugd("Unit: " + unit);
- if (unit == "MM") {
- debugd("Millimeters");
- cf = ppi / 25.4;
- } else if (unit == "IN") {
- debugd("Inches");
- cf = ppi;
- } else {
- ndebug("Invalid unit");
- n = lines.length;
- return;
- }
- debug("Scale: " + cf);
- ctx.scale(cf, cf);
- } else if (startsWith(line, " TD=")) {
- // Set tool diameter
- debugd("Tool Diameter: " + line.substring(4,12));
- td = parseFloat(line.substring(4,12));
- ctx.lineWidth = td;
- debug("ctx.lineWidth = " + ctx.lineWidth);
- } else if (startsWith(line, "FR")) {
- // TODO: set feed rate
- debugd("Setting feed rate for " + line.substr(3,3) + " to " + line.substring(8,12));
- if (line.indexOf("X") != -1) {
- max_frx = parseFloat(line.substring(8,12));
- debug(" set FR X = " + max_frx);
- }
- if (line.indexOf("Y") != -1) {
- max_fry = parseFloat(line.substring(8,12));
- debug(" set FR Y = " + max_fry);
- }
- if (line.indexOf("Z") != -1) {
- max_frz = parseFloat(line.substring(8,12));
- debug(" set FR Z = " + max_frz);
- }
- } else if (startsWith(line, "SETUP")) {
- // This step doesn't translate well, and would get annoying
- debug("Setup: " + line.substring(7,12));
- debug(" Note: in real life, this command would let you position the tool at a new 'zero' position.");
- } else if (startsWith(line, "Z>C")) {
- tool_z = tool_c;
- debug("Z>C: Z = " + String(tool_c));
- } else if (startsWith(line, "GO")) {
- goal_x = tool_x; time_x = 0;
- goal_y = tool_y; time_y = 0;
- goal_z = tool_z; time_z = 0;
- debugd("Go");
- do {
- if (line.substr(3,1) == "f") {
- // TODO: how fast is "fast" anyway?
- }
- if (line.substr(3,1) == "X") {
- goal_x = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- goal_x = -goal_x;
- }
- time_x = Math.abs((goal_x - tool_x) / max_frx);
- debugd("X coor: " + goal_x);
- } else if (line.substr(3,1) == "Y") {
- goal_y = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- goal_y = -goal_y;
- }
- time_y = Math.abs((goal_y - tool_y) / max_fry);
- debugd("Y coor: " + goal_y);
- } else if (line.substr(3,1) == "Z") {
- goal_z = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- goal_z = -goal_z;
- }
- time_z = Math.abs((goal_z - tool_z) / max_frz);
- debugd("Z coor: " + goal_z);
- }
- n = n+1;
- if (n >= lines.length) {
- break;
- }
- line = lines[n];
- } while (line.substr(0,2) == " ")
- n = n - 1;
- // Compute how many seconds it will take to execute this cut
- time = Math.max(Math.max(time_x, time_y), time_z);
- debugd("Time Required: "+time);
- x_inc = (goal_x - tool_x) / time * time_step;
- y_inc = (goal_y - tool_y) / time * time_step;
- z_inc = (goal_z - tool_z) / time * time_step;
- debug("X inc: " + x_inc + " Y inc: " + y_inc +" Z inc: " + z_inc);
- moving = true;
- } else if (startsWith(line, "ZERO AT")) {
- // Translate the canvas origin
- debugd("ZERO AT");
- goal_x = 0; time_x = 0;
- goal_y = 0; time_y = 0;
- goal_z = 0; time_z = 0;
- if (!nextLine()) { return; }
- while (line.substr(0,2) == " ") {
- if (line.substr(3,1) == "X") {
- goal_x = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- goal_x = -goal_x;
- }
- debug(" X coor: " + goal_x);
- } else if (line.substr(3,1) == "Y") {
- goal_y = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- goal_y = -goal_y;
- }
- debug(" Y coor: " + goal_y);
- } else if (line.substr(3,1) == "Z") {
- goal_z = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- goal_z = -goal_z;
- }
- debug(" Z coor: " + goal_z);
- }
- if (!nextLine()) { break; }
- }
- n = n - 1;
- // Translate the canvas origin
- ctx.save();
- ctx.translate(goal_x, goal_y);
- canvas_stack = canvas_stack + 1;
- // Untranslate tool
- tool_x = tool_x - goal_x;
- tool_y = tool_y - goal_y;
- } else if (startsWith(line, "ARC")) {
- debugd("ARC");
- if (!nextLine()) { return; }
- if (line.substr(0,4) == " XC=") {
- xc = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- xc = -xc;
- }
- debug(" XC: " + xc);
- } else {
- debug("I really expected a line starting with ' XC='");
- }
- if (!nextLine()) { return; }
- if (line.substr(0,4) == " YC=") {
- yc = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- yc = -yc;
- }
- debug(" YC: " + yc);
- } else {
- debug("I really expected a line starting with ' YC='");
- }
- if (!nextLine()) { return; }
- if (line.substr(0,4) == " a=") {
- // I call the variable 'ac' for resemblance
- ac = parseFloat(line.substring(5,12));
- if (line.substr(4,1) == "-") {
- ac = -ac;
- arc_dir = true;
- } else {
- arc_dir = false;
- }
- debugd(" AC: " + ac);
- ac = deg2rad(ac);
- debugd("in radians: " + ac);
- } else {
- debug("I really expected a line starting with ' a='");
- }
- arc_r = Math.sqrt( Math.pow(xc-tool_x, 2) +
- Math.pow(yc-tool_y, 2) );
- debugd("R = " + arc_r);
- var dist = Math.abs(arc_r*ac);
- var xyfr = (max_frx + max_fry)/2;
- time = dist/xyfr;
- debugd("Time Required: " + time);
- a_inc = ac/time*time_step;
- debugd("a_inc = " + a_inc);
- // Math.atan2 seems to be measuring Clockwise from the Y
- // axis. Ridiculous.
- tool_a = Math.atan2(tool_y-yc, tool_x-xc);
- debugd("tool_a = " + rad2deg(tool_a) + " degrees");
- goal_a = Math.atan2(tool_y-yc, tool_x-xc) + ac;
- debug("goal_a = " + rad2deg(goal_a) + " degrees");
- moving = true;
- arcing = true;
- //arcing = true;
- } else if (startsWith(line, "CALL SUB")) {
- // Push line # onto stack
- debugd("Calling Sub");
- stack.push(n);
- ctx.save();
- canvas_stack = canvas_stack + 1;
- // Get the SUB id
- var sub_id = line.substring(9,12).replace(" ","");
- var sub_id = "SUB " + sub_id;
- debugd("Scanning for '" + sub_id +"'");
- // Move the cursor location to the start of the subroutine.
- n = -1;
- while (n < lines.length) {
- n = n + 1;
- line = lines[n];
- if (line.substr(0,sub_id.length) == sub_id) {
- debugd("Found '" + sub_id + "' on line " + String(n));
- debug("Stack: " + String(stack));
- break;
- }
- }
- } else if (startsWith(line, "SUB RETURN")) {
- // Return to our line # in the stack.
- n = stack.pop();
- ctx.restore();
- canvas_stack = canvas_stack - 1;
- debugd("SUB RETURN return to line " + String(n));
- debug("Stack: " + String(stack));
- } else if (startsWith(line, "REPEAT END")) {
- if (stack.length > 0) {
- n = stack.pop();
- debug("REPEAT END return to line " + String(n));
- } else {
- debug("Passing REPEAT END");
- }
- } else if (startsWith(line, "REPEAT")) {
- var rep_num = parseInt(line.substring(10,12))
- debugd("REPEAT " + String(rep_num) + " times");
- for (var i = 1; i < rep_num; i++) {
- stack.push(n);
- }
- debug("Stack: " + String(stack));
- } else if (startsWith(line, "END")) {
- n = lines.length;
- debug("Encountered an END");
- } else {
- debug("Skipping line: " + line);
- }
- }
- }
- /*
- These are placed at the end, so if prior code has syntax errors,
- the page will clearly be broken.
- */
- function debug(str) {
- var obj;
- obj = $("output");
- obj.innerHTML = obj.innerHTML + str;
- }
- function ndebug(str) {
- var obj;
- obj = $("output");
- obj.innerHTML = obj.innerHTML + "\n" + str;
- }
- function debugn(str) {
- var obj;
- obj = $("output");
- obj.innerHTML = obj.innerHTML + str + "\n";
- }
- function ndebugn(str) {
- var obj;
- obj = $("output");
- obj.innerHTML = obj.innerHTML + "\n" + str + "\n";
- }
- function debugd(str) {
- var obj;
- obj = $("output");
- obj.innerHTML = obj.innerHTML + str + "... ";
- }
- </script>
- <footer>
- <hr/>
- <p style="text-align: center; font-style:italic"><a href="http://validator.w3.org/#validate-by-upload">Freaking valid HTML5 baby!!!</a></p>
- </footer>
- </body>
- </html>
|