Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Racheengel от Июль 21, 2007, 12:37



Название: Кривая по точкам
Отправлено: Racheengel от Июль 21, 2007, 12:37
Нужна функция, которая позволила бы провести плавную кривую по заданным точкам.
Точки задаются в виде массива Х и У, их может быть любое количество.

Методы cubicTo() и quadTo() не подходят, так как: 1. требуют контрольных точек, 2. ограничены отрезками из 2 или 3 точек, а стыкуются они криво.

Если ли у кого решение этой проблемы? Заранее спасибо.


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 21, 2007, 12:43
Оно ?
http://alglib.sources.ru/interpolation/spline3.php


Название: Кривая по точкам
Отправлено: Sergeich от Июль 21, 2007, 20:26
Достаточно вычислить контрольные точки. Это можно сделать через построение кубического сплайна для параметрической кривой: считаешь коэффициенты для сплайнов x(t) и y(t) (полагая что первая точка из заданного массива получается при t=0, вторая - при t=1, и т.д.), далее из коэффициентов сплайна легко получить контрольные точки для кривых Безье. Статей по построению куб. сплайнов в инете хуева туча.


Название: Кривая по точкам
Отправлено: Racheengel от Июль 21, 2007, 23:28
Спасибо за ссылку, я посмотрю. С первого взгляда то что надо.

Ну а по поводу статей - не нашел пока ни одной, решающей именно эту проблему - построить кривую по РЕАЛЬНЫМ точкам, а не по контрольным :(


Название: Кривая по точкам
Отправлено: joktar от Июль 22, 2007, 05:28
Рассчитывай необходимые контрольные точки.
Как - например Н.Н.Голованов Геометрическое моделирование или Адамс,Математические основы машинной графики.


Название: Кривая по точкам
Отправлено: Racheengel от Июль 22, 2007, 09:42
Проблема в том, что встроенные методы QPainter cubicTo() и quadTo() предназначены только для рисования отрезков из 3 точек. То есть, если их стыковать между собой для большей кривой, место стыка выглядит не плавно. Мне же нужна плавная кривая, проходящая более чем через 3 точки (их штук 100 может быть).


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 22, 2007, 10:10
Цитата: "Racheengel"
Проблема в том, что встроенные методы QPainter cubicTo() и quadTo() предназначены только для рисования отрезков из 3 точек. То есть, если их стыковать между собой для большей кривой, место стыка выглядит не плавно. Мне же нужна плавная кривая, проходящая более чем через 3 точки (их штук 100 может быть).

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


Название: Кривая по точкам
Отправлено: Racheengel от Июль 25, 2007, 08:32
Посмотрел я ссылку... к сожалению, это не то, что надо.
Алгоритм, приведенный там - не работает.
Я пытался построить сплайн всеми способами - но он либо просто соединяет узловые точки прямыми, либо вообще рисует бред.

Вопрос НЕ В РАСЧЕТАХ контрольных, производных и прочих точек. Пусть это останется уделом фанатов. Я ищу РЕАЛЬНО РАБОТАЮЩИЙ алгоритм. Когда на входе задан QVector<QPoint>, И ВСЕ. И рисуется сплайн по данным точкам.

добавлено спустя 7 часов 53 минуты:

 Все, вопрос решился небольшой переделкой Qwt.
Всем спасибо.
Если кому интересно - могу выслать класс отрисовки сплайна, отвязанный от Qwt.


Название: Кривая по точкам
Отправлено: vaprele07 от Июль 25, 2007, 16:16
в qt4.1 появился qpainterpathstroker
в демках можно посмотреть реализацию, вроде то что надо


Название: Кривая по точкам
Отправлено: Sergeich от Июль 25, 2007, 17:10
Цитировать
в qt4.1 появился qpainterpathstroker
в демках можно посмотреть реализацию, вроде то что надо
Причем тут QPainterPathStroker!? Он просто рисует кривую в виде прерывивистой линии по заданному паттерну!

добавлено спустя 15 минут:

 2 Racheengel: А как оно в QWT рисуется? Хуевой тучей мелких отрезков? Или все-таки через cubicTo() ?


Название: Кривая по точкам
Отправлено: Racheengel от Июль 25, 2007, 17:49
В qwt там сначала идет просчет аппроксимирующих отрезков, а потом - через drawLines(). Хуевой тучей :)


Название: Кривая по точкам
Отправлено: vaprele07 от Июль 26, 2007, 03:09
QGraphicsPathItem? qpainterpath (http://doc.trolltech.com/4.1/qpainterpath.html)? не спорю если речь идёт о qt без QGraphicsScene.


Название: Кривая по точкам
Отправлено: pastor от Июль 26, 2007, 11:14
2 vaprele07: Каким образом ты собираешься получить плавную кривую без контрольных точек при помощи QPainterPath?


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 26, 2007, 11:52
А что вы тут называете контрольными точками???

ЗЫ: У меня в свое время лабраторные по сплайнам были. Исходники правда не сохранились ( да и кому они нафиг нужны на паскале : ) ), но, помнится, ничего там сложного небыло, и все рисовалось как надо


Название: Кривая по точкам
Отправлено: Racheengel от Июль 26, 2007, 14:23
В том то и дело, что это два принципиально разных подхода к построению сплайна: по контрольным точкам и по реальным.
Мне нужно было построение по реальным.


Название: Кривая по точкам
Отправлено: vaprele07 от Июль 26, 2007, 15:12
вот кривая по заданным точкам:
Код:
QPainterPath createPath(QPointF cord, QList<QPointF> points)
{
  while (points.count() % 3 != 0)
    points << points.at(points.count() - 1);
         
  QPainterPath path;
  path.moveTo(cord);
  int i = 0;
  while (i + 2 < points.count()){
    path.cubicTo(
      points.at(i),
      points.at(i + 1),
      points.at(i + 2)
    );
    i += 3;
  }
  return path;    
}

Racheengel, объясни что в ней не так  :roll:


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 26, 2007, 15:25
Цитата: "Racheengel"
В том то и дело, что это два принципиально разных подхода к построению сплайна: по контрольным точкам и по реальным.
Мне нужно было построение по реальным.

Чем они отличаются???

2vaprele07 Так как ты написал, ч-з каждые 3 точки будет излом.


Название: Кривая по точкам
Отправлено: Racheengel от Июль 26, 2007, 17:48
vaprele07, мы пробовали подобный подход ранее. Он нас не устроил из-за того, что кривая получалась неравномерной, и заказчику это очень не нравилось. Пришлось искать альтернативные алгоритмы, мы нашли то что надо в исходниках Qwt 5 (сколько тут на него ни гнали, но свои плюсы в нем таки есть).

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


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 27, 2007, 09:16
Цитата: "Racheengel"

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

Можно конкретнее, в чем разница?


Название: Кривая по точкам
Отправлено: Racheengel от Июль 27, 2007, 21:42
Ну вот как тебе будет проще кривую построить:
задать массив координат (х.у) точек, через коротую она должна проходить,
или задать массив контрольных точек, которые находятся неизвестно где в пространстве, предварительно их просчитав?
Лично я вообще не понимаю, зачем нужны функции построение по контрольным точкам. КАК и ГДЕ их можно использовать?


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 27, 2007, 23:01
Вроде как понял - это разные задачи и не стоит их смешивать.
 Первый случай - это интерполяция. Это то что нам нужно для красивого отображения данных, снятых с датчика. Тут нам нужно нарисовать гладкую кривую, которая проходит ч-з все полученные точки.

Второй вариант, я так понял, - это аппроксимация. В этом случае у нас опять есть набор полученных в результате эксперимента точек. Также мы знаем общий вид зависимости, которая соответствует нашим точкам. Тут зависимость - это формула, но с неизвестными коэфициентами. Например y=Asin(bx+c). Для решения задачи нам необходимо найти все эти коэфициенты по известным точкам. Дополнительное условие - точки не обязательно точно соответствуют закономерности, так как датчики имеют некую погрешность.


Название: Кривая по точкам
Отправлено: Racheengel от Июль 28, 2007, 09:27
Ну, с моей точки зрения, первый случай - это плавная интерполяция при помощи вычисления аппроксимирующих отрезков.  То есть в пространстве между заданными точками, по которым должен пройти сплайн, вычисляются дополнительные точки, по которым он также проходит, а потом соединяются отрезками. Нужно это, да, для отображения данных с датчика, но не просто для красивого, а более достоверного в интервалах между точками контроля.

А второй способ построения сплайнов - отрезками из 2-х точек (начало и конец), плюс еще одна или две контрольных. Меняя положение контрольных точек, меняется вид сплайна, но сказать, через какие точки он пройдет, заранее невозможно. В итоге сплайн, состоящих из таких вот кусочков, получается не гладкий, а с изломами в узлах. Лично мне вообще трудно найти применение такому подходу.


Название: Кривая по точкам
Отправлено: Sergeich от Июль 29, 2007, 18:48
Рисовать сплайн между двумя точками хуевой тучей мелких отрезков не есть гуд. Рисовать надо кривыми Безье (cubicTo) - для их построения применяются оптимизированные алгоритмы и вычисления могут идти на хардварном уровне.
  Контрольные точки элементарно получаются из коэффициентов сплайна:
CP1 = P0 + 1/3*C
CP2 = P0 + 2/3*C + 1/3*B,
где CP1, CP2 - котрольные точки, P0 - точка от к-ой ты ведешь кривую, С и B - коээфициенты сплайна.
  Построение сплайна нагло пиздим (для использования в закрытых исходниках  :lol: ) из QwtSpline::buildNaturalSpline для незамкнутых кривых и из QwtSpline::buildPeriodicSpline для замкнутых. Вычисляем коэффициенты сплайнов x(t) и y(t), приняв t=0,1,2,... и по приведенным формулам получаем контрольные точки. Строим QPainterPath. Идем пить пиво :)
  Пример кода в аттаче.


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 29, 2007, 20:35
Звучит конечно круто!
Но хочу заметить, что на наиболее распространный девайс для отображения графиков - это монитор, который, увы, является растровым девайсом. Следовательно от кучи отрезков никуда не деться. Единственного помошника я вижу в видеокарте. Вполне возможно, что она умеет на своем процессоре произвести все вычисления и сгенерить все эти отрезки. Если кто знает, как все это сделать на прикладном уровне, то я снимаю шляпу :)
Кривая Безье  третего порядка, как и кубический сплайн, основывается но полиноме третего порядка. Посему я очень сильно сомневаюсь в том, что тут есть какая-то разница в затратах на расчет.
Насколько я знаю, контрольные точки в кривых Безье используются для задания направления выпуклости кривой. Это все просто замечательно, но зачем нам такая возможность для интерполяции???
Посему мой выбор - сплайны!  :D


Название: Кривая по точкам
Отправлено: Sergeich от Июль 29, 2007, 23:41
Цитата: "Alex Forth"
Насколько я знаю, контрольные точки в кривых Безье используются для задания направления выпуклости кривой. Это все просто замечательно, но зачем нам такая возможность для интерполяции???
Посему мой выбор - сплайны!
Мда... Кубический сплайн - это несколько кривых 3-ого порядка, соединенные вместе, в точках соединения требуется равенство первой и второй производной. Кубический сплайн Безье - это несколько кривых Безье 3-ого порядка, соединенных вместе и требующих  опять же равенства первых и вторых производных в точках соединения. Полином третьего порядка записывается в виде: At^3 + Bt^2 + Ct + P0, кривая Безье: P0(1-t)^3 + P1(1-t)^2*t + P2(1-t)*t^2+P3*t^3. Очевидно, что между их коэффициентами существует взаимооднозначное соответствие. Поэтому НИКАКОЙ РАЗНИЦЫ МЕЖДУ НИМИ НИХУЯ НЕТУ, кроме формы записи.
Только в случае если ты нашел коэффициенты сплайна, при растеризации ты должен сам рассчитывать промежуточные точки между опорными с каким-то хитро выбираемым шагом, чтобы все это выглядело как гладкая кривая. Если же ты переведешь рассчитанные коэффициенты в коэффициенты кривой Безье (aka контрольные точки) - всеми расчетами за тебя будет заниматься библиотека, плюс ты получишь стандартное переносимое представление кривой, к-ое можно сохранить хоть в SVG, хоть в PostScript.


Название: Кривая по точкам
Отправлено: Alex Forth от Июль 30, 2007, 20:30
Цитата: "Sergeich"

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

Ничего хитрого, ч-з пиксель и вперед. Наверняка библиотесная  реализация кривых безье также делает.
Цитата: "Sergeich"

Если же ты переведешь рассчитанные коэффициенты в коэффициенты кривой Безье (aka контрольные точки) - всеми расчетами за тебя будет заниматься библиотека,

Библиотечные реализации сплайнов тоже есть. Да и работы там - лабораторная для студента.
Цитата: "Sergeich"
ты получишь стандартное переносимое представление кривой, к-ое можно сохранить хоть в SVG, хоть в PostScript.

За SVG и PS зачет.  :D О них я как-то не вспомнил. Я привык данные от датчиков в файлы лить. Картинки при это генерить не приходилось.


Название: Кривая по точкам
Отправлено: Sergeich от Август 02, 2007, 00:34
Цитата: "Alex Forth"
Цитата: "Sergeich"

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

Ничего хитрого, ч-з пиксель и вперед. Наверняка библиотесная  реализация кривых безье также делает.
Оно не так уж просто. "Жизнь намного разнообразнее"(с) Посмотри, например, реализацию в qbezier.cpp (flattenBezierWithoutInflections(QBezier &bez, QPolygonF &p))
Цитата: "Alex Forth"
Цитата: "Sergeich"
Если же ты переведешь рассчитанные коэффициенты в коэффициенты кривой Безье (aka контрольные точки) - всеми расчетами за тебя будет заниматься библиотека
Библиотечные реализации сплайнов тоже есть. Да и работы там - лабораторная для студента.
Имелись в виду не реализации построения сплайна ( вычисления его коэффициентов ), а реализация рендеринга, к-ая с учетом произвольной ширины кривой, произвольного шаблона штриховки и антиалиасинга, вообщем-то нетривиальна.


Название: Кривая по точкам
Отправлено: kotofay от Август 02, 2007, 12:00
В GDI+ есть отрисовка как по контрольным точкам так и по узлам.
Для винды только :(


Название: Re: Кривая по точкам
Отправлено: BaltikS от Август 01, 2008, 13:29
Сергееич, мне понравился твой пример с сплайном. Попытался переписать функцию для периодического сплайна. Но не вышло. QPainterPath пустой. Видимо что то с коэф. не так. Привожу пример переписанной функции:
Код:
bool buildPeriodicSpline( int size, double* t, double* p, double* a, double* b, double* c )
{
int i;
//  set up tridiagonal equation system; use coefficient
//  vectors as temporary buffers
double* h = new double[size-1];
double* d = new double[size-1];
double* s = new double[size];
for (i = 0; i < size - 1; i++)
{
h[i] = t[i+1] - t[i];
if (h[i] <= 0) {
//h[i] = 0.1;
delete[] h;
return false;
}
}

const int imax = size - 2;
double htmp = h[imax];
double dy1 = (p[0] - p[imax]) / htmp;
for (i = 1; i < imax; i++)
{
b[i] = c[i] = h[i];
a[i] = 2.0 * (htmp + h[i]);

const double dy2 = (p[i+1] - p[i]) / h[i];
d[i] = 6.0 * ( dy1 - dy2);
dy1 = dy2;
htmp = h[i];
}

//
// solve it
//

// L-U Factorization
a[0] = sqrt(a[0]);
c[0] = h[imax] / a[0];
double sum = 0;

for(i = 1; i < imax - 1;i++)
{
b[i] /= a[i];
if (i > 0)
c[i] = - c[i-1] * b[i-1] / a[i];
a[i+1] = sqrt(a[i+1] - b[i]*b[i]);
sum += c[i]*c[i];
}
b[imax-1] = (b[imax-1] - c[imax-2]*b[imax-2])/a[imax-1];
a[imax] = sqrt(a[imax] - b[imax-1]*b[imax-1] - sum);
//a[imax] = sqrt(a[imax] - (b[imax-1] - sum)*(b[imax-1] - sum));

// forward elimination
//double* s = new double[size];
s[0] = d[0] / a[0];
sum = 0;
for ( i = 1; i < imax; i++)
{
s[i] = (d[i] - b[i-1]*s[i-1]) / a[i];
sum+=c[i-1]*s[i-1];
}
s[imax] = (d[imax] - b[imax-1]*s[imax-1] - sum) / a[imax];

// backward elimination
s[imax] = - s[imax] / a[imax];
s[imax-1] = -(s[imax-1]+b[imax-1]*s[imax]) / a[imax-1];
for (i = imax-2; i >=0; i--)
s[i] = - (s[i] + b[i] * s[i+1]+c[i]*s[imax]) / a[i];


//
// Finally, determine the spline coefficients
//
s[size-1] = s[0];
for (i = 0; i < size - 1; i++)
{
a[i] = ( s[i+1] - s[i] ) / ( 6.0 * h[i]);
b[i] = 0.5 * s[i];
c[i] = ( p[i+1] - p[i] ) / h[i]
- (s[i+1] + 2.0 * s[i] ) * h[i] / 6.0;
}

return true;
}


Название: Re: Кривая по точкам
Отправлено: Sergeich от Сентябрь 06, 2008, 12:41
Добавил к предыдущему коду построение периодических сплайнов, они строятся если последняя точка QPolygonF совпадает с первой. Код в аттаче.


Название: Re: Кривая по точкам
Отправлено: Racheengel от Сентябрь 10, 2008, 13:57
Смотрю, тема через год воскресла :)
А вот найденное решение для кривой по точкам:
http://ii-system.com/soft/devzone/spline.2007.09.16.zip



Название: Re: Кривая по точкам
Отправлено: Sergeich от Сентябрь 13, 2008, 09:32
Не работает ссылка.


Название: Re: Кривая по точкам
Отправлено: lit-uriy от Сентябрь 13, 2008, 10:13
2 Sergeich, дак ты на ii-system.com зайди в раздел "Developer Zone" (http://ii-system.com/soft/devzone/devzone.htm)


Название: Re: Кривая по точкам
Отправлено: Racheengel от Сентябрь 13, 2008, 15:49
хм, может сервер лежал - сейчас работает...


Название: Re: Кривая по точкам
Отправлено: miha-ha от Ноябрь 13, 2008, 17:58
для того, чтобы кривая была плавной в точках соединения нужно точки выбирать следующим образом:
первый участок кривой: 1, 2, 3
второй участок кривой: 2, 3,4
и т.д. тогда всё будет ок! с помощью встроенных функций... и не нуна выдумывать велосипед ;)


Название: Re: Кривая по точкам
Отправлено: Sergeich от Ноябрь 13, 2008, 22:30
Умный, да? Можешь дать определение плавности? И объяснить чо такое 123, 234? Это КТ Безье? или чо?


Название: Re: Кривая по точкам
Отправлено: miha-ha от Март 03, 2009, 17:44
Умный, да? Можешь дать определение плавности? И объяснить чо такое 123, 234? Это КТ Безье? или чо?
Хм... Если на память, то функция называется гладкой если дифференцируема в каждой точке...
а цифры - это контрольные точки, и если строить как я указал можно получить плавную кривую без изломов.


Название: Re: Кривая по точкам
Отправлено: Racheengel от Март 04, 2009, 01:00
вообще вопрос был про построение кривой через ПРОХОДЯЩИЕ точки, а не через контрольные...


Название: Re: Кривая по точкам
Отправлено: miha-ha от Март 04, 2009, 10:04
вообще вопрос был про построение кривой через ПРОХОДЯЩИЕ точки, а не через контрольные...
Вот в виде кода:
Код:
QPointF MainWindow::CatmulRom(QPointF &p1, QPointF &p2, QPointF &p3, QPointF &p4, double &t)
{
    return 0.5*(-t*(1-t)*(1-t)*p1+(2-5*t*t+3*t*t*t)*p2+t*(1+4*t-3*t*t)*p3-t*t*(1-t)*p4);
}

void MainWindow::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);

    QPointF p1(50,50), p2(100,80), p3(150,50), p4(200,100), p5(250,50), p6(300,100);

    painter.setPen(QPen(QBrush(Qt::red),5));
    painter.drawPoint(p1);
    painter.drawPoint(p2);
    painter.drawPoint(p3);
    painter.drawPoint(p4);
    painter.drawPoint(p5);
    painter.drawPoint(p6);

    double tStart=0, tFinish=0;

    int stepCount = 5;
    for(int i=0; i<stepCount; ++i)
    {
        tStart = tFinish;
        tFinish += 1.0/stepCount;
        painter.setPen(Qt::green);
        //сегмент рассчитывается на участке между 2-х внутренних точек
        painter.drawLine(CatmulRom(p1,p1,p2,p3,tStart), CatmulRom(p1,p1,p2,p3,tFinish));  //дублирование первой точки для построения первого сегмента p1-p2
        painter.drawLine(CatmulRom(p1,p2,p3,p4,tStart), CatmulRom(p1,p2,p3,p4,tFinish));  //p2-p3
        painter.drawLine(CatmulRom(p2,p3,p4,p5,tStart), CatmulRom(p2,p3,p4,p5,tFinish));  //p3-p4
        painter.drawLine(CatmulRom(p3,p4,p5,p6,tStart), CatmulRom(p3,p4,p5,p6,tFinish));  //p4-p5
        painter.drawLine(CatmulRom(p4,p5,p6,p6,tStart), CatmulRom(p4,p5,p6,p6,tFinish));  //дублирование последней точки для построения последнего сегмента p5-p6

    }


}

не отдельная функция как Вы просили, но думаю разберетесь!


Название: Re: Кривая по точкам
Отправлено: miha-ha от Март 04, 2009, 10:17
(http://скрин)


Название: Re: Кривая по точкам
Отправлено: Racheengel от Март 23, 2009, 15:31
Выглядит симпатично :)
Не желаете в виде компонента оформить и выложить на кути-апс например?


Название: Re: Кривая по точкам
Отправлено: Khs от Март 23, 2009, 15:48
Мне кажется прежде чем выкладывать, надо как-то усложнить данный пример :)


Название: Re: Кривая по точкам
Отправлено: miha-ha от Март 23, 2009, 16:02
Выглядит симпатично :)
Не желаете в виде компонента оформить и выложить на кути-апс например?

Спасибо!
Но боюсь, что как обычно не хватит времени... :(


Название: Re: Кривая по точкам
Отправлено: нуб от Июнь 15, 2012, 01:24
Народ сори за флуд но есть задачка по кривой безье помогите решить
2. Вычислить координатный вектор Р3, задающий касательный
вектор, проходящий вдоль кривой, соединяющей два сегмента кривой Безье,
иначе определяемых как P1[0 0 0], P2[2 2 -2], P4[4 0 0] и Q1[4 0 0], Q2[6 -2 1],
Q3[8 -3 2], Q4[10 0 1].


Название: Re: Кривая по точкам
Отправлено: deMax от Июль 24, 2013, 22:04
не отдельная функция как Вы просили, но думаю разберетесь!
Скопипастил фашу формулу, это сплайн Эрмита. Однако в моей задаче возникла проблема, точка вброса: в моей задаче есть случай, контур похож на яйцо(трансформированный круг) со множеством точек и иногда две нижние точки яйца разрываются и расходятся в стороны на большое расстояние, в результате сплайн на предыдущем отрезке шатает, как на картинке, а должно быть как со сплайном Акима.
(http://alglib.sources.ru/interpolation/i/akimaspline.gif)
Мне понравился вариант со сплайном Акимы, посоветуйте вариант для замкнутой кривой на плоскости и полегче алгоритм. Желательно чтобы сплайн проходил по точкам - это верные значения.

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