NTS and Proj.NET; linear units

Topics: General Topics
Mar 2, 2009 at 9:34 AM
Hi all,

I'm having a unit problem with NTS. I'm trying to calculate a new point coordinate along a LengthIndexedLine by giving a length to traverse along the line in meters.

I'm using a shape dataset that uses the following GCS WKT:
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]

The index number that I have to pass to the ExtractPoint function is currently a number in degrees(?). But i only know the number of meters i have to traverse along the line.

Do i need to use Proj.NET to project the line in order to be able to give the index in meters?
Mar 2, 2009 at 10:40 AM
hi...boxed,
Um new to NTS, just trying to get to know how to use it!! i want to create a new point shapefile of a specific lat long values on my map....i got to know that it is possible through NetTopologySuite...i made a gud search on internet but yet not got to know how would it work in my desktop application (um working with C#) i mean the code to create a new shapefile and saving it in a desktop application using C#...
help will be greatly appreciated!! 
Mar 2, 2009 at 10:58 AM
Hi Kiran,

That's not very related to my projection problem, but i can answer that one easily.
In the NTS example there is a file 'ShapeFileWriteTest.cs', I think that does exactl what you're looking for

Cheer, Richard
Coordinator
Mar 2, 2009 at 11:12 AM
Hi Richard, I am not sure about this, but perhaps you could convert the metre distance into degrees (http://en.wikipedia.org/wiki/Great-circle_distance may be helpful) and then use this in your calculation.. hth jd
Mar 2, 2009 at 11:21 AM
Hi John,

Thanks for your quick answer. The problem in my case is that I don't have 2 points to calculate the distance between.
Instead I just have a distance in meters which would probably be different everywhere across the globe. So that's why I thought that i have to change the projection of my data so I can use meters as an index.

Cheers, Richard
Coordinator
Mar 2, 2009 at 11:27 AM
I am sure projecting it in projnet will give a result but there may be distortions due to the projection itself which may or may not matter depending on your application..
Mar 2, 2009 at 11:46 AM
As long as the distortions are not too severe i could live with that.
Do you happen to know an example or have information on how to project a data set? In the SRSConversionTest.cs example of the NTS library
a bunch of projection parameters are used and I don't have the knowledge of how to fill them.
Coordinator
Mar 2, 2009 at 12:03 PM
Genarally you would use a CoordinateTransformation object which you build from two CoordinateSystems.
Use a CoordinateSystemFactory  to create the CoordinateSystems from their well known text (one for wgs84 and one for the projected cs you choose) then use  CoordinateTransformationFactory.CreateFromCoordinateSystems you can then use the IMathTransform property of the transfrom to do your conversion hth jd
Mar 3, 2009 at 8:01 AM
Okay, I've got it worked out.
The Proj.NET examples supply a .csv file containing a large number of GCS WKT strings. Also the SRIDReader.cs
supplies a function GetCSbyID (gold!).

In words what I do is:
- Construct source CS
- Construct wanted CS
- make transformation object
- transform Geometry object
- extract new coordinate point using meters as index
- transform the point back to the source CS.

Thanks for the help you all!

in code (This might not work by itself, I pasted the main functionality here):
using System;
using GeoAPI.Geometries;
using GeoAPI.CoordinateSystems;
using GeoAPI.CoordinateSystems.Transformations;
using GisSharpBlog.NetTopologySuite.CoordinateSystems.Transformations;
using GisSharpBlog.NetTopologySuite.LinearReferencing;
using GisSharpBlog.NetTopologySuite.Geometries;
using SharpMap.CoordinateSystems;
using SharpMap.CoordinateSystems.Transformations;

namespace TransformTest
{
    public class Testing
    {
        #region Private members

        private ICoordinateSystem m_datasetCS;
        private ICoordinateSystem m_WGS84UTM56S;

        #endregion

        /// <summary>
        /// Constructor
        /// </summary>
        public Testing()
        {
            Initialize();
        }

        private void Initialize()
        {
            // Set the used coordinate systems
            CoordinateSystemFactory cFact = new CoordinateSystemFactory();
            
            // EPSG:4326; For reference: http://sde.hobu.biz/ref/epsg/4326/
            m_datasetCS = SRIDReader.GetCSbyID(4326);
            // EPSG:32756; For reference: http://sde.hobu.biz/ref/epsg/32756/
            m_WGS84UTM56S = SRIDReader.GetCSbyID(32756);
            
            // Define a line to test with in WGS84 (EPSG:4326)
            GeometryFactory fact = new GeometryFactory();
            WKTReader wktRdr = new WKTReader(fact);
            IGeometry testLine = wktRdr.Read("LINESTRING(151.543710 -33.012934, 151.539649 -33.012883)");

            // Create a LengthIndexedLine with a unit in meters
            LengthIndexedLine lengthLine = new LengthIndexedLine(GeoInDegToGeoInMeters(testLine));

            // Extract a point 10m from the beginning of the line
            ICoordinate testCoord = lengthLine.ExtractPoint(10.0);
            IGeometry resultPoint = fact.CreatePoint(testCoord);

            // Display the result
            Console.WriteLine(GeoInMetersToGeoInDeg(resultPoint).ToString());
        }

        #region Testing Members

        /// <summary>
        /// Transform a Geometry object that has a coordinate system in degrees to one
        /// that has a coordinate system in meters
        /// </summary>
        /// <param name="g">The geometry to transform</param>
        /// <returns>Transformed geometry</returns>
        public IGeometry GeoInDegToGeoInMeters(IGeometry g)
        {
            //Set up coordinate transformations
            CoordinateTransformationFactory ctFac = new CoordinateTransformationFactory();
            ICoordinateTransformation transDeg2M = ctFac.CreateFromCoordinateSystems(m_datasetCS, m_WGS84UTM56S);  //Geocentric->Geographic (WGS84)
            return GeometryTransform.TransformGeometry(g, transDeg2M.MathTransform);
        }

        /// <summary>
        /// Transform a Geometry object that has a coordinate system in meters to one
        /// that has a coordinate system in degrees
        /// </summary>
        /// <param name="g">The geometry to transform</param>
        /// <returns>Transformed geometry</returns>
        IGeometry GeoInMetersToGeoInDeg(IGeometry g)
        {
            //Set up coordinate transformations
            CoordinateTransformationFactory ctFac = new CoordinateTransformationFactory();
            ICoordinateTransformation transDeg2M = ctFac.CreateFromCoordinateSystems(m_WGS84UTM56S, m_datasetCS);  //Geocentric->Geographic (WGS84)
            return GeometryTransform.TransformGeometry(g, transDeg2M.MathTransform);
        }
        #endregion
    }
}