1

我正在尝试确定拱门的限制几天,但没有取得多大成功。我知道这更像是一个几何类型的问题而不是编程,但它就在这里。让我首先展示这张图片来详细说明我正在尝试的内容在 C# 中实现。 在此处输入图像描述

在上图中,您可以看到一条绿色弧线,我试图确定“最左边”点在 X 轴上的位置(最终是“最右边”,但为了简单起见,我将关注“左边” most' 点)这个图像在 X 轴上“最左”的答案是 5,注意:即使拱门的后掠角更大,答案仍然是 5,但如果后掠角小于,答案会更多比 5. 我正在从基于文本的 G 代码文件中读取此信息,这里是 G 代码文件中绘制的弧的示例。

G1 X10. Y15.
G3 X5. Y10. I10. J10.

第一行表示拱形的起点,在本例中是 X 10 和 Y 15。第二行表示终点、拱形中心点和旋转。G3 表示弓的逆时针旋转(G2 表示顺时针旋转)。X 和 Y 表示端点,I 和 J 是(分别为 X 和 Y)拱中心点值。我尝试的第一件事是看看我是否可以检测到拱穿过 180* 红色没有太多成功的线主要是因为当我尝试处理不同类型的坐标时,我似乎无法正确地进行角度计算。这是我无法完成的代码示例:

else if (Gval == 3)
{
  //Values read from G-Code File
  double startX = Convert.ToDouble(oldXval);
  double startY = Convert.ToDouble(oldYval);
  double endX = Convert.ToDouble(Xval);
  double endY = Convert.ToDouble(Yval);
  double midX = Convert.ToDouble(Ival);
  double midY = Convert.ToDouble(Jval);

  //Get Start angle of Line
  double startAngle = Math.Atan2(startY - midY, startX - midX);
  startAngle = Math.Round(startAngle * (180.0 / Math.PI), 5);//Radiants to Degrees 
  startAngle = ((startAngle % 360) + 360) % 360;//Normalise

  //Get End angle of line
  double EndAngle = Math.Atan2(endY - midY, endX - midX);
  EndAngle = Math.Round(EndAngle * (180.0 / Math.PI), 5);//Radiants to Degrees 
  EndAngle = ((EndAngle % 360) + 360) % 360;//Normalise
  if (EndAngle == 0) EndAngle = 360;

  //Get Raiduis
  double raduis = Math.Round((Math.Sqrt(Math.Pow(Math.Abs(startX - midX), 2) + Math.Pow(Math.Abs(startY - midY), 2))),5);

  double deltaY = (midY) - (startX);
  double deltaX = (midX) - (startY);
  double angleInDegrees = Math.Atan(deltaY / deltaX)*180/Math.PI;

  if (startAngle <= 180 && EndAngle >= 180)
  {
     double LeftValue = midX - raduis;
  }
}

上面的代码仅适用于某些特定的弧。我在谷歌上搜索了一下,主要发现了关于线交点和线和圆交点的主题,但只有一个专门关于线与弧相交的主题,答案太模糊,无法确定这里应该发生的事情是链接

除此之外,还有一种类型的拱门,我认为可能必须通过某种 Pathegorem 进行不同的处理,但我还没有开始研究如何做到这一点。但这是它的图像:

在此处输入图像描述

这是G代码:

  G1 X30. Y15.
  G3 X25.4 Y11.96 I30. J10.

我认为“最左边”的 X 值为 25.4

我想知道,如果您知道可以帮助解决此问题的方法或库。谢谢

4

1 回答 1

0

这应该计算弧的 X 和 Y 边界。可以进行许多优化以获得更好的性能,但我认为这更容易理解。

    class Bounds
    {
        public double MinX, MinY, MaxX, MaxY;
    }

    Bounds GetArcBounds(float cx, float cy, float x1, float y1, float x2, float y2)
    {
        var a1 = GetAngle(y1 - cy, x1 - cx);
        var a2 = GetAngle(y2 - cy, x2 - cx);
        var r = (float)Math.Sqrt(Math.Pow(y1 - cy, 2) + Math.Pow(x1 - cx, 2));

        var bounds = new Bounds();
        bounds.MinX = double.MaxValue;
        bounds.MinY = double.MaxValue;
        bounds.MaxX = double.MinValue;
        bounds.MaxY = double.MinValue;

        ExpandBounds(bounds, x1, y1);
        ExpandBounds(bounds, x2, y2);

        if (IsAngleInArc(a1, a2, 0)) 
            ExpandBounds(bounds, cx + r, cy);
        if (IsAngleInArc(a1, a2, (float)Math.PI * 0.5f)) 
            ExpandBounds(bounds, cx, cy + r);
        if (IsAngleInArc(a1, a2, (float)Math.PI)) 
            ExpandBounds(bounds, cx - r, cy);
        if (IsAngleInArc(a1, a2, (float)Math.PI * 1.5f)) 
            ExpandBounds(bounds, cx, cy - r);

        return bounds;
    }

    float GetAngle(float dy, float dx)
    {
        var a = (float)Math.Atan2(dy, dx);
        if (a < 0) a += (float)Math.PI * 2.0f;
        return a;
    }

    void ExpandBounds(Bounds bounds, float x, float y)
    {
        if (x < bounds.MinX) bounds.MinX = x;
        if (y < bounds.MinY) bounds.MinY = y;
        if (x > bounds.MaxX) bounds.MaxX = x;
        if (y > bounds.MaxY) bounds.MaxY = y;
    }

    bool IsAngleInArc(float a1, float a2, float test)
    {
        if (a2 < a1)
        {
            a2 += (float)Math.PI * 2.0f;
        }
        if (test < a1)
        {
            test += (float)Math.PI * 2.0f;
        }
        return a1 <= test && test <= a2;
    }

如果您希望能够同时进行逆时针和顺时针操作,我相信您可以将逻辑更改为以下内容,尽管我尚未对此进行测试。

    if (IsAngleInArc(a1, a2, 0) ^ clockwise) 
        ExpandBounds(bounds, cx + r, cy);
    if (IsAngleInArc(a1, a2, (float)Math.PI * 0.5f) ^ clockwise) 
        ExpandBounds(bounds, cx, cy + r);
    if (IsAngleInArc(a1, a2, (float)Math.PI) ^ clockwise) 
        ExpandBounds(bounds, cx - r, cy);
    if (IsAngleInArc(a1, a2, (float)Math.PI * 1.5f) ^ clockwise) 
        ExpandBounds(bounds, cx, cy - r);
于 2016-10-28T05:32:26.390 回答