2016-06-21 63 views
1

我想确定一个拱几天的限制,现在没有太多的成功。我知道这是一个比编程更多的几何类型问题,但在这里它会。让我先展示这个图像来详细说明我在C#中实现的目标。 enter image description here从G代码计算拱门的X -Aixes Limmets

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

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

第一行表示拱的起点,女巫是在这种情况下X 10和Y 15,第二行表示的终点,拱中心点和旋转。 G3表示拱门的逆时针旋转(G2表示顺时针旋转)。 Y表示终点,而I表示拱形中心点的值。我尝试的第一件事是看看我能否检测到拱形180°*红线没有太多的成功,主要是因为我似乎无法得到的角度计算正常工作,当我尝试处理不同类型的coordinates.Here的是一个代码示例我无法完成:

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; 
    } 
} 

上面的代码只适用于某些特定的弧线。 我用Google搜索了一圈,发现主要是对线的交点与直线和圆的交点的话题,但只有大约相交弧行一个明确的答案是过于模糊,辨认出什么是应该发生在这里是Link

除还有一种拱门,我认为这种拱门可能需要通过某种Pathegorem进行不同的处理,但我还没有开始如何做到这一点。但这里是它的一个形象:

enter image description here

下面是G代码:

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

而且我觉得 '最左边的' X值是25.4

我想知道,如果你知道一个方法或图书馆,可以帮助与这一个。谢谢

回答

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