I'm using the Java 1.8 library geotools (version "23-SNAPSHOT") to generate a shapefile.

Opening the resulting .shp file with QGIS was successfull and I noticed that the gemeotry was apparently automatically set to "PointZM", which is exactly what I want. Every point surprisingly also lists an "M" value (but they're all 0).

How do I set the M value (additional to x, y and z!) using the library? Does the library now automatically default to using "PointZM" (it didn't with an older version)?

The code I more or less copied from here:

final SimpleFeatureType TYPE = DataUtilities.createType("Location","the_geom:Point:srid=4326,name:String,number:Integer");    
List<SimpleFeature> features = new ArrayList<SimpleFeature>();
GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);

//Create features/points
for(int i=0; i<maxpoints; i++) {
    Point p = geometryFactory.createPoint(new Coordinate(i*10,i*5,i));
    SimpleFeature feature = featureBuilder.buildFeature(null);

//Generate shapefile
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
Map<String, Serializable> params = new HashMap<String,Serializable>();
params.put("url", fileout.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);

//Write file
Transaction transaction = new DefaultTransaction("create");
String typeName = newDataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
SimpleFeatureType SHAPE_TYPE = featureSource.getSchema();

if (featureSource instanceof SimpleFeatureStore) {
    SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
    SimpleFeatureCollection collection = new ListFeatureCollection(TYPE, features);

    try {
    } catch (Exception e) {
    } finally {
} else {
    System.out.println(typeName + " does not support read/write access");

There's a setM function for Coordinate, so I tried this:

Coordinate c = new Coordinate(i*10,i*5,i);
Point p = geometryFactory.createPoint(c);

But this only throws an exception:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid ordinate index: 3

  • 1
    According to the shapefile specification the format does not actually support XYZ geometries because with Z comes automatically also M downloads.esri.com/support/whitepapers/mo_/shapefile.pdf.
    – user30184
    Sep 4 '19 at 10:45
  • @user30184 Thanks for the link. "PointM" only supports XYM, yes but check on page 15: A PointZ consists of a triplet of double-precision coordinates in the order X, Y, Z plus a measure.. That's exactly what I need but how do I set it up?
    – Neph
    Sep 4 '19 at 10:51
  • That's what I tried to say. If you have XYZ shapefile there is automatically place for storing M values as well. Unfortunately I do not know how that is done with GeoTools.
    – user30184
    Sep 4 '19 at 10:58

Using a Coordinate object throws an exception if you're trying to set its M value:

Coordinate c = new Coordinate(i*10,i*5,i);
Point p = geometryFactory.createPoint(c);

Exception in thread "main" java.lang.IllegalArgumentException: Invalid ordinate index: 3

This is because the normal Coordinate hasn't got an actual "m" value (so it would be the 4th of 3 available spots) and doesn't like having it set either:

public void setM(double m) {
    throw new IllegalArgumentException("Invalid ordinate index: " + M);

Instead use CoordinateXYZM, which extends Coordinate:

CoordinateXYZM c = new CoordinateXYZM(i*10,i*5,i,i*20);
Point p = geometryFactory.createPoint(c);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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