Как equidistant Resample линия (или кривая)?
Вопрос
У меня есть линия l_1
дано с серии точек p_1,...,p_n
. Отказ Теперь я хочу новую линию l_2
иметь k
точки: q_1,...,q_k.
Но для всех i \in {1,...,k-1}: abs( q_i - q_i+1 ) = const
, что означает сегменты l_2
равных или равномерных.
k >= 2
- и
p_1
и p_n должен быть вl_2
. abs( p_i - p_i+1 )
не конденс
Одним из решений является приближение строки с помощью сплайна, а затем снова подгружайтесь на это, чтобы иметь единую длину сегменты. Могу ли я сделать лучше? Есть ли код C ++ для этого?
Ах, я пропустил определенную деталь: те q_i
должно быть внутри l_1
, значение либо они находятся на линии сегментов l_1
Или они являются образцами l_1
.
Решение
Использование параметрической функции
Вы можете определить кусочно-параметрическую функцию:
f[t_] := Piecewise[
When x[i] <= t <= x[i + 1]
f[t]= (y[i+1]-y[i]) (t - x[i]) / (x[i+1]-x[i]) + y[i],
For {i, 1 ... N};
Затем выберите свои очки Q, идеально расположенные меньше, чем минимальный P [I + 1] -P [I
Наконец образец f [q] при равных интервалах T.
Результат образца:
Здесь вы можете увидеть эффект уменьшения размера интервала от самого большого до самого маленького в исходном образце:
Вы можете оценить доброе приближение, добавляя области (интеграцию) между оригинальными и повторными избранными кривыми:
Если вы постройте интегралы для различных размеров интервалов, вы можете решить, какая хорошая выборка:
Просто для записи код в Mathematica:
a = 0;
p = Table[{ a = a + RandomReal[], RandomReal[]}, {10}];
f[t_, h_] := Piecewise[Table[{(h[[i + 1, 2]] - h[[i, 2]]) (t - h[[i, 1]]) /
(h[[i + 1, 1]] - h[[i, 1]]) + h[[i, 2]],
h[[i, 1]] <= t <= h[[i + 1, 1]]},
{i, 1, Length[h] - 1}]];
minSeg[h_] := Min[Table[Norm[h[[i, 1]] - h[[i + 1, 1]]], {i, Length[h] - 1}]];
newSegSize[h_] := (h[[Length@h, 1]] - h[[1, 1]])/
Ceiling[(h[[Length@h, 1]] - h[[1, 1]])/minSeg[h]]
qTable = Table[{t, f[t, p]}, {t, p[[1, 1]], p[[Length@p, 1]], newSegSize[p]}];
Редактировать: Отвечая на ваш комментарий
Комментарий кода PGM:
a = 0; (* Accumulator to ensure an increasing X Value*)
p = Table[{a = a + RandomReal[],
RandomReal[]}, {10}]; (*Generates 10 {x,y} Rnd points with \
increasing x Value*)
f[t_, h_] := (* Def. a PWise funct:
Example of resulting function:
f[t,{{1,2},{2,2},{3,4}}]
Returns teh following function definition:
Value for Range
2 1<=t<=2
2+2*(-2+t) 2<=t<=3
0 True
*)
Piecewise[
Table[{(h[[i + 1, 2]] -
h[[i, 2]]) (t - h[[i, 1]])/(h[[i + 1, 1]] - h[[i, 1]]) + h[[i, 2]],
h[[i, 1]] <= t <= h[[i + 1, 1]]},
{i, 1, Length[h] - 1}]];
minSeg[h_] := (* Just lookup the min input point separation*)
Min[Table[Norm[h[[i, 1]] - h[[i + 1, 1]]], {i, Length[h] - 1}]];
newSegSize[h_] := (* Determine the new segment size for having
the full interval length as a multiple of the
segment size *)
(h[[Length@h, 1]] - h[[1, 1]])/
Ceiling[(h[[Length@h, 1]] - h[[1, 1]])/minSeg[h]]
qTable = (*Generates a table of points using the PW function *)
Table[
{t, f[t, p]},
{t, p[[1, 1]], p[[Length@p, 1]],newSegSize[p]}];
ListLinePlot[{qTable, p}, PlotStyle -> {Red, Blue}] (*Plot*)
Другие советы
Это зависит от ваших точек линии - что они? Если они определяют гладкую строку, то повторное повторное использование кубического сплайна - хорошая ставка.
По сути, если вы делаете Equidistant Points, вам нужно определить то, что вы хотите увидеть между точками - это гладкость важнее, чем пребывание в оригинальной строке? Есть ли ограничение скорости?
Насколько я вижу, вы, вероятно, получите здесь итеративный процесс, потому что если ваши исходные точки определяют гладкую строку, не просто рассчитать даже длину этой линии, не говоря уже о том, чтобы разделить это на равные части и определить координаты этих точек.
Если вы используете кубические сплайны, для каждого сплайна вы должны быть в состоянии рассчитать ее длину через формулу на Статья дуги Википедии. Отказ Тем не менее, это требует от вас интеграции - когда вы делаете численную интеграцию, это известно как «квадратура'. Для кубики (для расчета длины линейного сегмента между двумя исходными точками) это должно быть в конечном итоге в качестве взвешенной суммы коэффициентов кубического сплайна - особенно если вы используете гауссовую квадратуру.
Тем не менее, вы, вероятно, могли получить разумный ответ, используя кусочно-кубические многочлены (генерируют кубический полиномиальный от 2 баллов, а 2 балла в обеих сторонах), так и итерационный алгоритм, который улучшает догадывание значений XI, чтобы дать эквидистантные точки. Но это предполагает, что вы хотите скорость, а не точность.