GeoTools로지도를 만들고 이미지 (예 : JPEG)로 저장하고 싶습니다. 내 요구 사항은 간단합니다.
- 정치 경계와 계수 선이라는 2 개의 레이어로 세계지도를 만듭니다. 레이어는 다른 소스와 다른 투영에서 나온 것입니다.
- 다른 투영으로 맵을 출력합니다 (예 : "EPSG : 5070", "EPSG : 4326", "EPSG : 54012", "EPSG : 54009"등).
- 출력을 다른 AOI에 클립하십시오 (예 : -124.79 ~ -66.9 lon, 24.4 ~ 49.4 lat).
API를 통해 프로그래밍 방식으로 수행하고 싶습니다. 지금까지 나는 제한된 성공을 거두었 다. 이 접근법을 사용하여 다양한 투영법으로 맵을 작성하고 출력하는 법을 배웠습니다.
//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);
저장 방법은 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);
}
}
재 투영 방법은 저의 발명품입니다. 그것은 약간의 해킹이지만 이미지를 특정 투영으로 출력하는 유일한 방법입니다.
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;
}
출력이 정말 나쁩니다.
그래서 몇 가지 다른 질문이 있다고 생각합니다.
- 이것이 올바른 접근입니까? 레이어를 수동으로 재 투영해야합니까, 아니면 MapViewport가이 작업을 수행해야합니까?
- 출력을 특정 AOI에 클립하려면 어떻게해야합니까? MapViewport.setBounds (envelope) 메소드를 사용하여 경계를 설정하려고 시도했지만 saveImage 메소드가 경계를 무시하는 것 같습니다.
- 위도 선을 호로 렌더링하려면 어떻게해야합니까? 누락 된 변환 설정이 있습니까?
GeoTools 8.7을 사용하고 있습니다.