JavaScript и тригонометрия/Овал

#javascript #math #trigonometry

#javascript #математика #тригонометрия

Вопрос:

Я использовал эту функцию this oval (которую я нашел в Википедии http://en.wikipedia.org/wiki/Ellipse ) для нанесения точек на макет. Я раскладывал вещи с помощью двух-пяти точек, нанесенных вокруг овала, без каких-либо проблем. Функция имеет параметр, называемый «шаги»; параметр «шаги» задает количество точек для построения вокруг овала.

Вот основная проблема: если «шаги» (количество точек для построения графика) равны числам 7, 11, 13 или 14, это приводит к разрыву. Прошло несколько лет с тех пор, как я изучал тригонометрию, так что, по сути, я застрял.

Вторая незначительная проблема: у меня был код, распечатывающий все точки, но когда я скопировал / вставил и удалил посторонний код для публикации здесь, он печатает только последнюю точку построения (не уверен, почему).

 <html>
<head>
<script type="text/javascript">
    var elipticalLayout=new Array();
    for (i=0; i <36; i  ){
        elipticalLayout[i]=new Array(2);
    }

    /*
    * This functions returns an array containing the specified 
    *    number of 'steps' (points) to draw an ellipse.
    *
    * @param x {double} X coordinate
    * @param y {double} Y coordinate
    * @param a {double} Semimajor axis
    * @param b {double} Semiminor axis
    * @param angle {double} Angle of the ellipse
    *
    * Attribution: This function is from http://en.wikipedia.org/wiki/Ellipse
    */
    function calculateEllipticalLayout(x, y, a, b, angle, steps) {

      var points = [];

      // Angle is given by Degree Value
      var beta = -angle * (Math.PI / 180); //(Math.PI/180) converts Degree Value into Radians
      var sinbeta = Math.sin(beta);
      var cosbeta = Math.cos(beta);

      for (var i = 0; i < 360; i  = 360 / steps) //{
        var alpha = i * (Math.PI / 180) ;
        var sinalpha = Math.sin(alpha);
        var cosalpha = Math.cos(alpha);

        var X = x   (a * cosalpha * cosbeta - b * sinalpha * sinbeta);
        var Y = y   (a * cosalpha * sinbeta   b * sinalpha * cosbeta);
        elipticalLayout[i/(360/steps)][0]=X;
        elipticalLayout[i/(360/steps)][1]=Y;
    }

    </script>
</head>
<body>
    <script type="text/javascript">

        calculateEllipticalLayout(300, 300, 245, 125,  15,    15);

        for (i=0; i<elipticalLayout.length; i  ){
            document.write(i   ", "   elipticalLayout[i][0]   ", "   elipticalLayout[i][1]   "<br>");
        }
    </script>

</body>
</html>
  

Ответ №1:

Я бы объявил elipticalLayout внутри функции и вернул ее. Ниже показано, как бы я написал функцию.

Обратите внимание, что в javascript нет такого понятия, как «double» или даже целое число, тип переменной определяется ее значением. Числа — это просто числа, они могут быть примитивами или числовыми объектами (почти никогда не требуются).

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

 var elipticalLayout = [];

/*
* This functions returns an array containing the specified 
*    number of 'steps' (points) to draw an ellipse.
*
* @param x     - X coordinate
* @param y     - Y coordinate
* @param a     - Semimajor axis
* @param b     - Semiminor axis
* @param angle - Angle of the ellipse
*
* Attribution: This function is from http://en.wikipedia.org/wiki/Ellipse
*/
function calculateEllipticalLayout(x, y, a, b, angle, steps) {

  var points = [];
  var step = 360 / steps;
  var k = Math.PI/180;    // Convert deg to rad
  var cos = Math.cos;
  var sin = Math.sin;
  var i = 0;

  // Convert angle to radians
  var beta = -angle * k;
  var sinbeta = sin(beta);
  var cosbeta = cos(beta);

  while (i < 360) {

    var alpha = i * k;
    var sinalpha = sin(alpha);
    var cosalpha = cos(alpha);

    var X = x   (a * cosalpha * cosbeta - b * sinalpha * sinbeta);
    var Y = y   (a * cosalpha * sinbeta   b * sinalpha * cosbeta);

    // Truncate numbers to integer and put into array
    elipticalLayout.push([X|0, Y|0]);

    // Keep X,Y as floats
    // elipticalLayout.push([X, Y]);

    i  = step;
  }
}
  

Ответ №2:

Вы заполняете только steps количество элементов в elipticalLayout. Но пытаюсь вывести 36 из них.

Это elipticalLayout[i/(360/steps)][0]=X; неправильно, поскольку приведет к «дырам» в последовательности из-за float int округления.

У вас должно получиться что-то вроде этого:

 var n = 0;
for(...)
   elipticalLayout[n][0]=X;
   elipticalLayout[n][1]=Y;
     n;
  

Комментарии:

1. Я подумаю об этом; спасибо. Что касается массива, то массив используется снова и снова для построения разных овалов с разным количеством точек. Я отслеживал количество шагов (точек), поэтому тот факт, что массив больше, чем количество фактических точек, не был проблемой (хотя я понимаю, что это не элегантное решение, я не думаю, что размер массива является проблемой).