0

I am trying to draw lines on the map using GeoTools, and my goal here is to prevent reloading the window when I draw lines on the map every time.

I created a layer based on a featureCollection and added features to that layer each time when I draw a line on the map. The problem is when I draw a line, the line layer is not updating. But when I click the button with two arrows on it above the window, the lines are coming. Please help me on how can I make the line layer update without clicking this button?

In my code, you can draw lines by clicking 2 times in the map frame.

package org.geotools.tutorial.feature;

        import java.awt.*;
        import java.io.File;
        import java.io.IOException;
        import java.util.*;
        import java.util.List;

        import org.geotools.data.FileDataStore;
        import org.geotools.data.FileDataStoreFinder;
        import org.geotools.data.simple.SimpleFeatureSource;
        import org.geotools.feature.DefaultFeatureCollection;
        import org.geotools.feature.simple.SimpleFeatureBuilder;
        import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
        import org.geotools.geometry.jts.JTSFactoryFinder;
        import org.geotools.map.*;
        import org.geotools.referencing.crs.DefaultGeographicCRS;
        import org.geotools.styling.SLD;
        import org.geotools.styling.Style;
        import org.geotools.swing.JMapFrame;
        import org.geotools.swing.data.JFileDataStoreChooser;
        import org.geotools.swing.event.MapMouseEvent;
        import org.geotools.swing.tool.CursorTool;
        import org.locationtech.jts.geom.Coordinate;
        import org.locationtech.jts.geom.GeometryFactory;
        import org.locationtech.jts.geom.LineString;
        import org.locationtech.jts.geom.Point;
        import org.opengis.feature.simple.SimpleFeature;
        import org.opengis.feature.simple.SimpleFeatureType;
        import org.opengis.referencing.FactoryException;
        import org.opengis.referencing.operation.TransformException;

public abstract class DrawLine {
    static GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();

    public static void main(String[] args) throws Exception {
        // display a data store file chooser dialog for shapefiles
        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);
        mapFrame.setSize(1600, 1000);
        mapFrame.setVisible(true);

        List<MapMouseEvent> points = new ArrayList<MapMouseEvent>();

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

        final SimpleFeatureType TYPE = builder.buildFeatureType();

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

        Style lineStyle = SLD.createLineStyle(Color.red, 2.0f);
        Layer lineLayer = new FeatureLayer(featureCollection, lineStyle);
        map.addLayer(lineLayer);

        mapFrame.getMapPane()
                .setCursorTool(
                        new CursorTool() {

                            @Override
                            public void onMouseClicked(MapMouseEvent ev) {
                                try {
                                    if (points.size() == 0) {
                                        points.add(ev);
                                    } else {
                                        Point start = gf.createPoint(new Coordinate(points.get(0).getWorldPos().x, points.get(0).getWorldPos().y));
                                        Point end = gf.createPoint(new Coordinate(ev.getWorldPos().x, ev.getWorldPos().y));

                                        DrawLine.displayShapefile(  featureCollection, featureBuilder,  start, end);
                                        System.out.println(map.layers());
                                        points.clear();
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                } catch (FactoryException e) {
                                    e.printStackTrace();
                                } catch (TransformException e) {
                                    e.printStackTrace();
                                }
                            }

                        }
                );
    }

    public static void displayShapefile( DefaultFeatureCollection featureCollection ,  SimpleFeatureBuilder featureBuilder, Point start, Point end) throws IOException, FactoryException, TransformException {

        Coordinate[] coordinates = {start.getCoordinate(), end.getCoordinate() };
        LineString line = gf.createLineString(coordinates);

        featureBuilder.reset();

        featureBuilder.add(line);

        SimpleFeature feature = featureBuilder.buildFeature(null);

        featureCollection.add(feature);
    }
}

1 Answer 1

1

There is no direct connection between a FeatureCollection and the MapPane so until the map receives a request to redraw nothing will happen.

So when you add a new feature you will need to notify the MapPane that it needs to rerender. To help you do this there is a MapLayerEvent.DATA_CHANGED event which is propagated via the Layer.fireMapLayerListenerLayerChanged() method.

1
  • Thank you a lot, after adding a line to the featureCollection, I called getMapPane().reset(); and the line directly show in the map. Commented Dec 27, 2021 at 7:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.