1

I'm trying to retrieve data from a LuciadFusion wfs server using GeoTools, but is having troubles finding examples on how to achieve my goals.

The idea is that I'm tracking moving stuff, and want to retrieve map data (features) from the areas my moving tings is moving into, and then calculate distances (like how far to nearest road, nearest lake coastal shore).

I want to get the features, put them into a SpatialIndexFeatureCollection (kept in memory for quick access, as I'm tracking multiple moving objects), where I can query the stuff I want to know.

So far I'm querying some random wfs server I found with data: http://ogc.bgs.ac.uk/digmap625k_gsml32_insp_gs/wfs?. I'm able to read the capabilities, and from one of the typenames building my SpatialIndexFeatureCollection:

String url =  "http://ogc.bgs.ac.uk/digmap625k_gsml32_insp_gs/wfs?";

Map connectionParameters = new HashMap();
connectionParameters.put("WFSDataStoreFactory:GET_CAPABILITIES_URL", url)
connectionParameters.put(WFSDataStoreFactory.TIMEOUT.key, 100000);
WFSDataStoreFactory  dsf = new WFSDataStoreFactory();

try {
   WFSDataStore dataStore = dsf.createDataStore(connectionParameters);

   for(String s : dataStore.getTypeNames()){
      System.out.println(s);

   }

   SimpleFeatureSource source = dataStore.getFeatureSource("test:uk_625k_mapped_feature");
   SimpleFeatureCollection fc = source.getFeatures();
   System.out.println(fc.getBounds());

   SpatialIndexFeatureCollection index = new SpatialIndexFeatureCollection();
   fc.accepts(new FeatureVisitor() {
      @Override
      public void visit(Feature feature) {
         SimpleFeature simpleFeature = (SimpleFeature) feature;
         Geometry geom = (MultiPolygon) simpleFeature.getDefaultGeometry();

         if(geom != null) {
            Envelope env = geom.getEnvelopeInternal();

            if(!env.isNull()) {
               index.add(simpleFeature);
            }
         }
      }
   }, new NullProgressListener());

catch (FactoryException e) {
   aLog.error("", e);
}

Running it prints:

  • gsml:MappedFeature
  • gsmlgu:GeologicUnit
  • test:uk_625k_mapped_feature
  • ReferencedEnvelope[-132576.7891571155 : 743466.624998733, -15669.960592884949 : 1248847.1762802668]

However, when my own WFS server has been setup, it will contain many more typenames each describing fx roads or lakes for an area. And for many areas.

How do I get the typenames relevant for a defined area (a boundingbox BB), or maybe even only the features in a typename covered by the BB if it's possible?

Second, when extracting data from the example above, all the features is in a wrong CoordinateReferenceSystem - how do I force it to be EPSG:4326?

Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Mars
  • 45
  • 1
  • 6

1 Answers1

1

First to clarify terminology:

  1. a TypeName is an identifier of a type of data or a schema.
  2. a Feature is the actual piece of data that has position and attributes.

To restrict the number of features returned you need to make use of a Query object. This allows you to specify a Filter to restrict the features returned. In the case of a WFSDatastore (and most others) it is converted into something the underlying store understands and handled there. You can create features in all sorts of ways including a FilterFactory but the easiest is to use ECQL which allows you to write more human understandable filters directly. There is a helpful tutorial here.

    Filter filter = ECQL.toFilter("BBOX(the_geom, 500000, 700000, 501000, 701000)");
    query.setFilter(filter);
    query.setMaxFeatures(10);
    SimpleFeatureCollection fc = source.getFeatures(query);

As for reprojection WFS doesn't handle that directly but you could use a ReprojectingFeatureCollection to wrap your results.

ReprojectingFeatureCollection rfc = new ReprojectingFeatureCollection(fc, DefaultGeographicCRS.WGS84);

Unless you are expecting a lot of invalid polygons then you should be able to build a spatial indexed collection using:

SpatialIndexFeatureCollection index = new SpatialIndexFeatureCollection(fc.getSchema());
index.addAll(fc);
Ian Turton
  • 10,018
  • 1
  • 28
  • 47
  • Thank you so much for your answer! :-) Something might be wrong with our WFS server, I guess that to get the _source_ object, I still need to say 'SimpleFeatureSource source = dataStore.getFeatureSource("test:uk_625k_mapped_feature");' thus knowing the typeName I want to examine, right? When I do this on our own server, I get a 'java.io.IOException: Schema ' _772ced6e_45_54b5_45_4295_45_bb01_45_a50b9179f1ecWorldType' does not exist.' (yeah and the typename seems pretty random as well). ... – Mars Jun 19 '17 at 06:21
  • I don't see this schema error on the wfs server stated in the original question. If I point my browser to 'http://172.20.6.150:8085/LuciadFusion/wfs?REQUEST=GetFeature&SERVICE=WFS&VERSION=1.1.0&TYPENAME=_772ced6e_45_54b5_45_4295_45_bb01_45_a50b9179f1ecWorldType' I do get some xml full of data. Do I need the schema to access this data when using the geotools? Or can I read the data anyway (in case the guys trying to setup the Luciad server, can't figure out how to get the schema in place)? Thanks again - the help is really appreciated! – Mars Jun 19 '17 at 06:21
  • you do need to know the typeName of the featureCollection you want to fetch, you can read the getCapabilities response directly to see what is available. GeoTools should fetch and figure out the schema automatically. – Ian Turton Jun 19 '17 at 07:35
  • So I successfully creates a WFSDataStore from my server, and is able to list all the typeNames. But when trying to say dataStore.getFeatureSource(aTypeName); it fails with the "java.io.IOException: Schema '_772ced6e_45_54b5_45_4295_45_bb01_45_a50b9179f1ecWorldType' does not exist."-exception. What am I doing wrong? – Mars Jun 19 '17 at 08:18
  • what is the typename you used? – Ian Turton Jun 19 '17 at 08:19
  • I'm listing all typeNames by looping through dataStore.getTypeNames(), and one of them is "_772ced6e_45_54b5_45_4295_45_bb01_45_a50b9179f1ecWorldType". I can confirm that it should be full of data by going to http://172.20.6.150:8085/LuciadFusion/wfs?REQUEST=GetFeature&SERVICE=WFS&VERSION=1.1.0&TYPENAME=_772ced6e_45_54b5_45_4295_45_bb01_45_a50b9179f1ecWorldType. – Mars Jun 19 '17 at 08:24
  • Okay, I think our Luciad server is setup wrong - I can't find a GIS program that is able to read from it (the missing schema part). We also have a GeoServer, and here my code works just fine :-) However, a question to the original question: using the query to only get features within the BBox, do I have to use the same projection as the layer? I'm working in lat/long (EPSG:4326 - WGS84), but the WFS serves the layer in EPSG:26713. – Mars Jun 21 '17 at 07:57
  • Theoretically, later versions of the WFS spec allow you to specify the srs of the bbox but safest is to reproject the box to the target (i.e. server) SRS before building the filter. – Ian Turton Jun 21 '17 at 07:59