Opensource gis development - part 2


Published on

Second part of the Course "Java Open Source GIS Development - From the building blocks to extending an existing GIS application." held at the University of Potsdam in August 2011

1 Like
  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Opensource gis development - part 2

  1. 1. Java Open Source GIS DevelopmentFrom the building blocks to extending an existing GIS application. Geoinformation Research Group, Department of Geography University of Potsdam August 2011Part 2: Introduction of the main Geo-Objects Tutor: Andrea Antonello ydroloGIS nvironmental ngineeringHydroloGIS S.r.l. - Via Siemens, 19 - 39100 Bolzano
  2. 2. A gentle introduction to the main geo ObjectsThis part aims to give the student, even if not a fully fledged developer, agood usage-knowledge about the main geo-objects, leaving aside all thearchitectural design and deep and dark computer science part. All in all theaim is to get people to develop small algorithms in order to be able to extendexisting GIS frameworks such as uDig.Some of the often used geo-objects that will be presented throughout thispart are:Coordinate, GeometryFactory, Point, LineString, Polygon, Geometry,CoordinateReferenceSystem, SimpleFeature, SimpleFeatureType, Simple-FeatureCollection, GridCoverage2D, Filter
  3. 3. Two eclipse shortcuts before we startBefore we start right away with coding our first geo-objects, a short noteabout shortcuts. Using shortcuts inside an IDE is extremely helpful. In eclipsetwo shortcuts can save tons of time: Ctrl^SPACEThis shortcut provides the context menu. Depending on the cursor position itcan for example complete variable or class names and supply a list ofpossible methods on the current object. Ctrl^1This shortcut provides a quickfix menu, different depending on cursorposition. It can be used to rename variables, extract variable names, splitdeclarations and much more. It can even help you out to solve syntax errors.
  4. 4. Geometry (JTS)The JTS library provides the following set of spatial data types: Point GeometryCollection MultiPoint LineString MultiLineString LinearRing Polygon MultiPolygon
  5. 5. CoordinateCoordinates are the building blocks of all spatial data types.A Coordinate is a class that stores coordinates on the 2-dimensionalCartesian plane. It has a simple constructor: Coordinate coordinate2d = new Coordinate(11.0, 46.0);It allows for a Z-coordinate, even if it is ignored for any operation: Coordinate coordinate3d = new Coordinate(11.5, 46.0, 1200.0);Which is why the only available operation on coordinates, the distancecalculation, returns 0.5 in the following case: double distance = coordinate2d.distance(coordinate3d);
  6. 6. GeometryFactoryThe GeometryFactory supplies a set of utility methods for buildingGeometry objects. The following examples use it to build the maingeometries based on the main geographic building block, the Coordinate. GeometryFactory factory = new GeometryFactory();Create a Point: Point point = factory.createPoint(coordinate1);Create a LineString: LineString line = factory.createLineString(new Coordinate[]{coordinate1, coordinate2});Create a Polygon: LinearRing ring = factory.createLinearRing(new Coordinate[]{coordinate1, coordinate2, coordinate3, coordinate1}); Polygon polygon = factory.createPolygon(ring, null);
  7. 7. Well Known Text (WKT)The Well Known Text (WKT) representation of a geometry can be quitehandy, especially when creating testcases. It can be printed out simply byinvoking the toString() method of any geometry. A few examples: • POINT (130 120) • LINESTRING (50 380, 90 210, 180 160, 240 40, 240 40) • POLYGON ((210 350, 230 310, 290 350, 290 350, 210 350))The inverse, i.e. generating a Geometry object from WKT can be donethrough the WKTReader: String wktLine = "LINESTRING (50 380, 90 210, 180 160, 240 40, 240 40)"; WKTReader reader = new WKTReader(); Geometry readLine =;This representation of the geometries will help us to gain betterunderstanding of the different geometry types and operations.
  8. 8. (Multi)PointA Point models a single Coordinate, a MultiPoint models a collection ofpoints.A MultiPoint can be built through the factory: MultiPoint multiPoint = factory.createMultiPoint(new Point[]{point1, point2, point3});While the envelope of a point is the point itself, the envelope of a MultiPointgeometry is the smalles envelop that contains all the points in the collection. Geometry pointEnvelope = point1.getEnvelope(); Geometry multiPointEnvelope = multiPoint.getEnvelope();
  9. 9. (Multi)LineStringThe line has a couple more properties than a point: Geometry envelope = line.getEnvelope(); double length = line.getLength(); Point startPoint = line.getStartPoint(); Point endPoint = line.getEndPoint();You can bundle lines in a collection: MultiLineString multiLineString = factory.createMultiLineString(new LineString[]{line, line2});Riddle: what is the area of a line? double area = line.getArea();And of a multiline? double marea = multiLineString.getArea();
  10. 10. (Multi)PolygonPolygons can also have holes, that are passed as second argument: Polygon polygonWithHole = factory.createPolygon(linearRing, new LinearRing[]{hole});The polygon has a couple more properties than a line: Geometry envelope = polygon.getEnvelope(); double perimeter = polygon.getLength(); double area = polygon.getArea(); double areaWithHole = polygonWithHole.getArea(); Point centroid = polygon.getCentroid(); GeometryThe abstract class Geometry is the mother of all geometry classes.The abstraction can be used for all geometric operations (for exampleintersection and union).
  11. 11. Prj (GeoTools) CoordinateReferenceSystemWIKIPEDIA: "A spatial reference system (SRS) or coordinate referencesystem (CRS) is a coordinate-based local, regional or global system usedto locate geographical entities. A spatial reference system defines aspecific map projection, as well as transformations between differentspatial reference systems. Spatial reference systems are defined by theOGCs Simple feature access using well-known text, and support has beenimplemented by several standards-based geographic information systems.Spatial reference systems can be referred to using a SRID integer, includingEPSG codes defined by the International Association of Oil and GasProducers."
  12. 12. The DatumThe datum is a reference surface from which measurements are made(Wikipedia).Datums can be local, which are locally orientated ellissoid (no deviation onthe vertical, locally tangent), or global, which are used to cover the wholeglobe and designed to support satellitar measurements. global ellipsoid local ellipsoid geoid
  13. 13. Example DatumsRoma 40 local datum based on Hayford ellipsoid, with prime meridian on Monte MarioEuropean Datum 50 local datum based on Hayford ellipsoid, tangent in Potsdam area, with prime meridian in Greenwich. Used for UTM-ED50 CRS.World Geodetic System WGS84 global datum with origin on the earths mass center. Used for example in the classic GPS CRS (EPSG:4326)
  14. 14. The Universal Transverse Mercator (UTM)UTM maps the Earth with a transverse cylinder projection using 60 differentmeridians, each of which is a standard "UTM Zone". By rotating the cylinderin 60 steps (six degrees per step, about 800Km) UTM assures that all spotson the globe will be within 3 degrees from the center of one of the 60cylindrical projections.
  15. 15. Coordinate reprojection and transform, the (not so small) differenceOften reproject and transform are used the same way without much care.There is a big difference though.reproject This is what we would call coordinate transform (CT). A CT can be resolved in a well defined mathematical manner that doesnt lead to precision loss (even if usually there is some minor due to data precision and roundings).transform This is what we could call datum transform. Since datums are local approximations of the geoid, transformations between datums are based on statistical methods and lead most of the times to precision loss.
  16. 16. GeoTools javadoc• usually defined by a coordinate system (CS) and a datum• captures the choice of values for the parameters that constitute the degrees of freedom of the coordinate space• since the choice is made either arbitrarily or by adopting values from survey measurements, it leads to the large number of CRS in use around the world• is also the cause of the little understood fact that the latitude and longitude of a point are not unique• without the full specification of the CRS, coordinates are ambiguous at best and meaningless at worst
  17. 17. CoordinateReferenceSystem (this time for real)We now have the necessary (minimum) information to make use of CRSinside our code and do some reprojecting. First lets create two CRS to workwith, one based on the Lat/long WGS84: CoordinateReferenceSystem epsg4326Crs = CRS.decode("EPSG:4326");and one based on WGS 84 / UTM zone 32N: CoordinateReferenceSystem epsg32632Crs = CRS.decode("EPSG:32632");To reproject coordinates first a math transform has to be created: MathTransform transform = CRS.findMathTransform(epsg4326Crs, epsg32632Crs, lenient);To actually reproject the JTS class supplies the method: Coordinate newCoordinate = JTS.transform(coordinate, null, transform);
  18. 18. Vector (GeoTools) SimpleFeature and SimpleFeatureTypeIn the course SimpleFeature will be used for Vector Data and representsprobably the most central object for GIS applications. TheSimpleFeatureType can be seen as the blueprint of the data. Vector dataare composed of a geometry part and an attribute table. SimpleFeatureType: the_geom: LineString id: Integer road1 name: String length: Double id name length 1 road1 56.4 road2 2 road2 120.0 geometry attributes
  19. 19. To create a feature, first the blueprint has to be created (feature type): SimpleFeatureTypeBuilder featureTypeBuilder = new SimpleFeatureTypeBuilder(); featureTypeBuilder.setName("road"); featureTypeBuilder.setCRS(crs); featureTypeBuilder.add("the_geom", LineString.class); featureTypeBuilder.add("id", Integer.class); featureTypeBuilder.add("name", String.class); featureTypeBuilder.add("length", Double.class); SimpleFeatureType featureType = featureTypeBuilder.buildFeatureType();Using the blueprint, any feature can be created by defining its contents: // feature 1 SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); int id = 1; String name = "road1"; double length = line1.getLength(); Object[] values = new Object[]{line1, id, name, length}; featureBuilder.addAll(values); SimpleFeature feature1 = featureBuilder.buildFeature(null); // feature 2 id = 2; name = "road2"; length = line2.getLength(); values = new Object[]{line2, id, name, length}; featureBuilder.addAll(values); SimpleFeature feature2 = featureBuilder.buildFeature(null);
  20. 20. How to extract the information once the features are packaged? List<AttributeDescriptor> attributeDescriptors = featureType.getAttributeDescriptors(); for( AttributeDescriptor attributeDescriptor : attributeDescriptors ) { // get the name of the attribute from the descriptor String attributeName = attributeDescriptor.getLocalName(); // get the attribute value Object attribute = feature1.getAttribute(attributeName); // get the type of the attribute AttributeType attributeType = attributeDescriptor.getType(); Class< ? > binding = attributeType.getBinding(); // print a summary System.out.println(attributeName + " (type = " + binding.getSimpleName() + "): " + attribute); }Being the geometric part really important, for the default geometry we have adirect access: Geometry geometry = (Geometry) feature1.getDefaultGeometry();
  21. 21. SimpleFeatureCollectionFeatures can be bundled into collections (which is how they are usuallyserved by readers and fed into writers): SimpleFeatureCollection newCollection = FeatureCollections.newCollection(); newCollection.add(feature1); newCollection.add(feature2);FeatureCollections are best accessed through an iterator, in order to assurethat they are not all read into memory: SimpleFeatureIterator featureIterator = newCollection.features(); while( featureIterator.hasNext() ) { SimpleFeature feature =; // do something with it } // remember to close the handle! featureIterator.close();
  22. 22. Raster (GeoTools) GridCoverage2DA GridCoverage2D is what in the real world we usually call Raster or Grid,i.e. a rectangular regular grid of pixels, each containing a value. Thefollowing schema contains the main definitions we will use: cols grid space raster values north rows 0,0 1200 1800 1800 1800 1200 1170 1130 1130 y (northing) 2,1 1200 1170 1130 1100 west east x res y res equator x (easting) south world space
  23. 23. Raster maps are not all that famous in GeoTools. People usually need themto show nice ortophoto or similar imagery. This is probably the reason whythey have a quite tricky API. Building a GridCoverage2D object is quite apain.In this course we will need to read and create raster data as for exampleDTMs. To do so the JGrasstools API will be of help.Lets start by defining some elevation data in a matrix: double[][] elevationData = new double[][]{// {800, 900, 1000, 1000, 1200, 1250, 1300, 1350, 1450, 1500}, // {600, NaN, 750, 850, 860, 900, 1000, 1200, 1250, 1500}, // {500, 550, 700, 750, 800, 850, 900, 1000, 1100, 1500}, // {400, 410, 650, 700, 750, 800, 850, 490, 450, 1500}, // {450, 550, 430, 500, 600, 700, 800, 500, 450, 1500}, // {500, 600, 700, 750, 760, 770, 850, 1000, 1150, 1500}, // {600, 700, 750, 800, 780, 790, 1000, 1100, 1250, 1500}, // {800, 910, 980, 1001, 1150, 1200, 1250, 1300, 1450, 1500}// };
  24. 24. We now need to place them somewhere in the world, which means definingboundaries and reference system: double n = 5140020.0; double s = 5139780.0; double w = 1640650.0; double e = 1640950.0; double xRes = 30.0; double yRes = 30.0; CoordinateReferenceSystem crs = CRS.decode("EPSG:32632");The JGrasstools API supplies a method to create a GridCoverage from thedata defined before: RegionMap envelopeParams = new RegionMap(); envelopeParams.put(CoverageUtilities.NORTH, n); envelopeParams.put(CoverageUtilities.SOUTH, s); envelopeParams.put(CoverageUtilities.WEST, w); envelopeParams.put(CoverageUtilities.EAST, e); envelopeParams.put(CoverageUtilities.XRES, xRes); envelopeParams.put(CoverageUtilities.YRES, yRes); // build the coverage GridCoverage2D elevationRaster = CoverageUtilities.buildCoverage( // "elevation", elevationData, envelopeParams, crs, true);
  25. 25. To access data in a raster, we can either work in the world space (easting,northing): double[] value = elevationRaster.evaluate(new Point2D.Double(1640680, 5139820), (double[]) null);or in the grid space (col, row): value = elevationRaster.evaluate(new GridCoordinates2D(1, 6), (double[]) null);It is possible to access the underlying image to iterate over it: RenderedImage elevationRI = elevationRaster.getRenderedImage(); RandomIter iter = RandomIterFactory.create(elevationRI, null); for( int col = 0; col < elevationRI.getWidth(); col++ ) { for( int row = 0; row < elevationRI.getHeight(); row++ ) { double elev = iter.getSampleDouble(col, row, 0); System.out.print(elev + " "); } System.out.println(); }
  26. 26. FiltersA Filter defines a constraint that can be checked against an instance of anobject.We will handle filters only with regard to vector data.A filter can be seen as the WHERE clause of an SQL statement. It can applyboth to the alphanumeric values of an attribute table as well as to thegeometry.One example could be: give me all the cities of Canada that count more than10000 inhabitants.
  27. 27. CQL and ECQLTo help people in the construction of filters GeoTools supplies the classECQL.Creating a filter that compares the string inside a field is therefore simple: // name comparison filter Filter filter = ECQL.toFilter("name = road1");as is the comparison of numeric values: // numeric comparison filter filter = ECQL.toFilter("length < 1.0");one could also check the real length of a geometry, instead of the value in afield: // geometric filter filter = ECQL.toFilter("geomLength(the_geom) < 1.0");
  28. 28. it is possible to check if a field exists: // field existence filter = ECQL.toFilter("name EXISTS");regular expressions can be used to compare strings: // like comparison filter = ECQL.toFilter("name LIKE roa% AND length > 1.0");and maybe the most used check, the bounding box: // bounding box double w = 10.5; double e = 11.6; double s = 46.0; double n = 47.0; String filterString = "BBOX(the_geom, " + w + "," + s + "," + e + "," + n + ")"; filter = ECQL.toFilter(filterString);
  29. 29. The created filter can then for example be applied to a collection to extract asubcollection based on the filter constraint: SimpleFeatureCollection subCollection = collection.subCollection(filter);
  30. 30. StyleStyle is that part that allows us to make maps look pretty and get the neededsymbolization and coloring of the contained data.The OGC defines the Styled Layer Descriptor (SLD) as the standard tostyle maps. GeoTools supplies an API to generate styles.The programmatic approach to Style wont be handled in this course. Tocreate SLD styles, the style editor of uDig can be used.
  31. 31. ConclusionsIn part 2 we played with the main objects used when doing GIS development.We learned about the atomic entity, the Coordinate, how to build variousgeometries through the GeometryFactory. We built Point, LineString andPolygon geometries and now know that all their common behaviour can beaccessed through the Geometry class.We then added the spatial context to the geometries by approaching theCoordinateReferenceSystem. In the case of vectors, we created a blueprintof the vector data as a SimpleFeatureType, we "populated" it creating theactual SimpleFeature and bundled it to a SimpleFeatureCollection. We alsolearned how to extract data from collections based on a Filter.In the case of rasters we learned how to create a GridCoverage2D.
  32. 32. This work is released under Creative Commons Attribution ShareAlike (CC-BY-SA)Much of the knowledge needed to create this training material hasbeen produced by the sparkling knights of the GeoTools, JTS anduDig community. Another essential source has been the Wikipediacommunity effort.Particular thanks go to those friends that directly or indirectly helpedout in the creation and review of this developers handbook: JodyGarnett from the uDig/GeoTools community and the TANTO team.This tutorial was written with the support of the GeoinformationResearch Group of the University of Potsdam and HydroloGIS.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.