第02章 - 快速入门与环境配置
第02章 - 快速入门与环境配置
2.1 开发环境准备
2.1.1 系统要求
geometry-api-java 对系统环境的要求非常友好:
| 组件 | 最低要求 | 推荐版本 |
|---|---|---|
| Java | JDK 1.7+ | JDK 8/11/17 |
| Maven | 3.x | 3.6+ |
| 内存 | 512MB | 2GB+ |
| 操作系统 | 跨平台 | 任意 |
特别说明:
- geometry-api-java 是纯 Java 库,无需本地库依赖
- 与操作系统无关,Windows/Linux/macOS 均可运行
- 不依赖 GIS 软件环境,开箱即用
2.1.2 JDK 安装与配置
如果尚未安装 JDK,请按以下步骤操作:
Windows 环境:
- 下载 JDK(推荐 Adoptium)
- 运行安装程序
- 配置环境变量:
JAVA_HOME = C:\Program Files\Java\jdk-17 Path = %JAVA_HOME%\bin;%Path% - 验证安装:
java -version
Linux/macOS 环境:
# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-17-jdk
# macOS (使用 Homebrew)
brew install openjdk@17
# 验证安装
java -version
2.1.3 Maven 安装与配置
Windows 环境:
- 下载 Maven
- 解压到目录(如
C:\maven) - 配置环境变量:
MAVEN_HOME = C:\maven Path = %MAVEN_HOME%\bin;%Path% - 验证安装:
mvn -version
Linux/macOS 环境:
# Ubuntu/Debian
sudo apt install maven
# macOS
brew install maven
# 验证安装
mvn -version
配置国内镜像(可选,加速依赖下载):
编辑 ~/.m2/settings.xml:
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>
2.2 项目创建与依赖配置
2.2.1 创建 Maven 项目
使用命令行创建:
mvn archetype:generate \
-DgroupId=com.example.gis \
-DartifactId=geometry-demo \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
使用 IDE 创建:
IDEA:
- File → New → Project
- 选择 Maven
- 选择 JDK 版本
- 填写 GroupId 和 ArtifactId
Eclipse:
- File → New → Maven Project
- 选择 Create a simple project
- 填写项目信息
2.2.2 添加 Maven 依赖
编辑 pom.xml,添加 geometry-api-java 依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.gis</groupId>
<artifactId>geometry-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<geometry-api.version>2.2.4</geometry-api.version>
</properties>
<dependencies>
<!-- Esri Geometry API for Java -->
<dependency>
<groupId>com.esri.geometry</groupId>
<artifactId>esri-geometry-api</artifactId>
<version>${geometry-api.version}</version>
</dependency>
<!-- 可选:用于测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2.3 依赖说明
geometry-api-java 的核心依赖很少:
<!-- 核心依赖(自动引入) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
依赖树:
com.esri.geometry:esri-geometry-api:2.2.4
└── com.fasterxml.jackson.core:jackson-core:2.9.6
这种精简的依赖结构使得 geometry-api-java:
- 体积小巧(JAR 约 1MB)
- 集成简单,无依赖冲突
- 启动快速,内存占用低
2.3 第一个几何程序
2.3.1 创建点并计算缓冲区
创建文件 src/main/java/com/example/gis/HelloGeometry.java:
package com.example.gis;
import com.esri.core.geometry.*;
public class HelloGeometry {
public static void main(String[] args) {
// 1. 创建一个点(北京天安门坐标)
Point tiananmen = new Point(116.397428, 39.90923);
System.out.println("创建点: " + tiananmen);
// 2. 创建空间参考(WGS84,EPSG:4326)
SpatialReference sr = SpatialReference.create(4326);
System.out.println("空间参考容差: " + sr.getTolerance());
// 3. 创建 1 度缓冲区
Polygon buffer = GeometryEngine.buffer(tiananmen, sr, 1.0);
System.out.println("缓冲区顶点数: " + buffer.getPointCount());
// 4. 查询缓冲区边界
Envelope2D env = new Envelope2D();
buffer.queryEnvelope2D(env);
System.out.println("缓冲区范围: " +
"X[" + env.xmin + ", " + env.xmax + "], " +
"Y[" + env.ymin + ", " + env.ymax + "]");
// 5. 转换为 GeoJSON
String geoJson = GeometryEngine.geometryToGeoJson(sr, buffer);
System.out.println("GeoJSON 长度: " + geoJson.length() + " 字符");
// 6. 计算缓冲区面积
double area = buffer.calculateArea2D();
System.out.println("缓冲区面积: " + area + " 平方度");
}
}
运行程序:
mvn compile exec:java -Dexec.mainClass=com.example.gis.HelloGeometry
预期输出:
创建点: {"x":116.397428,"y":39.90923}
空间参考容差: 1.0E-9
缓冲区顶点数: 100
缓冲区范围: X[115.397428, 117.397428], Y[38.90923, 40.90923]
GeoJSON 长度: 4521 字符
缓冲区面积: 3.141592653589793 平方度
2.3.2 创建折线并计算长度
package com.example.gis;
import com.esri.core.geometry.*;
public class PolylineExample {
public static void main(String[] args) {
// 创建一条北京到上海的折线
Polyline route = new Polyline();
// 添加路径点
route.startPath(116.397428, 39.90923); // 北京
route.lineTo(117.200983, 39.084158); // 天津
route.lineTo(118.184086, 39.635508); // 唐山
route.lineTo(120.585316, 31.298886); // 苏州
route.lineTo(121.469170, 31.224361); // 上海
// 输出折线信息
System.out.println("路径数: " + route.getPathCount());
System.out.println("顶点数: " + route.getPointCount());
System.out.println("长度: " + route.calculateLength2D() + " 度");
// 获取各顶点
System.out.println("\n途经城市坐标:");
for (int i = 0; i < route.getPointCount(); i++) {
Point2D pt = route.getXY(i);
System.out.printf(" 点%d: (%.4f, %.4f)%n", i, pt.x, pt.y);
}
// 转换为 WKT
String wkt = GeometryEngine.geometryToWkt(route, 0);
System.out.println("\nWKT 表示:");
System.out.println(wkt);
}
}
2.3.3 创建多边形并进行空间分析
package com.example.gis;
import com.esri.core.geometry.*;
public class PolygonExample {
public static void main(String[] args) {
// 创建北京五环区域(简化多边形)
Polygon beijing5Ring = new Polygon();
beijing5Ring.startPath(116.1, 39.7);
beijing5Ring.lineTo(116.7, 39.7);
beijing5Ring.lineTo(116.7, 40.1);
beijing5Ring.lineTo(116.1, 40.1);
beijing5Ring.closePathWithLine();
// 创建一个查询点(故宫位置)
Point palace = new Point(116.397, 39.917);
// 创建空间参考
SpatialReference sr = SpatialReference.create(4326);
// 判断点是否在多边形内
boolean contains = GeometryEngine.contains(beijing5Ring, palace, sr);
System.out.println("故宫是否在五环内: " + contains);
// 计算多边形面积
double area = beijing5Ring.calculateArea2D();
System.out.println("五环面积: " + area + " 平方度");
// 计算多边形周长
double length = beijing5Ring.calculateLength2D();
System.out.println("五环周长: " + length + " 度");
// 获取边界框
Envelope env = new Envelope();
beijing5Ring.queryEnvelope(env);
System.out.println("边界框: " + env);
// 创建另一个多边形(朝阳区,简化)
Polygon chaoyang = new Polygon();
chaoyang.startPath(116.4, 39.85);
chaoyang.lineTo(116.65, 39.85);
chaoyang.lineTo(116.65, 40.0);
chaoyang.lineTo(116.4, 40.0);
chaoyang.closePathWithLine();
// 计算交集
Geometry intersection = GeometryEngine.intersect(beijing5Ring, chaoyang, sr);
if (!intersection.isEmpty()) {
double intersectArea = intersection.calculateArea2D();
System.out.println("与朝阳区交集面积: " + intersectArea + " 平方度");
}
// 判断两个多边形是否相交
boolean intersects = !GeometryEngine.disjoint(beijing5Ring, chaoyang, sr);
System.out.println("两区域是否相交: " + intersects);
}
}
2.4 使用 GeometryEngine 简化 API
2.4.1 GeometryEngine 概述
GeometryEngine 是 geometry-api-java 提供的便捷工具类,封装了常用的几何操作。它的特点是:
- 静态方法,无需创建实例
- 简化 API,参数更少
- 内部调用对应的 Operator
// GeometryEngine 常用方法
public class GeometryEngine {
// 格式转换
public static MapGeometry jsonToGeometry(String json);
public static String geometryToJson(SpatialReference sr, Geometry geometry);
public static String geometryToGeoJson(SpatialReference sr, Geometry geometry);
public static Geometry geometryFromWkt(String wkt, int importFlags, Geometry.Type type);
public static String geometryToWkt(Geometry geometry, int exportFlags);
// 空间操作
public static Geometry[] union(Geometry[] geometries, SpatialReference sr);
public static Geometry difference(Geometry g1, Geometry g2, SpatialReference sr);
public static Geometry intersect(Geometry g1, Geometry g2, SpatialReference sr);
public static Polygon buffer(Geometry geometry, SpatialReference sr, double distance);
public static Geometry clip(Geometry geometry, Envelope envelope, SpatialReference sr);
public static Geometry convexHull(Geometry geometry);
public static Geometry simplify(Geometry geometry, SpatialReference sr);
// 空间关系
public static boolean equals(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean contains(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean within(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean crosses(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean touches(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean overlaps(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean disjoint(Geometry g1, Geometry g2, SpatialReference sr);
public static boolean relate(Geometry g1, Geometry g2, SpatialReference sr, String relation);
// 距离计算
public static double distance(Geometry g1, Geometry g2, SpatialReference sr);
public static double geodesicDistanceOnWGS84(Point from, Point to);
}
2.4.2 与 Operator 的对比
使用 Operator(更灵活、功能更多):
// 获取缓冲区算子
OperatorBuffer op = (OperatorBuffer) OperatorFactoryLocal
.getInstance()
.getOperator(Operator.Type.Buffer);
// 执行缓冲区操作(可以使用游标处理多个几何)
Geometry result = op.execute(geometry, sr, 10.0, null);
使用 GeometryEngine(更简洁):
// 一行代码完成
Polygon result = GeometryEngine.buffer(geometry, sr, 10.0);
选择建议:
- 简单场景:使用 GeometryEngine
- 批量处理:使用 Operator + Cursor
- 需要进度回调:使用 Operator + ProgressTracker
- 需要几何加速:使用 Operator + accelerateGeometry
2.5 项目结构最佳实践
2.5.1 推荐的项目结构
geometry-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/gis/
│ │ │ ├── App.java # 应用入口
│ │ │ ├── service/ # 业务服务层
│ │ │ │ ├── GeometryService.java
│ │ │ │ └── SpatialAnalysisService.java
│ │ │ ├── util/ # 工具类
│ │ │ │ ├── GeometryUtils.java
│ │ │ │ └── FormatConverter.java
│ │ │ └── model/ # 数据模型
│ │ │ └── GeoFeature.java
│ │ └── resources/
│ │ └── data/ # 测试数据
│ │ └── sample.geojson
│ └── test/
│ └── java/
│ └── com/example/gis/
│ └── GeometryServiceTest.java
└── README.md
2.5.2 工具类封装示例
package com.example.gis.util;
import com.esri.core.geometry.*;
/**
* 几何工具类
*/
public class GeometryUtils {
// WGS84 空间参考(常用)
public static final SpatialReference WGS84 = SpatialReference.create(4326);
// CGCS2000 地理坐标系
public static final SpatialReference CGCS2000 = SpatialReference.create(4490);
/**
* 从 GeoJSON 字符串解析几何
*/
public static Geometry fromGeoJson(String geoJson) {
MapGeometry mapGeom = GeometryEngine.geoJsonToGeometry(
geoJson, 0, Geometry.Type.Unknown);
return mapGeom.getGeometry();
}
/**
* 将几何转换为 GeoJSON
*/
public static String toGeoJson(Geometry geometry) {
return GeometryEngine.geometryToGeoJson(WGS84, geometry);
}
/**
* 从 WKT 字符串解析几何
*/
public static Geometry fromWkt(String wkt) {
return GeometryEngine.geometryFromWkt(wkt, 0, Geometry.Type.Unknown);
}
/**
* 将几何转换为 WKT
*/
public static String toWkt(Geometry geometry) {
return GeometryEngine.geometryToWkt(geometry, 0);
}
/**
* 计算缓冲区(米为单位,仅适用于小范围)
* 注意:在 WGS84 坐标系下,此方法仅适用于赤道附近
*/
public static Polygon bufferInMeters(Geometry geometry, double meters) {
// 简化处理:1度 ≈ 111000米(赤道处)
double degrees = meters / 111000.0;
return GeometryEngine.buffer(geometry, WGS84, degrees);
}
/**
* 计算两点间的测地距离(米)
*/
public static double geodesicDistance(Point p1, Point p2) {
return GeometryEngine.geodesicDistanceOnWGS84(p1, p2);
}
/**
* 判断几何是否有效(非空且非空集)
*/
public static boolean isValid(Geometry geometry) {
return geometry != null && !geometry.isEmpty();
}
/**
* 获取几何的中心点
*/
public static Point getCentroid(Geometry geometry) {
Envelope2D env = new Envelope2D();
geometry.queryEnvelope2D(env);
return new Point(env.getCenterX(), env.getCenterY());
}
}
2.5.3 业务服务示例
package com.example.gis.service;
import com.esri.core.geometry.*;
import com.example.gis.util.GeometryUtils;
import java.util.List;
import java.util.ArrayList;
/**
* 空间分析服务
*/
public class SpatialAnalysisService {
private final SpatialReference sr;
public SpatialAnalysisService() {
this.sr = GeometryUtils.WGS84;
}
/**
* 查找指定范围内的点
*/
public List<Point> findPointsWithinPolygon(List<Point> points, Polygon area) {
List<Point> result = new ArrayList<>();
for (Point point : points) {
if (GeometryEngine.contains(area, point, sr)) {
result.add(point);
}
}
return result;
}
/**
* 合并多个多边形
*/
public Polygon unionPolygons(List<Polygon> polygons) {
if (polygons.isEmpty()) {
return new Polygon();
}
Geometry[] geoms = polygons.toArray(new Geometry[0]);
Geometry result = GeometryEngine.union(geoms, sr);
return (Polygon) result;
}
/**
* 计算多边形的面积覆盖统计
*/
public double calculateAreaInSquareKm(Polygon polygon) {
// 简化计算,仅适用于小范围
// 1平方度 ≈ 12321 平方公里(中纬度地区近似值)
double areaDegrees = Math.abs(polygon.calculateArea2D());
return areaDegrees * 12321;
}
}
2.6 编译与运行
2.6.1 编译项目
# 编译
mvn compile
# 跳过测试编译
mvn compile -DskipTests
2.6.2 运行程序
方式一:使用 Maven
mvn exec:java -Dexec.mainClass=com.example.gis.HelloGeometry
方式二:打包后运行
# 打包
mvn package
# 运行
java -cp target/geometry-demo-1.0-SNAPSHOT.jar:target/dependency/* \
com.example.gis.HelloGeometry
方式三:创建可执行 JAR
在 pom.xml 中添加:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.gis.HelloGeometry</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
# 打包
mvn package
# 运行
java -jar target/geometry-demo-1.0-SNAPSHOT.jar
2.6.3 运行测试
# 运行所有测试
mvn test
# 运行特定测试类
mvn test -Dtest=GeometryServiceTest
# 生成测试报告
mvn surefire-report:report
2.7 常见问题与解决方案
2.7.1 依赖下载失败
问题:Maven 下载依赖超时或失败
解决方案:
- 配置国内镜像(见 2.1.3 节)
- 清理本地仓库后重试:
rm -rf ~/.m2/repository/com/esri mvn clean install - 使用离线安装:
# 下载 JAR 后手动安装 mvn install:install-file \ -Dfile=esri-geometry-api-2.2.4.jar \ -DgroupId=com.esri.geometry \ -DartifactId=esri-geometry-api \ -Dversion=2.2.4 \ -Dpackaging=jar
2.7.2 编译版本问题
问题:编译时提示 Java 版本不兼容
解决方案:
确保 pom.xml 中的编译版本与安装的 JDK 一致:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
或者使用工具链指定 JDK:
mvn compile -Dmaven.compiler.source=11 -Dmaven.compiler.target=11
2.7.3 内存溢出
问题:处理大量几何时出现 OutOfMemoryError
解决方案:
- 增加 JVM 内存:
java -Xmx4g -jar app.jar - 使用流式处理(Cursor)代替批量处理
- 分批处理大数据集
2.7.4 数值精度问题
问题:几何计算结果与预期有偏差
解决方案:
- 使用适当的空间参考
- 检查几何数据是否有效
- 使用
simplify()清理问题几何
// 简化几何,修复可能的问题
Geometry simplified = GeometryEngine.simplify(geometry, sr);
2.8 本章小结
本章介绍了 geometry-api-java 的开发环境搭建和基本使用方法:
- 环境准备:JDK 和 Maven 的安装配置
- 项目创建:Maven 项目结构和依赖配置
- 基础示例:点、线、面的创建和空间分析
- API 使用:GeometryEngine 的便捷方法
- 最佳实践:项目结构和工具类封装
- 编译运行:多种运行方式和常见问题
通过本章学习,你应该能够:
- 搭建 geometry-api-java 开发环境
- 创建和操作基本几何对象
- 使用 GeometryEngine 进行空间分析
- 组织合理的项目结构
下一章,我们将深入学习几何对象的详细特性。

浙公网安备 33010602011771号