javascript - Given one side of a regular polygon, find the remaining sides -


we given:

  • the number of sides of regular polygon
  • one side defined coordinates (x1, y1) , (x2, y2)

i have find out remaining coordinates. how can this?

suppose have turtle has drawn 1 segment of n-sided regular polygon moving x1, y1 x2, y2. draw remaining sides, n-1 times:

  • turn angle
  • move forward distance

the angle have turn 360/n degrees. example, if we're drawing triangle, turtle has turn 120 degrees after each segment. if we're drawing triangle clockwise, subtract 120 degrees current orientation of turtle. if we're drawing counterclockwise, add 120 degrees.

the distance move forward length of first segment. can calculate length of segment using pythagorean theorem. in javascript, can implement thus:

var dx = x2-x1,     dy = y2-y1,     length = math.sqrt(dx*dx + dy*dy); 

the initial orientation of turtle same angle of first line segment, can calculate taking inverse cosine of dx/length:

var angle = math.acos(dx/length); if (dy < 0) {   angle = 2*math.pi - angle; } 

to make use of turning angle , segment length, have implement following turtle operations:

  • set turtle position x, y
  • set turtle orientation angle
  • move turtle distance units forward in current orientation
  • add delta turtle orientation
  • query current position x, y of turtle

after operations implemented, can write loop iterates n-1 times. in each iteration, turn , move forward prescribed amounts, query turtle position, , print coordinates.

to implement turtle operations, have store position , orientation of turtle. here easy way so:

var turtle = { x: 0, y: 0, angle: 0 }; 

to move turtle distance units forward in current orientation, use basic trigonometry:

turtle.x += math.cos(turtle.angle) * distance; turtle.y += math.sin(turtle.angle) * distance; 

note trigonometric functions in javascript work radians rather degrees. there 2π radians in circle, hence π radians in semicircle. if have angle r expressed in radians, equivalent in degrees r / math.pi * 180.

when add or subtract value turtle orientation, possible end angle less 0 or greater 2π. not affect our trigonometric calculations, can make program difficult debug. ensure angle in range [0, 2π), can following whenever turtle.angle gets modified:

turtle.angle -= math.floor(turtle.angle / (2*math.pi)) * 2*math.pi; 

i have written code snippet demonstrate turtle approach. run code clicking blue button below, click , drag draw first segment of polygon. can change number of sides clicking on plus , minus symbols.

var polygon = {    color: {      axes: '#ccc',      sides: {         hover: { plain: '#dddfa4', special: '#9d9c64' },         final: { plain: '#b0c598', special: '#4f7337' }      }    }  };    polygon.turtle = { x: 0, y: 0, angle: 0 };  polygon.turtle.setposition = function (x, y) {    var g = polygon,        turtle = g.turtle,        context = g.context,        origin = g.origin;    turtle.x = x;    turtle.y = y;    context.moveto(origin.left + turtle.x, origin.top - turtle.y);  };  polygon.turtle.setangle = function (angle) {    var g = polygon,        turtle = g.turtle;    turtle.angle = angle;  };  polygon.turtle.left = function (delta) {    var g = polygon,        turtle = g.turtle;    turtle.angle = g.normalizeangle(turtle.angle + delta);  };  polygon.turtle.right = function (delta) {    var g = polygon,        turtle = g.turtle;    turtle.angle = g.normalizeangle(turtle.angle - delta);  };       polygon.normalizeangle = function (angle) {    angle -= math.floor(angle / (2*math.pi)) * 2*math.pi;    return angle;  };  polygon.turtle.forward = function (distance) {    var g = polygon,         turtle = g.turtle,        canvas = g.canvas,        context = g.context,        origin = g.origin;    turtle.x += math.cos(turtle.angle) * distance;    turtle.y += math.sin(turtle.angle) * distance;    context.lineto(origin.left + turtle.x, origin.top - turtle.y);  };    polygon.resizecanvas = function() {    var g = polygon,        canvas = g.canvas,        context = g.context,        width = canvas.width = window.innerwidth,        height = canvas.height = window.innerheight;    g.origin = { left: math.floor(width/2), top: math.floor(height/2) };    g.drawaxes();  };  polygon.drawaxes = function() {    var g = polygon,        canvas = g.canvas,        context = g.context,        origin = g.origin,        color = g.color;    context.linewidth = 2;     context.strokestyle = color.axes;    context.beginpath();    context.moveto(origin.left, 0);    context.lineto(origin.left, canvas.height);    context.moveto(0, origin.top);    context.lineto(canvas.width, origin.top);    context.stroke();  };  polygon.drawpolygon = function (situation) {    var g = polygon,        canvas = g.canvas,        context = g.context,        turtle = g.turtle,        color = g.color,        n = parseint(document.getelementbyid('numsides').innerhtml, 10),        turn = 2*math.pi / n,        x1 = g.x1, y1 = g.y1, x2 = g.x2, y2 = g.y2,        dx = x2-x1,        dy = y2-y1,        length = math.sqrt(dx*dx + dy*dy);    var angle = math.acos(dx/length);    if (dy < 0) {      angle = 2*math.pi - angle;    }    context.clearrect(0, 0, canvas.width, canvas.height);    g.drawaxes();    context.linewidth = 4;    context.linecap = 'round';    context.beginpath();    context.strokestyle = color.sides[situation].plain;    turtle.setposition(x1, y1);    turtle.setangle(angle);    (var = 0; < n; ++i) {      turtle.forward(length);      turtle.left(turn);    }    context.closepath();    context.stroke();    context.strokestyle = color.sides[situation].special;    context.beginpath();    turtle.setposition(x1, y1);    turtle.forward(length);    context.stroke();  }  polygon.load = function () {    var g = polygon,        canvas = g.canvas = document.getelementbyid('surface'),        context = g.context = canvas.getcontext('2d'),        display = { begin: document.getelementbyid('begin'),                    end: document.getelementbyid('end') },        color = g.color;    g.resizecanvas();    window.onresize = g.resizecanvas;    function makeunselectable(element) {      element.classname += ' unselectable';      element.ondragstart = element.onselectstart = function (event) {        event.preventdefault();      };    }    makeunselectable(canvas);    var numsides = document.getelementbyid('numsides'),        minus = document.getelementbyid('minus'),        plus = document.getelementbyid('plus');    minus.onmousedown = function () {      var current = parseint(numsides.innerhtml, 10);      if (current == 3) {        return;      }      numsides.innerhtml = current-1;      g.drawpolygon('final');    };    plus.onmousedown = function () {      var current = parseint(numsides.innerhtml, 10);      if (current == 20) {        return;      }      numsides.innerhtml = current+1;      g.drawpolygon('final');    };    var controls = [display.begin, display.end, numsides, minus, plus,                    document.getelementbyid('options')];    (var = 0; < controls.length; ++i) {      makeunselectable(controls[i]);    }    var getposition = function (event) {      event = event || window.event;      var rect = canvas.getboundingclientrect(),          left = event.clientx - rect.left,          top = event.clienty - rect.top,          origin = g.origin,          x = left - origin.left,          y = origin.top - top;      return { x: x, y: y };    };    canvas.onmousedown = function (event) {      document.body.style.cursor = 'default';      var position = getposition(event);      g.x1 = g.x2 = position.x;      g.y1 = g.y2 = position.y;      display.begin.innerhtml =          '<span class="label">x1, y1 =</span> '+g.x1+', '+g.y1;      display.end.innerhtml = '';      g.drawpolygon('hover');      (var = 0; < controls.length; ++i) {        controls[i].style.zindex = -10;      }      canvas.onmousemove = function (event) {        var position = getposition(event);        g.x2 = position.x;        g.y2 = position.y;        display.end.innerhtml =            '<span class="label">x2, y2 =</span> '+g.x2+', '+g.y2;        g.drawpolygon('hover');      };    };    function noop() {    }    canvas.onmousemove = noop;    canvas.onmouseup = canvas.onmouseout = function (event) {      if (canvas.onmousemove === noop) {        return;      }      canvas.onmousemove = noop;      g.drawpolygon('final');      (var = 0; < controls.length; ++i) {        controls[i].style.zindex = 0;      }    };  };  window.onload = polygon.load;
body {    margin: 0;    padding: 0;    overflow: hidden;  }  .unselectable {    -webkit-user-select: none;    -khtml-user-drag: none;    -khtml-user-select: none;    -moz-user-select: none;    -moz-user-select: -moz-none;    -ms-user-select: none;    user-select: none;  }  canvas {    width: 100%;    height: 100%;  }  .display {    color: #444;    position: fixed;    left: 40px;    font-family: sans-serif;    font-size: 20px;  }  .label {    color: #aaa;  }  #begin {    top: 20px;  }  #end {    top: 60px;  }  #options {    position: fixed;    left: 40px;    top: 100px;    font-family: sans-serif;    font-size: 28px;  }  #options div {    display: inline;  }  #options .button {    font-size: 32px;    cursor: pointer;  }  #options .button:hover {    color: #55838e;  }  #options .button, #numsides {    padding: 0 5px;  }  #numsides {    cursor: default;  }
<div class="display" id="begin"></div>  <div class="display" id="end"></div>    <div id="options">    <div class="button" id="minus">&minus;</div><div         id="numsides">6</div><div         class="button" id="plus">&plus;</div>  </div>    <canvas id="surface"></canvas>


Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -