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?
1 Answer 1
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<Length> 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<Object> 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<Length> distance, CoordinateReferenceSystem origCRS, Geometry geom) {
Geometry pGeom = geom;
MathTransform toTransform, fromTransform = null;
// reproject the geometry to a local projection
Unit<Length> 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<Length>) 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;
}
-
Thanks for the answer! Could you say what imports you are using for Quantity<>, Unit<> and Length as I cannot figure out the right library.Bartors– Bartors2018年10月22日 14:31:18 +00:00Commented Oct 22, 2018 at 14:31
-
1depends on your version - see docs.geotools.org/stable/userguide/welcome/upgrade.html for more detailIan Turton– Ian Turton2018年10月22日 14:37:06 +00:00Commented Oct 22, 2018 at 14:37
-
Great! I do really appreciate your answers. Do you know any "step by step" tutorials for performing analysis in Geotools? I know it is all in docs but, as I hope you understand, it is quite a lot be look at for a beginner. Anyway, thank you for your time!Bartors– Bartors2018年10月22日 14:51:59 +00:00Commented Oct 22, 2018 at 14:51
-
1most analysis boils down to a SimpleFeatureIterator loop and some simple codeIan Turton– Ian Turton2018年10月22日 15:19:08 +00:00Commented Oct 22, 2018 at 15:19
-
hi ian , one question in your experience, Would it be possible to receive a wkt string and convert it to geometry, then apply the buffer to it, keeping in mind that the crs could see the source but it should always come out as 4326?Cristián Vargas Acevedo– Cristián Vargas Acevedo2022年12月29日 05:15:28 +00:00Commented Dec 29, 2022 at 5:15