Мышь Установления.NET находится на линии, проведенной между двумя произвольными точками

Мне привлекли стрелку между двумя объектами на Winform.

Что было бы самым простым способом решить, что моя мышь в настоящее время колеблется, или рядом, эта строка.

Я рассмотрел тестирование, пересекает ли точка мыши квадрат, определенный и экстраполируемый двумя точками, однако это только было бы выполнимо, если две точки имели очень похожий x или значения y.

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

С другой стороны, если библиотека.NET может справиться с функцией, еще лучше.

РЕДАКТИРОВАНИЕ спасибо за ответы, было несколько очень хороших все получение, отмечаемое, как отвечено.

Я выбрал ответ Coincoin's, как принято, поскольку мне нравится этот, он мог быть применен к любой оттянутой форме, однако законченной реализовать уравнение Tim Robinson, как это казалось намного более эффективным к с простым уравнением, а не newing графические контуры и перья, как в моем случае я должен сделать это onMouseMove для 1-n различных отношений (очевидно, было бы некоторое кэширование и оптимизации, но точка все еще остается),

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

Код (начальное сокращение, я, вероятно, уберу его немного), для заинтересованных, ниже

    if (Math.Sqrt( Math.Pow(_end.X - _start.X, 2) + 
           Math.Pow(_end.Y - _start.Y, 2) ) == 0)
    {
        _isHovering =
            new RectangleF(e.X, e.Y, 1, 1).IntersectsWith(_bounds);
    }
    else
    {
        float threshold = 10.0f;

        float distance = (float)Math.Abs( 
            ( ( (_end.X - _start.X) * (_start.Y - e.Y) ) -
            ( (_start.X - e.X) * (_end.Y - _start.Y) ) ) /
            Math.Sqrt( Math.Pow(_end.X - _start.X, 2) + 
            Math.Pow(_end.Y - _start.Y, 2) ));

        _isHovering = (
            distance <= threshold &&
                new RectangleF(e.X, e.Y, 1, 1).IntersectsWith(_bounds)
            );
    }

и _bounds определяется как:

    _bounds = new Rectangle(
    Math.Min(_start.X, _end.X),
    Math.Min(_start.Y, _end.Y),
    Math.Abs(_start.X - _end.X), Math.Abs(_start.Y - _end.Y));
7
задан johnc 20 March 2010 в 09:15
поделиться

5 ответов

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

Например, здесь мы создаем путь с линией:

GraphicsPath path = new GraphicsPath();

path.AddLine(x1, y1, x2, y2);
path.CloseFigure();

Затем расширяем путь и создаем область для проверки попадания:

path.Widen(new Pen(Color.Black, 3));
region = new Region(path);

Наконец, проверка попадания:

region.IsVisible(point);

Преимущество этого метода в его можно легко расширить до сплайнов, стрелок, дуг, кругов или почти всего, что можно рисовать с помощью GDI +. Один и тот же путь может использоваться как в логике HitTest , так и в логике Draw , извлекая его.

Вот код, объединяющий все это:

public GraphicsPath Path
{
    get { 
        GraphicsPath path = new GraphicsPath();
        path.AddLine(x1, y1, x2, y2);
        path.CloseFigure();

        return path;
    }
}

bool HitTest(Point point)
{
    using(Pen new pen = Pen(Color.Black, 3))
    using(GraphicsPaht path = Path)
    {
        path.Widen(pen);

        using(Region region = new Region(path))
            return region.IsVisible(point);
    }
}


void Draw(Graphics graphics)
{
    using(Pen pen = new Pen(Color.Blue, 0))
    using(GraphicsPaht path = Path)
        graphics.DrawPath(pen, path);
}
7
ответ дан 6 December 2019 в 15:20
поделиться

Чтобы ответить «Нависает ли указатель мыши над этой линией?», Вам нужно проверить пересечение точки с линией. Однако, поскольку вы спрашиваете «находится ли мышь рядом с линией?», Похоже, что вы хотите рассчитать расстояние между точкой мыши и линией.

Вот достаточно подробное объяснение расстояния точка-линия: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html

Я бы сказал, что вам нужно реализовать эту формулу в своем коде : (украдено с wolfram.com)

Где:

  • (x0, x0) - местоположение указателя мыши
  • (x1, y1) - один конец строки
  • (x2, y2) это другой конец строки
  • | n | это Math.Abs ​​(n)
  • Нижняя половина - Math.Sqrt
  • Вы можете игнорировать | vr | , если вы хотите
4
ответ дан 6 December 2019 в 15:20
поделиться

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

Вам не нужно рассчитывать расстояние от мыши до основной линии.

1
ответ дан 6 December 2019 в 15:20
поделиться

Проверьте MouseEnter(object sender, EventArgs e). Отлавливайте, когда мышь "входит" в область управления.

0
ответ дан 6 December 2019 в 15:20
поделиться

Я бы вычислил уравнение Склон-Интерцепция (y = mx + b) для моей линии и затем использовал его для проверки координат мыши. Вы можете легко поместить диапазон вокруг y, чтобы увидеть, "близки ли вы".

Редактировать для примера.

Я думаю, работает что-то вроде этого:

PointF currentPoint;
PointF p1, p2;
float threshold = 2.0f;
float m = (p1.Y - p2.Y) / (p1.X - p2.X);
float b = p1.Y - (m * p1.X);

if (Math.Abs(((m * currentPoint.X) + b) - currentPoint.Y) <= threshold)
{
    //On it.
}
2
ответ дан 6 December 2019 в 15:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: