Android的AddArc没有按预期工作

时间:2017-05-05 07:53:14

标签: c# android math xamarin geometry

我在Android上正确渲染弧线时遇到问题。我怀疑我的数学在这里失败了,但我已经检查并重新检查,无法发现问题。

请考虑以下事项:

Geometry rendering

其中:

  • R是椭圆的边界矩形
  • O是椭圆的原点
  • a是椭圆的x半径
  • b是椭圆的y半径
  • P1是椭圆上的第一个点
  • P2是椭圆上的第二个点

我希望弧线在P1和P2之间延伸,但正如你所看到的,它会提前开始并结束。

一旦我确定了椭圆的边界矩形(这是正确的),我首先绘制一些调试信息:

// highlight each important point
path.AddCircle(P1.X, P1.Y, 3, Graphics.Path.Direction.Cw);
path.AddCircle(P2.X, P2.Y, 3, Graphics.Path.Direction.Cw);
path.AddCircle(O.X, O.Y, 3, Graphics.Path.Direction.Cw);

// draw bounding rectangle
path.AddRect(rect, Graphics.Path.Direction.Cw);

// draw in ellipse radii (a and b)
path.MoveTo(O.X, O.Y);
path.RLineTo(radius.Width, 0);
path.MoveTo(O.X, O.Y);
path.RLineTo(0, radius.Height);

在上面描述的具体示例中,这些是我正在使用的值(为了清楚起见,我将稍微舍入所有值):

O = (644, 850.154)
P1 = (528.08, 1030.4)
P2 = (759.92, 1030.4)
R = (322, 656.954, 644, 386.4)

到目前为止,这么好。以上所有内容都应该是正确的。接下来,我计算从OP1P2的归一化向量:

var P1Vec = (P1 - O).Normalize();
var P2Vec = (P2 - O).Normalize();

这些出现为:

P1Vec = (-0.541, 0.841)
P2Vec = (0.541, 0.841)

为了确保这些是正确的,我添加了一些调试图形:

path.MoveTo(O.X, O.Y);
var end = startVec * 400;
path.RLineTo(end.X, end.Y);
path.MoveTo(O.X, O.Y);
end = endVec * 400;
path.RLineTo(end.X, end.Y);

正如您从图片中看到的那样,正如您所期望的那样,这些线条将完全切换为P1P2

所以下一步是弄清楚角度,因为那是Android的AddArc方法所期望的:

var P1VecDot = Point.UnitX.Dot(P1Vec);
var P2VecDot = Point.UnitX.Dot(P2Vec);

var P1Acos = Math.Acos(P1VecDot);
var P2Acos = Math.Acos(P2VecDot);

var P1Angle = P1Acos.ToDegrees();
var P2Angle = P2Acos.ToDegrees();

我在这里得到的价值是:

P1VecDot = -0.541
P2VecDot = 0.541
P1Acos = 2.142
P2Acos = 0.999
P1Angle = 122.745
P2Angle = 57.254

这些角度之间的跨度约为65°,感觉恰到好处。所以,P1Angle是我们的起始角度,因此我只需计算扫描然后绘制弧线:

var sweepAngle = P2Angle - P1Angle;
path.AddArc(R, startAngle, sweepAngle);

但绘制的弧线看起来不正确。

我确信这与绘制椭圆弧有关,而不是圆形,因为如果我使圆弧成圆形,那么一切都有效。我觉得我需要将椭圆上的点投影到圆上的等效点上并使用这些点来计算角度,但我还没有点击如何执行此操作。

有关如何修复的想法吗?

更新:我已经弄明白这里发生了什么,据我所知,这完全是无证件行为。我将在周末清理我的代码并发布一个答案(实际上,可能会在这篇文章上发表一篇博文)。

0 个答案:

没有答案