The code always knows ... how to reproject
Posted by jive on February 22, 2007 at 8:37 PM EST
To Review
The GeoTools API has fallen into a trap where we promissed to reproject data when asked the correct Query. Problem is none of the implementations picked up on this change. Here is what we want to make possible.
CoordinateReferenceSystem world = CRS.decode("EPSG:4326"); // world lon/lat
|
Since this is needed functionality the developer community quickly hacked around the problem, leaving us with several working examples to grab the right answer from.
Here is the "fix" for reprojecting the data:
if (forcedCS != null)
|
The Review
In part one we applied the example that changed the FeatureType, now we need to look at reprojecting the data.In part two we got distracted by some inconsistent error handling ... and made a choice between fail siliently, fail with an exception and doing the right thing. In this case it was easy - the query is experssed using set theory and we made a nice empty set.
Returning to our origional problem we had test failure when checking to see that the FeatureType in fact changed - turns out I was testing the wrong thing:
- FeatureCollection.getFeatureType() - returns the type of a the collection. Surprisingly collections are features as well. Makes sense if you consider that a feature is something that can be drawn on a map.
- FeatureCollection.getSchema() - is the type of the contents of the collection
Looking at the Solution
The two utility classes employed by the "fix" are pretty straight forward:- ForceCoordinateSystemFeatureResults - this one just changes the FeatureType ... something we have already accomplished.
- ReprojectFeaureResults - takes an existing FeatureCollection and grinds through the data applying a MathTransform to each Geometry
Feature next = reader.next();
|
Well that is pretty clear; grab the next Feature suck the attributes out into an array. For each Geometry use a MathTransform to reproject. And then use the FeatureType to create a new Feature with the results.
The MathTransform is produced using a utility class:
this.transform = CRS.findMathTransform(originalCs,destinationCS, true);
|
It sure would be nice if implementors made an optimized version avaialble, I will do this for PropertyDataStore as the last step.
Applying the Solution .. to AbstractFeatureSource? No
So we *could* just apply the wrapping classes as is ...
public FeatureCollection getFeatures(Query query) throws IOException {
|
Since we changed the FeatureType of DefaultFeaureResults (to reflect what should be happening) the traditional wrapping approach would be broken. When the ReprojectFeatureResults wrapper goes to produce a math transform it will see the expected CRS already ... and do nothing!
Since DefaultQueryResults is accepting a query I would like to see it do the work, let's get started.
Applying the Solution to DefaultFeatureResults
We need to pick up the correct MathTransform in the constructor (if we cannot do the work we may as well let them know early). Here is the code snip:
CoordinateReferenceSystem origionalCRS = origionalType.getDefaultGeometry().getCoordinateSystem();
|
We are going to use the utility class GeometryCoordinateSequenceTransformer mentioned above to do the actual work.
The next part is to look at the code that does the reading .. getReader():
public FeatureReader reader() throws IOException {
|
Oh look they already have a "wrapper" in place here ... MaxFeatureReader will cut off the feature supply when a specific max is reached.
Lets go shopping:
- ReprojectFeatureIterator ... utility class used when your collection is memory based
- ReprojectFeatureReader ... perfect!
public FeatureReader reader() throws IOException {
|
That should be it ... getBounds uses reader() and so on.
So we have two solutions:
- An example of how to support reprojection directly as part of your FeatureCollection (ie use of ReprojectFeatureReader or ReprojectFeatureIterator wrappers)
- An example of how to support reprojection after the fact .. modify your getFeatures( Query method ) to use ReprojectFeatureResults (or its colleciton based ReprojectingFeatureCollection)
Almost done
Tomorrow we will try testing and see what sorts of problems this occurs in two real applications. If there is time we will review the javadocs that started this problem ... and explore ways of preventing this in the future.Blog Links >>
- Login or register to post comments
- Printer-friendly version
- jive's blog
- 866 reads





