[GIS] Is it good practice to manage all JTS spatial objects as abstract Geometry instances

javajts-topology-suite

I'm new to all this GIS business, and am developing a Java web app using the JTS library. I'm trying to get my head around the JTS classes and how they're supposed to be used.

I have some existing code in which every spatial property is stored as a Geometry object, whether it's a Point or a Polygon. I understand that abstraction is generally nice, but if something is definitely a point (like Building.centerPoint), then surely it should be a Point type property? I'm further confused by the fact that the WKTReader returns a Geometry object no matter what type of WKT string you feed it (POINT or POLYGON), and that there does not appear to be any obvious way to convert such a Geometry object to a Point object without an ugly downcast or presumptive geomFactory.createPoint(geom.getCoordinate()), which is basically an implicit downcast anyway (it's probably not what you want if geom is a Polygon).

So my question is: is it good practice to manage all spatial objects as abstract Geometry instances? As motivational corollaries:

  • If not, what is the canonical way to convert a String to a Point?
  • If so, how should one determine the specific type of Geometry? For instance, if I want to validate that the user provided a Point rather than a Polygon?

I realise that functionally the distinction may not be of great importance; a Point may just have an area of zero, for instance, or perhaps a Polygon with a single coordinate should just be treated the same as a Point. However I'm primarily concerned with data storage and conversion, since I'm working with Spring Roo and I don't want any information getting lost or confused along the way.

Best Answer

I have been using NetTopologySuite(a C# port of JTS) for a while. So I assume that most things stay the same as that of JTS. Hopefully Java code could be similar to the c# ones :)

My attempts answering some questions..

what is the canonical way to convert a String to a Point?

A direct casting from IGeometry to IPoint has worked as the below code worked in c#

static void Main(string[] args)
        {
            WKTReader wktReader = new WKTReader();
            IGeometry ptGeometry = wktReader.Read("POINT(0 0)");

            IPoint point = (IPoint)ptGeometry;
            //printing the coordinates X,Y
            Console.WriteLine(point.X.ToString() + "," + point.Y.ToString());

            IGeometry lineGeometry = wktReader.Read("LINESTRING (30 10, 10 30, 40 40)");
            ILineString lineString = (ILineString)lineGeometry;
            //Printing Start and End Points of LineString
            Console.WriteLine(lineString.StartPoint.ToString() + "," + lineString.EndPoint.ToString());

            IGeometry polygonGeometry = wktReader.Read("POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))");
            IPolygon polygon = (IPolygon)polygonGeometry;
            Console.WriteLine(polygon.Centroid.ToString());
            Console.ReadLine();

        }

If so, how should one determine the specific type of Geometry? For instance, if I want to validate that the user provided a Point rather than a Polygon?

You could do something like below.

   IGeometry ptGeometry = wktReader.Read("POINT(0 0)");
    if (ptGeometry is IPoint)
    {
        //its a point
    }

is it good practice to manage all spatial objects as abstract Geometry instances?

I am not sure whether it is a good practice. But this is the way that it has worked for me. For example, If we are doing any spatial operations like intersect/contain, the parameters and the output of such functions are always IGeometry. So it is a good reason to work with the abstract Geometries.

For Example, the method to get the intersection of two geometries(whether they are line,point or polygon) is as shown below.

IGeometry Intersection(IGeometry other);