Java實(shí)現(xiàn)WGS84/GCJ02/BD09的坐標(biāo)互轉(zhuǎn)終極方案
工具類設(shè)計(jì)目標(biāo)
為簡化GIS開發(fā)中頻繁的坐標(biāo)轉(zhuǎn)換操作,本文封裝可復(fù)用的Java工具類,實(shí)現(xiàn)以下能力:
多坐標(biāo)系互轉(zhuǎn)(WGS84/GCJ02/BD09/UTM等)
線程安全的靜態(tài)方法調(diào)用
自動(dòng)處理坐標(biāo)軸順序(經(jīng)度優(yōu)先/緯度優(yōu)先)
異常捕獲與日志追蹤
核心源碼實(shí)現(xiàn)
1. Maven依賴配置
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>31-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.19.0</version>
</dependency>
2. 工具類源碼
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import lombok.extern.slf4j.Slf4j;
/**
* 坐標(biāo)轉(zhuǎn)換工具類(支持EPSG標(biāo)準(zhǔn))
*
* @author 技術(shù)派
*/
@Slf4j
public class CoordinateUtil {
/**
* 二維坐標(biāo)轉(zhuǎn)換
*
* @param x 源X坐標(biāo)
* @param y 源Y坐標(biāo)
* @param srcEPSG 源坐標(biāo)系EPSG碼
* @param targetEPSG 目標(biāo)坐標(biāo)系EPSG碼
* @return 轉(zhuǎn)換后坐標(biāo)對象
*/
public static Coordinate convert2D(double x, double y, int srcEPSG, int targetEPSG) {
try {
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:" + srcEPSG, true);
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:" + targetEPSG, true);
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
return JTS.transform(new Coordinate(x, y), new Coordinate(), transform);
} catch (FactoryException | TransformException e) {
log.error("坐標(biāo)轉(zhuǎn)換失敗: {}", e.getMessage());
throw new RuntimeException("Coordinate transform error", e);
}
}
public static Coordinate convert3D(Coordinate coordinate, int srcEPSG, int targetEPSG) {
try {
// 強(qiáng)制指定坐標(biāo)軸順序(兼容三維坐標(biāo)系)
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:" + srcEPSG, true);
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:" + targetEPSG, true);
// 創(chuàng)建帶高程的坐標(biāo)點(diǎn)(x,y,z)
Coordinate sourceCoord = new Coordinate(coordinate.x, coordinate.y, coordinate.z);
// 構(gòu)建三維坐標(biāo)轉(zhuǎn)換管道
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
Coordinate targetCoord = new Coordinate();
// 執(zhí)行坐標(biāo)轉(zhuǎn)換(自動(dòng)處理Z軸值)
JTS.transform(sourceCoord, targetCoord, transform);
// 高程值處理邏輯
if (Double.isNaN(targetCoord.z)) {
// 目標(biāo)坐標(biāo)系無高程維度時(shí)保留原始Z值
targetCoord.z = coordinate.z;
}
return targetCoord;
} catch (FactoryException | TransformException e) {
log.error("三維坐標(biāo)轉(zhuǎn)換異常:SRC={}, TAR={} | {}",
srcEPSG, targetEPSG, e.getMessage());
throw new RuntimeException("三維坐標(biāo)轉(zhuǎn)換失敗", e);
}
}
}
使用示例
場景1:WGS84轉(zhuǎn)Web墨卡托(EPSG:4326 → 3857)
public static void main(String[] args) {
// 原始WGS84坐標(biāo)(北京天安門)
Coordinate src = new Coordinate(116.3975, 39.9087);
// 執(zhí)行轉(zhuǎn)換
Coordinate result = CoordinateUtil.convert2D(
src.x, src.y,
4326, // WGS84
3857 // Web墨卡托
);
System.out.printf("轉(zhuǎn)換結(jié)果:X=%.2f, Y=%.2f", result.x, result.y);
}
輸出結(jié)果:
轉(zhuǎn)換結(jié)果:X=12958178.85, Y=4851434.41
場景2:高斯投影換帶計(jì)算(3度帶39→40)
Coordinate result = CoordinateUtil.convert2D(
4453572.07, 536385.21,
4524, // 3度帶39帶
4525 // 3度帶40帶
);
關(guān)鍵特性說明
| 特性 | 實(shí)現(xiàn)方案 | 圖標(biāo) |
|---|---|---|
| 坐標(biāo)系兼容性 | 支持5000+ EPSG標(biāo)準(zhǔn)坐標(biāo)系 | ?? |
| 性能優(yōu)化 | 緩存CRS對象避免重復(fù)解碼 | ? |
| 異常處理 | 統(tǒng)一捕獲Factory/Transform異常 | ?? |
| 日志追蹤 | 通過@Slf4j記錄詳細(xì)錯(cuò)誤信息 | ?? |
注意事項(xiàng)
坐標(biāo)軸順序
GeoTools默認(rèn)采用經(jīng)度,緯度順序,通過CRS.decode(code, true)強(qiáng)制指定軸順序
精度損失
高精度場景建議使用PrecisionModel配置計(jì)算精度
依賴沖突
注意GeoTools與其他GIS庫的版本兼容性
擴(kuò)展應(yīng)用場景
- 批量轉(zhuǎn)換:結(jié)合CSV文件實(shí)現(xiàn)海量數(shù)據(jù)轉(zhuǎn)換
- GIS系統(tǒng)集成:與GeoServer等平臺對接
- 移動(dòng)端適配:封裝為RESTful API服務(wù)
參考文檔:GeoTools官方文檔
引用說明:本文實(shí)現(xiàn)參考了GeoTools核心轉(zhuǎn)換邏輯,并結(jié)合笑臉坐標(biāo)轉(zhuǎn)換工具的設(shè)計(jì)思想優(yōu)化異常處理流程。
到此這篇關(guān)于Java實(shí)現(xiàn)WGS84/GCJ02/BD09的坐標(biāo)互轉(zhuǎn)終極方案的文章就介紹到這了,更多相關(guān)Java坐標(biāo)互轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java實(shí)現(xiàn)經(jīng)緯度坐標(biāo)轉(zhuǎn)換的示例代碼
- Java根據(jù)坐標(biāo)經(jīng)緯度計(jì)算兩點(diǎn)距離5種方法及校驗(yàn)經(jīng)緯度是否在圓/多邊形區(qū)域內(nèi)的算法推薦
- Java利用Geotools實(shí)現(xiàn)不同坐標(biāo)系之間坐標(biāo)轉(zhuǎn)換
- Java通過經(jīng)緯度坐標(biāo)獲取兩個(gè)點(diǎn)之間的直線距離的示例
- java 地心坐標(biāo)系(ECEF)和WGS-84坐標(biāo)系(WGS84)互轉(zhuǎn)的實(shí)現(xiàn)
- java實(shí)現(xiàn)計(jì)算地理坐標(biāo)之間的距離
- java實(shí)現(xiàn)百度坐標(biāo)的摩卡托坐標(biāo)與火星坐標(biāo)轉(zhuǎn)換的示例
- 地址到經(jīng)緯度坐標(biāo)轉(zhuǎn)化的JAVA代碼
相關(guān)文章
IntelliJ IDEA右鍵文件夾沒有Java Class文件的原因及解決方法
這篇文章主要介紹了IntelliJ IDEA右鍵文件夾沒有Java Class文件的原因及解決方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
Java用BigDecimal類解決Double類型精度丟失的問題
這篇文章主要介紹了Java用BigDecimal類解決Double類型精度丟失的問題,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12
Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(獨(dú)占模式)
這篇文章主要為大家詳細(xì)介紹了Java并發(fā)系列之AbstractQueuedSynchronizer源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02

