Холст: Как построить спираль вокруг указанной фиолетовой точки от указанной оранжевой точки до указанной зеленой точки - PullRequest
3 голосов
/ 18 марта 2019

Я пытаюсь нарисовать спираль, начиная с начальной точки и заканчивая конечной точкой. Спираль также имеет заданную центральную точку, поэтому она может нарисовать спирали вокруг этой центральной точки. Я не могу заставить это работать, как-то математика совершенно неверна. Любой совет, как решить эту проблему?

jsfiddle кода, который я попробовал, находится здесь.

<!DOCTYPE HTML>
<html>
<body>
  <canvas id="myCanvas" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>

  <script type="text/javascript">
    var c = document.getElementById("myCanvas");
    var cxt = c.getContext("2d");

    //center of the spiral coords:
    var centerX = 400;
    var centerY = 300;

    //draw the center of spiral point:
    drawCirc(centerX, centerY, 10, '#6f0c4f');

    var gap = 8;
    var STEPS_PER_ROTATION = 50;
    var rotations = 4;
    var increment = rotations * Math.PI / STEPS_PER_ROTATION;
    var theta = increment;

    //start point:
    var startX = 500;
    var startY = 380;

    //end point:
    var endX = 600
    var endY = 300;

    //draw the start and end points as small circles:
    drawCirc(startX, startY, 6, '#FF0000');
    drawCirc(endX, endY, 6, '#00FF00');

    //trying to calculate theta start position:
    theta = Math.abs(((centerX - startX) / Math.cos(theta)) / gap);

    var ind = 0;
    while (theta < rotations * Math.PI * 2) {
      var newX = centerX + theta * Math.cos(theta) * gap;
      var newY = centerY + theta * Math.sin(theta) * gap;
      var ukwObj = { x: newX, y: newY };
      if (ind == 0) {
        //draw start point with differnt color to differentiate
        drawCirc(newX, newY, 2, 'orange');
      } else {
        drawCirc(newX, newY);
      }
      ind++;
      theta = theta + increment;
    }

    function drawCirc(x, y, radius = 2, stroke = '#000000') {
      cxt.beginPath();
      cxt.arc(x, y, radius, 0, 2 * Math.PI);
      cxt.strokeStyle = stroke;
      cxt.stroke();
      cxt.fillStyle = stroke;
      cxt.fill();
    }

    cxt.stroke(); // draw the spiral
  </script>
</body>
</html>

1 Ответ

2 голосов
/ 18 марта 2019

Принцип построения круга:
Учитывая центр x,y, радиус r, мы можем построить точки, принадлежащие окружности, вычислив их координаты следующим образом: px = x + r * Math.cos(angle) и py = y + r * Math.sin(angle), когда угол изменяется от 0 до 2* Math.PI.
Если r увеличивается при изменении угла, мы получаем внешнюю спираль (от угла 0 до угла 2 * PI, что эквивалентно 0).

Для рассматриваемой задачи нам нужно вычислить начальное и конечное положение спирали в полярных координатах (расстояние, угол).
Поэтому нам нужно вычислить начальный угол, начальное расстояние, конечный угол и конечное расстояние и построить каждую точку, постепенно увеличивая угол и расстояние.

Первоначальный расчет тета был неверным, я изменил его.

Затем мне нужно было вычислить начальное расстояние между центром и начальной точкой, а также конечное расстояние между центром и конечной точкой.

Во время вращения вы прогрессируете от начального расстояния до конечного расстояния.

Общее угловое расстояние должно быть totalTheta = numberOfRotation * 2 * Math.PI + (endAngle - startAngle), я заменил rotations * Math.PI * 2 на totalTheta)

Просто для забавы и чтобы продемонстрировать, что это работает для любых начальных условий, я немного рандомизировал начальную позицию, конечную позицию и число оборотов.

Я также уменьшил приращение угла на каждой итерации, чтобы расстояние между каждой точкой выглядело более равномерным, но вы можете оставить комментарий, чтобы сохранить постоянную угловую скорость.

Приведенное ниже решение случайным образом выберет оранжевую точку, зеленую точку, число витков для завершения спирали и построит спираль вокруг неподвижной фиолетовой точки.

    var c = document.getElementById("myCanvas");
    var cxt = c.getContext("2d");

    //center of the spiral coords:
    var centerX = 200;
    var centerY = 150;

    //draw the center of spiral point:
    drawCirc(centerX, centerY, 10, '#6f0c4f');

    var gap = 8;
    var STEPS_PER_ROTATION = 50;
    var rotations = 1 + parseInt(Math.random() * 5, 10);
    var increment = rotations * Math.PI / STEPS_PER_ROTATION;
    var theta = increment;
    var dist = 0;

    //start point:
    var startX = centerX + (Math.random() * 150 - 75);
    var startY = centerY + (Math.random() * 150 - 75);
    var startAngleOffset = startX > centerX ? (startY > centerY ? 0 : 0) : (startY > centerY ? Math.PI : Math.PI);
    var startAngleSign = startX > centerX ? (startY > centerY ? 1 : -1) : (startY > centerY ? -1 : 1);

    //end point:
    var endX = centerX + (Math.random() * 150 - 75);
    var endY = centerY + (Math.random() * 150 - 75);
    var endAngleOffset = endX > centerX ? (endY > centerY ? 0 : 0) : (endY > centerY ? Math.PI : Math.PI);
    var endAngleSign = endX > centerX ? (endY > centerY ? 1 : -1) : (endY > centerY ? -1 : 1);

    //draw the start and end points as small circles:
    drawCirc(startX, startY, 6, '#FF0000');
    drawCirc(endX, endY, 6, '#00FF00');

    var startTheta = theta = startAngleOffset + startAngleSign * Math.atan(Math.abs(startY - centerY)/Math.abs(startX - centerX));

    var endTheta = endAngleOffset + endAngleSign * Math.atan(Math.abs(endY - centerY)/Math.abs(endX - centerX));

    var totalTheta = rotations * 2 * Math.PI + (endTheta - startTheta)
    dist = Math.sqrt(Math.pow(startY - centerY, 2) + Math.pow(startX - centerX, 2));

    finalDist = Math.sqrt(Math.pow(endY - centerY, 2) + Math.pow(endX - centerX, 2));
    var ind = 0;
    while (theta -startTheta < totalTheta) {
      var currentDist = (dist + ((finalDist - dist)* ((theta - startTheta) / (totalTheta))));
      var newX = centerX + currentDist * Math.cos(theta);
      var newY = centerY + currentDist * Math.sin(theta);
      var ukwObj = { x: newX, y: newY };
      if (ind == 0) {
        //draw start point with differnt color to differentiate
        drawCirc(newX, newY, 2, 'orange');
      } else {
        drawCirc(newX, newY);
      }
      ind++;
      theta = theta + increment;
      // decrement increment to make the space between points look more regular
      increment = Math.max(0.01, increment - 0.00096);
    }

    function drawCirc(x, y, radius = 2, stroke = '#000000') {
      cxt.beginPath();
      cxt.arc(x, y, radius, 0, 2 * Math.PI);
      cxt.strokeStyle = stroke;
      cxt.stroke();
      cxt.fillStyle = stroke;
      cxt.fill();
    }

    cxt.stroke(); // draw the spiral
<!DOCTYPE HTML>
<html>
<body>
  <canvas id="myCanvas" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>
</body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...