1

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

我基本上只是在相对于画布中心的六边形中生成点,然后在六边形的每个点上绘制圆圈,但仔细观察这些圆圈并没有正确对齐,除非你使用大圆圈,否则它实际上并不可见。

当我使用小圆圈时,它们似乎非常准确地放置在画布上,如下所示: 在此处输入图像描述

但是通过使用更大的圆圈(有点像放大)进行仔细检查,发现数学中存在一些不准确之处,这可以从这里不需要的空间/区域看出: 在此处输入图像描述

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

代码:

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);
4

2 回答 2

2

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

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

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

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

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

于 2013-04-17T06:11:34.060 回答
0

浮点数存储和三角函数都不是造成如此大误差的原因。

更有可能的是,您使用的圆绘图程序实际上是用 4 个贝塞尔样条曲线逼近一个圆。这是绘图库中非常非常常见的速度优化。您几乎完美地计算了中心,但圆圈根本没有完美绘制。

参见例如:http ://spencermortensen.com/articles/bezier-circle/

于 2017-04-17T08:22:02.953 回答