Tôi muốn tạo một bản đồ với GeoTools và lưu nó vào một hình ảnh (ví dụ JPEG). Yêu cầu của tôi rất đơn giản:
- Tạo một bản đồ thế giới với 2 lớp: Ranh giới chính trị và một mạng lưới. Các lớp là từ các nguồn khác nhau và dự đoán khác nhau.
- Xuất bản đồ thành các phép chiếu khác nhau (ví dụ: "EPSG: 5070", "EPSG: 4326", "EPSG: 54012", "EPSG: 54009", v.v.)
- Cắt đầu ra cho các AOI khác nhau (ví dụ: -124,79 đến -66,9 lon, 24,4 đến 49,4 lat).
Tôi muốn làm điều này theo chương trình, thông qua API. Cho đến nay, tôi đã có thành công hạn chế. Tôi đã học cách tạo ra một bản đồ và đầu ra trong các phép chiếu khác nhau bằng cách sử dụng phương pháp này:
//Step 1: Create map
MapContent map = new MapContent();
map.setTitle("World");
//Step 2: Set projection
CoordinateReferenceSystem crs = CRS.decode("EPSG:5070"); //Conic projection over US
MapViewport vp = map.getViewport();
vp.setCoordinateReferenceSystem(crs);
//Step 3: Add layers to map
CoordinateReferenceSystem mapCRS = map.getCoordinateReferenceSystem();
map.addLayer(reproject(getPoliticalBoundaries(), mapCRS));
map.addLayer(reproject(getGraticules(), mapCRS));
//Step 4: Save image
saveImage(map, "/temp/graticules.jpg", 800);
Phương thức lưu trực tiếp từ trang web GeoTools :
public void saveImage(final MapContent map, final String file, final int imageWidth) {
GTRenderer renderer = new StreamingRenderer();
renderer.setMapContent(map);
Rectangle imageBounds = null;
ReferencedEnvelope mapBounds = null;
try {
mapBounds = map.getMaxBounds();
double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0);
imageBounds = new Rectangle(
0, 0, imageWidth, (int) Math.round(imageWidth * heightToWidth));
} catch (Exception e) {
// failed to access map layers
throw new RuntimeException(e);
}
BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_RGB);
Graphics2D gr = image.createGraphics();
gr.setPaint(Color.WHITE);
gr.fill(imageBounds);
try {
renderer.paint(gr, imageBounds, mapBounds);
File fileToSave = new File(file);
ImageIO.write(image, "jpeg", fileToSave);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Phương pháp reproject là phát minh của tôi. Đó là một chút hack nhưng đó là cách duy nhất tôi có thể tìm thấy để đưa hình ảnh ra một hình chiếu cụ thể.
private static Layer reproject(Layer layer, CoordinateReferenceSystem mapCRS) throws Exception {
SimpleFeatureSource featureSource = (SimpleFeatureSource) layer.getFeatureSource();
//Define coordinate transformation
CoordinateReferenceSystem dataCRS = featureSource.getSchema().getCoordinateReferenceSystem();
boolean lenient = true; // allow for some error due to different datums
MathTransform transform = CRS.findMathTransform(dataCRS, mapCRS, lenient);
//Create new feature collection
SimpleFeatureCollection copy = FeatureCollections.newCollection("internal");
SimpleFeatureType featureType = SimpleFeatureTypeBuilder.retype(featureSource.getSchema(), mapCRS);
SimpleFeatureIterator iterator = featureSource.getFeatures().features();
try {
while (iterator.hasNext()) {
SimpleFeature feature = iterator.next();
Geometry geometry = (Geometry) feature.getDefaultGeometry();
Geometry geometry2 = JTS.transform(geometry, transform);
copy.add( SimpleFeatureBuilder.build( featureType, new Object[]{ geometry2 }, null) );
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
iterator.close();
}
//Return new layer
Style style = SLD.createLineStyle(Color.BLACK, 1);
layer = new FeatureLayer(copy, style);
layer.setTitle("Graticules");
return layer;
}
Đầu ra rất tệ:
Vì vậy, tôi đoán tôi có một vài câu hỏi khác nhau:
- Đây có phải là sự chấp thuận đúng đắn? Tôi có thực sự cần phải định nghĩa lại các lớp theo cách thủ công hay MapViewport có nghĩa vụ phải làm điều này cho tôi không?
- Làm cách nào để cắt đầu ra cho AOI cụ thể? Tôi đã thử thiết lập giới hạn bằng phương thức MapViewport.setBound (phong bì) nhưng phương thức saveImage dường như bỏ qua giới hạn.
- Làm cách nào để có được các đường vĩ độ của tôi hiển thị dưới dạng cung? Có một thiết lập biến đổi mà tôi đang thiếu?
Tôi đang sử dụng GeoTools 8.7.