Обнаружение столкновения на линии - PullRequest
0 голосов
/ 04 октября 2009

Как я могу обнаружить столкновение на линии, желательно с помощью мыши?

Я не использую XNA. Я использую просто простые WinForms. И я не создаю игру.

РЕДАКТИРОВАТЬ: я реализовал решение от Brone Link и получил действительно странные результаты. Вот небольшой фрагмент. Что я делаю не так? Pastebin link

Ответы [ 3 ]

5 голосов
/ 04 октября 2009

Минимальное расстояние между точкой и линией:

http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/

Больше справочного материала в его разделе общей геометрии:

http://local.wasp.uwa.edu.au/~pbourke/geometry/

1 голос
/ 04 октября 2009

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

  • Пусть AB будет вашим сегментом линии.
  • Пусть C будет вашей мышью.
  • Пусть D - точка на AB такая, что отрезок CD минимален.

Вы хотите узнать длину CD. Поскольку AB и CD перпендикулярны, вы знаете, что наклон AB является обратной величиной, обратной наклону CD. Вы знаете C и наклон, так что вы можете найти общее уравнение для CD. Затем найдите пересечение AB и CD, что даст вам точку D.

Как только у вас есть точка D, найти длину CD тривиально. Если это расстояние на меньше , чем какое-либо пороговое значение, то вы знаете, что щелкнули рядом с интересующим вас отрезком.

0 голосов
/ 04 октября 2009

Ну, я не буду объяснять это, так как не помню, как это работает. Но я написал это на C ++ еще в ... э-э ... 1995-м. Я уверен, что есть намного более изящные способы сделать это, так как я писал код только около двух лет. В любом случае здесь он конвертируется в C #:

static bool PointHitSegment(Point[] line, Point hitPoint, int errorMargin)
{
    if (hitPoint.X >= (Math.Max(line[0].X, line[1].X) + errorMargin) ||
        hitPoint.X <= (Math.Min(line[0].X, line[1].X) - errorMargin) ||
        hitPoint.Y >= (Math.Max(line[0].Y, line[1].Y) + errorMargin) ||
        hitPoint.Y <= (Math.Min(line[0].Y, line[1].Y) - errorMargin))
        return false;

    if (line[0].X == line[1].X || line[0].Y == line[1].Y)
        return true;

    double y1, y2, x1, x2;
    double m, b;
    int ny;

    if (Math.Abs(line[0].Y - line[1].Y) <= Math.Abs(line[0].X - line[1].X))
    {
        y1 = line[0].Y;
        y2 = line[1].Y;
        x1 = line[0].X;
        x2 = line[1].X;
    }
    else
    {
        y1 = line[0].X;
        y2 = line[1].X;
        x1 = line[0].Y;
        x2 = line[1].Y;

        int tmp = hitPoint.Y;
        hitPoint.Y = hitPoint.X;
        hitPoint.X = tmp;
    }

    m = (y2 - y1) / (x2 - x1);
    b = y1 - m * x1;

    ny = (int)((m * ((double)hitPoint.X) + b) + 0.5);

    if (Math.Abs(hitPoint.Y - ny) > errorMargin)
        return false;

    return true;
}
...