Линейная интерполяция двух векторных массивов с разными длинами - PullRequest
0 голосов
/ 10 октября 2019

PenInput & PenSmoot У меня есть две кривые. Один handdrawn и один сглаженный вариант handdrawn. Данные каждой кривой хранятся в 2 отдельных векторных массивах. Дельта времени также сохраняется в векторе кривой отрисовки от руки, поэтому я могу воспроизвести процесс рисования, чтобы он выглядел естественно.

Теперь мне нужно перевести Дельту времени из кривой 1 (необработанный ввод) в кривую 2 (уже сглаженная кривая).

Иногда размер первого вектора больше, а иногда меньше, чем у второго вектора.
(зависит от скорости рисования на входе)

Поэтому мой вопрос:Как мне заполнить вектор PenSmoot.time правильными значениями?

Случай 1: вектор ввода больше

PenInput.time[0] = 0         PenSmoot.time[0] = 0
PenInput.time[1] = 5         PenSmoot.time[1] = ?
PenInput.time[2] = 12        PenSmoot.time[2] = ?
PenInput.time[3] = 2         PenSmoot.time[3] = ?
PenInput.time[4] = 50        PenSmoot.time[4] = ?
PenInput.time[5] = 100
PenInput.time[6] = 20
PenInput.time[7] = 3
PenInput.time[8] = 9
PenInput.time[9] = 33

Случай 2: вектор вводаменьше

PenInput.time[0] = 0         PenSmoot.time[0] = 0
PenInput.time[1] = 5         PenSmoot.time[1] = ?
PenInput.time[2] = 12        PenSmoot.time[2] = ?
PenInput.time[3] = 2         PenSmoot.time[3] = ?
PenInput.time[4] = 50        PenSmoot.time[4] = ?
                             PenSmoot.time[5] = ?
                             PenSmoot.time[6] = ?
                             PenSmoot.time[7] = ?
                             PenSmoot.time[8] = ?
                             PenSmoot.time[9] = ?

Простое представление:

PenInput holds the whole data of a drawn curve (Raw Input)

PenInput.x         // X coordinate)
PenInput.y         // Y coordinate)
PenInput.pressure  // The pressure of the pen)
PenInput.timetotl  // Total elapsed time)
PenInput.timepart  // Time fragments)

PenSmoot holds the data of the massaged (smoothed,evenly distributed) curve of PenInput

PenSmoot.x         // X coordinate)
PenSmoot.y         // Y coordinate)
PenSmoot.pressure  // Unknown - The pressure of the pen)
PenSmoot.timetotl  // Unknown - Total elapsed time)
PenSmoot.timepart  // Unknown - Time fragments)


Это структура, которая у меня есть.

struct Pencil 
{
    sf::VertexArray vertices;
    std::vector<int> pressure;
    std::vector<sf::Int32> timetotl;
    std::vector<sf::Int32> timepart;
};

1 Ответ

2 голосов
/ 10 октября 2019

[Этот ответ был тщательно пересмотрен на основе редактирования вопроса.]

Хорошо, мне кажется, что вам почти нужно интерполировать метки времени параллельно с точками.

Я собираюсь догадаться, что входящие данные - это что-то порядка массива точек (например, координат X, Y) и массива дельт времени с одинаковым числом каждой, поэтому дельта времени N говорит вамвремя, необходимое для перехода из точки N-1 в точку N.

Когда вы интерполируете точки, вы, вероятно, захотите сделать это разумно. Например, в форме, показанной в вопросе, мы имеем то, что выглядит как две почти прямые линии, одна с положительным наклоном, а другая с отрицательным наклоном. Согласно рисунку, он состоит из 263 баллов. Мы могли бы уменьшить это до трех точек и все еще иметь достаточно разумное представление исходной формы, выбрав две конечные точки плюс одну точку, где две линии встречаются.

Нам, вероятно, не нужно идти совсем такдалеко, хотя. Особенно принимая во внимание время, мы, вероятно, хотели бы использовать по крайней мере 7 точек для вывода - по одной на каждую конечную точку каждого цветного сегмента. Это дало бы нам 6 прямых отрезков. Допустим, они находятся в точках 0, 30, 140, 180, 200, 250 и 263.

Затем мы использовали бы точно такую ​​же сегментацию для дельт времени. Сложите дельты от 0 до 30, чтобы получить среднюю скорость для первого сегмента. Сложите дельты от 31 до 140, чтобы получить среднюю скорость для второго сегмента (и так далее до конца).

Увеличение количества точек работает примерно так же. Нам нужно посмотреть, какие именно входные точки были использованы для создания пары выходных точек. Для упрощенного примера, давайте предположим, что мы создали вывод, который был точно вдвое больше точек ввода. Затем мы интерполировали бы дельты времени точно наполовину между каждой парой входных точек.

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

Это тоже хорошо. Мы интерполируем между двумя точками входа, чтобы выяснить время взлома для начальной точки выходного сегмента. Аналогично для конечной точки. Затем мы можем вычислить общее время, которое должно было пройти между ними, на основе разницы во времени между точками.

Если вы хотите проявить фантазию, вы можете использовать интерполяцию более высокого порядка вместо линейной. Для этого требуется больше входных точек на интерполяцию, но, похоже, у вас, вероятно, есть много чего сделать, например, квадратичную или кубическую интерполяцию (в большинстве случаев). Это, вероятно, будет иметь наибольшее значение при переходах - места, где «ручка» быстро ускорялась или замедлялась. В таком случае линейная интерполяция может дать несколько вводящие в заблуждение результаты (хотя, учитывая количество точек, с которыми вы, кажется, работаете, это может не иметь достаточного значения, чтобы заметить).

В качестве иллюстрации давайте рассмотримпрямая линия. Мы собираемся начать с 5 входных точек и произвести 7 выходных точек.

Итак, входными точками являются [0, 2, 7, 10, 15], а соответствующие временные дельты равны [0,1, 4, 8, 3].

Итак, общее пройденное расстояние составляет 16, и мы хотим, чтобы наши выходные точки были равномерно распределены. Таким образом, расстояние между выходными точками будет 16/7 = (примерно) 2,29.

Итак, очевидно, что первая выходная точка и время равны 0. Вторая выходная точка равна 2,29. Чтобы вычислить время вывода, мы берем все время до первой точки ввода (0-> 2) плюс .29 / (7-2) * (4-1). Эта интерполированная секция дает 1,37, поэтому наша первая дельта времени вывода равна 2,37.

Следующая выходная точка должна быть на расстоянии 4,58. Поскольку второй входной сегмент идет от 2 до 7, весь наш второй выходной сегмент будет находиться во втором входном сегменте. Итак, мы берем 2,29 / (7-2), говоря, что этот выходной сегмент занимает 0,485 входного сегмента. Затем мы умножаем это на время для второго входного сегмента, чтобы получить дельту времени для второго выходного сегмента: .458 * (4-1) = 1,337.

[... и она продолжается на том жепуть до конца.]

...