【问题标题】:Algorithm for triangulation of point travelling around a circle绕圆运动的点的三角剖分算法
【发布时间】:2013-07-10 09:31:34
【问题描述】:

给定以下系统:

地点:

  • A:存在于 xz 平面上半径为 r 的圆的边缘上任意位置的点。
  • θ:正 x 轴与从原点到点 A 的向量之间的角度。范围应为 -PI/2 到 PI/2。
  • B1:圆与正 x 轴的交点,高度为h1
  • B2:圆与正 z 轴的交点,高度为h2
  • d1B1A 之间的距离。
  • d2B2A 之间的距离。

假设:

  • h1h2r 是已知常量。
  • d1d2 是已知变量。

如何找到θ

这最终将在嵌入式系统中用 C 语言实现,在该系统中,arctan2sinecosine 具有相当快的功能。因此,性能绝对是重中之重,如果估计正确到小数点后 3 位(这就是我的三角函数的准确度),就可以使用估计。

但是,即使给出了一个数学算法,我相信我可以制定出具体的实现。

对于它的价值,我已经做到了:

(d1^2 - h1^2) / r = (sin(θ))^2        + (cos(θ))^2
(d2^2 - h2^2) / r = (sin(PI/4 - θ))^2 + (cos(PI/4 - θ))^2

在我意识到这之前,从数学上讲,这方式超出了我的范围。

【问题讨论】:

    标签: c geometry triangulation


    【解决方案1】:

    这不是一个完整的答案,而是一个开始。

    您可以进行两种简单的简化。

    让 H1 和 H2 成为平面中 B1 和 B2 下方的点。 由于您知道 h1 和 d1、h2 和 d2,您可以计算 2 个距离 A-H1 和 A-H2(使用毕达哥拉斯)。 现在您已将拼图简化为平面。

    此外,您实际上不需要同时查看 H1 和 H2。给定距离 A-H1,A 只有 2 个可能的位置,它们在 x 轴上镜像。然后你可以通过查看A-H2距离是否高于或低于阈值距离H2-H1来找到两者中的哪一个。

    这似乎是一个好的开始:-)

    【讨论】:

    • 这实际上是一个非常好的观点。那时,我有一个边为 r、r 和 A-H1 的三角形(我们称之为 d)。根据余弦定律,我认为这使得theta = arccos((2r^2 - d^2) / (2r^2))。然后,就像你提到的,只需要使用其他距离计算出象限。
    【解决方案2】:

    使用@Rhialto,对角落案例进行额外的简化和测试:

    // c1 is the signed chord distance A to (B1 projected to the xz plane)
    // c1*c1 + h1*h1 = d1*d1
    // c1 = +/- sqrt(d1*d1 - h1*h1)  (choose sign later)
    // c1 = Cord(r, theta) = fabs(r*2*sin(theta/2))
    // theta = asin(c1/(r*2))*2
    //
    // theta is < 0 when d2 > sqrt(h2*h2 + sqrt(2)*r*sqrt(2)*r)
    // theta is < 0 when d2 > sqrt(h2*h2 + 2*r*r)
    // theta is < 0 when d2*d2 > h2*h2 + 2*r*r
    
    #define h1 (0.1)
    #define h2 (0.25)
    #define r (1.333)
    
    #define h1Squared (h1*h1)
    #define rSquared  (r*r)
    #define rSquaredTimes2  (r*r*2)
    #define rTimes2   (r*2)
    #define d2Big (h2*h2 + 2*r*r)
    
    // Various steps to avoid issues with d1 < 0, d2 < 0, d1 ~= h1 and theta near pi
    double zashu(double d1, double d2) {
      double c1Squared = d1*d1 - h1Squared;
      if (c1Squared < 0.0)
        c1Squared = 0.0;  // _May_ be needed when in select times |d1| ~= |h1|
      double a = sqrt(c1Squared) / rTimes2;
      double theta = (a <= 1.0) ? asin(a)*2.0 : asin(1.0)*2.0; // Possible a is _just_ greater than 1.0
      if (d2*d2 > d2Big) // this could be done with fabs(d2) > pre_computed_sqrt(d2Big)
        theta = -theta;
      return theta;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-03-19
      • 2016-10-06
      • 1970-01-01
      • 2012-10-11
      • 2017-09-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      相关资源
      最近更新 更多