给出正多边形的一侧上,找到其余的边 [英] Given one side of a regular polygon, find the remaining sides

查看:173
本文介绍了给出正多边形的一侧上,找到其余的边的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们给出:

  • 正多边形的边数
  • 由坐标(x1,y1)和定义的一侧(X2,Y2)

我要找出剩余的坐标。我怎样才能做到这一点?

解决方案

假设我们有一个这已引起了 N -sided正多边形从 X1,Y1 移动到<$ C $的一个片段C> X2,Y2 。为了绘制其余的边,我们这样做 N-1 时间:

  • 转一定角度
  • 将推进一定距离

这是我们必须要打开角度为360 / N 度。例如,如果我们画一个三角形,龟有转120度,每一段后。如果我们在绘制三角形按顺时针方向,我们从乌龟的当前方向减去120度。如果我们绘制它逆时针,我们增加120度。

前进的距离是所述第一部分的长度。我们可以使用勾股定理的计算段的长度。在JavaScript中,我们可以这样实现:

 变种DX = X2-X1,
    DY = Y2,Y1,
    长度=的Math.sqrt(DX * DX + DY * DY);
 

龟的初始取向是相同的第一线段,我们可以通过取 DX /长度的逆余弦计算的角度:

  VAR角= Math.acos(DX /长度);
如果(镝℃,){
  角= 2 * Math.PI  - 角;
}
 

要利用转角和段长,我们必须实现以下乌龟操作:

  • 设置乌龟位置 X,Y
  • 设置龟方向角度
  • 将龟距离单位向前当前方向
  • 添加增量乌龟方向
  • 查询当前位置 X,Y 乌龟

在实现这些操作,我们可以写一个循环迭代 N-1 次。在每次迭代中,我们转身向前迈进了prescribed金额,查询乌龟位置,并打印的坐标。

要实现龟行动,我们必须保存乌龟的位置和方向。下面是一个简单的方法来做到这一点:

  VAR龟= {X:0,Y:0,角度:0};
 

要移动龟距离单位向前当前方向,我们使用基本的三角:

  turtle.x + = Math.cos(turtle.angle)*距离;
turtle.y + = Math.sin(turtle.angle)*距离;
 

请注意,在JavaScript中的三角函数与弧度,而不是学位工作。有2 PI;弧度转了一圈,因此亚太裔;弧度成半圆形。如果我们有一个夹角研究 EX pressed弧度,相当于以度为 R / Math.PI * 180

当我们增加或减少的龟取向的值,就可以结束了一个角,它比2圆周率小于零或大于;.这不会影响我们的三角函数计算,但它可以使程序难以调试。为了确保角度始终在区间[0,2 PI),我们可以做到以下几点,只要 turtle.angle 被修改:

  turtle.angle  -  = Math.floor(turtle.angle /(2 * Math.PI))* 2 * Math.PI;
 

我已经写了code片段展示乌龟的做法。运行code。通过点击下面的蓝色按钮,然后单击并拖动绘制多边形的第一段。您可以通过点击加号和减号更改边数。

VAR多边形= {   颜色: {     轴:#ccc,     双方:{        悬停:{平淡:#dddfa4,特别:#9d9c64}​​,        最后:{平淡:#b0c598,特别:#4f7337}     }   } }; Polygon.turtle = {X:0,Y:0,角度:0}; Polygon.turtle.setPosition =功能(X,Y){   VAR G =多边形,       龟= g​​.turtle,       上下文= g.context,       起源= g.origin;   turtle.x = X;   turtle.y = Y;   context.moveTo(origin.left + turtle.x,origin.top - turtle.y); }; Polygon.turtle.setAngle =功能(角度){   VAR G =多边形,       龟= g​​.turtle;   turtle.angle =角; }; Polygon.turtle.left =功能(增量){   VAR G =多边形,       龟= g​​.turtle;   turtle.angle = g.normalizeAngle(turtle.angle +增量); }; Polygon.turtle.right =功能(增量){   VAR G =多边形,       龟= g​​.turtle;   turtle.angle = g.normalizeAngle(turtle.angle - 三角洲); }; Polygon.normalizeAngle =功能(角度){   角 - = Math.floor(角度/(2 * Math.PI))* 2 * Math.PI;   返回角; }; Polygon.turtle.forward =功能(距离){   VAR G =多边形,       龟= g​​.turtle,       帆布= g.canvas,       上下文= g.context,       起源= g.origin;   turtle.x + = Math.cos(turtle.angle)*距离;   turtle.y + = Math.sin(turtle.angle)*距离;   context.lineTo(origin.left + turtle.x,origin.top - turtle.y); }; Polygon.resizeCanvas =功能(){   VAR G =多边形,       帆布= g.canvas,       上下文= g.context,       宽度= canvas.width = window.innerWidth,       身高= canvas.height = window.innerHeight;   g.origin = {左:Math.floor(宽度/ 2),顶部:Math.floor(高度/ 2)};   g.drawAxes(); }; Polygon.drawAxes =功能(){   VAR G =多边形,       帆布= g.canvas,       上下文= g.context,       起源= g.origin,       颜色= 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 =功能(情况){   VAR G =多边形,       帆布= g.canvas,       上下文= g.context,       龟= g​​.turtle,       颜色= g.color,       N = parseInt函数(的document.getElementById('即numSides')。innerHTML的,10),       转= 2 * Math.PI / n时,       X1 = g.x1,Y1 = g.y1,X2 = g.x2,Y2 = g.y2,       DX = X2-X1,       DY = Y2,Y1,       长度=的Math.sqrt(DX * DX + DY * DY);   VAR角= Math.acos(DX /长度);   如果(镝℃,){     角= 2 * Math.PI - 角;   }   context.clearRect(0,0,canvas.width,canvas.height);   g.drawAxes();   context.lineWidth = 4;   context.lineCap ='圆';   context.beginPath();   context.strokeStyle = color.sides [局面] .plain;   turtle.setPosition(X1,Y1);   turtle.setAngle(角度);   为(变种I = 0; I&n种++ⅰ){     turtle.forward(长);     turtle.left(转);   }   context.closePath();   context.stroke();   context.strokeStyle = color.sides [局面]。特别;   context.beginPath();   turtle.setPosition(X1,Y1);   turtle.forward(长);   context.stroke(); } Polygon.load =功能(){   VAR G =多边形,       帆布= g.canvas =的document.getElementById('面'),       上下文= g.context = canvas.getContext(2D),       显示器= {开始:的document.getElementById('开始'),                   结束:的document.getElementById('端')},       颜色= g.color;   g.resizeCanvas();   window.onresize = g.resizeCanvas;   功能makeUnselectable(元){     element.className + ='不可选择;     element.ondragstart = element.onselectstart =功能(事件){       。事件preventDefault();     };   }   makeUnselectable(画布);   无功即numSides =的document.getElementById('即numSides),       减=的document.getElementById('减'),       加=的document.getElementById('加');   minus.onmousedown =功能(){     变种电流= parseInt函数(numSides.innerHTML,10);     如果(当前== 3){       返回;     }     numSides.innerHTML =当前-1;     g.drawPolygon('最终');   };   plus.onmousedown =功能(){     变种电流= parseInt函数(numSides.innerHTML,10);     如果(当前== 20){       返回;     }     numSides.innerHTML =当前+ 1;     g.drawPolygon('最终');   };   无功控制= [display.begin,display.end,即numSides,减,加,                   的document.getElementById('选择');   对于(VAR I = 0; I&LT; controls.length ++我){     makeUnselectable(对照[I]);   }   VAR为getPosition =功能(事件){     事件=事件|| window.event;     VAR RECT = canvas.getBoundingClientRect()         左= event.clientX - rect.left,         顶部= event.clientY - rect.top,         起源= g.origin,         X =左 - origin.left,         Y = origin.top - 顶;     返回{X:X,Y:Y};   };   canvas.onmousedown =功能(事件){     document.body.style.cursor =默认;     VAR位置=为getPosition(事件);     g.x1 = g.x2 = position.x;     g.y1 = g.y2 = position.y;     display.begin.innerHTML =         '&LT;跨度类=标签&GT; X1,Y1 =&LT; / SPAN&GT; + g.x1 +','+ g.y1;     display.end.innerHTML ='';     g.drawPolygon('悬停');     对于(VAR I = 0; I&LT; controls.length ++我){       对照组[I] .style.zIndex = -10;     }     canvas.onmousemove =功能(事件){       VAR位置=为getPosition(事件);       g.x2 = position.x;       g.y2 = position.y;       display.end.innerHTML =           '&LT;跨度类=标签&GT; X2,Y2 =&LT; / SPAN&GT; + g.x2 +','+ g.y2;       g.drawPolygon('悬停');     };   };   功能空操作(){   }   canvas.onmousemove =空操作;   canvas.onmouseup = canvas.onmouseout =功能(事件){     如果(canvas.onmousemove ===空操作){       返回;     }     canvas.onmousemove =空操作;     g.drawPolygon('最终');     对于(VAR I = 0; I&LT; controls.length ++我){       对照组[I] .style.zIndex = 0;     }   }; }; 在window.onload = Polygon.load;

体{   保证金:0;   填充:0;   溢出:隐藏; } .unselectable {   -webkit-用户选择:无;   -khtml用户拖拽:无;   -khtml用户选:无;   -moz-用户选择:无;   -moz-用户选择:-moz-无;   -ms-用户选择:无;   用户选择:无; } 帆布 {   宽度:100%;   高度:100%; } 。显示 {   颜色:#444;   位置:固定;   左:40PX;   字体家庭:无衬线;   字体大小:20像素; } 。标签 {   颜色:#aaa; } #开始 {   顶:20像素; } #结束 {   顶部:60PX; } #options {   位置:固定;   左:40PX;   顶:100像素;   字体家庭:无衬线;   字体大小:28px; } #options DIV {   显示:内联; } #options .button {   字体大小:32PX;   光标:指针; } #options .button:悬停{   颜色:#55838e; } #options .button,#numSides {   填充:0 5px的; } #numSides {   光标:默认值; }

&LT; D​​IV CLASS =显示ID =开始&GT;&LT; / DIV&GT; &LT; D​​IV CLASS =显示ID =结束&GT;&LT; / DIV&GT; &LT; D​​IV ID =选项&GT;   &LT; D​​IV CLASS =按钮ID =减&GT;&安培;负;&LT; / DIV&GT;&LT; D​​IV        ID =即numSides&GT; 6≤/ DIV&GT;&LT; D​​IV        类=按钮ID =加上&GT;&安培;加;&LT; / DIV&GT; &LT; / DIV&GT; &LT;帆布ID =面&GT;&LT; /帆布&GT;

We are given:

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

I have to find out the remaining coordinates. How can I do this?

解决方案

Suppose we have a turtle that has drawn one segment of an n-sided regular polygon by moving from x1, y1 to x2, y2. To draw the remaining sides, we do this n-1 times:

  • turn by a certain angle
  • move forward a certain distance

The angle that we have to turn is 360/n degrees. For example, if we're drawing a triangle, the turtle has to turn 120 degrees after each segment. If we're drawing the triangle clockwise, we subtract 120 degrees from the current orientation of the turtle. If we're drawing it counterclockwise, we add 120 degrees.

The distance to move forward is the length of the first segment. We can calculate the length of the segment using the Pythagorean theorem. In JavaScript, we can implement it thus:

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

The initial orientation of the turtle is the same as the angle of the first line segment, which we can calculate by taking the inverse cosine of dx/length:

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

To make use of the turning angle and segment length, we have to implement the following turtle operations:

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

After those operations are implemented, we can write a loop that iterates n-1 times. In each iteration, we turn and move forward by the prescribed amounts, query the turtle position, and print the coordinates.

To implement the turtle operations, we have to store the position and orientation of the turtle. Here is an easy way to do so:

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

To move the turtle distance units forward in its current orientation, we use basic trigonometry:

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

Note that the trigonometric functions in JavaScript work with radians rather than degrees. There are 2π radians in a circle, hence π radians in a semicircle. If we have an angle r expressed in radians, the equivalent in degrees is r / Math.PI * 180.

When we add or subtract a value from the turtle orientation, it is possible to end up with an angle that is less than zero or greater than 2π. This does not affect our trigonometric calculations, but it can make the program difficult to debug. To ensure that the angle is always in the range [0, 2π), we can do the following whenever turtle.angle gets modified:

turtle.angle -= Math.floor(turtle.angle / (2*Math.PI)) * 2*Math.PI;

I have written a code snippet to demonstrate the turtle approach. Run the code by clicking the blue button below, then click and drag to draw the first segment of a polygon. You can change the number of sides by clicking on the plus and 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);
  for (var i = 0; i < 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')];
  for (var i = 0; i < 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');
    for (var i = 0; i < 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');
    for (var i = 0; i < 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>

这篇关于给出正多边形的一侧上,找到其余的边的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆