3

I use the java libraries geotools and vividsolutions to extract xyz data from a shapefile (Vienna from this example).

This works perfectly fine for x and y data, but all coordinate values for z are set to "NaN" (not a number), same as for regular 2D Shapefiles. I found other questions relating to Z=0, but i think this one is quite different since its about different tools, and the source file already does contain Z-Values (as can be seen in the example).

Using the code below, i can successfully extract x and y values for coordinates, but coordinate.z always yields "NaN". Since i know the shapefile in question contains z-Values, the problem must be in geotools/vividsolutions (or my use of those libraries). So, my question is, does anybody know how to read the Z coordinate value using geotools & vivdsolutions?

For reference, see below for the (condensed) code i used to exctract coordinates.

Getting the Geometries from Shapefile:

public List<Geometry> getShapefileGeometries(File shpFile) throws MalformedURLException, IOException {
    List<Geometry> shpGeometries = null;
    Map<String, Object> mapConnectionTypeInfo = new HashMap<>();
        mapConnectionTypeInfo.put("url", shpFile.toURI().toURL());
        DataStore myDataStore = DataStoreFinder.getDataStore(mapConnectionTypeInfo);
        String typeName = myDataStore.getTypeNames()[0];
        FeatureSource<SimpleFeatureType, SimpleFeature> dataSource = myDataStore.getFeatureSource(typeName);
        FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = dataSource.getFeatures();
        Object[] featureObjects = featureCollection.toArray();            
        if (featureObjects != null) {
            shpGeometries = new ArrayList<>();
            for (Object featureObject : featureObjects) {
                SimpleFeature feature = (SimpleFeature) featureObject;
                Object defaultGeometry = feature.getDefaultGeometry();
                if (defaultGeometry != null && defaultGeometry instanceof Geometry) {
                    shpGeometries.add((Geometry) defaultGeometry);
                }
            }
        }         
    return shpGeometries;
}

Searching Geometries for coordinates with Z-Values:

public void checkGeometriesForZ(List<Geometry> shpGeometries) {
    for (Geometry currentGeometry : shpGeometries) {
        for (int i = 0; i < currentGeometry.getNumGeometries(); i++) {
            Geometry g = currentGeometry.getGeometryN(i);
            Coordinate[] coordinates = null;
            if (g instanceof Polygon) coordinates = ((Polygon) g).getCoordinates();                
            if (g instanceof LineString) coordinates = ((LineString) g).getCoordinates();                
            if (g instanceof Point) coordinates = ((Point) g).getCoordinates();                
            if (coordinates != null) {
                for (Coordinate currentCoordinate : coordinates) {
                    System.out.println(String.format("X: %f, Y: %f, Z: %f", currentCoordinate.x, currentCoordinate.y, currentCoordinate.z));
                }
            }
        }
    }
}

Testing (using the vienna shapefile from the example):

@Test
public void searchSHPWithZ() throws IOException {
    File vienna = new File("shapefiles/105082_bkm.shp");
    CoordinateExtraction mySearch = new CoordinateExtraction();
    List<Geometry> currentGeometries = mySearch.getShapefileGeometries(vienna);
    mySearch.checkGeometriesForZ(currentGeometries);
}

Typical output:

"X: 2963,808248, Y: 341051,336212, Z: NaN"
1
  • 2
    please show us how you are reading in the file and how you access the coordinates – Ian Turton Jan 17 '18 at 16:21
2

The shapefile in question does not seem to contain Z values on the coordinates, it contains the information in attributes.

The Shapefile contains the following relevant attributes for 3D visualization

O_KOTE: absolute building height measured to the roof gutter(?) (“absolute Gebäudehöhe der Dachtraufe”)

U_KOTE: absolute height of the lower edge of the building block if floating above ground (“absolute Überbauungshöhe unten”)

HOEHE_DGM: absolute height of the terrain (“absolute Geländehöhe”)

T_KOTE: lowest point of the terrain for the given building block (“tiefster Punkt des Geländes auf den Kanten der Gebäudeteilfläche”)

So to access the absolute building height (for example) you can do something like:

FileDataStore ds = FileDataStoreFinder.getDataStore(new File("/home/ian/Downloads/105082_bkm.shp"));
SimpleFeatureCollection features = ds.getFeatureSource().getFeatures();
try (SimpleFeatureIterator iter = features.features()) {
  while (iter.hasNext()) {
    SimpleFeature f = iter.next();
      Object attribute = f.getAttribute("O_KOTE");
      if (attribute != null) {
        double height = (double) attribute;
        //do whatever with height
    }
  }
}
1
  • Thank you for taking a look at my problem! Searching for those attributes, i just found them in the .dbf file (using libreoffice calc), but i would need a way to get them in java (if possible using geotools or vivisolutions, so i don't need to find or create an extra dbf reader). Should i change my question/post a new question for that? – ptstone Jan 18 '18 at 11:05

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.