随着智慧城市的发展,GIS行业迎来了新机遇,时空数据也成为了这个行业的基石。作为一名有追求的程序员,终于在时空数据的道路上越走越远。
- JTS是什么?
- 怎么使用JTS?
- 来个入门案例
免责声明:
JTS是什么?
https://github.com/locationtech/jts
JTS Topology Suite的缩写,递归命名 or Java Topology Suite。
JTS是一个java api,它使用显式精度模型和健壮的几何算法实现一组空间数据变换的核心操作。
JTS试图尽可能精确地实现OpenGIS简单特性规范(SFS)。在某些SFS不清楚或省略的地方,JTS尝试选择合理且一致的替代方案。
术语解释
术语 | 解释 |
---|---|
Geometry | 几何体的统称,代码表示为所有几何体的父类 |
Coordinate | 空间中的一个点 |
Point | R^3中一个任意点 |
Node | 交点(节点),2条线段相交的点 |
Noding(Noded) | 一种计算过程:geometry相交时Node的计算过程 |
SFS | OGC Simple Features Specification |
Vertex | 几何体的顶点 |
几何对象定义
术语 | 解释 |
---|---|
Geometry | 所有几何对象的统称,可以认为是父类 |
Empty Geometry | 标准定义几何体可能是空的 |
GeometryCollection | |
Curve | 非空曲线必须至少有2个点,并且两个连续的点不能相等。注意,这里的曲线不一定是曲线,也可能是直线。 |
MultiCurve | 规范里有个“Mod 2”规则。 |
LineString | 线性点集,0个或至少2个点,可交叉,连续的点可相同。 |
LinearRing | 线性环,是LineString的子类,至少4个点,或0个点为空。 |
Polygon | 壳和孔都是LinearRing。有以下规则:* 壳和孔不能自相交 * 孔可以挨着壳(touch),但只能有一个点重合,不能是一条边重合 * 上面重合的点不需要是顶点(vertex) |
MultiPolygon |
合法的polygon
不合法的polygon
几何关系(二元谓词的方法规约)
JTS中基础类分析
了解一些基础实现类帮助开发。
Coordinate
一个轻量级的坐标点实现。
FAQ:Coordinate与Point的区别?
QA:Point是Geometry的子类,带有精度模型,空间引用信息等,Coordinate属于轻量级的点,主攻二维,3维作为附加属性。
CoordinateSequence
一个接口,代表一系列Geometry中的点。
Envelope
一个包含最大最小x、y值的类。
IntersectionMatrix
实现 Dimensionally Extended Nine-Intersection Model (DE-9IM)
模型计算的矩阵。
GeometryFactory
很多几何对象都由此工厂方法创建。
CoordinateFilter
使用访问者模式实现的 点过滤器。
GeometryFilter
几何对象过滤器。
JAVA实现与SFS的差别
- SFS有时使用整数来表示布尔值。在这种情况下,JTS将使用布尔值
- SFS中的方法名称以大写字母开头。在JTS中,所有方法名称都以小写字母开头
- JTS中的方法名称有时会添加前缀“get”或“set”,以符合Java bean的约定。
helloworld实践
了解下模块分布,用于按需引包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e79kFLPK-1610545503599)(./imgs/000.png)]
<properties>
<jts.version>1.16.1</jts.version>
</properties>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>${jts.version}</version>
</dependency>
<dependency>
<groupId>org.locationtech.jts.io</groupId>
<artifactId>jts-io-common</artifactId>
<version>${jts.version}</version>
</dependency>
构建可视化程序
https://github.com/locationtech/jts/blob/master/doc/JTSTestBuilder.md
- 先把源码pull下来
- package
modules/app
模块 - 通过
>java -jar JTSTestBuilder.jar
运行
演示demo
输入俩几何体 A和B (可绘制,也可手动输入polygon)
执行一些函数查看结果,比如 symDifference
这里没显示出效果,可以把结果copy到输入:
还可以转换成其他格式,比较方便, 比如转成geojson格式
使用程序实现
// 从WKT里创建几何体
WKTReader wktReader = new WKTReader();
Geometry a = wktReader.read("POLYGON ((50 150, 150 150, 150 50, 50 50, 50 150))");
// Geometry b = wktReader.read("POLYGON ((100 100, 200 100, 200 0, 100 0, 100 100))");
// 用工厂方法创建
GeometryFactory factory = new GeometryFactory();
Polygon b = factory.createPolygon(new Coordinate[]{
new Coordinate(100, 100),
new Coordinate(200, 100),
new Coordinate(200, 0),
new Coordinate(100, 0),
new Coordinate(100, 100),
});
// 关系运算
Geometry res = a.symDifference(b);
System.out.println(res.toText());
// 输出不同的格式
// WKTWriter wktWriter = new WKTWriter();
GeoJsonWriter geoJsonWriter = new GeoJsonWriter();
String json = geoJsonWriter.write(res);
System.out.println(json);
结果:
MULTIPOLYGON (((50 150, 150 150, 150 100, 100 100, 100 50, 50 50, 50 150)), ((100 50, 150 50, 150 100, 200 100, 200 0, 100 0, 100 50)))
{"type":"MultiPolygon","coordinates":[[[[50,150],[150,150],[150,100],[100,100],[100,50],[50,50],[50,150]]],[[[100,50],[150,50],[150,100],[200,100],[200,0.0],[100,0.0],[100,50]]]],"crs":{"type":"name","properties":{"name":"EPSG:0"}}}
附录
WKT
Well-Known Text:SFS定义的一种格式
<Geometry Tagged Text> :=
<Point Tagged Text>
| <LineString Tagged Text>
| <LinearRing Tagged Text>
| <Polygon Tagged Text>
| <MultiPoint Tagged Text>
| <MultiLineString Tagged Text>
| <MultiPolygon Tagged Text>
| <GeometryCollection Tagged Text>
<Point Tagged Text> :=
POINT <Point Text>
<LineString Tagged Text> :=
LINESTRING <LineString Text>
<LinearRing Tagged Text> :=
LINEARRING <LineString Text>
<Polygon Tagged Text> :=
POLYGON <Polygon Text>
<MultiPoint Tagged Text> :=
MULTIPOINT <Multipoint Text>
<MultiLineString Tagged Text> :=
MULTILINESTRING <MultiLineString Text>
<MultiPolygon Tagged Text> :=
MULTIPOLYGON <MultiPolygon Text>
<GeometryCollection Tagged Text> :=
GEOMETRYCOLLECTION <GeometryCollection Text>
<Point Text> := EMPTY | ( <Point> )
<Point> := <x> <y>
<x> := double precision literal
<y> := double precision literal
<LineString Text> := EMPTY
| ( <Point> {, <Point> }* )
<Polygon Text> := EMPTY
| ( <LineString Text> {, <LineString Text> }*)
<Multipoint Text> := EMPTY
| ( <Point > {, <Point > }* )
<MultiLineString Text> := EMPTY
| ( <LineString Text> {, <LineString Text> }* )
<MultiPolygon Text> := EMPTY
| ( <Polygon Text> {, <Polygon Text> }* )
<GeometryCollection Text> := EMPTY
| ( <Geometry Tagged Text>
DE-9IM
这个模型的定义参考SFS规范6.1.15.2小节。
来个比较直观的理解:
为什么要这样表示?可以从下面的计算过程发现:
要理解这里的T、F、*
达标什么意思,看下面
参考
- https://github.com/locationtech/jts
- https://www.ogc.org/standards
- SFS规范:https://www.ogc.org/standards/sfa