Я пытаюсь использовать научную библиотеку GNU (GSL), чтобы нарисовать плавный путь от A до B. Я использую API, который возвращает небольшое количество (8 в данном случае) точек с неравномерным расстоянием (красным), что Вы можете увидеть на следующем рисунке:
Фиолетовые точки представляют точки, которые я хотел бы видеть возвращенными из GSL.
Во-первых, можно ли получить этот вид 2D B-сплайна с помощью GSL? Я не знаю много о B-сплайнах, не говоря уже о 2D-B-сплайнах. Мне удалось показать пример B-Splines Вот без проблем запустить и создать гладкий файл .ps, но в этом примере используются единые точки останова со следующим кодом:
/* use uniform breakpoints on [0, 15] */
gsl_bspline_knots_uniform(0.0, 15.0, bw);
В моем случае, учитывая, что данные, которые я предоставляю, ошибочны и неравномерно распределены, придется ли мне использовать неоднородные узлы? Я пытался с помощью gsl_bspline_knots()
, чтобы использовать неоднородные точки останова в следующем тестовом коде, но я действительно не уверен, является ли это правильным направлением или нет.
#define NCOEFFS 8 // not sure what this number should be - number of data points?
#define NBREAK (NCOEFFS - 2)
const size_t nbreak = NBREAK;
int main (void) {
// (example code)...
gsl_vector *non_uniform = gsl_vector_alloc(nbreak);
// create some random breakpoint values
for (i=0; i<nbreak; i++) {
double val = gsl_ran_gaussian(r, 2.0);
printf("val: %f\n", val);
gsl_vector_set(non_uniform, i, val);
}
gsl_bspline_knots(non_uniform, bw);
// (more example code)...
}
Более того, как бы я перевел приведенный выше пример для рисования B-сплайнов в 2D координатном пространстве x / y? Если научная библиотека GNU не подходит для этого, может ли кто-нибудь дать рекомендацию для более подходящей библиотеки C / C ++?
Любая помощь или указатели в этом направлении будет высоко ценится.
Первый: 1D Базисные сплайны
Учитывая набор NBREAK
контрольные точки (t_1, ..., t_{NBREAK})
, имеются NCOEFFS=NBREAK+2
кубические компоненты b-сплайнов B_j(t)
, Эти функции и их первая и вторая производные всегда непрерывны, даже в точках останова. Следовательно, любое соответствие, данное линейной комбинацией f(t) = \sum m_j B_j(t)
также поделится этими свойствами (аналогично естественным кубическим сплайнам). Количество компонентов b-сплайна, NCOEFFS
, не должно быть равно количеству точек данных, NDATA
, Если NCOEFFS < NDATA
, вы должны использовать метод наименьших квадратов для подгонки (документация GSL содержит хороший пример расчета минимальной наименьшей площади для подбора b-сплайна Вот). NCOEFFS < NDATA
это хороший выбор, когда данные содержат шум, который, кажется, не ваш случай
Причина, по которой количество коэффициентов не равно числу точек останова, NCOEFFS=NBREAK+2
, связано с тем, что вы не указываете граничное условие при работе с базисными сплайнами. Учитывая, что люди обычно более знакомы с естественными кубическими сплайнами, стоит прокомментировать, что естественные кубические сплайны накладывать граничное условие d^2f(x)/dx^2=0
, Вот почему любое представление натуральных кубических сплайнов с использованием кубического полиномиального базиса NCOEFFS=NBREAK
, Вот ссылка к очень хорошему объяснению о подсчете степеней свободы, заданных коэффициентами кубических полиномов, которые представляют как естественные b-сплайны, так и число уравнений, необходимых для наложения непрерывности f(t)
, df(t)/dt
а также d^2f(t)/dt^2
).
В заключение: Подгоните параметрическую кривую, используя b-сплайны.
У вас есть набор «данных» точек (x_1, y_1)....(x_{NDATA},y_{NDATA})
и вы хотите построить параметрическую подгонку P(t)=( f_1(t), f_2(t) )
, Подгонка B-сплайнов не будет проходить через все точки данных, если NCOEFFS<NDATA
(вы можете потребовать, если вы тщательно выберете свои контрольные точки и NCOEFFS=N_DATA
). В своем исследовании я работаю только с одномерными непараметрическими подгонками (y=f(x)
) но я считаю, что этот параметрический случай похож. Я бы попробовал следующее
ШАГ 1: Создайте набор точек «данных» (t, x) = {(1, x_1), (2, x_2)...(NDATA, x_{NDATA})}
и используйте gsl 1D b-сплайны, чтобы соответствовать им. Это подойдет вам f_1(t) = sum_{i=1}^{NCOEFFS} mx_j B_j(t)
с t \in [1,NDATA]
,
ШАГ 2: Теперь создайте набор точек «данных» (t, y) = {(1, y_1), (2, y_2)...(NDATA, y_{NDATA})}
и используйте b-сплайны, чтобы соответствовать им. Это даст вам f_2(t) = sum_{i=1}^{NCOEFFS} my_j B_j(t)
с t \in [1,NDATA]
Сейчас сюжет P(t)=( f_1(t), f_2(t) ), t \in [1,NDATA]
, По сути, я поставил задачу о двухмерной параметрической кривой в двухмерных непараметрических подгонках (что и обеспечивает GSL).
Последний пункт — это выбор точек останова (и количества базовых компонентов NCOEFFS
) в шаге 1 и шаге 2. Пока вы охватите диапазон t\in[1, NDATA]
а также NCOEFFS <= NDATA
выбор точек останова производится произвольно. Я считаю, что если вы выберете контрольные точки {1, 3, ..., NDATA-2, NDATA }
соответствие будет проходить через точки данных (обратите внимание, что я пропустил внутренние точки t=2
а также t=NDATA-1
такой, что NBREAK=NDATA-2
а также NCOEFFS=NDATA
). Вот как NAG библиотека выбирает контрольные точки для получения интерполяционного соответствия (то есть соответствия, которое проходит через точки данных).