Wednesday, 18 January 2017

Creating buffer around features using GeoTools?


I want to develop a simple GIS application using GeoTools. I have looked at the tutorials but i could get to much meaningful from them.


I have a simple JMapFrame to which add can add a featureLayer from a shapefile


public void action(ActionEvent e) throws Throwable{
sourceFile = JFileDataStoreChooser.showOpenFile("shp", null);
if (sourceFile == null) {
return;
}

FileDataStore store = FileDataStoreFinder.getDataStore(sourceFile);
featureSource = store.getFeatureSource();

Style style = SLD.createSimpleStyle(featureSource.getSchema());
Layer layer = new FeatureLayer(featureSource, style);
map.addLayer(layer);
}

Now, lets say I want to create a buffer around my features. From what I have understood I have to get the featureSource, then create a featureCollection, iterate through the features and for each of those feature I have to cast them to a Geometry, then create a buffer.


When I have created a buffer should I go all the way back to featureLayer and add it to my map?




Answer



In general GeoTools always looks to display Layers in the JMapFrame, so any time you want to display something new you will need to construct a new layer and add it to the MapContext.


For any operation involving features (such as buffering) then you will need to loop through all of the features you need and apply the operation to them. This will usually use a SimpleFeatureIterator and generate a new SimpleFeatureCollection which you can generate a new layer from.


I'd use something like this to do the buffering:


  public SimpleFeature bufferFeature(SimpleFeature feature, Quantity distance) {
// extract the geometry
GeometryAttribute gProp = feature.getDefaultGeometryProperty();
CoordinateReferenceSystem origCRS = gProp.getDescriptor().getCoordinateReferenceSystem();

Geometry geom = (Geometry) feature.getDefaultGeometry();

Geometry retGeom = bufferPoint(distance, origCRS, geom);
// return a new feature containing the geom
SimpleFeatureType schema = feature.getFeatureType();
SimpleFeatureTypeBuilder ftBuilder = new SimpleFeatureTypeBuilder();
ftBuilder.setCRS(origCRS);

for (AttributeDescriptor attrib : schema.getAttributeDescriptors()) {
AttributeType type = attrib.getType();

if (type instanceof GeometryType) {

String oldGeomAttrib = attrib.getLocalName();
ftBuilder.add(oldGeomAttrib, Polygon.class);
} else {
ftBuilder.add(attrib);
}
}
ftBuilder.setName(schema.getName());

SimpleFeatureType nSchema = ftBuilder.buildFeatureType();
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(nSchema);

List atts = feature.getAttributes();
for (int i = 0; i < atts.size(); i++) {
if (atts.get(i) instanceof Geometry) {
atts.set(i, retGeom);
}
}
SimpleFeature nFeature = builder.buildFeature(null, atts.toArray());
return nFeature;
}


/**
* @param distance
* @param origCRS
* @param geom
* @return
*/
@SuppressWarnings("unchecked")
public Geometry bufferPoint(Quantity distance, CoordinateReferenceSystem origCRS, Geometry geom) {
Geometry pGeom = geom;
MathTransform toTransform, fromTransform = null;

// reproject the geometry to a local projection
Unit unit = distance.getUnit();
if (!(origCRS instanceof ProjectedCRS)) {

double x = geom.getCoordinate().x;
double y = geom.getCoordinate().y;

String code = "AUTO:42001," + x + "," + y;
// System.out.println(code);
CoordinateReferenceSystem auto;

try {
auto = CRS.decode(code);
toTransform = CRS.findMathTransform(origCRS, auto);
fromTransform = CRS.findMathTransform(auto, origCRS);
pGeom = JTS.transform(geom, toTransform);
unit = SI.METRE;
} catch (MismatchedDimensionException | TransformException | FactoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


} else {
unit = (Unit) origCRS.getCoordinateSystem().getAxis(0).getUnit();

}
UnitConverter converter = distance.getUnit().getConverterTo(unit);
// buffer
Geometry out = pGeom.buffer(converter.convert(distance.getValue()).doubleValue());
Geometry retGeom = out;
// reproject the geometry to the original projection

if (!(origCRS instanceof ProjectedCRS)) {
try {
retGeom = JTS.transform(out, fromTransform);

} catch (MismatchedDimensionException | TransformException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return retGeom;

}

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...