264 lines
9.3 KiB
Markdown
264 lines
9.3 KiB
Markdown
---
|
||
title: GeoTools 矢量网格(Vector Grid)
|
||
date: 2023-12-20
|
||
author: ac
|
||
categories:
|
||
- GIS
|
||
tags:
|
||
- GeoTools
|
||
---
|
||
|
||
## GeoTools 矢量网格(Vector Grid)
|
||
|
||
### 1.简介
|
||
|
||
`GeoTools` 的矢量网格化操作是
|
||
|
||
GeoTools矢量网格类使得创建由多边形或线元素组成的矢量网格(也称为网格)变得容易,其中每一个都表示为SimpleFeature。可以使用grids或Lines实用程序类轻松生成简单的网格,而当需要对网格布局和属性进行更多控制时,可以使用较低级别的类。
|
||
|
||
> 网格是在内存中构建的,整个网格一次构建。
|
||
|
||
|
||
|
||
### 2.添加依赖
|
||
|
||
```xml
|
||
<dependency>
|
||
<groupId>org.geotools</groupId>
|
||
<artifactId>gt-grid</artifactId>
|
||
<version>${geotools.version}</version>
|
||
</dependency>
|
||
```
|
||
|
||
|
||
|
||
### 3. Polygon grids
|
||
|
||
Grids实用类提供了创建**矩形**或**六边形**元素网格的方法。
|
||
|
||
创建基本网格的最简单方法是使用Grids实用程序类中的静态方法。下面的例子创建了一个经纬度网格,其宽度为10度,用于显示在浙江地图上:
|
||
|
||
```java
|
||
public class Le08PolygonGrids {
|
||
public static void main(String[] args) {
|
||
String path = "D:\\demo\\tutorial\\data\\china\\zhejiang.shp";
|
||
Le08PolygonGrids.readShpFile(path);
|
||
}
|
||
public static void readShpFile(String shpPath) {
|
||
File shpFile = new File(shpPath);
|
||
try {
|
||
ShapefileDataStore shapefileDataStore = new ShapefileDataStore(shpFile.toURI().toURL());
|
||
// 设置编码,防止属性的中文字符出现乱码
|
||
shapefileDataStore.setCharset(Charset.forName("UTF-8"));
|
||
// 这个typeNamae不传递,默认是文件名称
|
||
FeatureSource featuresource = shapefileDataStore.getFeatureSource(shapefileDataStore.getTypeNames()[0]);
|
||
// 读取bbox
|
||
ReferencedEnvelope bbox =featuresource.getBounds();
|
||
// 创建grids,0.2度为间隔
|
||
SimpleFeatureSource grid = Grids.createSquareGrid(bbox, 0.2);
|
||
|
||
// Create a map content and add our shapefile to it
|
||
MapContent map = new MapContent();
|
||
map.setTitle("polygon grids");
|
||
// 添加shp到map中
|
||
Style style = SLD.createSimpleStyle(featuresource.getSchema());
|
||
Layer layer = new FeatureLayer(featuresource, style);
|
||
map.addLayer(layer);
|
||
|
||
Style styleBox = SLD.createSimpleStyle(grid.getSchema());
|
||
Layer layerBox = new FeatureLayer(grid, styleBox);
|
||
map.addLayer(layerBox);
|
||
|
||
// Now display the map
|
||
JMapFrame.showMap(map);
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
System.out.println("读取完成!");
|
||
}
|
||
}
|
||
```
|
||
|
||
<img src="./images/image-20231220143856023.png" alt="image-20231220143856023" style="zoom:80%;width:50%" /><img src="./images/image-20231220144056349.png" alt="image-20231220144056349" style="zoom:80%;width:50%" />
|
||
|
||
创建的网格由`SimpleFeatures`组成,每个`SimpleFeatures`都有一个最小多边形,即一个由四个角顶点表示的多边形。
|
||
|
||
**选择性创建**
|
||
|
||
新建一个网格生成类,继承`GridFeatureBuilder`,重写`getCreateFeature`方法来过滤与原数据要素不重叠得网格。
|
||
|
||
```java
|
||
package learning.tools;
|
||
|
||
import java.io.IOException;
|
||
import java.util.Map;
|
||
import org.geotools.api.data.SimpleFeatureSource;
|
||
import org.geotools.api.feature.simple.SimpleFeatureType;
|
||
import org.geotools.api.filter.Filter;
|
||
import org.geotools.api.filter.FilterFactory;
|
||
import org.geotools.factory.CommonFactoryFinder;
|
||
import org.geotools.geometry.jts.JTSFactoryFinder;
|
||
import org.geotools.grid.GridElement;
|
||
import org.geotools.grid.GridFeatureBuilder;
|
||
import org.geotools.grid.PolygonElement;
|
||
import org.locationtech.jts.geom.Coordinate;
|
||
import org.locationtech.jts.geom.Geometry;
|
||
import org.locationtech.jts.geom.GeometryFactory;
|
||
|
||
public class IntersectionBuilder extends GridFeatureBuilder {
|
||
final FilterFactory ff2 = CommonFactoryFinder.getFilterFactory();
|
||
final GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();
|
||
|
||
final SimpleFeatureSource source;
|
||
int id = 0;
|
||
|
||
public IntersectionBuilder(SimpleFeatureType type, SimpleFeatureSource source) {
|
||
super(type);
|
||
this.source = source;
|
||
}
|
||
|
||
public void setAttributes(GridElement el, Map<String, Object> attributes) {
|
||
attributes.put("id", ++id);
|
||
}
|
||
|
||
@Override
|
||
public boolean getCreateFeature(GridElement el) {
|
||
Coordinate c = ((PolygonElement) el).getCenter();
|
||
Geometry p = gf.createPoint(c);
|
||
Filter filter = ff2.intersects(ff2.property("the_geom"), ff2.literal(p));
|
||
boolean result = false;
|
||
|
||
try {
|
||
result = !source.getFeatures(filter).isEmpty();
|
||
} catch (IOException ex) {
|
||
throw new IllegalStateException(ex);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|
||
```
|
||
|
||
```java
|
||
package learning;
|
||
|
||
import learning.tools.IntersectionBuilder;
|
||
import org.geotools.api.data.FeatureSource;
|
||
import org.geotools.api.data.Query;
|
||
import org.geotools.api.data.SimpleFeatureSource;
|
||
import org.geotools.api.feature.simple.SimpleFeature;
|
||
import org.geotools.api.feature.simple.SimpleFeatureType;
|
||
import org.geotools.api.feature.type.AttributeDescriptor;
|
||
import org.geotools.api.feature.type.GeometryType;
|
||
import org.geotools.api.geometry.BoundingBox;
|
||
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
|
||
import org.geotools.api.style.Style;
|
||
import org.geotools.data.shapefile.ShapefileDataStore;
|
||
import org.geotools.data.simple.SimpleFeatureCollection;
|
||
import org.geotools.data.simple.SimpleFeatureIterator;
|
||
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
|
||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||
import org.geotools.grid.GridElement;
|
||
import org.geotools.grid.GridFeatureBuilder;
|
||
import org.geotools.grid.Grids;
|
||
import org.geotools.grid.PolygonElement;
|
||
import org.geotools.map.FeatureLayer;
|
||
import org.geotools.map.Layer;
|
||
import org.geotools.map.MapContent;
|
||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||
import org.geotools.styling.SLD;
|
||
import org.geotools.swing.JMapFrame;
|
||
import org.locationtech.jts.geom.Geometry;
|
||
import org.locationtech.jts.geom.Polygon;
|
||
|
||
import java.awt.*;
|
||
import java.io.File;
|
||
import java.io.IOException;
|
||
import java.nio.charset.Charset;
|
||
import java.util.LinkedList;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* @author ac
|
||
* @date 2023/12/20 13:54
|
||
*/
|
||
public class Le08PolygonGrids {
|
||
public static void main(String[] args) {
|
||
String path = "D:\\demo\\tutorial\\data\\china\\zhejiang.shp";
|
||
Le08PolygonGrids.readShpFile(path);
|
||
}
|
||
public static void readShpFile(String shpPath) {
|
||
File shpFile = new File(shpPath);
|
||
try {
|
||
ShapefileDataStore shapefileDataStore = new ShapefileDataStore(shpFile.toURI().toURL());
|
||
// 设置编码,防止属性的中文字符出现乱码
|
||
shapefileDataStore.setCharset(Charset.forName("UTF-8"));
|
||
// 这个typeNamae不传递,默认是文件名称
|
||
FeatureSource featuresource = shapefileDataStore.getFeatureSource(shapefileDataStore.getTypeNames()[0]);
|
||
// 读取bbox
|
||
ReferencedEnvelope bbox =featuresource.getBounds();
|
||
Double sideLen = 0.2;
|
||
|
||
// 创建网格
|
||
// 新建一份面要素shp,名叫grid,有两个字段id,the_geom
|
||
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
|
||
tb.setName("grid");
|
||
tb.add(
|
||
GridFeatureBuilder.DEFAULT_GEOMETRY_ATTRIBUTE_NAME,
|
||
Polygon.class,
|
||
bbox.getCoordinateReferenceSystem());
|
||
tb.add("id", Integer.class);
|
||
SimpleFeatureType TYPE = tb.buildFeatureType();
|
||
|
||
// Build the grid the custom feature builder class
|
||
GridFeatureBuilder builder = new IntersectionBuilder(TYPE, (SimpleFeatureSource)featuresource);
|
||
SimpleFeatureSource grid = Grids.createHexagonalGrid(bbox, sideLen, -1, builder);
|
||
|
||
// Create a map content and add our shapefile to it
|
||
MapContent map = new MapContent();
|
||
map.setTitle("polygon grids");
|
||
// 添加shp到map中
|
||
Style style = SLD.createSimpleStyle(featuresource.getSchema());
|
||
Layer layer = new FeatureLayer(featuresource, style);
|
||
map.addLayer(layer);
|
||
|
||
Style styleBox = SLD.createSimpleStyle(grid.getSchema());
|
||
Layer layerBox = new FeatureLayer(grid, styleBox);
|
||
map.addLayer(layerBox);
|
||
|
||
// Now display the map
|
||
JMapFrame.showMap(map);
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
System.out.println("读取完成!");
|
||
}
|
||
}
|
||
|
||
```
|
||
|
||

|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
### 4.属性渲染
|
||
|
||
到目前为止,没有一个示例需要为矢量网格指定 feature type特征类型。相反,我们用两个属性创建了一个默认的 feature type特性类型:
|
||
|
||
- ‘element’ (the Polygon instance)
|
||
- ‘id’ (a sequential integer ID value.
|
||
|
||
当然,您也可以提供自己的特性类型,以便将其他属性与网格元素关联起来。要做到这一点,你需要重写GridFeatureBuilder类的setAttributes方法。下面的例子创建了一个带有' color '属性的特性类型。然后根据网格中每个六边形元素的位置设置颜色值:
|
||
|
||
|
||
|
||
|
||
|