Search code examples
javascriptchart.jsellipsefresnel

I am trying to rotate an ellipse with an arbitrary angle in JavaScript. But the outcome is not even an ellipse


I wish to display the Fresnel zone in the chart in which I am hoping to rotate an ellipse by an arbitrary angle. I have given the starting and ending x and y coordinates and I want the ellipse to be rotated not at the center but at the starting point. I have taken help from the below link still I am unable to get a proper ellipse rotated with an angle. Any help would be highly appreciated. Also, the x coordinates need to be formatted to bring the ellipse together. But I am unable to manage that too.

Drawing (Fresnel) ellipse and major axis

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

    <style>
      .chart-container {
        width: 600px;
      }
    </style>
  </head>
  <body>
    <div class="chart-container">
      <canvas id="myChart"></canvas>
    </div>
    <script>
      var step = (2 * Math.PI) / 30;
      console.log("step", step);
      f = 217.25; // frequency
      x1 = 0;
      x2 = 15;
      y2 = 250;
      y1 = 130;
      fr = f * Math.pow(10, 6); // frequency in Hz
      c = 2.997925 * Math.pow(10, 8); // speed of light
      lambda = c / fr;
      xarr = [];
      yarr = [];
      a = (1 / 2) * Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); // radius of major axis
      r = Math.sqrt((lambda * a) / 2); // radius of the minor axis
      w = Math.atan2(y2 - y1, x2 - x1);
      console.log(w);
      for (i = 0; i <= 2 * Math.PI; i += step) {
        xval = a * Math.cos(i);
        yval = r * Math.sin(i);
        xnew = (x1 + x2) / 2 + xval * Math.cos(w) - yval * Math.sin(w);
        ynew = (y1 + y2) / 2 + xval * Math.sin(w) + yval * Math.cos(w);
        xarr.push(xnew);
        yarr.push(ynew);
      }
      console.log(xarr);
      const data = {
        labels: xarr,
        datasets: [
          {
            data: yarr,
            borderColor: "rgba(0,0,0,1)",
          },
        ],
      };
      const config = {
        type: "line",
        data: data,
        options: {
          scales: {
            x: {
              ticks: {
                maxTicksLimit: 5,
                beginAtZero: true,
              },
            },
            y: {
              beginAtZero: true,
              maxTicksLimit: 5,
              grid: {
                display: true,
              },
            },
          },
        },
      };
      const mychart = new Chart(document.getElementById("myChart"), config);
    </script>
  </body>
</html>````

Solution

  • You need to make your x axis a linear scale for your use case. By default it is a category axis, which means it just takes your labels aarray as labels. If you make the scale linear it will map the data to the correct point in the axis:

    options: {
      scales: {
        x: {
          type: 'linear'
        }
      }
    }
    

    Live example:

    var step = (2 * Math.PI) / 30;
    f = 217.25; // frequency
    x1 = 0;
    x2 = 15;
    y2 = 250;
    y1 = 130;
    fr = f * Math.pow(10, 6); // frequency in Hz
    c = 2.997925 * Math.pow(10, 8); // speed of light
    lambda = c / fr;
    xarr = [];
    yarr = [];
    a = (1 / 2) * Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); // radius of major axis
    r = Math.sqrt((lambda * a) / 2); // radius of the minor axis
    w = Math.atan2(y2 - y1, x2 - x1);
    for (i = 0; i <= 2 * Math.PI; i += step) {
      xval = a * Math.cos(i);
      yval = r * Math.sin(i);
      xnew = ((x1 + x2) / 2 + xval * Math.cos(w) - yval * Math.sin(w)) + 2.335; // Just add the max amount that it goes into negative so it shifts the elipse into a positive x values only
      ynew = (y1 + y2) / 2 + xval * Math.sin(w) + yval * Math.cos(w);
      xarr.push(xnew);
      yarr.push(ynew);
    }
    
    var options = {
      type: 'line',
      data: {
        labels: xarr,
        datasets: [{
          label: '# of Votes',
          data: yarr,
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          x: {
            type: 'linear'
          }
        }
      }
    }
    
    var ctx = document.getElementById('chartJSContainer').getContext('2d');
    new Chart(ctx, options);
    <body>
      <canvas id="chartJSContainer" width="600" height="400"></canvas>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
    </body>