第14章 - 空间分析与处理
第14章 - 空间分析与处理
14.1 空间分析概述
14.1.1 分析类型
┌─────────────────────────────────────────────────────────────────────┐
│ 空间分析类型 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 几何操作 空间查询 │
│ ├── 缓冲区 (Buffer) ├── 空间过滤 │
│ ├── 合并 (Union) ├── 最近邻查询 │
│ ├── 相交 (Intersection) └── 距离查询 │
│ ├── 差集 (Difference) │
│ └── 凸包 (ConvexHull) 叠加分析 │
│ ├── 相交分析 │
│ 拓扑分析 ├── 联合分析 │
│ ├── 空间关系判断 └── 裁剪分析 │
│ ├── 拓扑验证 │
│ └── 拓扑修复 网络分析 │
│ ├── 最短路径 │
│ 统计分析 └── 服务区分析 │
│ ├── 面积统计 │
│ └── 长度统计 │
│ │
└─────────────────────────────────────────────────────────────────────┘
14.2 缓冲区分析
14.2.1 基本缓冲区
public class BufferAnalysis {
// 点缓冲区
public static Geometry pointBuffer(Point point, double distance) {
return point.buffer(distance);
}
// 线缓冲区
public static Geometry lineBuffer(LineString line, double distance) {
return line.buffer(distance);
}
// 面缓冲区(外扩)
public static Geometry polygonBuffer(Polygon polygon, double distance) {
return polygon.buffer(distance);
}
// 面缓冲区(内缩)
public static Geometry polygonShrink(Polygon polygon, double distance) {
return polygon.buffer(-distance); // 负值表示内缩
}
// 控制缓冲区质量
public static Geometry qualityBuffer(Geometry geom, double distance,
int quadrantSegments) {
// quadrantSegments: 每象限的线段数,值越大越圆滑
return geom.buffer(distance, quadrantSegments);
}
// 不同端点样式的缓冲区
public static Geometry styledBuffer(LineString line, double distance,
int capStyle, int joinStyle) {
BufferParameters params = new BufferParameters();
params.setEndCapStyle(capStyle); // CAP_ROUND, CAP_FLAT, CAP_SQUARE
params.setJoinStyle(joinStyle); // JOIN_ROUND, JOIN_MITRE, JOIN_BEVEL
return BufferOp.bufferOp(line, distance, params);
}
// 单侧缓冲区
public static Geometry singleSideBuffer(LineString line, double distance,
boolean leftSide) {
BufferParameters params = new BufferParameters();
params.setSingleSided(true);
double d = leftSide ? distance : -distance;
return BufferOp.bufferOp(line, d, params);
}
}
14.2.2 要素集合缓冲区
public class CollectionBuffer {
public static SimpleFeatureCollection bufferCollection(
SimpleFeatureCollection features, double distance) throws Exception {
SimpleFeatureType originalType = features.getSchema();
// 创建结果类型
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.setName(originalType.getTypeName() + "_buffer");
typeBuilder.setCRS(originalType.getCoordinateReferenceSystem());
typeBuilder.add("the_geom", Polygon.class);
// 复制原有属性
for (AttributeDescriptor desc : originalType.getAttributeDescriptors()) {
if (!(desc instanceof GeometryDescriptor)) {
typeBuilder.add(desc);
}
}
SimpleFeatureType resultType = typeBuilder.buildFeatureType();
// 创建缓冲区
DefaultFeatureCollection result = new DefaultFeatureCollection();
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);
try (SimpleFeatureIterator iter = features.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
Geometry buffer = geom.buffer(distance);
builder.add(buffer);
for (int i = 0; i < feature.getAttributeCount(); i++) {
if (!(feature.getAttribute(i) instanceof Geometry)) {
builder.add(feature.getAttribute(i));
}
}
result.add(builder.buildFeature(null));
}
}
return result;
}
}
14.3 叠加分析
14.3.1 相交分析
public class OverlayAnalysis {
// 两个几何的交集
public static Geometry intersection(Geometry geom1, Geometry geom2) {
return geom1.intersection(geom2);
}
// 要素裁剪
public static SimpleFeatureCollection clipFeatures(
SimpleFeatureCollection features, Geometry clipGeom) throws Exception {
DefaultFeatureCollection result = new DefaultFeatureCollection();
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(features.getSchema());
try (SimpleFeatureIterator iter = features.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
if (geom.intersects(clipGeom)) {
Geometry clipped = geom.intersection(clipGeom);
if (!clipped.isEmpty()) {
for (int i = 0; i < feature.getAttributeCount(); i++) {
Object attr = feature.getAttribute(i);
if (attr instanceof Geometry) {
builder.add(clipped);
} else {
builder.add(attr);
}
}
result.add(builder.buildFeature(null));
}
}
}
}
return result;
}
// 合并几何
public static Geometry union(List<Geometry> geometries) {
return CascadedPolygonUnion.union(geometries);
}
// 差集
public static Geometry difference(Geometry geom1, Geometry geom2) {
return geom1.difference(geom2);
}
// 对称差集
public static Geometry symmetricDifference(Geometry geom1, Geometry geom2) {
return geom1.symDifference(geom2);
}
}
14.3.2 空间连接
public class SpatialJoin {
public static SimpleFeatureCollection spatialJoin(
SimpleFeatureCollection target,
SimpleFeatureCollection join,
String joinType) throws Exception { // "intersects", "contains", "within"
// 构建空间索引
STRtree index = new STRtree();
Map<Envelope, SimpleFeature> joinFeatures = new HashMap<>();
try (SimpleFeatureIterator iter = join.features()) {
while (iter.hasNext()) {
SimpleFeature f = iter.next();
Geometry g = (Geometry) f.getDefaultGeometry();
Envelope env = g.getEnvelopeInternal();
index.insert(env, f);
joinFeatures.put(env, f);
}
}
index.build();
// 构建结果类型
SimpleFeatureType targetType = target.getSchema();
SimpleFeatureType joinTypeDef = join.getSchema();
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.init(targetType);
for (AttributeDescriptor desc : joinTypeDef.getAttributeDescriptors()) {
if (!(desc instanceof GeometryDescriptor)) {
String name = "join_" + desc.getLocalName();
typeBuilder.add(name, desc.getType().getBinding());
}
}
SimpleFeatureType resultType = typeBuilder.buildFeatureType();
DefaultFeatureCollection result = new DefaultFeatureCollection();
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);
// 执行连接
try (SimpleFeatureIterator iter = target.features()) {
while (iter.hasNext()) {
SimpleFeature targetFeature = iter.next();
Geometry targetGeom = (Geometry) targetFeature.getDefaultGeometry();
// 查询候选
List<?> candidates = index.query(targetGeom.getEnvelopeInternal());
for (Object candidate : candidates) {
SimpleFeature joinFeature = (SimpleFeature) candidate;
Geometry joinGeom = (Geometry) joinFeature.getDefaultGeometry();
boolean matches = false;
switch (joinType) {
case "intersects":
matches = targetGeom.intersects(joinGeom);
break;
case "contains":
matches = targetGeom.contains(joinGeom);
break;
case "within":
matches = targetGeom.within(joinGeom);
break;
}
if (matches) {
// 复制目标属性
for (int i = 0; i < targetFeature.getAttributeCount(); i++) {
builder.add(targetFeature.getAttribute(i));
}
// 复制连接属性
for (int i = 0; i < joinFeature.getAttributeCount(); i++) {
if (!(joinFeature.getAttribute(i) instanceof Geometry)) {
builder.add(joinFeature.getAttribute(i));
}
}
result.add(builder.buildFeature(null));
}
}
}
}
return result;
}
}
14.4 空间查询
14.4.1 最近邻查询
public class NearestNeighbor {
// 查找最近的要素
public static SimpleFeature findNearest(SimpleFeatureCollection features,
Geometry queryGeom) throws Exception {
SimpleFeature nearest = null;
double minDistance = Double.MAX_VALUE;
try (SimpleFeatureIterator iter = features.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
double distance = queryGeom.distance(geom);
if (distance < minDistance) {
minDistance = distance;
nearest = feature;
}
}
}
return nearest;
}
// 使用空间索引的最近邻查询
public static SimpleFeature findNearestWithIndex(STRtree index,
Point queryPoint) {
Object nearest = index.nearestNeighbour(
queryPoint.getEnvelopeInternal(),
queryPoint,
new ItemDistance() {
@Override
public double distance(ItemBoundable item1, ItemBoundable item2) {
Geometry g1 = (Geometry) item1.getItem();
Geometry g2 = (Geometry) item2.getItem();
return g1.distance(g2);
}
}
);
return (SimpleFeature) nearest;
}
// 查找距离范围内的所有要素
public static List<SimpleFeature> findWithinDistance(
SimpleFeatureCollection features,
Geometry queryGeom, double distance) throws Exception {
List<SimpleFeature> result = new ArrayList<>();
// 先用缓冲区粗筛
Geometry buffer = queryGeom.buffer(distance);
try (SimpleFeatureIterator iter = features.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
if (geom.intersects(buffer) && queryGeom.distance(geom) <= distance) {
result.add(feature);
}
}
}
return result;
}
}
14.4.2 空间过滤器
public class SpatialFilters {
private static final FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// BBOX 过滤
public static Filter createBBoxFilter(String geomProperty,
double minX, double minY, double maxX, double maxY, String srs) {
return ff.bbox(ff.property(geomProperty), minX, minY, maxX, maxY, srs);
}
// 相交过滤
public static Filter createIntersectsFilter(String geomProperty, Geometry geom) {
return ff.intersects(ff.property(geomProperty), ff.literal(geom));
}
// 包含过滤
public static Filter createContainsFilter(String geomProperty, Geometry geom) {
return ff.contains(ff.property(geomProperty), ff.literal(geom));
}
// 在...内部
public static Filter createWithinFilter(String geomProperty, Geometry geom) {
return ff.within(ff.property(geomProperty), ff.literal(geom));
}
// 距离过滤
public static Filter createDWithinFilter(String geomProperty,
Geometry geom, double distance, String units) {
return ff.dwithin(ff.property(geomProperty), ff.literal(geom),
distance, units);
}
// 超出距离
public static Filter createBeyondFilter(String geomProperty,
Geometry geom, double distance, String units) {
return ff.beyond(ff.property(geomProperty), ff.literal(geom),
distance, units);
}
}
14.5 统计分析
14.5.1 几何统计
public class GeometryStatistics {
// 计算面积统计
public static Map<String, Double> calculateAreaStats(
SimpleFeatureCollection features) throws Exception {
double totalArea = 0;
double minArea = Double.MAX_VALUE;
double maxArea = 0;
int count = 0;
try (SimpleFeatureIterator iter = features.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
double area = geom.getArea();
totalArea += area;
minArea = Math.min(minArea, area);
maxArea = Math.max(maxArea, area);
count++;
}
}
Map<String, Double> stats = new HashMap<>();
stats.put("total", totalArea);
stats.put("min", minArea);
stats.put("max", maxArea);
stats.put("mean", count > 0 ? totalArea / count : 0);
stats.put("count", (double) count);
return stats;
}
// 按属性分组统计
public static Map<Object, Double> groupBySum(SimpleFeatureCollection features,
String groupField, String sumField) throws Exception {
Map<Object, Double> result = new HashMap<>();
try (SimpleFeatureIterator iter = features.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Object groupValue = feature.getAttribute(groupField);
double sumValue = ((Number) feature.getAttribute(sumField)).doubleValue();
result.merge(groupValue, sumValue, Double::sum);
}
}
return result;
}
}
14.6 Process API
14.6.1 使用内置处理
import org.geotools.process.vector.VectorProcess;
public class ProcessExample {
// 使用缓冲区处理
public static SimpleFeatureCollection bufferProcess(
SimpleFeatureCollection features, double distance) throws Exception {
BufferProcess process = new BufferProcess();
Map<String, Object> input = new HashMap<>();
input.put(BufferProcess.INPUT.key, features);
input.put(BufferProcess.DISTANCE.key, distance);
Map<String, Object> result = process.execute(input, null);
return (SimpleFeatureCollection) result.get(BufferProcess.RESULT.key);
}
// 点聚合处理
public static SimpleFeatureCollection pointStacker(
SimpleFeatureCollection features, int cellSize) throws Exception {
PointStackerProcess process = new PointStackerProcess();
Map<String, Object> input = new HashMap<>();
input.put("data", features);
input.put("cellSize", cellSize);
Map<String, Object> result = process.execute(input, null);
return (SimpleFeatureCollection) result.get("result");
}
}
14.7 本章小结
本章详细介绍了 GeoTools 的空间分析功能:
-
缓冲区分析
- 基本缓冲区
- 样式控制
- 单侧缓冲区
-
叠加分析
- 相交、合并、差集
- 空间裁剪
- 空间连接
-
空间查询
- 最近邻查询
- 空间过滤器
-
统计分析
- 几何统计
- 分组统计
-
Process API
- 内置处理
- 自定义处理
关键要点
- 使用空间索引提高查询效率
- 合理选择空间关系类型
- Process API 提供可重用的分析功能

浙公网安备 33010602011771号