确保计算返回的坐标完全相同

问题描述 投票:0回答:1

我将 4 个小圆圈以

0, 90, 180, 270
度角放置在一个大圆圈上。我希望javascript为红色和蓝色圆圈返回完全相同
y
(因为移位是水平的,y相同但x改变),为绿色和粉色圆圈返回完全相同
x
(因为移位是垂直,x 相同但 y 改变)。

虽然下面的javascript返回相同的x但返回不同的y(红色= 237.76900370542438和蓝色= 237.7690037054244)。展望未来,它会搞乱所有的计算,因为它们不一样。

我不知道这个问题的根本原因是什么,但是有办法解决吗?我需要它们完全相同。

const angle = [0, 90, 180, 270];
const angleCoord = [];

angle.forEach(
    (a, i) => {
        const element = d3.select('.circ1').node();
        const cx = parseFloat(element.getAttribute('cx'));
        const cy = parseFloat(element.getAttribute('cy'));
        const r = parseFloat(element.getAttribute('r'));
        const x = cx + Math.cos(a * Math.PI / 180) * r;
        const y = cy + Math.sin(a * Math.PI / 180) * r;
        angleCoord.push({
            angle: a,
            x: x,
            y: y
        })
    }
);

const color = ['red', 'green', 'blue', 'pink'];

d3.select('svg').append('g')
    .attr('class', 'circles')
    .selectAll('circle')
    .data(angleCoord)
    .join('circle')
    .attr('class', (_, i) => color[i])
    .attr('cx', d => d.x)
    .attr('cy', d => d.y)
    .attr('r', '4')
    .attr('fill', (_, i) => color[i]);
<!DOCTYPE html>
<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>
  </head>
  <script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
  <script type="text/javascript" src='https://cdn.jsdelivr.net/npm/[email protected]/bignumber.min.js'></script>
  <body>
    <div id="container" class="svg-container"></div>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1536 720">
      <circle class="circ1" cx="384" cy="237.76900370542438" r="122.23099629457562" fill="none" stroke="black"></circle>
    </svg>
    <script src="prod3.js"></script>
  </body>
</html>

javascript svg geometry precision
1个回答
0
投票

sin 180 的精度大约与 PI/2 的精度加上或减去一些无穷小误差一样准确。

如果您想要“精确”值,请考虑使用 90° 角度倍数的 sin 和 cos 的“精确”值。例如:

const lookupTable = {
  0: { sin: 0, cos: 1 },
  90: { sin: 1, cos: 0 },
  180: { sin: 0, cos: -1 },
  270: { sin: -1, cos: 0 }
};

const exactSin = degrees => lookupTable[degrees].sin;
const exactCos = degrees => lookupTable[degrees].cos;

const angle = [0, 90, 180, 270];
const angleCoord = [];

const lookupTable = {
  0: { sin: 0, cos: 1 },
  90: { sin: 1, cos: 0 },
  180: { sin: 0, cos: -1 },
  270: { sin: -1, cos: 0 }
};

const exactSin = (degrees) => lookupTable[degrees].sin;
const exactCos = (degrees) => lookupTable[degrees].cos;

angle.forEach(
    (a, i) => {
        const element = d3.select('.circ1').node();
        const cx = parseFloat(element.getAttribute('cx'));
        const cy = parseFloat(element.getAttribute('cy'));
        const r = parseFloat(element.getAttribute('r'));
        const x = cx + exactCos(a) * r;
        const y = cy + exactSin(a) * r;
console.log({x, y});
        angleCoord.push({
            angle: a,
            x: x,
            y: y
        })
    }
);

const color = ['red', 'green', 'blue', 'pink'];

d3.select('svg').append('g')
    .attr('class', 'circles')
    .selectAll('circle')
    .data(angleCoord)
    .join('circle')
    .attr('class', (_, i) => color[i])
    .attr('cx', d => d.x)
    .attr('cy', d => d.y)
    .attr('r', '4')
    .attr('fill', (_, i) => color[i]);
<!DOCTYPE html>
<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>
  </head>
  <script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
  <script type="text/javascript" src='https://cdn.jsdelivr.net/npm/[email protected]/bignumber.min.js'></script>
  <body>
    <div id="container" class="svg-container"></div>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1536 720">
      <circle class="circ1" cx="384" cy="237.76900370542438" r="122.23099629457562" fill="none" stroke="black"></circle>
    </svg>
    <script src="prod3.js"></script>
  </body>
</html>

© www.soinside.com 2019 - 2024. All rights reserved.