第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 的空间分析功能:

  1. 缓冲区分析

    • 基本缓冲区
    • 样式控制
    • 单侧缓冲区
  2. 叠加分析

    • 相交、合并、差集
    • 空间裁剪
    • 空间连接
  3. 空间查询

    • 最近邻查询
    • 空间过滤器
  4. 统计分析

    • 几何统计
    • 分组统计
  5. Process API

    • 内置处理
    • 自定义处理

关键要点

  • 使用空间索引提高查询效率
  • 合理选择空间关系类型
  • Process API 提供可重用的分析功能

← 上一章:OGC服务客户端 | 返回目录 | 下一章:性能优化与最佳实践 →

posted @ 2025-12-29 11:40  我才是银古  阅读(5)  评论(0)    收藏  举报