【问题标题】:Calculate the X -aixes Limmets of a arch from G-Code从 G 代码计算拱门的 X-aixes Limmets
【发布时间】:2016-10-28 22:14:16
【问题描述】:

我试图确定拱门的限制已经有几天了,但没有取得太大的成功。我知道这更像是一个几何类型的问题而不是编程,但它就在这里。让我先展示这张图片来详细说明什么我正在尝试在 C# 中实现。

在上图中,您可以看到一条绿色弧线,我试图确定“最左边”点在 X 轴上的位置(最终是“最右边”点,但为了简单起见,我将重点关注“最左边”点) 这张图片在 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;
  }
}

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

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

这是 G 代码:

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

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

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

【问题讨论】:

    标签: c# g-code


    【解决方案1】:

    这应该计算弧的 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      • 2019-09-08
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      相关资源
      最近更新 更多