2012-01-28 80 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