Main menu:

 

PALMA IT

Locations of visitors to this page

Site search

  • Categories

  • Archive

    March 2007
    M T W T F S S
    « Feb   Apr »
     1234
    567891011
    12131415161718
    19202122232425
    262728293031  

    Entering the world of GIS

    At my current project we store information about buildings in a database. A part of that information is geographic information about the location of the building. This information is sent in a SOAP message and the geographic part is formatted according to the GML standard. This information (both geographic and ‘normal’ data) is persisted in the database (PostgreSQL with PostGIS) by using Hibernate.

    Until now we didn’t have to validate this geographic data so we just stored it in the database by using a custom FieldType in Hibernate (just the most important parts are shown here):

    1. import org.hibernate.HibernateException;
    2. import org.hibernate.usertype.EnhancedUserType;
    3. import org.postgis.PGgeometry;
    4.  
    5. /**
    6. * This class is the Hibernate UserType class,
    7. * for more information see the hibernate docs at
    8. * http://www.hibernate.org
    9. *
    10. * @author Rob Augustinus, OpenSolutions
    11. */
    12. public class GeometryType implements EnhancedUserType {
    13.  
    14.  
    15.    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
    16.       return (PGgeometry) rs.getObject(names[0]);
    17.    }
    18.  
    19.    public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException,
    20.             SQLException {
    21.       if (value == null) {
    22.          statement.setNull(index, Types.OTHER);
    23.       } else {
    24.          statement.setObject(index, value);
    25.       }
    26.    }
    27.  
    28.    public Class returnedClass() {
    29.       return PGgeometry.class;
    30.    }
    31.  
    32.    public int[] sqlTypes() {
    33.       return new int[] { Types.OTHER };
    34.    }
    35. }

    So to persist the data of a building we create a Model object ‘Building’ which has one field ‘Geometry’ that is of the type ‘GeometryType’.

    But, as usual, the demands of the application change and it now looks like we will have to perform some validations on the geographic data, prefferable before we store it in the database. So I was asked if this was possible and how it should be done.
    The standard for this kind of geometric validations is JTS (JTS Topology Suite) API. After downloading an implementation I got to the next problem. The XML message we receive is translated to our Hibernate model object which is using the type open.gis.PGgeometry as a wrapper around the org.opengis.Geometry class. Now in the new situation I have to translate the openGIS Geometry type to the JTS implementation to be able to perform the necessary validations. I started to write some code myself, because I couldn’t find a clear answer for this on the internet. I used the WKT (Well Known Text) option of both types. You will get something like this:

    1. org.postgis.Geometry postGisGeometry1 = org.postgis.PGgeometry.geomFromString(“LINESTRING (0 0, 30 30)”);
    2. org.postgis.Geometry postGisGeometry2 = org.postgis.PGgeometry.geomFromString(“LINESTRING (30 0, 0 30)”);
    3.       
    4. com.vividsolutions.jts.geom.Geometry jtsGeometry1 = new WKTReader().read( postGisGeometry1.toString());
    5. com.vividsolutions.jts.geom.Geometry jtsGeometry2 = new WKTReader().read( postGisGeometry2.toString());
    6.       
    7. System.out.println(“Lines do cross?: “+ jtsGeometry1.crosses(jtsGeometry2));

    But writing every coordinate to a String and read that back into another object isn’t an acceptable solution. So I dug some more and ended up with the beta code of the OpenGIS JDBC driver. I compiled it, jarred it added it to my project. With this JDBC-extension the resultSet getObject() will not return an org.opengis.PGGeometry object but the JTS implementation, org.postgis.jts.JtsGeometry. If you then perform a getGeometry at this object you will get a JTS object. See this code:

    1. Statement st = conns[0].createStatement();
    2. ResultSet rs = st.executeQuery(“select geometry from building”);
    3.  
    4. while (rs.next()) {
    5.   Object obj = rs.getObject(1);
    6.   System.out.println(“Obj Class =  “ + obj.getClass().getName());
    7.  
    8.   Geometry geo = ((JtsGeometry)obj).getGeometry();
    9.   System.out.println(“Geo Class =  “ + geo.getClass().getName());
    10. }

    With this JDBC extension in place we can modify our custom-made GeometryType and work with JTS types directly. No more String conversions!
    To make this last example work you will need to add this
    JTS-jdbc.jar
    to your classpath and you will have to modify your database-url to ‘jdbc:postgres_jts:’ instead of ‘jdbc:postgresql’. The source code of this jar can be found here and is still in beta! So use it at your own risk :-)

    Comments

    Comment from mehran
    Time: 13 October 2008, 11:55 am

    hello..i m mehran from iran ..so impressed by your site…would you please introduce me the good site for open gis source - samples and training and also good source of gml - vrml eai - postgis