Нарисовать кривую Эрмита на холсте браузера (JavaScript)
Я пытаюсь нарисовать кривую отшельника на холсте браузера. Кривая Эрмита определяется в терминах 2 точек и 2 производных.
Point1X = 71
Point1Y = 165
Deriv1X = -12
Deriv1Y = 2
Point2X = 210
Point2Y = 153
Deriv2X = 108
Deriv2Y = 0
Я могу рисовать только кривые Безье на холсте. Есть ли способ, которым я могу преобразовать точки и производные кривой Эрмита в кривую Безье, чтобы я мог нарисовать ее на холсте?
Есть ли другой вариант, что я могу нарисовать кривую Эрмита в браузере?
Спасибо за помощь.
2 ответа
Canvas2d не поддерживает произвольные сплайны Эрмита, но поддерживает кубические кривые Безье, и поскольку кубические кривые Безье являются кривыми Эрмита 2-го порядка, мы можем свободно конвертировать между вашими данными и кривой Безье.
Математика для этого может быть найдена в этом учебнике для начинающих на кривых Безье, и специально для этой задачи мы можем преобразовать точки Эрмита, упорядоченные [p1, d1, p2, d2] как:
Hermite points [p1,d1,p2,d2] = Bezier [p1, (p1 + d1/(2*t)), (p2 - d2/(2*t)), p2]
Обратите внимание, что t
Значение является напряжением кривой и определяет порядок кривизны в каждой точке (чем выше натяжение, тем выше скорость изменения кривизны вдоль кривой вблизи точки на кривой), в этом случае просто 1
,
(без значения натяжения ваши четыре координаты фактически определяют гексагональную область песочных часов на плоскости, а не одну кривую, поскольку векторы направленности не гарантируются как истинные касательные; это просто векторы, представляющие направление движения. Площадь, определяемая этими значениями ограничен линией {начало, конец} с одной стороны, с бесконечно простирающимися границами вдоль направлений движения в начале и в конце).
Таким образом, вы можете нарисовать любую кривую Эрмита на холсте на холсте, используя API Canvas2d для кубических кривых Безье:
// Hermite data
var p1 = ..., d1 = ..., p2 = ..., d2 = ...;
var cmpoints = [p1.x, p1.y, d1.x, d1.y, p2.x, p2.y, d2.x, d2.y];
// Bezier data
var tension = 1;
var tensionFactor = 2 * tension;
var bpoints = [
p1.x,
p1.y,
p1.x + d1.x/tensionFactor,
p1.y + d1.y/tensionFactor,
p2.x - d2.x/tensionFactor,
p2.y - d2.y/tensionFactor,
p2.x,
p2.y
]
// Draw code (where we assume you already
// have your canvas context as "ctx")
ctx.beginPath();
ctx.moveTo.apply(bpoints.slice(0,2));
ctx.bezierCurveTo.apply(bpoints.slice(2);
ctx.stroke();
Кривая кубического Эрмита (определяемая с помощью C (0), C '(0), C (1) и C' (1)) и кривая Кубического Безье (определяемая с помощью P0, P1, P2 и P3) могут быть связаны друг с другом от
C (0) = P0,
C (1) = P3,
C '(0) = 3 (P1-P0),
C '(1) = 3 (P3-P2)
Таким образом, вы можете найти контрольные точки как
Р0 = С (0),
P1 = (1/3) * С '(0)+ Р0,
Р2=P3-(1/3)* С '(1),
Р3 = С (1)