У меня есть две части кривой. Положение точек (x, y) кривой известно. Как их соединить и получить положение соединительной кривой? Вот похожий вопрос.аналогичный вопрос
Он сказал использовать кривые Безье. Но, на мой взгляд, обычно кривая подгонки не проходит через контрольные точки. Поэтому, если я выберу несколько точек из двух частей кривой в качестве контрольных точек, результат подгонки может быть таким, как на следующем рисунке. Это не моя цель. Может кто-нибудь дать мне совет?
Используйте кривую Катмулла-Рома, которая связана с кривыми Безье и которую легко преобразовать в форму Безье, с преимуществом, которое проходит через точки, а не просто управляется ими. Для мелких деталей см http://pomax.github.io/bezierinfo/#catmullconv, но нам в основном нужны эти две конечные точки и две точки вне кривой, которые гарантируют, что у нас есть правильная касательная в наших двух точках на кривой:
p2 и p3 — это «ваши» точки, а p1 и p4 несколько произвольны: нам просто нужно убедиться, что линия p1--p3
параллельна касательной в точке p2 (касательная и ее параллельная линия обозначены голубовато-пурпурным цветом) и аналогично линии p2--p4
параллельна касательной в точке p3 (касательная и ее параллельная линия обозначены розоватым оттенком). Как правило, простой подход заключается в том, чтобы просто проецируйте точки p2 и p3 на параллельные линии.
Пока мы уверены, что это правда, мы можем сформировать соединительный сегмент в виде сегмента Catmull-Rom с координатами кривой (p1, p2, p3, p4). Однако, если примитив для рисования Catmull-Rom отсутствует, мы можем тривиально нарисовать его в виде кривой Безье, используя следующие кубические координаты кривой Безье:
t
значение здесь — напряжение кривой Катмулла-Рома; чем выше вы делаете это, тем «теснее» выглядит соединение (с напряжением по умолчанию в большинстве графических контекстов, которые поддерживают Catmull-Rom, просто равным 1).
Некоторые примеры значений:
Обратите внимание, что в каждом примере направление касательной в точках p2 и p3 сохраняется, но длина вектора касательных отличается, что приводит к очень плотному, приятному, слишком свободному соединению.
Как я уже говорил, в этом случае Сплайны могут быть лучшим решением, чем Безье. Тем не менее, вы также можете использовать более простой. у вас есть 4 балла (красный). Попробуйте подогнать их к полиному (3-й степени, поскольку у вас всего 4), используя следующую формулу:
A x^3 + B x^2 + C x + D = y
У вас есть 4 балла (P0,P1,P2,P3
):
A x0^3 + B x0^2 + C x0 + D = y0
A x1^3 + B x1^2 + C x1 + D = y1
A x2^3 + B x2^2 + C x2 + D = y2
A x3^3 + B x3^2 + C x3 + D = y3
Решение этой системы линейных уравнений даст вам значения A,B,C,D
,
Чтобы получить часть кривой, которая отсутствует:
for(auto x=P1.x; x<P2.x; ++x){
auto y=A*x*x*x + B*x*x + C*x + D;
cv::circle(image,cv::Point(x,y),.......);
}
Не исключаю кривые Безье. Вы правы в том, что кривая часто не пересекает контрольные точки, но конечные точки проходят, и вы можете использовать это, чтобы ограничить форму кривой.
Чтобы быть более точным, вы можете объединить линии, построив новую квадратичную кривую Безье — используйте конечные точки двух ваших линий в качестве конечных точек кривой, где средняя точка является пересечением двух воображаемых отрезков прямой линии, вытянутых от концов текущая строка.
В приведенном выше примере красные круги — это фиксированные конечные точки кривой, зеленые линии — это расширенные линии, синий круг — это их точка пересечения (используется в качестве контрольной точки), а синяя линия — это приблизительная кривая, в конечном итоге.
Редактировать: Подумав об этом немного больше, вы, вероятно, захотите использовать кубическую кривую и иметь две синие контрольные точки, по одной на каждой зеленой линии. Позиционирование каждого Л / 2 расстояние от конечных точек, где L прямое расстояние между красными конечными точками, вероятно, даст хорошие результаты. Проблема с квадратичной кривой состоит в том, что, когда зеленые линии приближаются параллельно, квадратичная кривая будет иметь острый угол вблизи контрольной точки. Параллельно они вообще не пересекаются. Использование кубической кривой даст намного более округлую линию и не будет иметь проблем с параллельными касательными. Например, на рисунке ниже верхняя кривая использует квадратичную (одна контрольная точка), а нижняя — кубическую (две контрольные точки).