[GIS] Draw a point, line and polygon on map using GeoTools

geotools

I am using geotools v20. I want to allow the users to draw the new features using the mouse to click on the map area to draw new points, lines and polygons. The user should be able to draw a point on the clicked location and should be visible on map. Please send the source code of geotools, I have tried in geotools library but i didn't get any code for draw points on map.

Here is the sample code, But when we execute the layer is creating but the features are not showing. Please help me on how to display the drawn features on map.

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JToolBar;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Fill;
import org.geotools.styling.Graphic;
import org.geotools.styling.Mark;
import org.geotools.styling.Rule;
import org.geotools.styling.SLD;
import org.geotools.styling.Stroke;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.Symbolizer;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.JMapPane;
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.MultiLineString;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.identity.FeatureId;

public class SelectionLab {
    MapContent map = new MapContent();  
    public enum GeomType {
        POINT, LINE, POLYGON
    };
    private JMapFrame mapFrame;
    public static void main(String[] args) throws Exception {
        SelectionLab me = new SelectionLab();
        me.displayShapefile();
    }

    public void displayShapefile() throws Exception {       
        map.setTitle("Draw Feature tool example");
        mapFrame = new JMapFrame(map);
        mapFrame.enableToolBar(true);
        mapFrame.enableStatusBar(true);

        JToolBar toolBar = mapFrame.getToolBar();
        JButton btn = new JButton("Draw");
        toolBar.addSeparator();
        toolBar.add(btn);

        btn.addActionListener(e -> mapFrame.getMapPane().setCursorTool(new CursorTool() {
            @Override
            public void onMouseClicked(MapMouseEvent ev) {
                DirectPosition2D p = ev.getWorldPos();
                System.out.println(p.getX() + " -- " + p.getY());
                drawMyPoint(p.getX(), p.getY());
            }
        }));        
        mapFrame.setSize(600, 600);
        mapFrame.setVisible(true);
    }

    void drawMyPoint(double x, double y) {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName("MyFeatureType");
        builder.setCRS( DefaultGeographicCRS.WGS84 ); // set crs        
        builder.add("location", Point.class); // add geometry

        // build the type
        SimpleFeatureType TYPE = builder.buildFeatureType();

        // create features using the type defined
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        org.locationtech.jts.geom.Point point = geometryFactory.createPoint(new Coordinate(x, y));
        featureBuilder.add(point);
        SimpleFeature feature = featureBuilder.buildFeature("FeaturePoint");
        DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);
        featureCollection.add(feature); // Add feature 1, 2, 3, etc

        Style style = SLD.createPointStyle("Star", Color.BLUE, Color.BLUE, 0.3f, 15);
        Layer layer = new FeatureLayer(featureCollection, style);
        layer.setTitle("NewPointLayer");
        map.addLayer(layer);
        // mapPane.repaint();
    }

}

Best Answer

It seems the issue comes from the DefaultFeatureCollection you were using to create the points layer. Changing that to this works for me:

SimpleFeature feature = featureBuilder.buildFeature("FeaturePoint");
List<SimpleFeature> featureCollection = new ArrayList<>();
featureCollection.add(feature); // Add feature 1, 2, 3, etc

Style style = SLD.createPointStyle("Star", Color.BLUE, Color.BLUE, 0.3f, 15);
Layer layer = new FeatureLayer(DataUtilities.collection(featureCollection), style);
layer.setTitle("NewPointLayer");
map.addLayer(layer);
Related Question