Java GeoTools – Resolving AddLayer Method Screen Reloading Issues

addlayergeotoolsjavalinestringmap-drawing

I am trying to draw lines on map using GeoTools. Firstly I added a map layer, and while the program still is running, the user draws a line with mouse clicks. But every time addLayer method calls, the screen reloads again and the white screen seems for a while. I could not understand it is a Java desktop application problem or a geotools problem.

Here is the code. How can I prevent the reloads screen?

        File file = JFileDataStoreChooser.showOpenFile("shp", null);
        if (file == null) {
            return;
        }

        FileDataStore store = FileDataStoreFinder.getDataStore(file);
        SimpleFeatureSource featureSource = store.getFeatureSource();

        // Create a map content and add our shapefile to it
        MapContent map = new MapContent();
        map.setTitle("Geotool application");

        Style style = SLD.createSimpleStyle(featureSource.getSchema());
        Layer layer = new FeatureLayer(featureSource, style);
        map.addLayer(layer);

        JMapFrame mapFrame = new JMapFrame(map);
        mapFrame.enableToolBar(true);
        mapFrame.enableStatusBar(true);

And the method to draw lines by coming mouse clicks.

public static void displayShapefile(File file, MapContent map, MapMouseEvent ev1, MapMouseEvent ev2, boolean isClicked) throws IOException, FactoryException, TransformException {

        GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();

        double latitude, longitude, latitudeDest, longitudeDest;

        longitude = ev1.getWorldPos().x;
        latitude = ev1.getWorldPos().y;
        //  System.out.println("Enter destination longitude and latitude:\n");
        longitudeDest =  ev2.getWorldPos().x;
        latitudeDest = ev2.getWorldPos().y;

final String EPSG4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\"," +
        "\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\", " +
        "0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
        CoordinateReferenceSystem crs = CRS.parseWKT(EPSG4326);


        Point start = gf.createPoint(new Coordinate(longitude, latitude));
        Point end = gf.createPoint(new Coordinate(longitudeDest, latitudeDest));

        GeodeticCalculator gc = new GeodeticCalculator(crs);
        gc.setStartingPosition(JTS.toDirectPosition(start.getCoordinate(), crs));
        gc.setDestinationPosition(JTS.toDirectPosition(end.getCoordinate(), crs));
        
        Coordinate[] coordinates = {start.getCoordinate(), end.getCoordinate()};
        LineString line = gf.createLineString(coordinates);

        FileDataStore store = FileDataStoreFinder.getDataStore(file);
        SimpleFeatureSource featureSource = store.getFeatureSource();

        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName("TwoDistancesType");
        builder.setCRS(DefaultGeographicCRS.WGS84);
        builder.add("line", LineString.class);

        final SimpleFeatureType TYPE = builder.buildFeatureType();

        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
        featureBuilder.add(line);

        SimpleFeature feature = featureBuilder.buildFeature(null);
        DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);
        featureCollection.add(feature);

        Style style = SLD.createLineStyle(Color.red, 2.0f);
        Layer layer = new FeatureLayer(featureCollection, style);

        map.addLayer(layer);
}

Best Answer

Your screen refreshes slowly because of the number of things you are doing in your displayShapefile method.

  1. get start and end points
  2. parse a WKT string to get a projection
  3. Initialise a Geodetic calculator
  4. Add points to geodetic calculator
  5. create a linestring
  6. Look for a datastore
  7. load a shapefile
  8. create a featuretype
  9. create a featurebuilder
  10. build a feature
  11. create a default featurecollection
  12. create a simple style
  13. create a layer
  14. add layer to map

So obviously this all takes time, most of the steps are unneeded - you never use the GeodeticCalculator, you never use the shapefile you load. The schema, featurebuilder and style are identical every time you use the method, so why create them from new each time.

A far simpler idea would be to create a single layer based on a collection and add features to that layer each time you need to draw something.

If speed is really important then you need to rewrite the Swing MapPane to use a cached image for the base (or unchanging) layers and only redraw the changed layer on refresh. The GeoTools team welcomes PRs that implement new functionality like that.

Related Question