javascript - 想要将 6 个圆圈放置在数学上精确的几何形状中,但它们没有正确对齐

标签 javascript math canvas geometry kineticjs

相关的 live-javascript/jsbin:http://jsbin.com/ekuyam/2/edit

我基本上只是在相对于 Canvas 中心的六边形中生成点,然后在六边形中的每个点绘制圆圈,但仔细检查圆圈没有正确对齐,它实际上是不可见的,除非你使用大圈子。

当我使用小圆圈时,它们似乎非常准确地放置在 Canvas 上,如下所示: enter image description here

但是通过使用更大的圆圈进行仔细检查(有点像放大),发现数学中存在一些不准确的地方,从这里不需要的空间/区域可以看出: enter image description here

线条应该完美对齐,但我得到了一些不需要的空间。为什么会这样,我该如何修改?

代码:

function hexagon(w, h, p) {
  var points = 6;
  var width = w;
  var height = h;
  var angle = ((2 * Math.PI) / points);
  var hexagon = [];

  for (i = 0; i < points; i++) {
    hexagon.push({
      x: width * Math.sin(angle * i) + p.x, 
      y: height * Math.cos(angle * i) + p.y
    })
  }

  return hexagon
}

var stage = new Kinetic.Stage({
  container: "container",
  width: 600,
  height: 600
});

var layer = new Kinetic.Layer();
var group = new Kinetic.Group({x: 600/2, y: 600/2, draggable: false});

var radius = 1000;
var s = new Kinetic.Circle({
  radius: radius,
  stroke: 'black',
  strokeWidth: 1,
  draggable: true
});
group.add(s);

var hex_points = hexagon(radius, radius, {x: 600/2, y: 600/2});
for (p in hex_points) {
  var s = new Kinetic.Circle({
    radius: radius,
    stroke: 'black',
    strokeWidth: 1,
    draggable: true
  });
  s.setPosition({x: hex_points[p].x - 600/2, y: hex_points[p].y - 600/2})
  group.add(s);
}

layer.add(group);
stage.add(layer);

最佳答案

这是因为 sin(2 * Math.PI)/6 = sqrt(3)/2 是一个无理数。然而, float 只能表示有理数(实际上只有分母是 2 的幂)。因此,您总会有一些舍入误差。如果将圆圈放大到足够大,则可以看到此舍入误差。为了防止这种情况,您需要限制放大倍率。

如果您绝对必须绕过它,最简单的方法就是追求更高的算术精度。

另一种方法是使用公式 (x-x_0)^2 + (y-y_0)^2 = R^2 并在不使用三 Angular 函数的情况下围绕已知交点局部求解。更具体地说,函数 f(x,y):= (x-x_0)^2+(y-y_0)^2 满足 inverse function theorem 的条件。除 x=x_0 和 y=y_0 之外的任何地方。请注意,圆示例包含在另一篇关于 implicit function theorem 的维基百科文章中。 .手头的例子是一个全纯函数,因此局部逆也将是全纯的。特别是它有一个很好的局部近似 Taylor series expansion. .这种方法的要点是您不要围绕中心绘制圆圈,而是“通过所需的交点”绘制它。因此,您可以强制它“与”这一点“相交”。但请记住,他的“交点”只是一个近似值,因为 float 永远无法正确表示 sqrt(3) 或其有理倍数。

现在怎么办?我会做什么:一旦放大倍数使得屏幕上只有一个交点,我会通过替换 R 作弊,使得 R^2 = (x_i-x_0)^2+(y_i-y_0)^2 其中 (x_i , y_i) 是所需的交点,“(x_0,y_0)”是圆心。然后我会继续使用标准圆公式。

一个非常简单的方法是确保圆线也得到缩放。因此,对于高倍率,不精确性将隐藏在圆的“厚”周长下。

关于javascript - 想要将 6 个圆圈放置在数学上精确的几何形状中,但它们没有正确对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16052630/

相关文章:

javascript - (javascript) 是否可以将不同对象类型的数组拆分为一种对象类型的多个数组

c++ - 在运行时求解 y 立方方程

c++ - 椭圆旋转矩阵?

javascript - 当我们有很多动画时,canvas 不是应该比 dom 操作更快吗?

javascript - 对于圆内的点,找出它在哪四分之一?

javascript - 如何在不模糊的情况下拉伸(stretch) WebGL Canvas ?样式 "image-rendering"不起作用

javascript - 如果使用 javascript 选中复选框,则显示更多内容

javascript - 数组附加项未进行到结帐

javascript - 根据正则表达式检查 json 值会抛出不是函数错误

algorithm - 这个有趣事件的最快算法