9

我有一条l_1带有点系列的线p_1,...,p_n。我现在想要一条有点的新线l_2kBut q_1,...,q_k.for all i \in {1,...,k-1}: abs( q_i - q_i+1 ) = const,这意味着 的线段l_2是等距的或均匀的。

  • k >= 2
  • 并且p_1p_n 应该在l_2.
  • abs( p_i - p_i+1 )不是常量

一种解决方案是用样条曲线逼近一条线,然后再次对其进行二次采样,然后获得均匀长度的段。我还能做得更好吗?是否有任何 C++ 代码?

啊,我错过了一个具体细节:那些q_i应该在 中l_1,这意味着它们要么在 的线段上,l_1要么是 的样本点l_1

4

2 回答 2

8

使用参数函数

您可以定义分段参数函数:

 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]

最后以相等的 t 个间隔对 f[q] 进行采样。

样本结果:

替代文字

在这里您可以看到将原始样本中的区间大小从最大减小到最小的效果:

替代文字

您可以评估将原始曲线和重新采样曲线之间的面积(积分)相加的近似值:

替代文字

如果您绘制不同区间大小的积分,您可能会决定什么是好的采样:

替代文字

仅作记录,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*)
于 2010-10-29T15:10:16.790 回答
2

这取决于你的线点——它们是什么?如果他们定义了一条平滑线,那么重新采样三次样条是一个不错的选择。

本质上,如果您使点等距,您需要定义您希望在点之间看到的内容 - 平滑度是否比保持原线更重要?有速度限制吗?

据我所知,你很可能会在这里得到一个迭代过程,因为如果你的原始点定义了一条平滑的线,那么即使是这条线的长度也不容易​​计算出来,更不用说把它分成相等的部分了并确定这些点的坐标。

如果您使用三次样条,对于每个样条,您应该能够通过Wikipedia's Arc Length article上的公式计算其长度。但是,它需要您进行积分 - 当您进行数值积分时,它被称为“正交”。对于三次(计算两个原始点之间的线段的长度),这应该最终作为三次样条的系数的加权和 - 特别是如果您使用高斯求积。

但是,使用分段三次多项式(从 2 个点和它们两侧的 2 个点生成三次多项式)和改进 xi 的猜测值以给出等距点的迭代算法,您可能会得到一个合理的答案。但这是假设您想要速度而不是准确性。

于 2010-10-29T15:32:41.450 回答