我正在使用NetTopologySuite进行一些简化线路。
我面临的问题是我有自己的类存储Point3D列表(System.Windows.Media) 和NetTopology有自己的Coordinate类,具有几乎相同的属性和功能。
要将point3D列表转换为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列表转换为Coordinate []。
从一个类转换到另一个类也是如此。
答案 0 :(得分: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();
}
}
答案 1 :(得分:0)
没有办法让这种方法更快。您可以在最后一个块中缓冲listToClone.ElementAt(0),但这与长列表的整体性能几乎无关。
如果来源&amp;目标坐标是等价值类型,您可以尝试使用指针直接复制数据。但遗憾的是GeoApiGeometries.Coordinate是一个引用类型,可能是因为库是从Java移植的,所以你必须手动分配每个新元素,就像现在一样。
答案 2 :(得分:0)
我在foreach中调用了这个函数,它取代了foreach for for,它改善了性能。我应该发布整个代码。