3

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));
    featureBuilder.add(p);
    featureBuilder.add("P"+i);
    featureBuilder.add(i);
    SimpleFeature feature = featureBuilder.buildFeature(null);
    features.add(feature);
}

//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);
newDataStore.createSchema(TYPE);

//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);
    featureStore.setTransaction(transaction);

    try {
        featureStore.addFeatures(collection);
        transaction.commit();
    } catch (Exception e) {
        e.printStackTrace();
        transaction.rollback();
    } finally {
        transaction.close();
    }
} else {
    System.out.println(typeName + " does not support read/write access");
    System.exit(1);
}

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

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

But this only throws an exception:

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

Neph
  • 235
  • 1
  • 9
  • 1
    According to the shapefile specification the format does not actually support XYZ geometries because with Z comes automatically also M http://downloads.esri.com/support/whitepapers/mo_/shapefile.pdf. – user30184 Sep 04 '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 04 '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 04 '19 at 10:58

1 Answers1

1

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);
c.setM(i*20);
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);
Neph
  • 235
  • 1
  • 9