.isPointInPath () для штриховых линий и полилиний

Мне нужен механизм для обнаружения события наведения мыши для линий, кривых и полилиний с разной шириной штриха, я уже сделал такой механизм для прямоугольников и эллипсов, поэтому я не новичок в Canvas API. Я очерчиваю все нарисованные объекты и определяю положение мыши над ними, когда прямоугольники или эллипсы имеют ширину обводки более 1 пикселя, я расширяю путь, чтобы он также содержал границу. Для линий и полилиний мне сложно понять, как мне их расширять, если у меня, например, ширина линии 20 пикселей.

Мой вопрос: как преобразовать линии, кривые и полилинии в некоторый путь формы, чтобы этот путь мог содержать всю их ширину?

красный - путь, черный - контур»></p> <div style=

Мне нужно, чтобы созданный путь содержал ширину линии / кривой, представленной черным цветом на этом изображении.

---------- Дополнительная информация ----------

Я попытаюсь упростить задачу: у нас есть 2 точки (выделены красным на изображении ниже), они образуют линию, которая имеет определенную формулу (y = mx + n), мне нужно описать формулы перпендикулярных линий, которые пройдя через эти две начальные точки, после необходимо определить положения «синих» точек, которые находятся на расстоянии половины значения context.lineWidth, когда все точки определены, можно создать новый путь с использованием последовательности moveTo () и lineTo (). Этот метод должен быть применим для квадратичных кривых и кривых Безье с использованием контрольных точек. Проблема остается только в этих математических расчетах.


person micnic    schedule 14.07.2012    source источник
comment
Вы можете попробовать обратиться за помощью по Mathematics SE.   -  person Inkbug    schedule 16.07.2012
comment
Хорошо, попробую и там ответить :)   -  person micnic    schedule 16.07.2012
comment
Итак, вам нужен способ найти формулу для перпендикулярной линии в упрощенной версии?   -  person Some Guy    schedule 16.07.2012
comment
нет, мне нужно получить координаты синих точек, я только что объяснил, как их можно определить логически, теперь мне нужно знать, как определить их математически   -  person micnic    schedule 16.07.2012
comment
Связанное сообщение stackoverflow.com/a/8462037/380384. Как сместить многоугольник.   -  person John Alexiou    schedule 12.09.2014
comment
спасибо @ ja72, проверю кажется интересным;)   -  person micnic    schedule 12.09.2014


Ответы (3)


Я нашел решение на math.stackexchange здесь , это решение предназначено только для линий, но оно применимо для кривых и полилиний с некоторыми специфическими изменениями. Прежде всего, нам нужно определить формулу линии, проходящей через две начальные точки:

Шаг 1

Наши точки: P1 (x1, y1) и P2 (x2, y2)

Расстояние между точками и их соседями: d

Общая форма: Ax + By + C = 0

Где: A = y2 - y1; B = x1 - x2; С = x2y1 - x1y2.

После этого необходимо в краткой форме определить эту формулу:

Шаг 2

Краткая форма: y = mx + n

Где: m = - A / B; n = - C / B (когда B! = 0)

Если A == 0, то у нас есть формула: y = C (случай, когда у нас есть горизонтальная линия)

Если B == 0, то у нас есть формула: x = C (случай, когда у нас есть вертикальная линия)

Когда у нас есть наклон линии, нам нужен наклон перпендикулярной линии на ней:

Шаг 3

Наклон перпендикулярной линии: м2 = - 1 / м

Если A == 0 или B == 0, переходите к шагу 4

Теперь нам нужно получить соседние точки для обеих начальных точек:

Шаг 4

Я отмечу соседние точки как P1N1, P1N2 для первой точки и P2N1 и P2N2 для второй.

Для особых случаев (горизонтальные и вертикальные линии, когда A == 0 или B == 0) у нас будет:

Для A == 0 (горизонтальная линия):

P1N1(x1, y1 - d / 2); P1N2(x1, y1 + d / 2); P2N1(x2, y2 + d / 2); P2N2(x2, y2 - d / 2).

Для B == 0 (вертикальная линия):

P1N1(x1 - d / 2, y1); P1N2(x1 + d / 2, y1); P2N1(x2 + d / 2, y2); P2N2(x2 - d / 2, y2).

Для других случаев (A! = 0 и B! = 0):

P1N1:

х = (d / 2) / Math.sqrt (1 + Math.pow (m2, 2)) + x1;

y = (m2 * (d / 2)) / Math.sqrt (1 + Math.pow (m2, 2)) + y1;

P1N2:

х = - (d / 2) / Math.sqrt (1 + Math.pow (m2, 2)) + x1;

y = - (m2 * (d / 2)) / Math.sqrt (1 + Math.pow (m2, 2)) + y1;

P2N1:

х = (d / 2) / Math.sqrt (1 + Math.pow (m2, 2)) + x2;

y = (m2 * (d / 2)) / Math.sqrt (1 + Math.pow (m2, 2)) + y2;

P2N2:

х = - (d / 2) / Math.sqrt (1 + Math.pow (m2, 2)) + x2;

y = - (m2 * (d / 2)) / Math.sqrt (1 + Math.pow (m2, 2)) + y2;

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

person micnic    schedule 18.07.2012

Если у вас кривая Безье имеет следующий вид.

x(t) = x0 + x1*t + x2*t*t + x3*t*t*t
y(t) = y0 + y1*t + y2*t*t + y3*t*t*t

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

x'(t) = x1 + 2*x2*t + 3*x3*t*t
y'(t) = y1 + 2*y2*t + 3*y3*t*t

и нормальная линия в любой момент. Нормаль - это перпендикуляр в любой точке, который является опорой для двух ваших точек.

(-y'(t), x'(t))
((y'(t), -(x'(t))
person karlcow    schedule 16.07.2012

Вы пробовали использовать метод .isPointInStroke () в Canvas 2D API:

ctx.isPointInStroke(x, y);
ctx.isPointInStroke(path, x, y);

Взгляните на: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInStroke

person Laiacy    schedule 03.10.2017
comment
Когда был задан этот вопрос, ctx.isPointInStroke() не был частью стандарта Canvas API, и вопрос был о том, чтобы вычислить значение x и y, а не проверять, является ли точка частью пути / штриха. - person micnic; 04.10.2017