基于GeoTools的道路相交多個點容差冗余計算實戰

目錄

前言

一、關于道路相交

1、相交四個點

2、點更多的情況

二、基于距離的相交點去重

1、冗余距離計算

2、調用過程

3、去重后的結果

三、總結


前言

????????在地理信息系統(GIS)領域,道路網絡數據的處理與分析一直是關鍵課題。隨著城市化進程的加速,日益復雜的道路網絡對數據精度和處理效率提出了更高要求。而道路相交多個點容差冗余計算,作為道路網絡分析中的基礎且重要環節,關乎著后續諸多應用的準確性和可靠性。在之前的博客中,我們介紹了基于道路的名稱來進行兩條道路的相交點計算。原文地址:基于GeoTools和OSM路網求解兩條道路相交點-以長沙市為例。

????????在實際場景中,使用這種處理辦法時往往會出現道路相交處存在多個相近點的情況。這些冗余點不僅增加了數據量,還會對諸如路徑分析、網絡建模等操作產生干擾。例如,在構建道路連通性模型時,過多的冗余點可能導致錯誤的連通性判斷,進而影響整個模型的準確性。那么如何解決這種問題呢?這里使用一種基于容差的處理方法,即設定固定距離閾值進行點的刪除或合并。而借助 GeoTools,我們可以通過靈活運用其幾何處理工具,結合不同的數據結構和算法,實現更具針對性和適應性的容差冗余計算。通過深入研究其幾何對象的操作方法,如點、線幾何關系的判定,能夠精準地定位道路相交處的冗余點。同時,利用 GeoTools 的數據結構優勢,可對道路數據進行高效組織和遍歷,從而快速地進行容差范圍內的點對比和甄別。

????????本次實戰將從 GeoTools 的環境搭建入手,詳細闡述如何導入和讀取道路數據,展示如何對道路幾何對象進行解析和操作。接著,重點介紹容差冗余計算的核心算法實現,包括如何設定合理的容差參數,以及如何根據幾何計算結果對冗余點進行處理。通過對基于 GeoTools 的道路相交多個點容差冗余計算的實戰研究,不僅可以提升道路數據的質量和可用性,還能為后續的地理數據分析和應用奠定堅實的基礎。同時,這一過程也展示了 GeoTools 在解決實際 GIS 問題中的強大能力和靈活性,為相關的地理信息開發工作提供了寶貴的實踐經驗和參考案例。接下來,我們將逐步深入到具體的實現細節中,一同探索這一關鍵問題的有效解決方案。

一、關于道路相交

????????在之前的博文中留了兩個問題給朋友們,這兩個問題就是:1、表示經過我們的計算,為什么兩條道路(金星北路和岳麓大道)的相交點是四個?2、會不會有更多的情況?這里就這兩個問題來進行詳細的答疑。

1、相交四個點

????????首先來回答第一個問題,為什么是相交四個點?關于這個問題,其實大家可以結合生活的常識進行判斷。這里為了方便將不同的道路類型在地圖上進行展示,這里我們根據道路級別將道路的寬度進行不同的設置。設置的方法為,在對道路進行標繪時,選擇分類標繪,界面如下圖所示:

????????根據分類列表信息,點擊更多的分類,使用鼠標雙擊分類,打開當前選擇分類的樣式設置,管理界面如下:

?????????完成后,點擊Ok進行應用,可以看到以下的最終結果:

????????為了方便更加直觀地查看兩條道路的相交,我們將數據進一步的放大,能更直觀的顯示道路相交信息。這里選取騎龍路和楓林三路為例,如下所示:

?????????相信通過上面的圖,大家應該很直觀的就能看到根據兩條路來求解相交是會有A、B、C、D四個相交點的。到這里就詳細的說明了為什么存在多個交點的問題。

2、點更多的情況

????????在上一小節中,我們使用QGIS軟件來介紹了如何根據道路的名稱對道路進行相交求解,并且回答了上一篇博客中提到的兩條路相交,為什么有四個點的原因。之前還留了一個小問題,即除了上述的四個點的情況之外,還有沒有其它更多的相交點的時候呢?答案是一定的。確實會存在,同上而言,我們的道路一般是上面的這種連接關系,或者是下面的連接關系:

????????還有一種情況需要大家考慮,就是其中有一條道路是一個環形或者可以類似的S型,這里使用畫圖軟件來表示:

????????上面是一個簡單的示意圖,道路2是一條曲折蜿蜒的路,而道路1是一條直線,在道路的A和B出分別有前面描述的點相交的情況。共八個點,同理,如果兩條路更加蜿蜒曲折,那么可以知道的是兩條路勢必有更多的交點。 可能在城市道路中這種道路不多見。通過本例也回答了相交點是否存在更多的問題。以長沙為例,城市環島道路就會有這種情況,以中山路和黃興路環島為例:

二、基于距離的相交點去重

????????在知曉了道路相交計算的幾種結果情況之后,接下來我們來講講如何基于距離的計算將道路的相交點保留一個,在一些路口的計算當中,保留一個點比保留四個點更加容易理解。當然,是否需要這么處理,請根據自身的業務和需求來確定。

1、冗余距離計算

????????這里介紹一種基于冗余距離的計算方法,將四個交點合并成一個交點信息。基于冗余距離的計算方法可以描述為如下文字:

假設道路在同一個交叉點有四個交點:

  1. 第一個點被添加到結果集和空間索引

  2. 后續三個點距離第一個點很近(< 閾值)

  3. 每個后續點都會與第一個點進行距離比較

  4. 距離小于閾值,被視為重復點而跳過

  5. 最終結果集中只保留第一個點

????????使用Geotools來求解上述過程的關鍵代碼如下:

//近似計算
private static final BigDecimal DISTANCE_TOLERANCE =  new BigDecimal(0.00003) ; // 不同坐標系下需要處理單位,4326單位為度,3米以視為同一個點private static void addUniquePointSimple(Point point,Set<Point> output,Set<String> uniqueKeys,String pointName) {for (Point np : output) {BigDecimal distance = new BigDecimal(point.distance(np));System.out.println(distance);if ( DISTANCE_TOLERANCE.compareTo(distance) < 0 ) {System.out.println("存在容差");// 在容差范圍內,跳過return;}}output.add(point);
}

2、調用過程

????????那么基于上面的距離來進行冗余點計算,與之前的生成邏輯相比。這里需要增加一步,即將根據Geotools求解的四個相交點進行容差計算,最后保留容差閾值外的點位置信息。調用過程關鍵代碼如下:

/*** -兩條道路集合的所有交點(簡單實現,帶名稱屬性且空間唯一)* * @param road1 第一條道路要素集合* @param road2 第二條道路要素集合* @param road1Name 第一條道路名稱(用于屬性)* @param road2Name 第二條道路名稱(用于屬性)* @return 帶名稱屬性的相交點集合(空間唯一)*/
private static Set<Point> findUniqueIntersectionsSimple(SimpleFeatureCollection road1,SimpleFeatureCollection road2,String road1Name,String road2Name) {// 1. 使用組合名稱final String pointName = road1Name + " & " + road2Name + " 交叉點";// 2. 使用坐標鍵值進行去重Set<String> uniqueKeys = new HashSet<>();Set<Point> uniquePoints = new HashSet<>();try (SimpleFeatureIterator iter1 = road1.features()) {while (iter1.hasNext()) {SimpleFeature f1 = iter1.next();Geometry geom1 = (Geometry) f1.getDefaultGeometry();if (geom1 == null || geom1.isEmpty()) continue;try (SimpleFeatureIterator iter2 = road2.features()) {while (iter2.hasNext()) {SimpleFeature f2 = iter2.next();Geometry geom2 = (Geometry) f2.getDefaultGeometry();if (geom2 == null || geom2.isEmpty()) continue;// 3. 計算交點Geometry result = OverlayNGRobust.overlay(geom1, geom2, OverlayNG.INTERSECTION);// 4. 處理結果并添加唯一點processIntersectionsSimple(result,uniquePoints,uniqueKeys,pointName);}}}}return uniquePoints;
}
/*** -處理交點結果(簡單實現)*/
private static void processIntersectionsSimple(Geometry geom,Set<Point> output,Set<String> uniqueKeys,String pointName) {if (geom == null || geom.isEmpty()) return;if (geom instanceof Point) {addUniquePointSimple((Point) geom, output, uniqueKeys, pointName);} else if (geom instanceof MultiPoint) {for (int i = 0; i < geom.getNumGeometries(); i++) {Geometry g = geom.getGeometryN(i);if (g instanceof Point) {addUniquePointSimple((Point) g, output, uniqueKeys, pointName);}}} else if (geom instanceof GeometryCollection) {for (int i = 0; i < geom.getNumGeometries(); i++) {processIntersectionsSimple(geom.getGeometryN(i), output,uniqueKeys, pointName);}}
}

3、去重后的結果

????????最后來調用一下去重之后的道路相交點代碼,并返回最后的計算結果信息。主要的去重調用代碼如下:

public static void main(String[] args) throws Exception {// 1. 加載OSM道路shp文件File shpFile = new File("F:/vector_data/2024年OSM長沙路網/長沙路網OSM2024.shp");SimpleFeatureSource featureSource = loadShapefile(shpFile);// 2. 輸入兩條道路名稱String roadName1 = "聽雨路";String roadName2 = "賞月路";// 3. 獲取兩條道路的所有幾何線SimpleFeatureCollection road1Features = filterRoadsByName(featureSource, roadName1);SimpleFeatureCollection road2Features = filterRoadsByName(featureSource, roadName2);// 4. 計算所有相交點Set<Point> intersections = findIntersections(road1Features, road2Features);// 5. 輸出結果System.out.println("Found " + intersections.size() + " intersections:");for (Point p : intersections) {System.out.printf("POINT (%.6f %.6f)\n", p.getX(), p.getY());}System.out.println("*******************************");System.out.println("執行冗余計算");//6、去掉可以清理的冗余點intersections = findUniqueIntersectionsSimple(road1Features, road2Features,roadName1,roadName2);System.out.println("Found " + intersections.size() + " intersections:");for (Point p : intersections) {System.out.printf("POINT (%.6f %.6f)\n", p.getX(), p.getY());}
}

????????這里對比了執行冗余計算前后的兩種相交點的求解,并且將點的經緯度信息進行了打印輸入,在IDE中執行完上述代碼,可以看到以下的輸出:

????????可以直觀的看到,經過我們的計算之后,最后的相交點就是1個,即第一個點。 輸出信息如下:

六月 12, 2025 10:02:58 下午 org.geotools.image.ImageWorker <clinit>
信息: Warp/affine reduction enabled: true
Found 4 intersections:
POINT (112.867947 28.194721)
POINT (112.867948 28.194679)
POINT (112.867790 28.194655)
POINT (112.867791 28.194618)
*******************************
執行冗余計算
0.00017015393031127507331677628510391286908998154103755950927734375
存在容差
0.0000412077662565200070611363958317241440454381518065929412841796875
存在容差
0.00018686000107234120048461945007289841669262386858463287353515625
存在容差
Found 1 intersections:
POINT (112.867947 28.194721)

????????基本以上輸出是符合我們的預期的,也符合冗余計算的結果要求。?

三、總結

????????以上就是本文的主要內容。本次實戰將從 GeoTools 的環境搭建入手,詳細闡述如何導入和讀取道路數據,展示如何對道路幾何對象進行解析和操作。接著,重點介紹容差冗余計算的核心算法實現,包括如何設定合理的容差參數,以及如何根據幾何計算結果對冗余點進行處理。通過對基于 GeoTools 的道路相交多個點容差冗余計算的實戰研究,不僅可以提升道路數據的質量和可用性,還能為后續的地理數據分析和應用奠定堅實的基礎。同時,這一過程也展示了 GeoTools 在解決實際 GIS 問題中的強大能力和靈活性,為相關的地理信息開發工作提供了寶貴的實踐經驗和參考案例。

????????未來的展望,在面對復雜多變的道路數據時,本案例可能存在局限性,比如無法充分考慮到不同區域、不同道路類型對容差的差異化要求,容易造成過度簡化或冗余點未被有效排除的問題。也期待更多的朋友一起探討研究。行文倉促,定有不足之處,歡迎各位朋友在評論區批評指正,不勝感激

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84687.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84687.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84687.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android:foregroundServiceType詳解

在 Android 中&#xff0c;foregroundServiceType 是用于聲明前臺服務類型的屬性&#xff0c;主要從 Android 10&#xff08;API 29&#xff09;開始引入&#xff0c;并在 Android 11&#xff08;API 30&#xff09;及更高版本 中進一步細化。以下是所有可用的 foregroundServi…

React+Taro 微信小程序做一個頁面,背景圖需貼手機屏幕最上邊覆蓋展示

話不多說 直接上圖 第一步 import { getSystemInfoSync } from tarojs/taro;第二步 render() {const cardBanner getImageUrlByGlobal(member-merge-bg.png);const { safeArea, statusBarHeight } getSystemInfoSync();const NAV_BAR_HEIGHT 44;const navBarHeight NAV…

從零開始的云計算生活——番外,實戰腳本。

目錄 題目一&#xff1a;系統信息收集腳本 題目二&#xff1a;用戶管理配置腳本 題目三&#xff1a;磁盤空間管理腳本 題目四&#xff1a;網絡配置檢查腳本 題目五&#xff1a;系統日志分析腳本 題目一&#xff1a;系統信息收集腳本 編寫一個腳本名為 collect_system_info…

MySQL基礎知識(DDL、DML)

什么是數據庫&#xff1f; 數據庫&#xff1a;英文為 DataBase&#xff0c;簡稱DB&#xff0c;它是存儲和管理數據的倉庫。 注釋&#xff1a; 單行注釋&#xff1a;-- 注釋內容 或 # 注釋內容(MySQL特有)多行注釋&#xff1a; /* 注釋內容 */ 分類 SQL語句根據其功能被分為…

用volatile修飾數組代表什么意思,Java

文章目錄 volatile 修飾數組引用的含義volatile 對數組元素無效總結 如何讓數組元素也具有 volatile 特性&#xff1f; 當用 volatile 關鍵字修飾一個數組時&#xff0c;它只保證數組引用的可見性和部分原子性&#xff0c;而不保證數組元素的可見性和原子性。 換句話說&#x…

Ubuntu 24.04 LTS 長期支持版發布:對服務器用戶意味著什么?新特性、升級建議與性能影響初探

更多云服務器知識&#xff0c;盡在hostol.com 在服務器運維的廣闊世界里&#xff0c;每一次主流操作系統長期支持&#xff08;LTS&#xff09;版本的發布&#xff0c;都無異于一次重要的“時代交替”。它不僅帶來了一系列令人矚目的技術革新&#xff0c;更重要的是&#xff0c…

題目 3241: 藍橋杯2024年第十五屆省賽真題-挖礦

題目 3241: 藍橋杯2024年第十五屆省賽真題-挖礦 時間限制: 3s 內存限制: 512MB 提交: 1267 解決: 224 題目描述 小藍正在數軸上挖礦&#xff0c;數軸上一共有 n 個礦洞&#xff0c;第 i 個礦洞的坐標為 ai 。小藍從 0 出發&#xff0c;每次可以向左或向右移動 1 的距離&#xf…

vue3+ts+vite創建的后臺管理系統筆記

Vue3+ Vite + Element-Plus + TypeScript 從0到1搭建企業級后臺管理系統(前后端開源):參考有來科技學習搭建項目 創建項目bug匯總,知識點src 路徑別名配置和tsconfig.json文件報錯【這個不配置好,會引起其他頁面引用時報錯:見--整合 Pinia】:整合 Pinia 【參考-- src 路徑…

指針01 day13

十三&#xff1a;指針變量 一&#xff1a;數據類型 ? 指針類型---------對應處理的數據是指針 (地址)這種數據 ? 整型類型---------對應處理的數據是整數這種類型 二&#xff1a;定義指針類型的變量 ? 語法&#xff1a; 基類型&#xff08;1&#xff09; *&#xff08;…

基于深度學習的智能文本生成:從模型到應用

前言 隨著人工智能技術的飛速發展&#xff0c;自然語言處理&#xff08;NLP&#xff09;領域取得了顯著的進展。其中&#xff0c;智能文本生成技術尤其引人注目。從聊天機器人到內容創作&#xff0c;智能文本生成不僅能夠提高效率&#xff0c;還能創造出令人驚嘆的內容。本文將…

Oracle業務用戶的存儲過程個數及行數統計

Oracle業務用戶的存儲過程個數及行數統計 統計所有業務用戶存儲過程的個數獨立定義的存儲過程定義在包里的存儲過程統計所有業務用戶存儲過程的總行數獨立定義的存儲過程定義在包里的存儲過程通過DBA_SOURCE統計類型個數和代碼行數?? 對存儲過程進行統計主要用到以下三個系統…

多線程安全:核心解決方案全解析

在多線程環境下保證共享變量的線程安全,需解決原子性、可見性、有序性三大問題。以下是核心解決方案及適用場景: 一、同步鎖機制(互斥訪問) synchronized 關鍵字 原理:通過 JVM 監視器鎖(Monitor)確保同一時間僅一個線程訪問臨界區。示例:public class Counter {privat…

2025-06-01-Hive 技術及應用介紹

Hive 技術及應用介紹 參考資料 Hive 技術原理Hive 架構及應用介紹Hive - 小海哥哥 de - 博客園https://cwiki.apache.org/confluence/display/Hive/Home(官方文檔) Apache Hive 是基于 Hadoop 構建的數據倉庫工具&#xff0c;它為海量結構化數據提供類 SQL 的查詢能力&#xf…

Python爬蟲(52)Scrapy-Redis分布式爬蟲架構實戰:IP代理池深度集成與跨地域數據采集

目錄 一、引言&#xff1a;當爬蟲遭遇"地域封鎖"二、背景解析&#xff1a;分布式爬蟲的兩大技術挑戰1. 傳統Scrapy架構的局限性2. 地域限制的三種典型表現 三、架構設計&#xff1a;Scrapy-Redis 代理池的協同機制1. 分布式架構拓撲圖2. 核心組件協同流程 四、技術實…

HashMap真面目

背景 今天數據采集項目碰到一個性能問題&#xff0c;3000多個采集點&#xff0c;每一個采集點每秒送一個數據&#xff0c;接收到數據之后首先需要內存中做緩存&#xff0c;之后有一系列的業務分析處理&#xff0c;所以&#xff0c;對系統性能要求比較高。 最近幾天發現服務器…

STM32CubeMX-H7-19-ESP8266通信(中)--單片機控制ESP8266實現TCP地址通信

前言 上篇文章我們已經能夠使用串口助手實現esp8266的幾種通信&#xff0c;接下來我們使用單片機控制實現。這篇文章會附帶教程&#xff0c;增加.c和,.h&#xff0c;把串口和定時器放到對應的編號&#xff0c;然后調用初始化就可以使用了。 先講解&#xff0c;然后末尾再放源碼…

歐盟RED網絡安全標準EN 18031-2的要求

歐盟RED網絡安全標準EN 18031-2的要求 歐盟RED網絡安全標準EN 18031-2的要求 ? 適用產品范圍&#xff1a; 能夠處理個人隱私數據的可聯網無線電設備。 不具備聯網能力的三類無線電設備&#xff1a;玩具、兒童護理類設備、可穿戴類設備。 主要測試與評估內容&#xff1a; EN…

一起了解--CAST函數

CAST函數在SQL中用途廣泛&#xff0c;不僅可以轉換為數值類型&#xff0c;還可以在多種場景下用于數據類型轉換。以下是一些常見的用途和示例&#xff1a; 類型轉換 使用CAST函數可以在查詢數據庫時根據需要調整數據格式或類型 CAST(expression AS target_type) expression …

(50)課71:查看指定 query_id 的 SQL 語句的執行各個階段的耗時情況 show profile for query query_id;

&#xff08;137&#xff09;查看指定 query_id 的 SQL 語句的執行各個階段的耗時情況 show profile for query query_id &#xff1a; &#xff08;138&#xff09; 謝謝

AWS中國云的定時任務(AWS EventBridge+AWS Lambda)

問題 最近有一個每天在凌程定時同步數據給第三方系統的需求。需要使用AWS EventBridge和AWS Lambda結合的方式來同步數據給第三方系統。 思路 使用Python的ORM框架(例如&#xff1a;SQLAlchemy)查詢到需要同步的數據&#xff0c;然后&#xff0c;使用http客戶端&#xff08;…