自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

點線面的智慧: 轉(zhuǎn)轉(zhuǎn)JTS技術如何塑造上門履約地理布局

開發(fā)
JTS,全稱 Java Topology Suite,是一個用于創(chuàng)建和操作向量幾何的 Java 庫。提供了對幾何模型的抽象,以及各種空間操作和空間關系判斷,非常強大。

1、引言

圖片

如上圖所示,在轉(zhuǎn)轉(zhuǎn)上門履約的場景中,上門服務的覆蓋區(qū)域是在地圖上畫電子圍欄來劃定的。這就涉及到一些幾何圖形的操作和空間關系判斷,其中最核心問題就是要解決如何判斷位置是否在上門覆蓋范圍內(nèi)。下面介紹下 JTS,以及如何通過 JTS 的空間之力來解決這些問題。

2、JTS 介紹

JTS,全稱 Java Topology Suite,是一個用于創(chuàng)建和操作向量幾何的 Java 庫。提供了對幾何模型的抽象,以及各種空間操作和空間關系判斷,非常強大。

2.1 引入 jar 包

JTS 有多個模塊,這里只使用了核心的模塊。

  • jts-core:提供幾何模型的抽象、空間操作、空間關系判斷算法等
  • jts-io-common:提供各種格式描述幾何模型的輸入輸出包,如對 WKT、WKB 等格式
<dependency>
  <groupId>org.locationtech.jts</groupId>
  <artifactId>jts-core</artifactId>
  <version>1.19.0</version>
</dependency>

<dependency>
    <groupId>org.locationtech.jts.io</groupId>
    <artifactId>jts-io-common</artifactId>
    <version>1.19.0</version>
</dependency>

2.2 基本的幾何模型

JTS 提供了常見的幾何模型抽象,并且各具特點。

模型

定義

常見應用

點(Point)

空間中的單個位置,由一對 x,y 坐標表示

興趣點、事件位置等

多點(MultiPoint)

由多個獨立的點組成的幾何對象

表示多個相關但分散的位置,如連鎖店分布,多個不同人位置

線(LineString)

由一系列點組成的一維幾何對象,有起點和終點,中間可以有任意數(shù)量的點

表示道路、河流等線性特征

多線(MultiLineString)

由多個不相連的 LineString 組成的幾何對象

表示復雜的道路網(wǎng)絡、等高線等

多邊形(Polygon)

由一系列首尾相連的線段圍成的平面區(qū)域(可以有內(nèi)部空洞)

表示行政區(qū)劃、建筑物輪廓等

多多邊形(MultiPolygon)

由多個獨立的 Polygon 組成的幾何對象,可以表示不相連的多個區(qū)域

表示群島、復雜的行政區(qū)劃

幾何集合(GeometryCollection)

可以包含任意類型幾何對象的集合,最靈活的幾何類型,可以混合包含點、線、面等

表示復雜的空間場景,如包含多種類型要素的地圖

在 JTS 中的各幾何模型對象關系如下所示:圖片

在實際應用場景中,最常使用的模型如下:

  • 點(Point):表示位置信息,如用戶地址位置、工程師位置等
  • 多邊形(Polygon)、多多邊形(MultiPolygon):用來表示上門履約的覆蓋區(qū)域

2.3 幾何模型的描述格式

WKT(Well-Know Text)格式是一種文本格式,用于描述二維和三維幾何對象的空間特征。WKT 的基本語法格式如下:

幾何模型類型 (模型數(shù)據(jù))

示例如下所示:

點:POINT (282 455)
線:LINESTRING (260 250, 485 248, 520 380)
多邊形:POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))

JTS 支持對該格式的讀寫操作,主要是兩個對象WKTReaderWKTWriter,代碼示例如下:

// 讀取wkt描述的幾何對象
WKTReader wktReader = new WKTReader();
Geometry point = wktReader.read("POINT (282 455)");
Geometry line = wktReader.read("LINESTRING (260 250, 485 248, 520 380)");
Geometry polygon = wktReader.read("POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))");

// 輸出幾何對象的wkt描述
WKTWriter wktWriter = new WKTWriter();
System.out.println(wktWriter.write(point));
System.out.println(wktWriter.write(line));
System.out.println(wktWriter.write(polygon));

2.4 空間關系

JTS 中的空間關系是基于 DE-9IM(Dimensionally Extended Nine-Intersection Model)模型定義的,這里列舉常見的空間關系

空間關系

定義

相等 (Equals)

兩個幾何對象在拓撲上相等

相離 (Disjoint)

兩個幾何對象沒有任何共同點

相交 (Intersects)

兩個幾何對象有至少一個共同點

內(nèi)含 (Within)

幾何對象 A 完全位于幾何對象 B 內(nèi)部

包含 (Contains)

幾何對象 A 完全包含幾何對象 B

以該圖形為例,兩個多邊形的關系判斷的代碼示例圖片

WKTReader wktReader = new WKTReader();
Geometry geometryA = wktReader.read("POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))");
Geometry geometryB = wktReader.read("POLYGON ((500 420, 430 360, 530 260, 500 420))");

System.out.println("Equal: " + geometryA.equals(geometryB));
System.out.println("Disjoint: " + geometryA.disjoint(geometryB));
System.out.println("Intersects: " + geometryA.intersects(geometryB));
System.out.println("Within: " + geometryA.within(geometryB));
System.out.println("Contains: " + geometryA.contains(geometryB));

在實際場景中,判斷上門位置是否在上門區(qū)域內(nèi),轉(zhuǎn)換成空間關系的判斷就是點是否在多邊形內(nèi)。解決該問題的實例代碼如下:

WKTReader wktReader = new WKTReader();
Geometry geometryA = wktReader.read("POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))");
Geometry geometryB = wktReader.read("POLYGON ((500 420, 430 360, 530 260, 500 420))");
Geometry point = wktReader.read("POINT (390 380)");

System.out.println("point in geometryA: " + geometryA.contains(point));
System.out.println("point in geometryB: " + geometryB.contains(point));

2.5 空間操作

JTS 提供了豐富的空間操作功能,用于處理和分析幾何對象。這里列舉常見的幾種

空間操作

定義

相交 (Intersection)

計算兩個幾何對象的共同部分

并集 (Union)

合并兩個或多個幾何對象

差集 (Difference)

從一個幾何對象中減去另一個幾何對象

以該圖為例,操作示例代碼如下:圖片

WKTReader wktReader = new WKTReader();
Geometry geometryA = wktReader.read("POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))");
Geometry geometryB = wktReader.read("POLYGON ((500 420, 430 360, 530 260, 500 420))");

System.out.println("Intersection: " + wktWriter.write(geometryA.intersection(geometryB)));
System.out.println("Union: " + wktWriter.write(geometryA.union(geometryB)));
System.out.println("Difference: " + wktWriter.write(geometryA.difference(geometryB)));

下面是 Union 合并后的效果圖片

3、快速判斷是否支持上門

在上門履約實際場景中,需要快速的識別用戶所在位置、地址位置是否在上門服務的覆蓋區(qū)域內(nèi)。轉(zhuǎn)換成空間關系的判斷上,也就是點是否在多邊形內(nèi)(PIP,Point-In-Polygon)問題了。

在上述的 JTS 介紹中,已經(jīng)得知 JTS 提供了 contains 的關系判斷能力。但是這只是解決了單個問題,假設全國共有 N 個多邊形,那么就需要遍歷 N 個多邊形來判斷,復雜度是 O(N),并且還需要全部多邊形加載到內(nèi)存中??上攵?,直接使用的話會存在性能問題。為此,我們需要一個快速解決 PIP 問題的方案。

3.1 最小外接矩形(MBR)

最小外接矩形 MBR (Minimum Bounding Retangle),是能夠完全包含一個幾何對象的最小矩形。如下圖所示,這個規(guī)則的矩形就是該多邊形的 MBR 表示。圖片

表示 MBR 非常簡單,只需要知道他的左下角和右上角,那么就可以知道這個 MBR 圖形了。如下圖所示:圖片

知道了這個最小外接矩形有什么用?可以斷定:如果點不在這個 MBR 內(nèi)了,那么肯定不在這個多邊形內(nèi)。所以把點和 MBR 進行比較,就能夠快速排除不可能有關系的多邊形對象。

那么如何快速的判斷點是否在 MBR 中?比較坐標值的大小就可以了。示例代碼如下:

mbr.getLngMin() <= point.getLng()
&& mbr.getLngMax() >= point.getLng()
&& mbr.getLatMin() <= point.getLat()
&& mbr.getLatMax() >= point.getLat()

綜上,MBR 用簡單的矩形來近似表示復雜的幾何形狀,將復雜的空間關系簡化為矩形之間的關系。 通過 MBR 這一層的初步篩選,就能夠快速排除不可能有關系的多邊形對象。

在 JTS 中,Envelope 對象來表示 MBR。代碼示例如下:

WKTReader wktReader = new WKTReader();
Geometry geometryA = wktReader.read("POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))");

Envelope envelope = geometryA.getEnvelopeInternal();
System.out.println(envelope.getMaxX());
System.out.println(envelope.getMaxY());
System.out.println(envelope.getMinX());
System.out.println(envelope.getMinY());

3.2 空間索引

上述構(gòu)建 MBR 可以理解為簡單索引的一種,實際上有復雜的空間索引。常見空間索引有

  • R 樹(R-tree):平衡樹,適用于多維空間數(shù)據(jù)(類似一維的 B+樹)
  • 四叉樹(Quad-tree):將二維空間遞歸地分為四個象限
  • 網(wǎng)格(Grid):將空間劃分為規(guī)則的網(wǎng)格單元

空間索引的基本原理基本類似,采用分割原理,逐級劃分地理空間。舉個不那么恰當?shù)睦?,一個自上而下、逐級劃分地理空間的索引定位過程如下:

北方 還是 南方 ? 南方
廣東 還是 廣西 ? 廣東
深圳 還是 廣州 ? 深圳
福田 還是 南山 ? 福田

JTS 提供了四叉樹和 R 樹的實現(xiàn)

  • Quadtree(四叉樹)
  • STRtree(基于 R 樹的變體)

以這個圖形為例,使用 JTS 構(gòu)建 R 樹空間索引

圖片

示例代碼如下:

WKTReader wktReader = new WKTReader();
Geometry geometryA = wktReader.read("POLYGON ((320 390, 370 330, 470 360, 460 430, 375 432, 320 390))");
Geometry geometryB = wktReader.read("POLYGON ((500 420, 430 360, 530 260, 500 420))");

STRtree rtree = new STRtree();
// 向R樹種添加MBR,和自己的數(shù)據(jù)
rtree.insert(geometryA.getEnvelopeInternal(), "Polygon-A");
rtree.insert(geometryB.getEnvelopeInternal(), "Polygon-B");
rtree.build();

// 點只在Polygon-A中
System.out.println(rtree.query(wktReader.read("POINT (337 391)").getEnvelopeInternal()));
// 點只在Polygon-B中
System.out.println(rtree.query(wktReader.read("POINT (496 390)").getEnvelopeInternal()));
// 點在Polygon-A和Polygon-B的交集中
System.out.println(rtree.query(wktReader.read("POINT (452 367)").getEnvelopeInternal()));

3.3 整體方案流程

綜上所述,快速定位點(Point)在哪些多邊形中的具體流程如下:

  1. 先通過 STRtree 構(gòu)建空間索引
  2. 利用空間索引快速篩選可能包含點的多邊形
  3. 對篩選后的多邊形進行精確的空間關系判斷

多邊形是隨時都有可能可以調(diào)整,如果一個多邊形發(fā)生了調(diào)整就需要重構(gòu)整顆索引樹。但是在實踐中,為了降低構(gòu)建索引樹的頻次,通過定時任務去間隔 10 分鐘在內(nèi)存中構(gòu)建一次。并且為了減少索引樹占用的內(nèi)存大小,向索引樹中添加 MBR 關聯(lián)的是多邊形的 Id,初篩后再根據(jù) id 從緩存中取具體的多邊形數(shù)據(jù)進行精確的空間關系判斷,實現(xiàn)一個類似懶加載的過程。

具體流程如下圖所示:圖片

4、幾何圖形的修復處理

在實際運營過程中,畫的圖形各種形狀,會出現(xiàn)不少異常的情況,如點重疊、邊之間細微的間隙、自交等問題。實際操作中還提拱了圖形合并的能力,合并出來的圖像也有可能也是不符合規(guī)范的。為此,需要對這些異常的圖像進行修復。

常見的修復手段有兩種

  • Buffer 操作:在幾何對象周圍的創(chuàng)建緩沖區(qū),一般用來修復自相交問題、精度導致的小間隙等
  • Snap 操作:一個幾何對象的頂點捕捉到另一個幾何對象的頂點或邊緣,一般用來修復小的拓撲錯誤

這兩種操作也不是萬能,也是需要自己根據(jù)實際情況進行不斷地調(diào)整。

下面來看一個修復自交的例子,一個自交的圖形如下所示:圖片

修復代碼示例如下:

WKTReader wktReader = new WKTReader();
Geometry geometryA = wktReader.read("POLYGON ((340 490, 370 330, 730 350, 700 270, 340 490))");

WKTWriter wktWriter = new WKTWriter();
wktWriter.setPrecisionModel(new PrecisionModel(0));
System.out.println(wktWriter.write(geometryA.buffer(0)));

修復之后如下圖所示圖片

5、總結(jié)

Java Topology Suite (JTS) 作為一個功能強大的空間數(shù)據(jù)處理庫,為開發(fā)者提供了豐富的工具來處理復雜的空間問題。它在許多地理信息系統(tǒng)得到了廣泛的應用。這里只是對其的一個簡單應用,后續(xù)還待更深入的挖掘。

6、參考

  • Java Topology Suite (JTS):https://github.com/locationtech/jts
  • OSGeo中國:https://www.osgeo.cn/
責任編輯:龐桂玉 來源: 轉(zhuǎn)轉(zhuǎn)技術
相關推薦

2023-03-02 08:54:32

2023-03-02 08:32:41

2024-07-17 21:02:42

2018-05-16 16:13:49

開發(fā)架構(gòu)師轉(zhuǎn)型

2025-03-28 11:35:36

數(shù)字化轉(zhuǎn)型

2021-09-22 09:54:42

數(shù)字化

2018-12-13 05:30:24

2018-05-03 09:28:32

程序員避坑指南

2018-04-23 09:16:47

程序員知識體系

2023-06-06 10:25:53

面部識別智慧城市

2022-12-09 08:45:08

運維數(shù)字化轉(zhuǎn)型

2024-09-04 09:36:27

2021-12-07 23:07:41

區(qū)塊鏈音樂產(chǎn)業(yè)技術

2024-02-26 15:35:04

2023-03-02 13:32:02

2020-06-01 11:01:28

智慧城市物聯(lián)網(wǎng)技術

2019-04-10 16:35:39

華為智能計算智能服務器

2023-09-05 10:30:51

智能交通智慧城市

2024-01-30 11:41:36

6G技術邊緣計算

2022-12-26 15:53:10

點贊
收藏

51CTO技術棧公眾號