2012-01-28 140 views
2

我正在使用NetTopologySuite进行一些简化行。将Point3D列表转换为坐标数组

我面临的问题是我有我自己的类,Point3D(System.Windows.Media) 的商店列表和NetTopology有它自己的坐标类,几乎具有相同的属性和功能。

要转换的三维点列表coorinate阵列我使用这个功能:

public static GeoApiInterfaces.ICoordinate[] ToCoordinateArray(this IEnumerable<Point3D> listToClone, 
              bool isClosed = false) 
{ 
    // if geometry is to be closed the size of array will be one more than the 
    // current point count 
    var coordinateList = new GeoApiInterfaces.ICoordinate[isClosed ? 
                 listToClone.Count() + 1 
                 : listToClone.Count()]; 

    // loop through all the point in the list to create the array 
    int elementIndex = 0; 
    foreach (var point in listToClone) 
    { 
    var coordinate = new GeoApiGeometries.Coordinate(point.X, 
                point.Y, 
                point.Z); 

    coordinateList[elementIndex] = coordinate; 
    elementIndex++; 
    } // foreach 

    // if geometry is closed the add the first point to the last 
    if (isClosed) 
    { 
    var coordinate = new GeoApiGeometries.Coordinate(listToClone.ElementAt(0).X, 
                listToClone.ElementAt(0).Y, 
                listToClone.ElementAt(0).Z); 

    coordinateList[elementIndex] = coordinate; 
    } // if isClosed 

    return coordinateList; 
} 

一切工作正常,但是当我异形我的代码几乎95%的时间采取的是此功能。我想知道,有没有其他方法将System.Windows.Media.Point3D的列表转换为坐标[]。

从一个类到另一个类的转换同样如此。

+0

在这个函数中大部分时间花在哪里?创建“坐标”对象?还有别的吗? – Oded 2012-01-28 11:45:23

+0

我假设您要求更高性能的选项? – Oded 2012-01-28 11:45:55

+0

@Oded是的,我正在寻找更好的性能 – Mohit 2012-01-28 11:52:03

回答

0

我在foreach中调用这个函数,它将foreach替换为for,它提高了性能。我应该发布整个代码。

0

无法使此方法更快。您可以在最后一个块中缓冲listToClone.ElementAt(0),但这与长列表的整体性能几乎没有关系。

如果源目标坐标是等价值类型,您可以尝试使用指针直接复制其数据的技巧。但令人遗憾的是,GeoApiGeometries.Coordinate是一个引用类型,可能是因为该库是从Java移植过来的,所以您必须手动分配每个新元素,就像现在一样。

1

更新 如果集合是List<>那么我们可以做一次反思为基础数组这样

static FieldInfo f_items = typeof(List<Point3D>).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance); 
static FieldInfo f_size = typeof(List<Point3D>).GetField("_size", BindingFlags.NonPublic | BindingFlags.Instance); 

,然后用它,我们要为List<Point3D>转换成Point3D每个时间码像这样

Point3D[] array = f_items.GetValue(list) as Point3D[]; 
int size= (int)f_size.GetValue(list); 

然后你可以继续下面的代码。如果IEnumerable<>集合是不同的,那么你需要先找到元素是如何在内部存储的。

原始

我认为,如果能限制自己的数组,而不是IEnumerable<>那么你可以达到更快的速度。

这里是一个简洁的示例代码,应尽可能快地工作。

public struct Point3D 
{ 
    public double x, y, z;   
} 

public static class Extensions 
{ 
    public static ICoordinate[] ToCoord(this Point3D[] points, int size) 
    { 
     size = Math.Min(points.Length,size); //make sure there are enough points 
     ICoordinate[] res = new ICoordinate[size]; 
     for (int i = 0; i < size; i++) 
     { 
      res[i] = new Coordinate(points[i].x, points[i].y, points[i].z); 
     } 
     return res; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Point3D[] array1 = new Point3D[N]; 
     // Fill the array .. 
     ICoordinate[] array2 = array1.ToCoord(); 
    } 
} 
+0

这个答案是完全错误的。“unchecked”关键字抑制了算术溢出检查,这在这里不适用,不是数组边界检查。 JIT优化器自动最小化对数组上的/ foreach循环的边界检查。但是,这假设你有一个输入数组,并且使用ToArray生成这样的数组肯定会比原始代码慢。 – 2012-01-29 09:36:00

+1

@ChrisNahr - 完全错误?你对'uncheked'关键字是否正确(我检查了它),但也许正确的方法是找到'IEnumerable <>'后面的底层集合类型并直接访问它的元素。 – ja72 2012-01-29 22:32:59