【问题标题】:Detect the intersection point of 2 lines检测2条线的交点
【发布时间】:2011-01-11 19:41:41
【问题描述】:

我的表单上有 2 个 (VisualBasic.PowerPacks)LineShapes:

alt text http://lh4.ggpht.com/_1TPOP7DzY1E/S2cIJan7eHI/AAAAAAAADAw/qwA0jFHEbBM/s800/intersection.png

当我单击其中一个时,会出现一个特定的上下文菜单。用户可以移动线条。上下文菜单与一行相关联。但是,如果用户单击交叉点(如果存在),我需要显示另一个菜单,它将选择一条交叉线来执行操作。

现在,我想知道如何检测在点击点处相交的 2 条(或更多)线,因为在这种情况下应该出现另一个上下文菜单。

我想做什么:

    private void shapeContainer1_MouseDown(object sender, MouseEventArgs e)
    {
        // right click only
        if (e.Button == MouseButtons.Right)
        {
            LineShape target = 
                (shapeContainer1.GetChildAtPoint(e.Location) as LineShape);

            if (target != null)
            {
                Console.WriteLine(new Point(target.X1, target.Y1));
            }

        }
    }

我想我的容器中只有 LineShapes。这就是说,如果鼠标下方有任何 LineShape,ShapeContainer 将不会引发 MouseDown 事件。

但是这段代码只给了我 mostTop 行,但我也想要其他人的列表。

【问题讨论】:

    标签: .net powerpacks


    【解决方案1】:

    serhio,很简单Maths...

    计算出线条的交点(可能在添加并存储结果时执行此操作),然后查看鼠标是否足够靠近以防止显示上下文菜单,因此您不需要像素完美点击。

    【讨论】:

    • 啊,但他需要线段/线段交叉点,而不是线交叉点......这(有点)棘手。
    • 我的交叉点移动了。用户可以移动线条。我需要一种方法来检查单击某行时的点,因为该行是 Control(Component)
    【解决方案2】:

    在您的坐标网络中,您有两条线,分别是 y1 = ax + c1y2 = bx + c2。找到x1=x2y1=y2的交点
    y = ax + c1, y = bx + c2
    ax + c1 = bx + c2
    x = (c2 - c1)/(a - b)
    然后检查交叉点是否超出线边界并计算接近度+-像素或两个。

    【讨论】:

    • 是的。这就是理论。在实践中,这似乎有点复杂。当我单击该行时,该行本身会响应 Clicked(eevnt)。所以,现在,如果我将上下文菜单关联到该行,那么这个上下文菜单将会出现。
    【解决方案3】:

    您只需要计算两条线段的交点。这很简单。

    一个完整的,working algorithm is described here。它适用于由两点定义的线段,因此应该很容易适应您的情况。

    【讨论】:

    • 可能这很简单。但是线条不仅是 2 条,而且可以移动很多条线,如果我单击 lineShape 对象,它会像普通控件一样接收 eventClick。所以,这个控件应该首先验证其他“兄弟”是否不在同一个点击点。
    • 计算这些速度很快——您始终可以维护一个交点列表,当您“移动”一条线段时,重新计算该线段的交点。坦率地说,它足够快(除非您有数百或数千行)您可能可以按需计算它......
    【解决方案4】:

    除了线相交算法(如本页几个人所示),您需要将上下文菜单与线解耦。在伪代码中,您需要以下内容:

    onLine1Click:
    if intersection then handle intersection
    else handle line1 click
    
    onLine2Click:
    if intersection then handle intersection
    else handle line2 click
    

    这个处理可以显示上下文菜单。我相信这个 if/then/else 是解决您剩余的问题所必需的。

    【讨论】:

      【解决方案5】:
          /// obtains a list of shapes from a click point
          private List<LineShape> GetLinesFromAPoint(Point p) 
          {
              List<LineShape> result = new List<LineShape>();
              Point pt = shapeContainer1.PointToScreen(p);
      
              foreach (Shape item in shapeContainer1.Shapes)
              {
                  LineShape line = (item as LineShape);
                  if (line != null && line.HitTest(pt.X, pt.Y))
                  {
                      result.Add(line);                    
                  }
              }
              return result;
          }
      
          private void shapeContainer1_MouseDown(object sender, MouseEventArgs e)
          {
              // right click only
              if (e.Button == MouseButtons.Right)
              {
                  List<LineShape> shapesList = GetLinesFromAPoint(e.Location);
                  Console.WriteLine(DateTime.Now);
                  Console.WriteLine("At this point {0} there are {1} lines.", 
                      e.Location, shapesList.Count);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多