4 Geotools坐標參考系與轉換

在地理信息系統 (GIS) 開發中,坐標參考系統 (Coordinate Reference System, CRS) 是核心概念之一。無論是處理地圖投影、坐標轉換,還是在 Spring Boot 應用中管理空間數據,理解和正確使用 CRS 都至關重要。本文將圍繞 GeoTools 庫,深入探討 CRS 的重要性、EPSG 代碼的概念與查詢,以及如何在代碼中定義 CRS 和執行坐標轉換,最后結合 Spring Boot 展示實際應用場景。

坐標參考系統 (CRS) 的重要性

坐標參考系統定義了地理數據如何在二維或三維空間中表示。不同的 CRS 使用不同的投影方法和單位(例如,度、米),以適應特定場景的需求。簡單的說坐標系類型分地理坐標(球面坐標,只有橢球信息,以經度為x軸,緯度為Y軸的),投影坐標系(平面坐標,橢球信息+投影方式,以橫坐標經線為x軸,縱坐標緯線投影為Y軸。分帶的投影有中央經線)以下是幾種常見的 CRS 及其應用場景:

  • WGS84 (EPSG:4326): 基于經緯度的全球通用 CRS,常用于 GPS 和全球地圖數據。單位是度,適合存儲和表示地理坐標。
  • UTM (Universal Transverse Mercator): 基于米單位的投影系統,將地球劃分為 60 個區域,適合局部區域的高精度計算。例如,UTM Zone 50N (EPSG:32650) 用于東亞部分地區。
  • Web Mercator (EPSG:3857): 廣泛用于在線地圖(如 Google Maps、OpenStreetMap),以米為單位,適合網絡地圖渲染,但會引入投影變形。
  • **CGCS2000(EPSG:4490)**2000國家大地坐標系,是中國當前最新的國家大地坐標系,000國家大地坐標系的原點為包括海洋和大氣]的整個地球的質量中心

為什么 CRS 重要?

  1. 數據一致性: 不同數據源可能使用不同 CRS,未正確轉換會導致位置錯誤。
  2. 計算精度: 不同 CRS 的單位和投影會影響距離、面積等計算結果。
  3. 互操作性: 在多系統集成時,統一 CRS 確保數據無縫對接。

示例場景:

  • 假設你有一個 WGS84 坐標點 (經度: 116.4, 緯度: 39.9,北京),需要將其轉換為 Web Mercator 以在地圖上顯示。如果不進行 CRS 轉換,直接繪制會導致位置偏差。

EPSG 代碼的概念與查詢

EPSG 代碼是由國際石油工業協會 (OGP) 定義的標準化編號,用于唯一標識 CRS。例如:

  • EPSG:4326 表示 WGS84。
  • EPSG:3857 表示 Web Mercator。
  • EPSG:32650 表示 UTM Zone 50N。

如何查詢 EPSG 代碼?

  1. 在線資源:
    • epsg.io: 輸入地區或 CRS 名稱(如 “WGS84” 或 “China”)即可查找相關 EPSG 代碼。
    • spatialreference.org: 提供 CRS 定義和 GeoTools 兼容的引用。
  2. GeoTools 內置查詢: GeoTools 提供了 CRS.lookupIdentifier() 方法,可以通過 CRS 對象反查 EPSG 代碼。

代碼示例: 查詢 CRS 的 EPSG 代碼

import org.geotools.referencing.CRS;public class CRSLookupExample {public static void main(String[] args) throws Exception {// 定義 WGS84 CRSCoordinateReferenceSystem crs = CRS.decode("EPSG:4326");// 查詢 EPSG 代碼String epsgCode = CRS.lookupIdentifier(crs, true);System.out.println("EPSG Code: " + epsgCode); // 輸出: EPSG:4326}
}

定義和獲取 CRS

GeoTools 使用 CRS.decode() 方法通過 EPSG 代碼定義 CRS。以下是常見操作的代碼示例。

定義 CRS

import org.geotools.referencing.CRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;public class DefineCRSExample {public static void main(String[] args) throws Exception {// 定義 WGS84 (EPSG:4326)CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");System.out.println("WGS84 CRS: " + wgs84.getName());// 定義 Web Mercator (EPSG:3857)CoordinateReferenceSystem webMercator = CRS.decode("EPSG:3857");System.out.println("Web Mercator CRS: " + webMercator.getName());// 定義 UTM Zone 50N (EPSG:32650)CoordinateReferenceSystem utm50N = CRS.decode("EPSG:32650");System.out.println("UTM Zone 50N CRS: " + utm50N.getName());}
}

輸出:

WGS84 CRS: WGS 84
Web Mercator CRS: WGS 84 / Pseudo-Mercator
UTM Zone 50N CRS: WGS 84 / UTM zone 50N

處理異常

CRS.decode() 可能拋出 FactoryException,通常是因為 EPSG 代碼無效或 GeoTools 無法解析。建議始終使用 try-catch 捕獲異常。


坐標轉換

坐標轉換是將一個 CRS 中的坐標轉換為另一個 CRS 的過程。GeoTools 提供了 CRS.findMathTransform() 和 JTS.transform() 方法來實現轉換。

基本流程

  1. 獲取源和目標 CRS。
  2. 使用 CRS.findMathTransform(sourceCRS, targetCRS) 創建轉換器。
  3. 使用 JTS.transform() 執行坐標轉換。

代碼示例:點轉換

以下示例將北京的 WGS84 坐標 (116.4, 39.9) 轉換為 Web Mercator。(記得看注意事項)

import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;public class CoordinateTransformExample {public static void main(String[] args) throws Exception {// 定義源和目標 CRSCoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");CoordinateReferenceSystem webMercator = CRS.decode("EPSG:3857");// 創建坐標轉換器MathTransform transform = CRS.findMathTransform(wgs84, webMercator);// 創建 WGS84 坐標點 (北京: 116.4, 39.9)GeometryFactory factory = new GeometryFactory();Point point = factory.createPoint(new Coordinate(116.4, 39.9));// 執行轉換Point transformedPoint = (Point) JTS.transform(point, transform);// 輸出結果System.out.println("WGS84 Point: " + point);System.out.println("Web Mercator Point: " + transformedPoint);}
}

輸出:

WGS84 Point: POINT (116.4 39.9)
Web Mercator Point: POINT (12957326.04 4852936.40)

解釋:

  • WGS84 坐標 (116.4, 39.9) 是經緯度,單位為度。
  • Web Mercator 坐標 (12957326.04, 4852936.40) 是以米為單位的投影坐標。

柵格坐標轉換

import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.coverage.processing.operation.Resample;
import org.geotools.referencing.CRS;
import org.geotools.util.factory.Hints;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CoordinateReferenceSystem;import java.io.File;public class RasterTransformExample {public static void main(String[] args) throws Exception {// 輸入和輸出文件路徑File inputFile = new File("input.tif"); // 替換為你的 GeoTIFF 文件File outputFile = new File("output_transformed.tif");// 讀取柵格數據GridCoverage2DReader reader = GridFormatFinder.getFormat(inputFile).getReader(inputFile);GridCoverage2D coverage = reader.read(null);// 定義源和目標 CRSCoordinateReferenceSystem sourceCRS = coverage.getCoordinateReferenceSystem();CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); // Web Mercator// 配置重采樣參數CoverageProcessor processor = CoverageProcessor.getInstance();ParameterValueGroup params = processor.getOperation("Resample").getParameters();params.parameter("Source").setValue(coverage);params.parameter("CoordinateReferenceSystem").setValue(targetCRS);params.parameter("InterpolationType").setValue("bilinear"); // 雙線性插值// 執行重投影GridCoverage2D reprojected = (GridCoverage2D) processor.doOperation(params);// 保存結果AbstractGridFormat format = GridFormatFinder.getFormat(outputFile);format.write(reprojected, new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE), outputFile);System.out.println("Raster transformation completed. Output saved to: " + outputFile.getAbsolutePath());}
}

說明

  • 輸入: 一個 GeoTIFF 文件 (input.tif),假設其 CRS 為 WGS84 (EPSG:4326)。
  • 轉換: 使用 CoverageProcessor 和 Resample 操作將柵格數據重投影到 Web Mercator (EPSG:3857)。
  • 插值: 使用雙線性插值 (bilinear) 確保像素值平滑過渡,也可選擇 nearest(最近鄰)或 bicubic(雙三次)。
  • 輸出: 保存為新的 GeoTIFF 文件 (output_transformed.tif)。
  • 注意: 確保 input.tif 存在且具有正確的 CRS 元數據。GeoTools 依賴文件的 CRS 信息來識別源 CRS。

shape數據轉換

import org.geotools.data.DataStore;
import org.geotools.data.DataUtilities;
import org.geotools.data.FeatureWriter;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;import java.io.File;
import java.nio.charset.StandardCharsets;public class ShapefileTransformExample {public static void main(String[] args) throws Exception {// 輸入和輸出文件File inputFile = new File("input.shp"); // 替換為你的 ShapefileFile outputFile = new File("output_transformed.shp");// 讀取 ShapefileShapefileDataStore inputStore = new ShapefileDataStore(inputFile.toURI().toURL());String typeName = inputStore.getTypeNames()[0];SimpleFeatureSource featureSource = inputStore.getFeatureSource(typeName);SimpleFeatureCollection featureCollection = featureSource.getFeatures();// 定義源和目標 CRSCoordinateReferenceSystem sourceCRS = featureSource.getSchema().getCoordinateReferenceSystem();CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); // Web Mercator// 創建坐標轉換器MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS);// 創建輸出 Shapefile 的 FeatureTypeSimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();builder.setName(featureSource.getSchema().getName());builder.setAttributes(featureSource.getSchema().getAttributes());builder.setCRS(targetCRS); // 設置目標 CRSSimpleFeatureType targetFeatureType = builder.buildFeatureType();// 創建輸出 ShapefileShapefileDataStore outputStore = new ShapefileDataStore(outputFile.toURI().toURL());outputStore.createSchema(targetFeatureType);outputStore.setCharset(StandardCharsets.UTF_8);// 寫入轉換后的特征try (FeatureWriter<SimpleFeatureType, SimpleFeature> writer = outputStore.getFeatureWriterAppend(typeName)) {try (SimpleFeatureIterator iterator = featureCollection.features()) {while (iterator.hasNext()) {SimpleFeature feature = iterator.next();SimpleFeature newFeature = DataUtilities.createFeature(targetFeatureType, feature.getID());// 復制屬性for (int i = 0; i < feature.getAttributeCount(); i++) {newFeature.setAttribute(i, feature.getAttribute(i));}// 轉換幾何Geometry geometry = (Geometry) feature.getDefaultGeometry();Geometry transformedGeometry = JTS.transform(geometry, transform);newFeature.setDefaultGeometry(transformedGeometry);// 寫入新特征writer.next().setAttributes(newFeature.getAttributes());writer.write();}}}// 清理資源inputStore.dispose();outputStore.dispose();System.out.println("Shapefile transformation completed. Output: " + outputFile.getAbsolutePath());}
}

說明

  • 輸入: 一個 WGS84 的 Shapefile (input.shp)。
  • 轉換: 使用 JTS.transform() 轉換每個特征的幾何對象。
  • 輸出: 保存為新的 Shapefile (output_transformed.shp),CRS 為 Web Mercator。
  • 注意:
    • 確保輸入 Shapefile 包含 .shp、.shx、.dbf 和 .prj 文件,尤其是 .prj 文件定義了源 CRS。
    • 使用 StandardCharsets.UTF_8 避免中文屬性亂碼。

geojson轉換

import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;import java.io.File;
import java.io.FileOutputStream;public class GeoJSONTransformExample {public static void main(String[] args) throws Exception {// 輸入和輸出文件File inputFile = new File("input.geojson"); // 替換為你的 GeoJSON 文件File outputFile = new File("output_transformed.geojson");// 讀取 GeoJSONFeatureJSON featureJSON = new FeatureJSON();SimpleFeatureCollection featureCollection = featureJSON.readFeatureCollection(inputFile);// 定義源和目標 CRSCoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326"); // GeoJSON 默認 WGS84CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); // Web Mercator// 創建坐標轉換器MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS);// 創建輸出 FeatureTypeSimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();builder.setName("TransformedFeatures");builder.setAttributes(featureCollection.getSchema().getAttributes());builder.setCRS(targetCRS);SimpleFeatureType targetFeatureType = builder.buildFeatureType();// 創建新的 FeatureCollectionorg.geotools.feature.FeatureCollection<SimpleFeatureType, SimpleFeature> transformedFeatures =DataUtilities.collection(featureCollection.size());// 轉換每個特征try (SimpleFeatureIterator iterator = featureCollection.features()) {while (iterator.hasNext()) {SimpleFeature feature = iterator.next();SimpleFeature newFeature = DataUtilities.createFeature(targetFeatureType, feature.getID());// 復制屬性for (int i = 0; i < feature.getAttributeCount(); i++) {newFeature.setAttribute(i, feature.getAttribute(i));}// 轉換幾何Geometry geometry = (Geometry) feature.getDefaultGeometry();Geometry transformedGeometry = JTS.transform(geometry, transform);newFeature.setDefaultGeometry(transformedGeometry);// 添加到集合transformedFeatures.add(newFeature);}}// 保存轉換后的 GeoJSONtry (FileOutputStream fos = new FileOutputStream(outputFile)) {featureJSON.writeFeatureCollection(transformedFeatures, fos);}System.out.println("GeoJSON transformation completed. Output: " + outputFile.getAbsolutePath());}
}

說明

  • 輸入: 一個 GeoJSON 文件 (input.geojson),默認 CRS 為 WGS84。
  • 轉換: 使用 JTS.transform() 轉換每個特征的幾何。
  • 輸出: 保存為新的 GeoJSON 文件 (output_transformed.geojson),幾何坐標為 Web Mercator。
  • 注意:
    • GeoJSON 標準默認使用 WGS84,輸出的 GeoJSON 文件不會顯式存儲 CRS 信息,需在文檔或元數據中說明。
    • 確保 GeoJSON 文件格式正確,包含 type: FeatureCollection 或 type: Feature。

注意事項

  • 經緯度順序: WGS84 使用 (經度, 緯度),但某些 CRS 可能要求 (緯度, 經度)。GeoTools 會自動處理,但建議檢查 CRS.getAxisOrder()。

  • 性能優化: MathTransform 對象可復用,避免重復創建。

  • 異常處理: 確保捕獲 FactoryException 和 TransformException。

    上述示例代碼沒有任何問題,但是運行絕對不會得到輸出的結果,24-R得不到。原因就出在了經緯度順序上。如果你換一種方式定義,就沒問題了

        public  String transformAndBufferWkt(String wkt, double bufferDistance) throws Exception {// 1. 解析 WKT 字符串為 Geometry 對象WKTReader wktReader = new WKTReader();Geometry geometry = wktReader.read(wkt);// 2. 定義源坐標系 (EPSG:4326) 和目標坐標系 (EPSG:3857)CoordinateReferenceSystem sourceCRS = getCRS4326();CoordinateReferenceSystem targetCRS =getCRS3857();// 3. 創建坐標轉換器MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);// 4. 將幾何對象從 EPSG:4326 轉換為 EPSG:3857Geometry geometry3857 = JTS.transform(geometry, transform);// 5. 生成緩沖區(單位為米,因為 EPSG:3857 使用米)Geometry buffer = geometry3857.buffer(bufferDistance);// 6. 將緩沖區幾何對象轉換回 WKTWKTWriter wktWriter = new WKTWriter();return wktWriter.write(buffer);}private  CoordinateReferenceSystem getCRS4326(){try {String str = "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433],AUTHORITY[\"EPSG\",4326]]";return CRS.parseWKT(str);}catch (Exception e){System.out.println(e.getMessage());return null;}}private  CoordinateReferenceSystem getCRS3857() {try {String str = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\",GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_Auxiliary_Sphere\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"Standard_Parallel_1\",0.0],PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",3857]]";return CRS.parseWKT(str);}catch (Exception e){System.out.println(e.getMessage());return null;}}

在 Spring Boot 應用中處理 CRS 數據

在實際項目中,Spring Boot 常用于構建 REST API,處理不同 CRS 的空間數據。以下是一個完整示例,展示如何在 Spring Boot 中接收 WGS84 坐標,轉換為 Web Mercator,并返回結果。

項目依賴

在 pom.xml 中添加 GeoTools 和 JTS 依賴:

<dependencies><!-- GeoTools --><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>25.0</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>25.0</version></dependency><!-- JTS --><dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.18.2</version></dependency><!-- 柵格 支持 --><dependency><groupId>org.geotools</groupId><artifactId>gt-geotiff</artifactId><version>25.0</version></dependency><!-- Shapefile 支持 --><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>25.0</version></dependency><!-- GeoJSON 支持 --><dependency><groupId>org.geotools</groupId><artifactId>gt-geojson</artifactId><version>25.0</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-coverage</artifactId><version>25.0</version></dependency><!-- Spring Boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.2.0</version></dependency>
</dependencies><repositories><repository><id>osgeo</id><url>https://repo.osgeo.org/repository/release/</url></repository>
</repositories>

創建 REST API

以下是一個 Spring Boot 控制器,用于接收 WGS84 坐標并轉換為 Web Mercator。

import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class CoordinateController {private final GeometryFactory factory = new GeometryFactory();@GetMapping("/transform")public String transformCoordinates(@RequestParam double lon,@RequestParam double lat) throws Exception {// 定義源和目標 CRSCoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");CoordinateReferenceSystem webMercator = CRS.decode("EPSG:3857");// 創建坐標轉換器MathTransform transform = CRS.findMathTransform(wgs84, webMercator);// 創建 WGS84 坐標點Point point = factory.createPoint(new Coordinate(lon, lat));// 執行轉換Point transformedPoint = (Point) JTS.transform(point, transform);// 返回結果return String.format("WGS84: %s, Web Mercator: %s", point, transformedPoint);}
}

測試 API

啟動 Spring Boot 應用后,使用以下命令測試:

curl "http://localhost:8080/transform?lon=116.4&lat=39.9"

響應:

WGS84: POINT (116.4 39.9), Web Mercator: POINT (12957326.04 4852936.40)

擴展:處理多種 CRS

若需要支持用戶指定的目標 CRS,可以添加參數:

@GetMapping("/transform")
public String transformCoordinates(@RequestParam double lon,@RequestParam double lat,@RequestParam String targetEpsg) throws Exception {CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");CoordinateReferenceSystem targetCrs = CRS.decode(targetEpsg);MathTransform transform = CRS.findMathTransform(wgs84, targetCrs);Point point = factory.createPoint(new Coordinate(lon, lat));Point transformedPoint = (Point) JTS.transform(point, transform);return String.format("WGS84: %s, %s: %s", point, targetEpsg, transformedPoint);
}

測試:

curl "http://localhost:8080/transform?lon=116.4&lat=39.9&targetEpsg=EPSG:32650"

響應:

WGS84: POINT (116.4 39.9), EPSG:32650: POINT (370139.44 4412630.12)

實際應用中的注意事項

  1. CRS 選擇:
    • 根據應用場景選擇合適的 CRS。例如,Web 地圖使用 EPSG:3857,區域分析使用 UTM。
  2. 性能優化:
    • 緩存 MathTransform 對象,避免重復創建。
    • 使用批量轉換處理大量坐標點。
  3. 數據驗證:
    • 驗證輸入坐標是否在 CRS 的有效范圍內(例如,UTM 僅適用于特定區域)。
  4. 異常處理:
    • 捕獲 FactoryException(CRS 定義失敗)和 TransformException(轉換失敗)。

通過本文,我們深入探討了 GeoTools 中 CRS 和坐標轉換的核心概念:

  • CRS 重要性: 確保數據一致性和計算精度。
  • EPSG 代碼: 標準化的 CRS 標識,可通過在線工具或 GeoTools 查詢。
  • 定義和轉換: 使用 CRS.decode() 定義 CRS,CRS.findMathTransform() 和 JTS.transform() 實現坐標轉換。
  • Spring Boot 集成: 通過 REST API 實現靈活的坐標轉換服務。

希望這些示例和講解能幫助你快速上手 GeoTools 的 CRS 功能,并在實際項目中高效處理空間數據!如果有更多問題,歡迎隨時交流。


參考資源:

  • GeoTools 官方文檔
  • EPSG 數據庫
  • GeoTools GitHub

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

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

相關文章

docker start mysql失敗,解決方案

文章目錄 1.查看端口占用情況2.關閉7767進程3.再次檢查4.運行docker start mysql 1.查看端口占用情況 sudo netstat -tanlp | grep :33062.關閉7767進程 sudo kill -9 77673.再次檢查 進程已關閉 4.運行docker start mysql 正確啟動 備注&#xff1a;可能要關閉防火墻

SQL關鍵字三分鐘入門:DELETE —— 刪除數據

在數據庫操作中&#xff0c;除了添加和修改記錄外&#xff0c;我們有時還需要刪除不需要的記錄。例如&#xff1a; 清除不再使用的用戶賬號&#xff1b;刪除已完成并歸檔的訂單&#xff1b;移除測試時插入的數據。 這時候就需要用到 SQL 中非常基礎但極其重要的關鍵字 —— D…

electron 全量更新

electron-builder.yml配置更新地址 # 配置自動更新的信息 publish:provider: generic # 更新服務提供者url: http://xxx.xxxx.com/pc/xxx-xx# 更新的地址服務器地址 會自動讀取latest.yml 下的版本號比較 檢測更新方法autoUpdater.js// src/main/autoUpdater.jsimport { app, d…

《大模型 Agent 應用實戰指南》第2章:商業目標與 Agent 能力邊界定義

在任何技術項目,特別是像大模型 Agent 這樣具有創新性和復雜性的項目啟動之初,明確清晰的商業目標是成功的基石。這不僅僅是技術團隊的職責,更需要產品、運營、銷售甚至高層管理者的深度參與。一個明確的目標能確保所有團隊成員步調一致,資源有效分配,并最終衡量項目的成功…

提供穩定可靠的自助共享空間系統,支撐客戶無人自助門店運營不錯數據,歷程感想

以技術產品研發系統為主&#xff0c;為客戶提供自助共享空間系統解決方案&#xff0c;適用于共享棋牌室&#xff0c;共享麻將室&#xff0c;共享臺球室&#xff0c;共享KTV&#xff0c;共享舞蹈室等場景&#xff0c;以下是其中一位客戶真實門店運營數據&#xff0c;第一家店本月…

Golang單例實現

Go語言中&#xff0c;實現單例模式的方式有很多種。單例模式確保一個類只有一個實例&#xff0c;并提供一個全局訪問點。Go語言沒有類的概念&#xff0c;但是可以通過結構體、函數和包級變量來實現類似的功能。 懶漢實現 type Product interface {DoSomething() }type single…

JVM元空間(Metaspace)詳解及其工作流程

JVM元空間(Metaspace)詳解與工作流程分析 元空間概述 元空間(Metaspace)是Java虛擬機(JVM)在HotSpot VM 1.8及以后版本中引入的&#xff0c;用于替代永久代(PermGen)的內存區域。它主要存儲類的元數據信息&#xff0c;包括&#xff1a; 類的結構信息&#xff08;如方法、字段…

【JAVA】idea中打成jar包后報錯錯誤: 找不到或無法加載主類

排查步驟 首先要排查的是&#xff0c;將jar文件打開&#xff0c;查看里面的內容是否完整是否有META-INF/MANIFEST.MF是否有MANIFEST.MF里面類路徑的目錄排查路徑里面是否有class文件&#xff0c;如主類 com.example.Main 對應的 class 文件應位于 com/example/Main.class 常見…

Fisco Bcos學習 - 開發第一個區塊鏈應用

文章目錄 一、前言二、業務場景分析&#xff1a;簡易資產管理系統三、智能合約設計與實現3.1 存儲結構設計3.2 接口設計3.3 完整合約代碼 四、合約編譯與Java接口生成五、SDK配置與項目搭建5.1 獲取Java工程項目5.2 項目目錄結構5.3 引入Web3SDK5.4 證書與配置文件 六、業務開發…

軟件設計模式選擇、判斷解析-1

前言 解析是我個人的理解&#xff0c;相對來說我覺得是能對上定義的邏輯的 目錄 一.單選題 1.設計模式的兩大主題是(??)? 解析&#xff1a;無 2.下列模式中,屬于行為型模式的是&#xff08;&#xff09; 解析&#xff1a; 排除A和D&#xff0c;剩下的觀察者的“觀察”…

【編程基本功】Win11中Git安裝配置全攻略,包含Git以及圖形化工具TortoiseGit

1 摘要 今天田辛老師給大家帶來了一份超實用的博客&#xff0c;手把手教你安裝并配置 Git 及其圖形化界面 TortoiseGit&#xff0c;從官網下載到最終完成配置&#xff0c;每一個步驟都給大家講得明明白白&#xff0c;還配有相應的截圖&#xff0c;即使是新手小白也能輕松上手&…

細談QT信號與槽機制

轉自個人博客 信號與槽是我個人認為QT中最牛的機制之一&#xff0c;最近沒有其他的內容可寫&#xff0c;今天就來細細總結一下這個信號與槽機制。 1. 信號與槽機制概述 信號與槽機制可以理解為QT中的一種通信手段&#xff0c;在運行相關代碼前&#xff0c;分別聲明信號和槽&a…

Docker Swarm 與 Kubernetes 在集群管理上的主要區別

Docker Swarm 和 Kubernetes 是兩種流行的容器編排工具&#xff0c;它們都可以用于部署、管理和擴展容器化應用&#xff0c;但在集群管理方面有明顯的差異。 下面從多個維度對比它們在集群管理上的主要區別&#xff1a; ? 一、總體定位 項目Docker SwarmKubernetes官方支持D…

【StarRocks系列】查詢優化

步驟參考官網 分析查詢 | StarRocks StarRocks-Profile分析及優化指南 StarRocks-Profile分析及優化指南 - 經驗教程 - StarRocks中文社區論壇

軟測八股--測試理論 1 測試基礎

軟件測試&#xff1f; 發現程序中的側屋執行程序工程 目的&#xff1a;不僅是找出錯誤&#xff0c;還要分析錯誤產生原因和錯誤分布。檢查開發如阿健過程出現的bug&#xff0c;使開發人員及時修改。測試只能說明軟件中存在錯誤 目標&#xff1a;盡可能發現多的錯誤。一個好的…

mfc與vs成功在xp系統所需做的修改

目錄 前言一、MFC程序 inet_pton 、CT2A 未聲明問題1&#xff09;問題1&#xff1a;inet_pton &#xff1a;undeclared identifier - inet_pton未聲明2&#xff09;問題1&#xff1a;CT2A &#xff1a;undeclared identifier - CT2A未聲明 二、VS程序 使用事件、委托問題1&…

SpringMVC系列(三)(請求處理的十個實驗(上))

0 引言 作者正在學習SpringMVC相關內容&#xff0c;學到了一些知識&#xff0c;希望分享給需要短時間想要了解SpringMVC的讀者朋友們&#xff0c;想用通俗的語言講述其中的知識&#xff0c;希望與諸位共勉&#xff0c;共同進步&#xff01; 本系列會持續更新&#xff01;&…

Python案例練習:函數專題

用函數重新設計文章單詞出現次數程序 composition This is my family. We have a father, a mother and two brothers. My father is a doctor. He works in a hospital. My mother is a teacher. She teaches English in a school. My older brother is a student. He stu…

數據驅動 AI 時代:數據庫行業的技術躍遷與生態重構

在數據驅動的 AI 戰場&#xff0c;真正的決勝武器不是復雜精妙的算法模型&#xff0c;而是深埋在企業核心系統中的高維數據網絡&#xff08;圖&#xff09;。 時至今日&#xff0c;市場對AI的風向正從“狂飆突進”轉向“精耕細作”&#xff0c;就在上周&#xff08;米國時間6月…

碼分復用通俗理解

一、碼分復用&#xff08;CDMA&#xff09;的通俗理解 碼分復用&#xff08;Code Division Multiple Access&#xff0c;CDMA&#xff09;是一種讓多個用戶在同一時間、同一頻段上同時傳輸數據的技術。它的核心思想是&#xff1a;給每個用戶分配一個唯一的“編碼鑰匙”&#x…