Guest User

triangulate.html (v0.3)

a guest
Feb 17th, 2018
6,958
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 10.47 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Minecraft :: Stronghold Triangulator</title>
  6. <!--
  7.  
  8. v0.2
  9.  
  10. Updates:
  11. - Minor text revision in instructions for clarification
  12. - Input validation -- all 6 inputs must highlight green, otherwise calculation won't run.
  13.  
  14. v0.3
  15. - Clear output when recalculating
  16. - Clear graph canvas when recalculating
  17. - Clear optional debug info when recalculating
  18. - Changed formula for converting Minecraft heading to trigonometric degrees (possibly unnecessary?)
  19. - Added calculated reference points for cast lines
  20. - Fixed inverted Z axis coordinates for second and third strongholds
  21.  
  22. DISCLAIMER:  
  23.  
  24. Standard disclaimers apply, all wrongs reserved.  Your mileage may vary.  Lather, rinse, repeat.
  25.  
  26. -->
  27. <style>
  28. body {
  29.     font-family : Tahoma, Arial, Sans-serif;
  30.     font-size : 9pt;
  31. }
  32. th {
  33.     background-color : #004080;
  34.     font-weight : bold;
  35.     color : #fff;
  36. }
  37. td {
  38.     text-align : center;
  39.     font-size : 12pt;
  40. }
  41. .blank {
  42.   background-color : #c0c0ff;
  43.   border : none;
  44. }
  45. .err {
  46.   background-color : #ffc0c0;
  47.   border : none;
  48. }
  49. .ok {
  50.   background-color : #c0ff00;
  51.   border : none;
  52. }
  53. </style>
  54. <script type="text/javascript">
  55.    
  56. function isNumber(n) {
  57.  
  58.     return !isNaN(parseFloat(n)) && isFinite(n);
  59.  
  60. }
  61.  
  62. function validInput (o) {
  63.  
  64.     if (o.value == '') {
  65.         o.className = 'blank';
  66.         return false;
  67.     } else if (isNumber(o.value)) {
  68.         o.className = 'ok';
  69.         return false;
  70.     } else {
  71.         o.className = 'err';
  72.         return false;
  73.     }
  74.  
  75. }
  76.    
  77. function deg2rad (deg) {
  78.     return deg * Math.PI / 180;
  79. }
  80.  
  81. function rad2deg (rad) {
  82.     return rad * 180 / Math.PI;
  83. }
  84.    
  85. function mca2deg (mca) {
  86.  
  87.     if (mca < -90) {
  88.         return Math.abs(mca) - 90
  89.     } else if (mca < 0) {
  90.         return 270 + mca;
  91.     } else {
  92.         return 270 - mca;
  93.     }
  94. }
  95.  
  96. function deg2mca (deg) {
  97.  
  98.     deg = deg % 360;
  99.     if (deg < 90) {
  100.         return -90 - deg;
  101.     } else {
  102.         return 270 - deg;
  103.     }
  104.  
  105. }
  106.    
  107. function formatFloat (f, dec) {
  108.  
  109.     return Math.round(f * Math.pow(10,dec)) / Math.pow(10,dec);
  110.  
  111. }
  112.  
  113. function drawGraph() {
  114.    
  115.     var c = document.getElementById('map').getContext('2d');
  116.  
  117.     // clear contents
  118.        c.fillStyle = '#FFFFFF';
  119.        c.fillRect(0,0,1200,1200);
  120.    
  121.     c.strokeStyle = '#808080';
  122.     c.beginPath();
  123.     c.moveTo(0,601);
  124.     c.lineTo(1201,601);
  125.     c.moveTo(601,0);
  126.     c.lineTo(601,1201);
  127.     c.stroke();
  128.    
  129. }
  130.  
  131. function scalePlot (x, n) {
  132.    
  133.     if (n != 0) {
  134.         return (x / n);
  135.     } else {
  136.         return 0;
  137.     }
  138.    
  139. }
  140.  
  141. function castLine (x1, y1, x2, y2, col) {
  142.    
  143.     var c = document.getElementById('map').getContext('2d');
  144.    
  145.     c.strokeStyle = col;
  146.     c.beginPath();
  147.     c.moveTo(601 + scalePlot (x1, 2), 601 + scalePlot (y1, 2));
  148.     c.lineTo(601 + scalePlot (x2, 2), 601 + scalePlot (y2, 2));
  149.     c.stroke();
  150.    
  151. }
  152.  
  153. function plotPoint (x, y, col) {
  154.  
  155.     var c = document.getElementById('map').getContext('2d');
  156.     c.fillStyle = col;
  157.     c.fillRect(600 + scalePlot(x, 2), 600 + scalePlot(y, 2), 3, 3)
  158.  
  159. }
  160.  
  161. function recalc() {
  162.    
  163.     // requires some testing -- may not work if (x1,z1) and (x2,z2) are in different quadrants
  164.    
  165.     var debug = false;
  166.    
  167.     var x1 = document.getElementById('x1').value;
  168.     var z1 = document.getElementById('z1').value;
  169.     var a1 = document.getElementById('a1').value;
  170.     var x2 = document.getElementById('x2').value;
  171.     var z2 = document.getElementById('z2').value;
  172.     var a2 = document.getElementById('a2').value;
  173.  
  174.     if (!isNumber(x1) || !isNumber(z1) || !isNumber(a1) || !isNumber(x2) || !isNumber(z2) || !isNumber(a2)) return false;
  175.    
  176.     x1 = parseFloat(x1);
  177.     z1 = parseFloat(z1);
  178.     a1 = parseFloat(a1); var a1d = mca2deg(a1);
  179.     x2 = parseFloat(x2);
  180.     z2 = parseFloat(z2);
  181.     a2 = parseFloat(a2); var a2d = mca2deg(a2);
  182.     var xc = document.getElementById('xcalc');
  183.     var zc = document.getElementById('zcalc');
  184.     var angular = document.getElementById('angular');
  185.    
  186.     // determine point from casting angle
  187.     var x1n = 0+x1+500*Math.cos(deg2rad(mca2deg(a1)));
  188.     var z1n = 0+z1-500*Math.sin(deg2rad(mca2deg(a1)));
  189.     var x2n = 0+x2+500*Math.cos(deg2rad(mca2deg(a2)));
  190.     var z2n = 0+z2-500*Math.sin(deg2rad(mca2deg(a2)));
  191.    
  192.     // calculate intersection of lines
  193.     // adapted from intersection code here:  http://jsfiddle.net/justin_c_rounds/Gd2S2/light/
  194.     d = ((z2n - z2) * (x1n - x1)) - ((x2n - x2) * (z1n - z1));
  195.     a = z1 - z2;
  196.     b = x1 - x2;
  197.     n1 = ((x2n - x2) * a) - ((z2n - z2) * b);
  198.     n2 = ((x1n - x1) * a) - ((z1n - z1) * b);
  199.     a = n1 / d;
  200.     b = n2 / d; // ?
  201.     var int_x = x1 + (a * (x1n - x1));
  202.     var int_z = z1 + (a * (z1n - z1));
  203.    
  204.     if (debug) {
  205.         var dbg = document.getElementById('debug');
  206.         dbg.innerHTML = 'x1 = '+x1+'; z1 = '+z1+'; a1 = '+a1+'; a1d = '+a1d;
  207.         dbg.innerHTML += '<br>x2 = '+x2+'; z2 = '+z2+'; a2 = '+a2+'; a2d = '+a2d;
  208.         dbg.innerHTML += '<br>x1n = '+x1n+'; z1n = '+z1n;
  209.         dbg.innerHTML += '<br>x2n = '+x2n+'; z2n = '+z2n;
  210.         dbg.innerHTML += '<br>d = '+d+'; a = '+a+'; b = '+b+'; n1 = '+n1+'; n2 = '+n2;
  211.         dbg.innerHTML += '<br>int_x = '+int_x+'; int_z = '+int_z;
  212.     }
  213.  
  214.     var deg1 = rad2deg(Math.atan2(-int_z,int_x));
  215.     var deg2 = (deg1 + 120) % 360;
  216.     var deg3 = (deg2 + 120) % 360;
  217.    
  218.     drawGraph();
  219.    
  220.     // draw stronghold
  221.     plotPoint (int_x, int_z, '#000000');
  222.  
  223.     // draw initial points
  224.     plotPoint (x1, z1, '#008080'); // (first throw)
  225.     plotPoint (x2, z2, '#008080'); // (second throw)
  226.  
  227.     // draw cast points
  228.     plotPoint (x1n, z1n, '#007f7f');
  229.     plotPoint (x2n, z2n, '#007f7f');
  230.  
  231.     // draw throw shadows
  232.     castLine (x1, z1, x1n, z1n, '#c0c0c0');
  233.     castLine (x2, z2, x2n, z2n, '#c0c0c0');
  234.    
  235.     castLine (x1, z1, int_x, int_z, '#ff8000'); // (first point to stronghold)
  236.     castLine (x2, z2, int_x, int_z, '#ffc000'); // (second point to stronghold)
  237.  
  238.     angular.innerHTML = ''
  239.     angular.innerHTML += 'Stronghold is approximately '+formatFloat(deg1,2)+'&deg; ('+formatFloat(deg2mca(deg1),2)+'<sup>m</sup>) from center (0,0).<br>';
  240.  
  241.     // second stronghold range
  242.     x1 = Math.round(Math.cos(deg2rad(deg2))*640);
  243.     z1 = -Math.round(Math.sin(deg2rad(deg2))*640);
  244.     x2 = Math.round(Math.cos(deg2rad(deg2))*1152);
  245.     z2 = -Math.round(Math.sin(deg2rad(deg2))*1152);
  246.  
  247.     castLine (x1, z1, x2, z2, '#404040');
  248.    
  249.     angular.innerHTML += 'Second stronghold is at about '+formatFloat(deg2,2)+'&deg; ('+formatFloat(deg2mca(deg2),2)+'<sup>m</sup>) somewhere between (X:'+x1+', Z:'+z1+') and (Z:'+x2+', Z:'+z2+').<br>';
  250.  
  251.     // third stronghold range
  252.    
  253.     x1 = Math.round(Math.cos(deg2rad(deg3))*640);
  254.     z1 = -Math.round(Math.sin(deg2rad(deg3))*640);
  255.     x2 = Math.round(Math.cos(deg2rad(deg3))*1152);
  256.     z2 = -Math.round(Math.sin(deg2rad(deg3))*1152);
  257.    
  258.     castLine (x1, z1, x2, z2, '#c0c0c0');
  259.    
  260.     angular.innerHTML += 'Third stronghold is at about '+formatFloat(deg3,2)+'&deg; ('+formatFloat(deg2mca(deg3),2)+'<sup>m</sup>) somewhere between (X:'+x1+', Z:'+z1+') and (Z:'+x2+', Z:'+z2+').<br>';
  261.    
  262.     xc.innerHTML = ''+Math.round(int_x);
  263.     zc.innerHTML = ''+Math.round(int_z);
  264.    
  265. }
  266. </script>
  267. </head>
  268. <body onload="document.getElementById('x1').focus()">
  269. <h1>Stronghold Triangulator</h1>
  270. <table width="80%" align="center">
  271. <tr><th colspan="6">How to Use</th></tr>
  272. <tr><td colspan="6"></td></tr>
  273. <p>Minecraft stronghold finder with as few as two throws!</p>
  274. <ol>
  275. <li>Throw an Eye of Ender and face the direction it travels, making sure to line your view up
  276.     with the trail as closely as possible.  Center the crosshair over the eye before it falls to
  277.     the ground or shatters.  Using the F3 screen, note current X, Z, and angle (diplayed after
  278.     "f:" below the X, Y, and Z coordinates).  You won't necessarily need all the decimal points,
  279.     but keeping those may improve accuracy of results.</li>
  280. <li>Pick a direction roughly perpendicular  to your current view angle, and travel a couple hundred
  281.     blocks.  The larger the angle between both throws to more chance there is to be accurate.
  282.   Again, throw the Eye of Ender, line up your view, and note new X, Z, and angle.</li>
  283. <li>Enter the values in the corresponding fields then click calculate.  The result should be
  284.     fairly close to the End Portal.  A graph is also displayed (required browser capable of HTML5
  285.     canvas drawing) that shows the casting directions (yellow/orange) and the rough locations of
  286.     the other two strongholds.</li>
  287. </ol>
  288.  
  289. <p>How does it work?</p>
  290.  
  291. <p>Each throw describes a position and angle.  These are used to calculate a position 100 blocks away
  292. (though any reasonable distance will work). This defines two lines which can be used to calculate
  293. the intersection where they cross.</p>
  294.  
  295. <p>Many cases have been tested to work properly, though a few additional possibilities need to
  296. be verified.  As long as both throws are targeting the same stronghold, it should be accurate.</p>
  297.  
  298. <p>Version 1.9 increased the number of strongholds generated from 3 to 128.  This will still work
  299. to find a stronghold beyond the innermost 3, but the second and third calculated positions will
  300. be incorrect and the graph will be erroneous.  The two throws used for input still need to
  301. point at the same stronghold in order to give accurate results.</p>
  302.  
  303. <tr><td class="title" colspan="2">X1</td><td class="title" colspan="2">Z1</td><td class="title" colspan="2">Angle 1</td></tr>
  304. <tr><td class="entry" colspan="2"><input type="text" class="blank" id="x1" size="10" maxlength="10" onkeyup="validInput(this);"></td><td class="entry" colspan="2"><input type="text" class="blank" id="z1" size="10" maxlength="10" onkeyup="validInput(this);"></td><td class="entry" colspan="2"><input type="text" class="blank" id="a1" size="10" maxlength="10" onkeyup="validInput(this);"></td></tr>
  305. <tr><td class="title" colspan="2">X2</td><td class="title" colspan="2">Z2</td><td class="title" colspan="2">Angle 2</td></tr>
  306. <tr><td class="entry" colspan="2"><input type="text" class="blank" id="x2" size="10" maxlength="10" onkeyup="validInput(this);"></td><td class="entry" colspan="2"><input type="text" class="blank" id="z2" size="10" maxlength="10" onkeyup="validInput(this);"></td><td class="entry" colspan="2"><input type="text" class="blank" id="a2" size="10" maxlength="10" onkeyup="validInput(this);"></td></tr>
  307. <!-- uncomment this section and set "debug = true;" above to show details
  308. <tr><th colspan="6">Debug</th</tr>
  309. <tr><td colspan="6"><span id="debug">&nbsp;</span></td></tr>   
  310. -->
  311. <tr><th colspan="6">Result</th</tr>
  312. <tr><td colspan="3">X : <span id="xcalc">?</span></td><td colspan="3">Z : <span id="zcalc">?</span></td></tr>
  313. <tr><td colspan="6"><span id="angular">&nbsp;</span></td></tr>
  314. <tr><td colspan="6"><input type="button" value="calculate" onclick="recalc(); return false"></td></tr>
  315. <tr><td colspan="6"><canvas id="map" width="1201" height="1201" /></td></tr>
  316. </table>
  317. </body>
  318. </html>
Advertisement
Add Comment
Please, Sign In to add comment