2

I am using NetTopologySuite for some simplificaiton of lines.

The issue I am facing is I have my own class that store list of Point3D (System.Windows.Media) and NetTopology has its own Coordinate class with almost the same properties and functions.

To convert the point3D list to coorinate array I am using this function:

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;
}

Everything works fine, but when I profiled my code almost 95% time is taken by this function. I am wondering, are there any other ways to convert the list of System.Windows.Media.Point3D to Coordinate[].

Same will be true from one class to another conversion.

5
  • Where in this function is most of the time spent? Creation of the Coordinate objects? Something else? Commented Jan 28, 2012 at 11:45
  • I am assuming you are asking for a more performant option? Commented Jan 28, 2012 at 11:45
  • @Oded yes i am looking for better performance Commented Jan 28, 2012 at 11:52
  • What about the breakdown of what in this function is taking the most time? The implementation looks pretty good (and any other option, like using LINQ would be similar in performance). Commented Jan 28, 2012 at 11:54
  • Looks actually fine to me. As there isn't any "direct mapping" between both type, you're kinda obliged to loop through Point3D lists and instantiate Coordinates one by one. Commented Jan 28, 2012 at 12:01

3 Answers 3

1

Update If the collection is a List<> then we can do a one time reflection to the underlying array like this

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);

and then use it code each time we want to convert as List<Point3D> into Point3D like this

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

Then you can proceed with the code below. If the IEnumerable<> collections is something different then you need to find how the elements are stored internally first.

Original

I think if you can limit yourself to arrays instead of IEnumerable<> then you can achieve faster speeds.

Here an example code that is compact and shall work as fast as possible.

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();
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

This answer is entirely wrong. The "unchecked" keyword suppresses arithmetic overflow checking, which does not apply here, not array bounds checking. The JIT optimizer automatically minimizes bounds checks on for/foreach loops over arrays. But this assumes that you have an input array, and using ToArray to generate such an array is definitely going to be slower than the original code.
@ChrisNahr - Entirely Wrong? You are correct about the uncheked keyword (I checked it) but maybe the correct way to approach this is to find the underlying collection type behind 'IEnumerable<>` and access its elements directly.
0

There's no way to make this method faster. You could buffer listToClone.ElementAt(0) in the last block, but that's hardly relevant to overall performance with long lists.

If the source & target coordinates were equivalent value types you could try tricks with pointers to copy their data directly. But sadly GeoApiGeometries.Coordinate is a reference type, presumably because the library was ported from Java, so you definitely must allocate each new element manually, just as you do now.

Comments

0

I was calling this function in foreach it replace that foreach to for and it improved the performance. I should have posted the whole code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.