第07章 - 几何处理与空间分析
第07章 - 几何处理与空间分析
7.1 GeometryUtil概述
7.1.1 设计理念
GeometryUtil是OGU4J的几何处理核心类,基于以下设计理念:
- 双重API:同时提供基于JTS Geometry对象和基于WKT字符串的方法
- 功能全面:覆盖格式转换、空间关系、空间分析、几何属性等
- 易于使用:静态方法,无需实例化
- 线程安全:所有方法都是无状态的
7.1.2 API分类
GeometryUtil
├── 格式转换
│ ├── WKT ↔ Geometry
│ ├── GeoJSON ↔ Geometry
│ ├── ESRI JSON ↔ Geometry
│ └── WKT ↔ GeoJSON ↔ ESRI JSON
├── 空间关系(基于JTS)
│ ├── intersects, contains, within
│ ├── touches, crosses, overlaps
│ ├── disjoint, equals
│ └── relate, relatePattern
├── 空间关系(基于WKT/ESRI)
│ └── xxxWkt 方法
├── 空间分析
│ ├── buffer, intersection, union
│ ├── difference, symDifference
│ ├── convexHull, concaveHull
│ └── splitPolygon, polygonize
├── 几何属性
│ ├── area, length
│ ├── centroid, interiorPoint
│ ├── dimension, numPoints
│ └── boundary, envelope
└── 几何验证
├── isValid, isSimple
├── validate, simplify
└── densify
7.2 格式转换
7.2.1 WKT与Geometry互转
import com.znlgis.ogu4j.geometry.GeometryUtil;
import org.locationtech.jts.geom.Geometry;
// WKT转Geometry
String wkt = "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))";
Geometry geom = GeometryUtil.wkt2Geometry(wkt);
// Geometry转WKT
String wktOutput = GeometryUtil.geometry2Wkt(geom);
// 各种几何类型的WKT示例
String pointWkt = "POINT(116.4 39.9)";
String lineWkt = "LINESTRING(0 0, 10 10, 20 0)";
String polygonWkt = "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))";
String multiPointWkt = "MULTIPOINT((0 0), (10 10), (20 20))";
String multiLineWkt = "MULTILINESTRING((0 0, 10 10), (20 20, 30 30))";
String multiPolygonWkt = "MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0)), " +
"((20 20, 20 30, 30 30, 30 20, 20 20)))";
// 带洞多边形
String polygonWithHoleWkt = "POLYGON((0 0, 0 100, 100 100, 100 0, 0 0), " +
"(20 20, 20 80, 80 80, 80 20, 20 20))";
7.2.2 GeoJSON与Geometry互转
// GeoJSON转Geometry
String geojson = "{\"type\":\"Point\",\"coordinates\":[116.4,39.9]}";
Geometry geom = GeometryUtil.geojson2Geometry(geojson);
// Geometry转GeoJSON
String output = GeometryUtil.geometry2Geojson(geom);
// 复杂几何的GeoJSON
String polygonGeojson = "{" +
"\"type\":\"Polygon\"," +
"\"coordinates\":[[[0,0],[0,10],[10,10],[10,0],[0,0]]]" +
"}";
Geometry polygon = GeometryUtil.geojson2Geometry(polygonGeojson);
7.2.3 ESRI JSON与其他格式互转
// WKT转ESRI JSON
int wkid = 4490; // CGCS2000
String wkt = "POLYGON((116 39, 116 40, 117 40, 117 39, 116 39))";
String esriJson = GeometryUtil.wkt2EsriJson(wkt, wkid);
// ESRI JSON转WKT
String wktBack = GeometryUtil.esriJson2Wkt(esriJson);
// GeoJSON与ESRI JSON互转
String geojson = "{\"type\":\"Point\",\"coordinates\":[116.4,39.9]}";
String esriJsonFromGeo = GeometryUtil.geoJson2EsriJson(wkid, geojson);
String geojsonBack = GeometryUtil.esriJson2GeoJson(esriJsonFromGeo);
// ESRI JSON与Geometry互转
Geometry geom = GeometryUtil.esriJson2Geometry(esriJson);
String esriJsonFromGeom = GeometryUtil.geometry2EsriJson(geom, wkid);
7.2.4 WKT与GeoJSON直接转换
// WKT转GeoJSON(无需先转Geometry)
String wkt = "POINT(116.4 39.9)";
String geojson = GeometryUtil.wkt2Geojson(wkt);
// GeoJSON转WKT
String wktBack = GeometryUtil.geojson2Wkt(geojson);
7.3 空间关系判断
7.3.1 基于JTS Geometry的方法
// 创建测试几何
Geometry geomA = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
Geometry geomB = GeometryUtil.wkt2Geometry(
"POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))");
Geometry geomC = GeometryUtil.wkt2Geometry(
"POLYGON((20 20, 20 30, 30 30, 30 20, 20 20))");
// 相交判断 - 两个几何是否有公共点
boolean intersects = GeometryUtil.intersects(geomA, geomB); // true
boolean intersectsC = GeometryUtil.intersects(geomA, geomC); // false
// 包含判断 - A是否完全包含B
Geometry smallGeom = GeometryUtil.wkt2Geometry(
"POLYGON((2 2, 2 8, 8 8, 8 2, 2 2))");
boolean contains = GeometryUtil.contains(geomA, smallGeom); // true
// 在内判断 - A是否完全在B内部
boolean within = GeometryUtil.within(smallGeom, geomA); // true
// 相接判断 - 只在边界相接
Geometry touchGeom = GeometryUtil.wkt2Geometry(
"POLYGON((10 0, 10 10, 20 10, 20 0, 10 0))");
boolean touches = GeometryUtil.touches(geomA, touchGeom); // true
// 交叉判断 - 线穿过面
Geometry line = GeometryUtil.wkt2Geometry("LINESTRING(5 -5, 5 15)");
boolean crosses = GeometryUtil.crosses(line, geomA); // true
// 重叠判断 - 部分重叠
boolean overlaps = GeometryUtil.overlaps(geomA, geomB); // true
// 分离判断 - 完全不相交
boolean disjoint = GeometryUtil.disjoint(geomA, geomC); // true
// 相等判断
Geometry geomACopy = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
boolean equals = GeometryUtil.equalsTopo(geomA, geomACopy); // true
7.3.2 各种相等判断
Geometry g1 = GeometryUtil.wkt2Geometry("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
Geometry g2 = GeometryUtil.wkt2Geometry("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))");
// 精确相等 - 坐标顺序完全相同
boolean exactEquals = GeometryUtil.equalsExact(g1, g2); // false
// 精确相等(带容差)
boolean exactTol = GeometryUtil.equalsExactTolerance(g1, g2, 0.001);
// 规范化相等 - 规范化后比较
boolean normEquals = GeometryUtil.equalsNorm(g1, g2); // true
// 拓扑相等 - 表示相同的点集
boolean topoEquals = GeometryUtil.equalsTopo(g1, g2); // true
7.3.3 DE-9IM关系模式
Geometry geomA = GeometryUtil.wkt2Geometry("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
Geometry geomB = GeometryUtil.wkt2Geometry("POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))");
// 获取DE-9IM矩阵
String matrix = GeometryUtil.relate(geomA, geomB);
System.out.println("DE-9IM: " + matrix); // 输出: 212101212
// 使用模式匹配
boolean matches = GeometryUtil.relatePattern(geomA, geomB, "T*T***FF*");
7.3.4 基于WKT的方法(使用ESRI API)
String wktA = "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))";
String wktB = "POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))";
int wkid = 4490;
// 空间关系判断
boolean intersects = GeometryUtil.intersectsWkt(wktA, wktB, wkid);
boolean contains = GeometryUtil.containsWkt(wktA, wktB, wkid);
boolean within = GeometryUtil.withinWkt(wktA, wktB, wkid);
boolean disjoint = GeometryUtil.disjointWkt(wktA, wktB, wkid);
boolean touches = GeometryUtil.touchesWkt(wktA, wktB, wkid);
boolean crosses = GeometryUtil.crossesWkt(wktA, wktB, wkid);
boolean overlaps = GeometryUtil.overlapsWkt(wktA, wktB, wkid);
boolean equals = GeometryUtil.equalsWkt(wktA, wktB, wkid);
// 模式匹配
boolean pattern = GeometryUtil.relatePatternWkt(wktA, wktB, wkid, "T*T***FF*");
7.4 空间分析
7.4.1 缓冲区分析
// 基于Geometry
Geometry point = GeometryUtil.wkt2Geometry("POINT(116.4 39.9)");
Geometry buffer = GeometryUtil.buffer(point, 0.01); // 缓冲距离
Geometry line = GeometryUtil.wkt2Geometry("LINESTRING(0 0, 10 10)");
Geometry lineBuffer = GeometryUtil.buffer(line, 2.0);
// 基于WKT
String wkt = "POINT(116.4 39.9)";
String bufferWkt = GeometryUtil.bufferWkt(wkt, 4490, 0.01);
7.4.2 交集/并集/差集
Geometry geomA = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
Geometry geomB = GeometryUtil.wkt2Geometry(
"POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))");
// 交集 - 公共部分
Geometry intersection = GeometryUtil.intersection(geomA, geomB);
System.out.println("交集: " + intersection.toText());
// POLYGON ((5 5, 5 10, 10 10, 10 5, 5 5))
// 并集 - 合并
Geometry union = GeometryUtil.union(geomA, geomB);
System.out.println("并集: " + union.toText());
// 差集 - A减去B
Geometry difference = GeometryUtil.difference(geomA, geomB);
System.out.println("差集: " + difference.toText());
// 对称差 - 两个几何的非公共部分
Geometry symDiff = GeometryUtil.symDifference(geomA, geomB);
System.out.println("对称差: " + symDiff.toText());
7.4.3 基于WKT的空间分析
String wktA = "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))";
String wktB = "POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))";
int wkid = 4490;
// 交集
String intersection = GeometryUtil.intersectionWkt(wktA, wktB, wkid);
// 差集
String difference = GeometryUtil.differenceWkt(wktA, wktB, wkid);
// 对称差
String symDiff = GeometryUtil.symDifferenceWkt(wktA, wktB, wkid);
// 并集(支持多个几何)
List<String> wktList = Arrays.asList(wktA, wktB);
String union = GeometryUtil.unionWkt(wktList, wkid);
// 缓冲区
String buffer = GeometryUtil.bufferWkt(wktA, wkid, 1.0);
7.4.4 凸包与凹包
// 凸包 - 最小凸多边形
Geometry points = GeometryUtil.wkt2Geometry(
"MULTIPOINT((0 0), (0 10), (10 10), (10 0), (5 5))");
Geometry convexHull = GeometryUtil.convexHull(points);
System.out.println("凸包: " + convexHull.toText());
// 凹包 - 考虑凹入部分的外包
Geometry concaveHull = GeometryUtil.concaveHull(points);
System.out.println("凹包: " + concaveHull.toText());
// 基于WKT的凸包
String wkt = "MULTIPOINT((0 0), (0 10), (10 10), (10 0), (5 5))";
String convexHullWkt = GeometryUtil.convexHullWkt(wkt);
7.4.5 多边形分割
// 使用线分割多边形
Geometry polygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
Geometry splitLine = GeometryUtil.wkt2Geometry(
"LINESTRING(5 -1, 5 11)");
Geometry result = GeometryUtil.splitPolygon(polygon, splitLine);
System.out.println("分割结果: " + result.toText());
// GEOMETRYCOLLECTION (POLYGON(...), POLYGON(...))
7.4.6 多边形化
// 从线构建多边形
Geometry lines = GeometryUtil.wkt2Geometry(
"MULTILINESTRING(" +
"(0 0, 0 10), (0 10, 10 10), (10 10, 10 0), (10 0, 0 0)" +
")");
Geometry polygons = GeometryUtil.polygonize(lines);
System.out.println("多边形化: " + polygons.toText());
7.5 几何属性
7.5.1 面积与长度
// 面积计算
Geometry polygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
double area = GeometryUtil.area(polygon);
System.out.println("面积: " + area); // 100.0
// 基于WKT
double areaWkt = GeometryUtil.areaWkt(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
// 长度计算
Geometry line = GeometryUtil.wkt2Geometry(
"LINESTRING(0 0, 10 0, 10 10)");
double length = GeometryUtil.length(line);
System.out.println("长度: " + length); // 20.0
// 多边形周长
double perimeter = GeometryUtil.length(polygon);
System.out.println("周长: " + perimeter); // 40.0
// 基于WKT
double lengthWkt = GeometryUtil.lengthWkt("LINESTRING(0 0, 10 0, 10 10)");
7.5.2 质心与内点
Geometry polygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
// 质心 - 几何中心
Geometry centroid = GeometryUtil.centroid(polygon);
System.out.println("质心: " + centroid.toText()); // POINT (5 5)
// 内点 - 保证在几何内部
Geometry interiorPoint = GeometryUtil.interiorPoint(polygon);
System.out.println("内点: " + interiorPoint.toText());
// 基于WKT
String centroidWkt = GeometryUtil.centroidWkt(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
7.5.3 维度与点数
Geometry point = GeometryUtil.wkt2Geometry("POINT(0 0)");
Geometry line = GeometryUtil.wkt2Geometry("LINESTRING(0 0, 10 10)");
Geometry polygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
// 维度
int dimPoint = GeometryUtil.dimension(point); // 0
int dimLine = GeometryUtil.dimension(line); // 1
int dimPolygon = GeometryUtil.dimension(polygon); // 2
// 点数
int numPoints = GeometryUtil.numPoints(polygon);
System.out.println("点数: " + numPoints); // 5
// 几何类型
GeometryType type = GeometryUtil.geometryType(polygon);
System.out.println("类型: " + type); // POLYGON
// 是否为空
boolean isEmpty = GeometryUtil.isEmpty(polygon); // false
// 基于WKT
int dimWkt = GeometryUtil.dimensionWkt("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
boolean isEmptyWkt = GeometryUtil.isEmptyWkt("POINT EMPTY");
GeometryType typeWkt = GeometryUtil.geometryTypeWkt("LINESTRING(0 0, 10 10)");
7.5.4 边界与外包矩形
Geometry polygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
// 边界 - 几何的边界
Geometry boundary = GeometryUtil.boundary(polygon);
System.out.println("边界: " + boundary.toText());
// LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)
// 外包矩形
Geometry envelope = GeometryUtil.envelope(polygon);
System.out.println("外包矩形: " + envelope.toText());
// POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
// 基于WKT
String boundaryWkt = GeometryUtil.boundaryWkt(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
7.5.5 距离计算
Geometry point1 = GeometryUtil.wkt2Geometry("POINT(0 0)");
Geometry point2 = GeometryUtil.wkt2Geometry("POINT(10 0)");
// 计算距离
double distance = GeometryUtil.distance(point1, point2);
System.out.println("距离: " + distance); // 10.0
// 判断是否在指定距离内
boolean withinDist = GeometryUtil.isWithinDistance(point1, point2, 15);
System.out.println("距离小于15: " + withinDist); // true
// 基于WKT
double distWkt = GeometryUtil.distanceWkt("POINT(0 0)", "POINT(10 0)", 4490);
7.6 几何验证与修复
7.6.1 有效性验证
import com.znlgis.ogu4j.engine.model.TopologyValidationResult;
// 有效几何
Geometry validPolygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
TopologyValidationResult result1 = GeometryUtil.isValid(validPolygon);
System.out.println("有效: " + result1.isValid()); // true
// 无效几何(自相交)
Geometry invalidPolygon = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))"); // 8字形
TopologyValidationResult result2 = GeometryUtil.isValid(invalidPolygon);
System.out.println("有效: " + result2.isValid()); // false
System.out.println("错误类型: " + result2.getErrorType().getDesc());
System.out.println("错误位置: " + result2.getCoordinate());
System.out.println("错误信息: " + result2.getMessage());
7.6.2 简单性验证
import com.znlgis.ogu4j.engine.model.SimpleGeometryResult;
// 检查几何是否简单(无自相交)
Geometry line = GeometryUtil.wkt2Geometry(
"LINESTRING(0 0, 10 10, 0 10, 10 0)"); // 自相交线
SimpleGeometryResult result = GeometryUtil.isSimple(line);
System.out.println("简单: " + result.isSimple()); // false
System.out.println("非简单点: " + result.getNonSimplePts());
// 基于WKT
boolean isSimple = GeometryUtil.isSimpleWkt(
"LINESTRING(0 0, 10 10)", 4490);
7.6.3 几何修复
// 无效几何
Geometry invalid = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))");
// 修复几何
Geometry validated = GeometryUtil.validate(invalid);
System.out.println("修复后: " + validated.toText());
// 验证修复结果
TopologyValidationResult result = GeometryUtil.isValid(validated);
System.out.println("现在有效: " + result.isValid()); // true
7.6.4 几何简化
// 复杂多边形
Geometry complex = GeometryUtil.wkt2Geometry(
"POLYGON((0 0, 1 1, 2 0.5, 3 1, 4 0, 4 10, 0 10, 0 0))");
// 简化(Douglas-Peucker算法)
double tolerance = 1.0;
Geometry simplified = GeometryUtil.simplify(complex, tolerance);
System.out.println("简化后: " + simplified.toText());
// 基于WKT
String simplifiedWkt = GeometryUtil.simplifyWkt(
"POLYGON((0 0, 1 1, 2 0.5, 3 1, 4 0, 4 10, 0 10, 0 0))", 4490);
7.6.5 几何加密
// 为几何添加更多点
Geometry line = GeometryUtil.wkt2Geometry("LINESTRING(0 0, 100 0)");
// 加密,每隔10单位添加一个点
Geometry densified = GeometryUtil.densify(line, 10);
System.out.println("加密后点数: " + GeometryUtil.numPoints(densified));
7.7 错误类型详解
7.7.1 TopologyValidationErrorType枚举
/**
* 拓扑验证错误类型
*/
public enum TopologyValidationErrorType {
ERROR("拓扑检查错误"),
REPEATED_POINT("点重叠"),
HOLE_OUTSIDE_SHELL("洞在图形外"),
NESTED_HOLES("洞重叠"),
DISCONNECTED_INTERIOR("图形内部不连通"),
SELF_INTERSECTION("自相交"),
RING_SELF_INTERSECTION("环自相交"),
NESTED_SHELLS("图形重叠"),
DUPLICATE_RINGS("环重复"),
TOO_FEW_POINTS("点太少无法构成有效几何"),
INVALID_COORDINATE("无效坐标"),
RING_NOT_CLOSED("环未闭合");
private final String desc;
// ...
}
7.7.2 常见错误示例
// 自相交
String selfIntersect = "POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))";
// 环未闭合
String notClosed = "POLYGON((0 0, 0 10, 10 10, 10 0))"; // 首尾不同
// 点太少
String tooFew = "POLYGON((0 0, 5 5))"; // 少于3个点
// 洞在外面
String holeOutside = "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), " +
"(20 20, 20 25, 25 25, 25 20, 20 20))";
// 重复点
String repeated = "POLYGON((0 0, 0 0, 0 10, 10 10, 10 0, 0 0))";
7.8 实战案例
7.8.1 面积统计
public class AreaStatistics {
public static void calculateAreas(OguLayer layer) {
if (layer.getGeometryType() != GeometryType.POLYGON &&
layer.getGeometryType() != GeometryType.MULTIPOLYGON) {
System.out.println("只支持面状图层");
return;
}
double totalArea = 0;
double maxArea = 0;
double minArea = Double.MAX_VALUE;
for (OguFeature feature : layer.getFeatures()) {
Geometry geom = GeometryUtil.wkt2Geometry(feature.getWkt());
double area = GeometryUtil.area(geom);
totalArea += area;
maxArea = Math.max(maxArea, area);
minArea = Math.min(minArea, area);
// 将面积写入属性
feature.setValue("CALC_AREA", area);
}
int count = layer.getFeatureCount();
System.out.printf("要素数量: %d%n", count);
System.out.printf("总面积: %.2f%n", totalArea);
System.out.printf("平均面积: %.2f%n", totalArea / count);
System.out.printf("最大面积: %.2f%n", maxArea);
System.out.printf("最小面积: %.2f%n", minArea);
}
}
7.8.2 空间查询
public class SpatialQuery {
/**
* 查询与指定范围相交的要素
*/
public static List<OguFeature> queryByBounds(OguLayer layer,
double minX, double minY, double maxX, double maxY) {
String boundsWkt = String.format(
"POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))",
minX, minY, maxX, minY, maxX, maxY, minX, maxY, minX, minY);
Geometry bounds = GeometryUtil.wkt2Geometry(boundsWkt);
List<OguFeature> result = new ArrayList<>();
for (OguFeature feature : layer.getFeatures()) {
Geometry geom = GeometryUtil.wkt2Geometry(feature.getWkt());
if (GeometryUtil.intersects(bounds, geom)) {
result.add(feature);
}
}
return result;
}
/**
* 查询包含指定点的要素
*/
public static List<OguFeature> queryByPoint(OguLayer layer,
double x, double y) {
Geometry point = GeometryUtil.wkt2Geometry(
String.format("POINT(%f %f)", x, y));
List<OguFeature> result = new ArrayList<>();
for (OguFeature feature : layer.getFeatures()) {
Geometry geom = GeometryUtil.wkt2Geometry(feature.getWkt());
if (GeometryUtil.contains(geom, point)) {
result.add(feature);
}
}
return result;
}
}
7.8.3 几何验证批处理
public class BatchValidator {
/**
* 批量验证并修复几何
*/
public static void validateAndFix(OguLayer layer) {
int valid = 0;
int fixed = 0;
int failed = 0;
for (OguFeature feature : layer.getFeatures()) {
if (feature.getWkt() == null) continue;
Geometry geom = GeometryUtil.wkt2Geometry(feature.getWkt());
TopologyValidationResult result = GeometryUtil.isValid(geom);
if (result.isValid()) {
valid++;
} else {
System.out.printf("FID %s: %s%n",
feature.getFid(), result.getErrorType().getDesc());
try {
Geometry fixedGeom = GeometryUtil.validate(geom);
feature.setWkt(GeometryUtil.geometry2Wkt(fixedGeom));
fixed++;
} catch (Exception e) {
System.err.println("修复失败: " + e.getMessage());
failed++;
}
}
}
System.out.printf("%n验证完成: 有效 %d, 已修复 %d, 失败 %d%n",
valid, fixed, failed);
}
}
7.8.4 缓冲区分析
public class BufferAnalysis {
/**
* 创建缓冲区图层
*/
public static OguLayer createBufferLayer(OguLayer inputLayer,
double distance) {
OguLayer bufferLayer = new OguLayer();
bufferLayer.setName(inputLayer.getName() + "_Buffer");
bufferLayer.setWkid(inputLayer.getWkid());
bufferLayer.setGeometryType(GeometryType.POLYGON);
bufferLayer.setFields(inputLayer.getFields());
List<OguFeature> features = new ArrayList<>();
for (OguFeature inputFeature : inputLayer.getFeatures()) {
Geometry geom = GeometryUtil.wkt2Geometry(inputFeature.getWkt());
Geometry buffer = GeometryUtil.buffer(geom, distance);
OguFeature bufferFeature = new OguFeature();
bufferFeature.setFid(inputFeature.getFid());
bufferFeature.setWkt(GeometryUtil.geometry2Wkt(buffer));
// 复制属性
for (OguField field : inputLayer.getFields()) {
Object value = inputFeature.getValue(field.getName());
bufferFeature.setValue(field.getName(), value);
}
features.add(bufferFeature);
}
bufferLayer.setFeatures(features);
return bufferLayer;
}
}

浙公网安备 33010602011771号