[GIS] Adding multiple points to same layer using GeoTools

geotoolslayers

I've got a java Swing application which loads a shapefile and draw a map. Now I need to allow the user to click on the map and add points. I've successfully completed that with the following code.

        private void runMe(double x, double y) {
        final SimpleFeatureType TYPE = createFeatureType();
        final SimpleFeatureBuilder BLDR = new SimpleFeatureBuilder(TYPE);


        DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);

        // arbitrary start pos 
        Coordinate pos = new Coordinate(x, y);
        int id = 0;
        featureCollection.add(createFeature(BLDR, pos, id));

        // Display the points on screen 
        Style style = SLD.createPointStyle("circle", Color.BLUE,
                Color.BLUE, 1.0f, 5.0f);
        Layer layer = new FeatureLayer(featureCollection, style);

        map.addLayer(layer);
    }

This function is called from a onMouseClicked() event. As obviously seen, this function adds a layer each time the function is called. Points are correctly displayed on the map.

Now I want to add only one layer to the existing map and add all the points to that layer. I've read that featurecollections can be added at a later time, so I've first added the layer with an empty feature collection as follows.

    DefaultFeatureCollection featureCollection;
    SimpleFeatureBuilder BLDR;

public void addPointFeature() {
    final SimpleFeatureType TYPE = createFeatureType();
    BLDR = new SimpleFeatureBuilder(TYPE);

    featureCollection = new DefaultFeatureCollection("internal", TYPE);

    // Display the points on screen 
    Style style = SLD.createPointStyle("circle", Color.BLUE,
            Color.BLUE, 1.0f, 5.0f);
    Layer layer = new FeatureLayer(featureCollection, style);

    map.addLayer(layer);
}

Then at each onMouseClicked() event I add a point to the featureCollection as follows.

        @Override
    public void onMouseClicked(MapMouseEvent ev) {
        DirectPosition2D p = ev.getWorldPos();

        runMe2(p.getX(), p.getY());

    }

    private void runMe2(double x, double y){
        // arbitrary start pos 
        Coordinate pos = new Coordinate(x, y);
        val++;

        featureCollection.add(createFeature(BLDR, pos, val));

        mapPane.repaint();
    }

    private SimpleFeature createFeature(SimpleFeatureBuilder bldr,
            Coordinate pos, int id) {
        com.vividsolutions.jts.geom.Point p = GEOMFAC.createPoint(pos);
        bldr.add(p);
        bldr.add(id);

        // null arg means allow the builder to generate a default feature ID 
        return bldr.buildFeature(null);
    }

I can see the layer being added to the map. But none of the points are visible on the map.


I just noticed that, when I make any layer of the map invisible and visible again, all the points that I clicked appear (I use the map layer table toggle visibility button). This problem should be related to the layers not being refreshed/redrawn.

Best Answer

As you noticed in the previous discussion GeoTools used to have a complex event system to handle updates but it fell into disuse and no one has felt the need to fix it. The majority of GeoTools users manage the GUI (if they have one at all) themselves and "know" when to do a redraw based on the internal logic of the program.

You can directly call redraw on your JPane after you have updated your points. Or you could hook into the GeoTools event system by using a wrapper around your FeatureLayer:

import org.geotools.feature.FeatureCollection;
import org.geotools.map.FeatureLayer;
import org.geotools.map.event.MapLayerEvent;
import org.geotools.styling.Style;

public class UpdatableLayer extends FeatureLayer {

  public UpdatableLayer(FeatureCollection collection, Style style) {
    super(collection, style);
    // TODO Auto-generated constructor stub
  }

  public void updated() {
    fireMapLayerListenerLayerChanged(MapLayerEvent.DATA_CHANGED);
  }
}

Then you can call layer.update() when you update the FeatureCollection for the full Event experience you could also extend the FeatureCollection to fire an event that your layer listened for to handle updates automatically.

Related Question