我正在尝试使用Geotools用H3网格定义的图块来绘制历史政治领土。我的输入shapefile使用WGS84 / EPSG:4326 CRS。 H3十六进制网格是面向中心的gnomonic投影,但我假设它们仍使用WGS84 CRS。 (据我所知,这仅是Kevin Sahr在DGGS软件中使用的,该软件启发了H3项目。)
我得到一些奇怪的结果,我怀疑问题是因为我没有在我的方法中处理侏儒投影。既不放置六边形,也不将生成的多边形保存在shapefile输出中。
这是我的方法:
h3.polyfillAddress()
方法提取边界以收集分辨率为3(或在某些情况下为4)的该边界的六边形SimpleFeatureTypeBuilder
输入多边形的geojson输入位于:https://pastebin.com/wH1SgCY8
H3磁贴的geojson输出位于:https://pastebin.com/0Zuc7awv
地图中心附近的shapefile(使用QGIS查看的Prime Meridian / Equator)似乎是正确的,但离中心较远的地方却得到了奇怪的结果。投影显然是一个问题,但是我不知道奇怪的填充结果是由H3的填充方法的某些限制引起的,还是因为在尝试进行填充操作之前应该已经处理了输入边界的投影。
我的SimpleFeatureTypeBuilder使用WGS84 CRS指定输出。在构建每个多边形之前,我应该对它们进行一些变换吗?
代码如下:
private static void saveShapefile(String name, String abb, Set<String> hexes) throws IOException {
/*
Takes a country name, it's abbreviation and a set of hexagons that will represent it and writes out a shapefile
*/
String filename = "src/main/data/hexMaps/politicalBoundaryHexes_" + yearString + "_" + name + ".shp";
File file = new File(filename);
H3Core h3 = H3Core.newInstance();
List<SimpleFeature> features = new ArrayList<>();
GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();
DefaultFeatureCollection output = new DefaultFeatureCollection();
final SimpleFeatureType HEX = createFeatureType();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(HEX);
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
Map<String, Serializable> params = new HashMap<>();
params.put("url", file.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
dataStore.createSchema(HEX);
int index = 0;
for (String h:hexes) {
List<GeoCoord> geocoords = h3.h3ToGeoBoundary(h);
int numVerts = geocoords.size();
Coordinate[] coordinates = new Coordinate[numVerts + 1];
if(debugging){System.out.println("Processing hex " + index + ", @ " + h);}
for (int i=0; i<geocoords.size(); i++){
coordinates[i] = new Coordinate(geocoords.get(i).lat, geocoords.get(i).lng);
}
coordinates[numVerts] = new Coordinate(geocoords.get(0).lat, geocoords.get(0).lng);
Polygon polygon = gf.createPolygon(coordinates);
Object[] values = new Object[]{polygon, index, h};
index++;
featureBuilder.addAll(values);
SimpleFeature polyFeature = featureBuilder.buildFeature(h);
features.add(polyFeature);
}
org.geotools.data.Transaction transaction = new DefaultTransaction("create");
String typeName = dataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
if (featureSource instanceof SimpleFeatureStore) {
SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
SimpleFeatureCollection collection = new ListFeatureCollection(HEX, features);
featureStore.setTransaction(transaction);
try {
featureStore.addFeatures(collection);
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
} finally {
transaction.close();
}
} else {
System.out.println("Writing the Shapefile failed.");
System.exit(1); // Failure!
}
}
private static SimpleFeatureType createFeatureType() {
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("polygon");
builder.setCRS(DefaultGeographicCRS.WGS84);
builder.add("the_geom", Polygon.class);
builder.add("id", Long.class);
builder.add("address", String.class);
final SimpleFeatureType TYPE = builder.buildFeatureType();
return TYPE;
}