Определить точку пересечения 2 линий - PullRequest
4 голосов
/ 01 февраля 2010

У меня есть 2 (VisualBasic.PowerPacks) LineShapes в моей форме:

альтернативный текст 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. Это говорит о том, что ShapeContainer не будет вызывать событие MouseDown, если какой-либо LineShape будет находиться под мышью.

Но этот код дает мне только самую верхнюю строку, но я также хочу список других.

Ответы [ 5 ]

3 голосов
/ 01 февраля 2010

В вашей сети координат у вас есть две строки с y1 = ax + c1 и y2 = bx + c2. Найдите точку пересечения, где x1=x2 и y1=y2
y = ax + c1, y = bx + c2
ax + c1 = bx + c2
x = (c2 - c1)/(a - b)
Затем убедитесь, что точка пересечения не находится за границами линии, и рассчитайте близость + - пиксель или два.

2 голосов
/ 01 февраля 2010

Вам нужно просто вычислить пересечение двух отрезков.Это довольно просто.

Полный, рабочий алгоритм описан здесь .Он работает на отрезках, определенных двумя точками, поэтому его легко адаптировать к вашей ситуации.

0 голосов
/ 02 февраля 2010
    /// 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);
        }
    }
0 голосов
/ 01 февраля 2010

Помимо алгоритма пересечения линий (как показано несколькими людьми на этой странице), вам необходимо отделить контекстное меню от линий. В псевдокоде вам понадобится что-то вроде:

onLine1Click:
if intersection then handle intersection
else handle line1 click

onLine2Click:
if intersection then handle intersection
else handle line2 click

Эта обработка может показывать контекстное меню. Я полагаю, что если / то / иное требуется для решения оставшейся проблемы.

0 голосов
/ 01 февраля 2010

Серхио, вот так просто Математика ...

Определите точки пересечения ваших линий (возможно, сделайте это, когда они будут добавлены, и сохраните результат), а затем посмотрите, достаточно ли приблизилась мышь для отображения контекстного меню, чтобы вам не требовалось совершенного щелчка по пикселям.

...