点之间的距离均匀

时间:2010-06-08 17:47:35

标签: objective-c math geometry calculus

我怎么能有一条路径由几个相距不均匀的点定义,沿同一路径重新定义相同数量的点,但距离均匀。我正在尝试使用NSArray的{​​{1}} s在Objective-C中执行此操作,但到目前为止,我还没有任何运气。 谢谢你的帮助。

修改

我想知道它是否有助于减少点数,例如当检测到3点是否共线时我们可以删除中间点,但我不确定这会有所帮助。

修改

龙虎斗: 红色是原始点,蓝色是后处理点:

alt text http://img139.imageshack.us/img139/3235/exampleg.jpg

蓝点定义的新路径与原始路径不对应。​​

5 个答案:

答案 0 :(得分:3)

我认为你不能做你所说的你想做的事。但这可能是我的误解。例如,我从你的评论中了解到,连续点之间的路径是直的,而不是弯曲的。

例如,采用不同长度的3点(0,1,2)和2线段(0-1,1-2)的简单路径。将点0和2保留在它们所在的位置并引入一个新的点1',它与点0和2等距离。如果点1'位于其中一个线段0-1,1-2上,则其中一个线段0 -1',1'-2与0-1,1-2不一致。 (更容易绘制这个,我建议你这样做。)如果点1'不在任何一个原始线段上,那么整个路径是新的,除了它的端点。

那么,您想要新路径和旧路径之间的关系?

编辑:更多的是扩展评论,比如我的“答案”,但评论框太小了。

我还不清楚你想如何定义新路径以及它与旧路径的关系。首先,您希望保持相同的点数,但在编辑中,您说这不是必需的。您同意用新点替换点将改变路径。您是否想要一条从0点到N-1的新路径,由在路径上均匀分布的N个点定义,在笛卡尔平面上绘制时最小化旧路径和新路径之间的区域?

或者,您可能首先要定义一条通过原始点的多项式(或样条曲线或其他简单曲线)路径,然后沿着曲线来回移动这些点,直到它们均匀分布?

答案 1 :(得分:1)

我认为问题很简单,实际上很容易解决:)

基本理念是:

  • 首先检查当前点(P)与您所在线段的终点之间的距离是否> = P与下一个点(Q)之间的距离。

  • 如果它很好,我们会使用一些简单的三角函数来解决它。

  • 否则,我们移动到相邻的线段(在您的订购中),扣除P与您所在线段的端点之间的距离并继续该过程。

伪代码:

之前定义

struct LineSegment
{
  Point start,end;
  int ID;
  double len; // len = EuclideanDistance(start,end);
  LineSegment *next_segment;
  double theta; // theta = atan2(slope_of_line_segment);
}

Function [LineSegment nextseg] = FindNextLineSegment(LineSegment lineseg)
Input: LineSegment object of the current line segment
Output: LineSegment object of the adjacent line segment in your ordering. 
nextseg.ID = -1 if there are no more segments

功能:找到路径中的下一个点

Function [Point Q, LineSegment Z] = FindNextPt(Point P, LineSegment lineseg, int dist): 
Input: The current point P, the distance between this point and the next, and the LineSegment of the line segment which contains P.
Output: The next point Q, and the line segment it is on

Procedure:
distToEndpt = EuclideanDistance(P,lineseg->end);
if( distToEndpt >= d )
{
 Point Q(lineseg->start.x + dist*cos(lineseg.theta), lineseg->start.y + dist*sin(lineseg.theta));
 Z = lineseg;
}
else
{
 nextseg = lineseg->next_segment;
    if( nextseg.ID !=-1 )
    {
  [Q, Z] = FindNextPt(nextseg->start,nextseg->ID,dist-distToEndpt);
 }
    else
    {
  return [P,lineseg];
 }
}
 return [Q,Z]

入口点

Function main()
Output: vector of points
Procedure:

vector<LineSegment> line_segments;
// Define it somehow giving it all the properties
// ....

vector<Point> equidistant_points;
const int d = DIST;

[Q Z] = FindNextPoint(line_segments[0].start,line_segments[0],DIST);
while( Z.ID != -1 )
{
 equidistant_points.push_back(Q);
 [Q Z] = FindNextPt(Q,Z,d);
}

答案 2 :(得分:1)

我的感觉是这是一个非常难的问题。

它基本上等于约束优化问题。目标函数测量新线与旧线的接近程度。约束强制新点的距离相同。

找到一个好的目标函数是一个棘手的问题,因为它必须是可微分的,并且我们不会提前知道每个新点将位于哪个段上:例如,有两个新点可能位于特长的老段,并且在一些超短的旧段上没有新的点。如果你以某种方式知道新点将在哪些段上的先验,你可以将点和它们的目标段之间的距离相加并将其用作你的目标函数(注意这个距离函数是非常重要的,因为这些段是有限的:它是由三个部分组成,其水平集是“药丸形状”。)

或者您可能忘记要求新点位于旧段上,只需寻找与旧段相近的新折线。例如,您可能会尝试在折线之间写下类似L2的度量标准,并将其用作目标函数。我不希望这个指标在记下或区分时是愉快的。

答案 3 :(得分:0)

这将使用相当多的矢量数学,但实际上非常简单。

首先,您需要找到路径的总距离。根据路径点的存储方式,您将如何进行操作。这是伪代码中二维路径的基本示例。

// This would generally be done with vectors, however I'm not sure
// if you would like to make your own class for them as I do so I will use arrays.

// The collection of points
int Points[4][2] = { {0,0}, {1,2}, {5,4}, {6,5} };
int Points2 = Points;

// goes to 3 because there are 4 points
for(int i=0; i<3; i++) {
     x = Points[i+1][0] - Points[i][0];
     y = Points[i+1][1] - Points[i][1];
     d += sqrt(( x * x ) + ( y * y ));
}

// divide distance by number of points to get uniform distance
dist = d/4;

// now that you have the new distance you must find the points
// on your path that are that far from your current point
// same deal here... goes to 3 because there are 4 points
for(int i=0; i<3; i++) {
     // slope
     m = ( Points[i+1][1] - Points[i][1] ) / ( Points[i+1][0] - Points[i][0] );
     // y intercept
     b = -(M * Points[i][0]) + Points[i][1];
     // processor heavy which makes this problem difficult
     // if some one knows a better way please say something
     // check every degree grabbing the points till one matches
     // if it doesn't then check next segment.
     for(float j=0; j<360; j += 0.1) {
          x = dist * sin(j);
          y = sqrt((dist * dist) - ( x * x ));
          if (y - (M * x + C)) {
               // then the point is on the line so set it
               Points2[i+1][0] = x;
               Points2[i+1][1] = y;
          }
     }
}

最后一步是什么使它不合理,但这应该适合你。 可能会有一个小的数学错误我在这里多次检查了几次,但可能有一些我错过了。因此,如果有人注意到某些事情,请通知我,我会编辑它。

希望这有帮助, 大风

答案 4 :(得分:0)

我认为一种微扰方法适用于此。

我假设:

  1. 我们知道如何在路径上滑动一个点并重新计算距离(非常简单),以及
  2. 端点必须保持固定(否则整个问题变得微不足道)。

迭代剩余的(n-2)个点:如果点k更接近点(k-1)而不是点(k + 1),则沿着路径向前移动一点。同样,如果它更靠近点(k + 1),沿着路径向后移动一点。

最好从大步长(速度)开始,然后缩小(精度)。即使这些点相互传递,我认为这种方法会将它们重新排序。