目录
前言
地理信息系统(GIS)作为现代信息技术的重要组成部分,已经广泛应用于城市规划、资源管理、环境保护、交通运输等诸多领域。在GIS数据处理过程中,空间数据的分析与可视化是核心环节之一。其中,格网(Grid)作为一种重要的空间数据结构,不仅能够有效地组织和管理空间数据,还能为各种空间分析提供基础支持。特别是在处理矢量数据时,如何根据现有的Shapefile(Shp)文件生成一个完全包围的格网,成为许多GIS应用中的关键步骤。
如上图所示,我们利用GeoTools组件生成了两个不同的格网,红色的表示最小的包围格网,完全是按照目标的矢量文件的BBOX来自动生成的,虽然也能完整的生成格网。但是其外围也是有明显的凸出的,从制图的美观上来讲有所欠缺。 而图中浅蓝色生成的格网则比较规整,生成的格网较美观。生成完全包围的格网,意味着格网不仅要覆盖Shapefile中的所有几何对象,还要确保格网的边界能够完全包含这些对象,避免数据遗漏或边界截断。这一过程看似简单,实则涉及多个技术难点。首先,如何准确计算Shapefile中所有几何对象的空间范围(即边界框),是生成格网的基础。其次,如何根据边界框确定格网的尺寸和分辨率,直接影响到格网的精度和后续分析的效果。此外,在处理复杂几何对象(如多边形、多部件几何体)时,如何确保格网生成的效率和准确性,也是必须考虑的问题。
本实战将详细介绍如何基于GeoTools,根据Shapefile文件生成完全包围的格网。我们将从Shapefile的读取入手,逐步讲解如何提取几何对象的空间范围,如何根据边界框计算格网的参数,以及如何生成并输出格网数据。通过具体的代码示例和步骤解析,帮助读者掌握这一实用的GIS数据处理技术。无论是GIS开发者、数据分析师,还是对地理信息科学感兴趣的学者,都能从中获得有价值的参考和启发。
一、最小BBOX生成
其实关于根据shp文件自动生成格网信息的相关内容,在之前的博文中曾经有所提及,原文地址如下:基于Java和GeoTools的根据矢量BBOx自动生成格网文件实践。在当时的博文中曾经详细的介绍了如何根据shp文件的bbox来进行经纬度生成。后来有朋友也曾经留言,在生成的成果中,经纬格网的最外层存在着一些瑕疵,就是经纬线的技术段比较突出,闭环不够完满。为了照顾对相关生成不太了解的朋友,这里依然对相关的生成过程进行一个简单的介绍,更详细的代码可以私聊或者看之前的内容。
1、Geotools经纬线生成
这是基于Geotools来读取BBOX,然后生成对应的经纬线的流程图,这个整体流程其实是一样的。
流程步骤说明如下:
1、使用GeoTools读取矢量数据 。
2、提取矢量数据的边界框(BBOX)。
3、创建要素集合
4、生成经纬线格网(根据BBOX计算格网大小与分辨率)
5、写入到Shp矢量文件中
6、文件写入
如何生成更完美的大包围经纬线,其实也是做了一个优化,这里暂且不表,在下一节中进行详细叙述。直接读取BBOX,然后生成经纬度的核心代码如下:
/**
* 生成经纬网要素集合
* @param minLon 最小经度
* @param maxLon 最大经度
* @param minLat 最小纬度
* @param maxLat 最大纬度
* @param interval 间隔(度)
*/
private static SimpleFeatureCollection generateGraticule(double minLon, double maxLon, double minLat, double maxLat, double interval) throws SchemaException {
// 创建要素类型
SimpleFeatureType TYPE = createFeatureType();
// 存储所有要素的集合
List<SimpleFeature> features = new ArrayList<>();
// 生成经线(固定经度,纬度从 minLat 到 maxLat)
for (double lon = minLon; lon <= maxLon; lon += interval) {
LineString line = createLine(lon, minLat, lon, maxLat);
features.add(createFeature(TYPE, line, "LON", lon));
}
// 生成纬线(固定纬度,经度从 minLon 到 maxLon)
for (double lat = minLat; lat <= maxLat; lat += interval) {
LineString line = createLine(minLon, lat, maxLon, lat);
features.add(createFeature(TYPE, line, "LAT", lat));
}
return new ListFeatureCollection(TYPE, features);
}
2、实际效果
使用直接读取BBOX的方式来生成包围经纬线,其成果如下图所示:
请尤其重点查看该矢量文件的四至,也就是东南西北四个方面。在四至的顶点位置,可以看到其包围并不是那么的友好,在展示的时候有一点毛刺的感觉。如下框标识所示:
那么如何在生成图片的时候,可以进行自适应的配置呢?这也是本文的核心内容。
二、最大包围框生成
通过以上的代码和网格成果可以看到,我们生成的经纬网数据并没有很好的满足我们的需求。我们需要在生成格网时,那么包围框应该最大的实现包围。从而保证都是完整一个瓦片正方向。因此本节我们来详细说明如何生成最大包围框的知识。
1、生成范围调整
通观察和研读之前的根据BBOX来自动生成经纬度网格的程序不难发现,在之前的代码中,对生辰经纬网线的数据没有做约束,都是直接使用bbox来自动计算的,这样就特别容易出现上面的问题。因此调整的方法也比较简单,在生成的BBOX中增加冗余量,这样就可以实现一个完整的封闭正方形。因此在生成格网数据时,首先需要对数据进行一个冗余计算,关键代码如下:
/**
* 范围调整算法
* @return 调整后的 [min, max]
*/
private static double[] adjustRange(double min, double max, double interval, double lowerBound, double upperBound) {
double adjustedMin = Math.floor(min / interval) * interval;
double adjustedMax = Math.ceil(max / interval) * interval;
return new double[] {
Math.max(adjustedMin, lowerBound),
Math.min(adjustedMax, upperBound)
};
}
在经过上面的调整之后再来生成对应的经纬格网就是符合我们的预期的。在生成时进行调用的方法如下:
// 自动调整范围
double[] adjustedLon = adjustRange(minLon, maxLon, interval, -180, 180);
double[] adjustedLat = adjustRange(minLat, maxLat, interval, -90, 90);
// 生成经纬网
features = generateGraticule(
adjustedLon[0], adjustedLon[1],
adjustedLat[0], adjustedLat[1],
interval
);
// 写入文件
writeToShapefile(features, new File("D:/shp_test/自闭和adaptive_graticule.shp"));
经过上述的程序调用,就可以实现格网数据的自动扩展并且可以生成符合我们业务预期的格网数据,下一节将来展示一些最终的效果。
2、实例展示
还是以之前的区划数据为例,叠加我们的全包围数据的效果如下:
可以看到,在生成的格网中,已经非常完美的实现四至的格网闭合。至此,基本使用geotools来实现了我们的业务需求。
三、总结
以上就是文本的主要内容, 本实战将详细介绍如何基于GeoTools,根据Shapefile文件生成完全包围的格网。我们将从Shapefile的读取入手,逐步讲解如何提取几何对象的空间范围,如何根据边界框计算格网的参数,以及如何生成并输出格网数据。通过具体的代码示例和步骤解析,帮助读者掌握这一实用的GIS数据处理技术。无论是GIS开发者、数据分析师,还是对地理信息科学感兴趣的学者,都能从中获得有价值的参考和启发。文章首先介绍了如何根据BBOX来自动生成格网,带大家回顾了相关的基础知识点,接着基于BBOX来做一个冗余的计算,保障生成的结果符合我们的业务需要,弥补了之前的技术方案的不足,保证了比较好的视觉效果。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。