Для приложения для рисования я сохраняю координаты движения мыши в массив, а затем рисую их с помощью lineTo. Получившаяся линия не гладкая. Как я могу построить единую кривую между всеми собранными точками?
Я погуглил, но нашел только 3 функции для рисования линий: Для 2 точек выборки просто используйте lineTo
. Для 3 точек выборки quadraticCurveTo
, для 4 точек выборки bezierCurveTo
.
(Я попытался нарисовать a bezierCurveTo
для каждых 4 точек в массиве, но это приводит к перегибам через каждые 4 точки выборки вместо непрерывной плавной кривой.)
Как написать функцию для рисования плавной кривой с 5 точками выборки и более?
Ответы:
Проблема с объединением последующих точек выборки вместе с непересекающимися функциями типа «curveTo» состоит в том, что место пересечения кривых не является гладким. Это связано с тем, что две кривые имеют общую конечную точку, но на них влияют полностью непересекающиеся контрольные точки. Одно из решений состоит в том, чтобы «изгибаться» до средних точек между следующими двумя последующими точками выборки. Соединение кривых с использованием этих новых интерполированных точек дает плавный переход в конечных точках (то, что является конечной точкой для одной итерации, становится контрольной точкой для следующей итерации). Другими словами, у двух несвязанных кривых теперь гораздо больше общего.
Это решение было извлечено из книги «Анимация Foundation ActionScript 3.0: заставляем вещи двигаться». с.95 - приемы рендеринга: создание нескольких кривых.
Примечание: это решение фактически не прорисовывает каждую из точек, как это было в заголовке моего вопроса (скорее, оно аппроксимирует кривую через точки выборки, но никогда не проходит через точки выборки), но для моих целей (приложение для рисования), для меня это достаточно хорошо, и визуально вы не заметите разницы. Там является решение пройти через все точки выборки, но это гораздо более сложная (см http://www.cartogrammar.com/blog/actionscript-curves-update/ )
Вот код чертежа для метода аппроксимации:
источник
Немного поздно, но для протокола.
Вы можете добиться плавных линий, используя кардинальные сплайны (также известные как канонические сплайны ), чтобы рисовать плавные кривые, проходящие через точки.
Я сделал эту функцию для холста - она разделена на три функции для повышения универсальности. Основная функция-оболочка выглядит так:
Для того, чтобы нарисовать кривой есть массив с й, у точек в порядке:
x1,y1, x2,y2, ...xn,yn
.Используйте это так:
Приведенная выше функция вызывает две подфункции, одна для вычисления сглаженных точек. Это возвращает массив с новыми точками - это основная функция, которая вычисляет сглаженные точки:
И чтобы на самом деле нарисовать точки как сглаженную кривую (или любые другие сегментированные линии, если у вас есть массив x, y):
Показать фрагмент кода
Это приводит к следующему:
Вы можете легко расширить холст и называть его так:
Добавьте в javascript следующее:
Вы можете найти более оптимизированную версию в NPM (
npm i cardinal-spline-js
) или в GitLab .источник
ptsa
должен бытьpts
, а то выдадут ошибки.Первый ответ не пройдет через все пункты. Этот график точно пройдет через все точки и будет идеальной кривой с точками как [{x:, y:}] n таких точек.
источник
Как указывает Дэниел Ховард , Роб Спенсер описывает то, что вы хотите, на http://scaledinnovation.com/analytics/splines/aboutSplines.html .
Вот интерактивная демонстрация: http://jsbin.com/ApitIxo/2/
Вот фрагмент кода на случай, если jsbin не работает.
источник
Я нашел, что это хорошо работает
источник
Я решаю добавить, а не размещать свое решение в другом посте. Ниже приведено решение, которое я создаю, может быть не идеальным, но пока результат хороший.
Важно: пройдет все точки!
Если у вас есть идеи, как сделать это лучше , поделитесь со мной. Спасибо.
Вот сравнение до и после:
Сохраните этот код в HTML, чтобы проверить его.
источник
Попробуйте KineticJS - вы можете определить сплайн с массивом точек. Вот пример:
Старый URL: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-spline-tutorial/
См. URL-адрес архива: https://web.archive.org/web/20141204030628/http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-spline-tutorial/
источник
Невероятно поздно, но вдохновленный гениально простым ответом Хомана, позвольте мне опубликовать более общее решение (общее в том смысле, что решение Хомана дает сбой на массивах точек с менее чем 3 вершинами):
источник
Чтобы добавить к методу кардинальных сплайнов K3N и, возможно, решить проблемы TJ Crowder, связанные с `` провисанием '' кривых в ложных местах, я вставил следующий код в
getCurvePoints()
функцию непосредственно передres.push(x);
Это эффективно создает (невидимую) ограничивающую рамку между каждой парой последовательных точек и гарантирует, что кривая остается в пределах этой ограничительной рамки, т.е. если точка на кривой находится выше / ниже / слева / справа от обеих точек, она меняет свое положение, чтобы оказаться внутри прямоугольника. Здесь используется средняя точка, но ее можно улучшить, возможно, используя линейную интерполяцию.
источник
Если вы хотите определить уравнение кривой через n точек, следующий код предоставит вам коэффициенты полинома степени n-1 и сохранит эти коэффициенты в
coefficients[]
массиве (начиная с постоянного члена). Координаты x не обязательно должны быть в порядке. Это пример полинома Лагранжа .источник