您的位置:首页 > 编程语言 > C#

关于道格拉斯算法的一些思考

2015-12-29 23:32 671 查看
第一种算法的代码下载

第三种算法的代码下载

道格拉斯-普克压缩算法不多说了,我认为问题的难点在于如何将筛选出来的点按照顺序添加入新的集合中,这也是下面我将要介绍的,我关于这的一点思考。

算法简介:

道格拉斯-普克压缩算法维基百科介绍

可以通过下面的动图来理解(来自维基百科介绍页面):



1,比较原始的方法:

我需要新建一个这样的类,来保存点的位置信息以及点在所属线段中的索引值。

class GeoPoint
{
public PointF Point { get; private set; }
public int Index { get; private set; }

public GeoPoint(PointF point, int index)
{
this.Point = point;
this.Index = index;
}
}


继而,每当我通过计算出得到一个满足条件的点时,我需要将它添加到一个List中,最终再根据List中所有的点的在原线段中的索引值排序。

下面是道格拉斯算法的关键方法:

private void DouglasPeucker(int startIndex,int endIndex)
{
if (endIndex - startIndex <= 1) return;

int middleIndex = startIndex + 1;
float maxDistance = 0;
GeoPoint lineStartPoint = searchLine.Points[startIndex];
GeoPoint lineEndPoint = searchLine.Points[endIndex];

for (int n = startIndex + 1; n < endIndex; n++)
{
float distance = DistanceFromPointToLine(
searchLine.Points
, lineStartPoint, lineEndPoint);
if (distance > maxDistance)
{
middleIndex = n;
maxDistance = distance;
}
}

if(maxDistance>this.criticalValue)
this.points.Add(searchLine.Points[middleIndex]);

DouglasPeucker(startIndex, middleIndex);
DouglasPeucker(middleIndex,endIndex);
}


通过不断的迭代来完成算法的实现。

对一条直线处理完之后,对List中的点按照原索引值排序,这里用了委托方法,下面还有Lambda的例子:

points.Sort(delegate (GeoPoint p1, GeoPoint p2)
{ return p1.index.CompareTo(p2.index); });


至此,算法就基本完成了。

2,不新建类如何实现:

在向List中添加点时,需要计算插入点的位置,过于复杂,我未能实现。

3,不新建类且不用计算插入点位置

这个方法与刚刚上面的类似,区别在于没有使用带有索引值信息的点类。

private void DouglasPeucker(PointF leftPoint, PointF rightPoint)
{
int leftIndex = tempLine.IndexOf(leftPoint);
int rightIndex = tempLine.IndexOf(rightPoint);

if ((rightIndex - leftIndex) <= 2) return;
int middleIndex = leftIndex + 1;

float maxDistance = 0;
for (int n = leftIndex + 1; n < rightIndex; n++)
{
float distance =
DistanceFromPointToLine(tempLine
, leftPoint, rightPoint);
if (distance > maxDistance)
{
middleIndex = n;
maxDistance = distance;
}
}

if (maxDistance > criticalValue)
tempPointList.Add(tempLine[middleIndex]);

DouglasPeucker(leftPoint, tempLine[middleIndex]);
DouglasPeucker(tempLine[middleIndex], rightPoint);
}


在处理完一条直线后,存在List中的点依旧是乱的,此时需要对其中的点排序,但是这些点没有了原先的索引值信息,为此,想出的排序方法是:

tempPointList.Sort(
(p1, p2) => {
return tempLine.IndexOf(p1).CompareTo(tempLine.IndexOf(p2)); });


这样,就能实现排序了。

附:道格拉斯压缩算法的压缩结果







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 C# GIS