第10章-坐标系统与投影转换

第10章:坐标系统与投影转换

10.1 坐标系统基础

10.1.1 常用坐标系统

EPSG 名称 类型 用途
4326 WGS84 地理坐标系 GPS、通用经纬度
3857 Web Mercator 投影坐标系 网络地图
4490 CGCS2000 地理坐标系 中国国家标准
4547 CGCS2000 / 3度带 投影坐标系 中国大比例尺测绘

10.1.2 WKT 格式

// WGS84 WKT
string wgs84Wkt = @"
GEOGCS[""WGS 84"",
    DATUM[""WGS_1984"",
        SPHEROID[""WGS 84"",6378137,298.257223563]],
    PRIMEM[""Greenwich"",0],
    UNIT[""degree"",0.0174532925199433]]";

// Web Mercator WKT
string webMercatorWkt = @"
PROJCS[""WGS 84 / Pseudo-Mercator"",
    GEOGCS[""WGS 84"",
        DATUM[""WGS_1984"",
            SPHEROID[""WGS 84"",6378137,298.257223563]],
        PRIMEM[""Greenwich"",0],
        UNIT[""degree"",0.0174532925199433]],
    PROJECTION[""Mercator_1SP""],
    PARAMETER[""central_meridian"",0],
    PARAMETER[""scale_factor"",1],
    PARAMETER[""false_easting"",0],
    PARAMETER[""false_northing"",0],
    UNIT[""metre"",1]]";

10.2 ProjNet 使用

10.2.1 安装配置

Install-Package ProjNet

10.2.2 创建坐标系统

using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;

var csFactory = new CoordinateSystemFactory();
var ctFactory = new CoordinateTransformationFactory();

// 从 WKT 创建
var wgs84 = csFactory.CreateFromWkt(wgs84Wkt);

// 使用预定义
var wgs84_2 = GeographicCoordinateSystem.WGS84;

// 创建投影坐标系
var webMercator = csFactory.CreateFromWkt(webMercatorWkt);

10.2.3 坐标转换

// 创建转换
var wgs84ToMercator = ctFactory.CreateFromCoordinateSystems(wgs84, webMercator);
var mercatorToWgs84 = ctFactory.CreateFromCoordinateSystems(webMercator, wgs84);

// 转换单个坐标
double[] input = { 116.4, 39.9 };  // 经度, 纬度
double[] output = wgs84ToMercator.MathTransform.Transform(input);
Console.WriteLine($"Mercator: {output[0]}, {output[1]}");

// 批量转换
double[] coords = { 116.4, 39.9, 121.5, 31.2, 113.3, 23.1 };
double[] transformed = new double[coords.Length];
wgs84ToMercator.MathTransform.Transform(coords, 0, transformed, 0, 3);

10.2.4 应用到图层

// 设置图层坐标转换
vectorLayer.CoordinateTransformation = wgs84ToMercator;
vectorLayer.ReverseCoordinateTransformation = mercatorToWgs84;

// 或者转换整个数据源
public static Geometry TransformGeometry(Geometry geometry, 
    ICoordinateTransformation transformation)
{
    var transformed = geometry.Copy();
    TransformCoordinates(transformed, transformation.MathTransform);
    return transformed;
}

private static void TransformCoordinates(Geometry geometry, IMathTransform transform)
{
    foreach (var coord in geometry.Coordinates)
    {
        var result = transform.Transform(new[] { coord.X, coord.Y });
        coord.X = result[0];
        coord.Y = result[1];
    }
}

10.3 CGCS2000 坐标系

10.3.1 CGCS2000 定义

// CGCS2000 地理坐标系
string cgcs2000Wkt = @"
GEOGCS[""China Geodetic Coordinate System 2000"",
    DATUM[""China_2000"",
        SPHEROID[""CGCS2000"",6378137,298.257222101]],
    PRIMEM[""Greenwich"",0],
    UNIT[""degree"",0.0174532925199433]]";

// CGCS2000 / 3度带 (以 117度为中央经线)
string cgcs2000_3degreeWkt = @"
PROJCS[""CGCS2000 / 3-degree Gauss-Kruger zone 39"",
    GEOGCS[""China Geodetic Coordinate System 2000"",
        DATUM[""China_2000"",
            SPHEROID[""CGCS2000"",6378137,298.257222101]],
        PRIMEM[""Greenwich"",0],
        UNIT[""degree"",0.0174532925199433]],
    PROJECTION[""Transverse_Mercator""],
    PARAMETER[""latitude_of_origin"",0],
    PARAMETER[""central_meridian"",117],
    PARAMETER[""scale_factor"",1],
    PARAMETER[""false_easting"",39500000],
    PARAMETER[""false_northing"",0],
    UNIT[""metre"",1]]";

10.3.2 CGCS2000 转换

public class Cgcs2000Helper
{
    private readonly CoordinateSystemFactory _csFactory;
    private readonly CoordinateTransformationFactory _ctFactory;
    
    public Cgcs2000Helper()
    {
        _csFactory = new CoordinateSystemFactory();
        _ctFactory = new CoordinateTransformationFactory();
    }
    
    // WGS84 转 CGCS2000(两者差异很小,通常可直接使用)
    public Coordinate Wgs84ToCgcs2000(Coordinate point)
    {
        // WGS84 和 CGCS2000 椭球参数几乎相同
        // 在厘米级精度下可直接使用
        return point;
    }
    
    // CGCS2000 地理坐标转投影坐标
    public Coordinate Cgcs2000ToProjected(Coordinate point, int centralMeridian)
    {
        var geoCS = _csFactory.CreateFromWkt(GetCgcs2000GeographicWkt());
        var projCS = _csFactory.CreateFromWkt(GetCgcs2000ProjectedWkt(centralMeridian));
        
        var transform = _ctFactory.CreateFromCoordinateSystems(geoCS, projCS);
        var result = transform.MathTransform.Transform(new[] { point.X, point.Y });
        
        return new Coordinate(result[0], result[1]);
    }
    
    // 根据经度自动选择带号
    public int GetZoneNumber(double longitude)
    {
        return (int)Math.Floor((longitude + 1.5) / 3);
    }
    
    private string GetCgcs2000GeographicWkt() => cgcs2000Wkt;
    
    private string GetCgcs2000ProjectedWkt(int centralMeridian)
    {
        int zoneNumber = (centralMeridian + 3) / 3;
        return $@"
PROJCS[""CGCS2000 / 3-degree Gauss-Kruger zone {zoneNumber}"",
    GEOGCS[""China Geodetic Coordinate System 2000"",
        DATUM[""China_2000"",
            SPHEROID[""CGCS2000"",6378137,298.257222101]],
        PRIMEM[""Greenwich"",0],
        UNIT[""degree"",0.0174532925199433]],
    PROJECTION[""Transverse_Mercator""],
    PARAMETER[""latitude_of_origin"",0],
    PARAMETER[""central_meridian"",{centralMeridian}],
    PARAMETER[""scale_factor"",1],
    PARAMETER[""false_easting"",{zoneNumber * 1000000 + 500000}],
    PARAMETER[""false_northing"",0],
    UNIT[""metre"",1]]";
    }
}

10.4 坐标转换工具类

10.4.1 通用转换器

public class CoordinateTransformService
{
    private readonly Dictionary<string, ICoordinateSystem> _coordinateSystems;
    private readonly CoordinateSystemFactory _csFactory;
    private readonly CoordinateTransformationFactory _ctFactory;
    
    public CoordinateTransformService()
    {
        _csFactory = new CoordinateSystemFactory();
        _ctFactory = new CoordinateTransformationFactory();
        _coordinateSystems = new Dictionary<string, ICoordinateSystem>();
        
        InitializeCommonCoordinateSystems();
    }
    
    private void InitializeCommonCoordinateSystems()
    {
        _coordinateSystems["EPSG:4326"] = GeographicCoordinateSystem.WGS84;
        _coordinateSystems["EPSG:3857"] = CreateWebMercator();
        // 添加更多...
    }
    
    public void RegisterCoordinateSystem(string code, string wkt)
    {
        _coordinateSystems[code] = _csFactory.CreateFromWkt(wkt);
    }
    
    public Coordinate Transform(Coordinate point, string sourceCode, string targetCode)
    {
        var sourceCS = _coordinateSystems[sourceCode];
        var targetCS = _coordinateSystems[targetCode];
        var transform = _ctFactory.CreateFromCoordinateSystems(sourceCS, targetCS);
        
        var result = transform.MathTransform.Transform(new[] { point.X, point.Y });
        return new Coordinate(result[0], result[1]);
    }
    
    public IEnumerable<Coordinate> TransformAll(IEnumerable<Coordinate> points, 
        string sourceCode, string targetCode)
    {
        var sourceCS = _coordinateSystems[sourceCode];
        var targetCS = _coordinateSystems[targetCode];
        var transform = _ctFactory.CreateFromCoordinateSystems(sourceCS, targetCS);
        
        return points.Select(p =>
        {
            var result = transform.MathTransform.Transform(new[] { p.X, p.Y });
            return new Coordinate(result[0], result[1]);
        });
    }
}

10.5 与地图集成

10.5.1 动态投影

public class ProjectedMapManager
{
    private readonly Map _map;
    private readonly CoordinateTransformService _transformService;
    private string _currentProjection = "EPSG:3857";
    
    public ProjectedMapManager(Map map)
    {
        _map = map;
        _transformService = new CoordinateTransformService();
    }
    
    public void SetProjection(string projectionCode)
    {
        if (_currentProjection == projectionCode)
            return;
        
        // 更新所有图层的坐标转换
        foreach (var layer in _map.Layers.OfType<VectorLayer>())
        {
            UpdateLayerTransformation(layer, projectionCode);
        }
        
        _currentProjection = projectionCode;
    }
    
    private void UpdateLayerTransformation(VectorLayer layer, string targetProjection)
    {
        // 假设数据源坐标系为 WGS84
        string sourceProjection = "EPSG:4326";
        
        // ... 设置坐标转换
    }
}

10.6 本章小结

本章介绍了 SharpMap 的坐标系统与投影转换:

  1. 坐标系基础:了解了常用坐标系和 WKT 格式
  2. ProjNet 使用:掌握了坐标转换的基本方法
  3. CGCS2000:学习了中国坐标系的处理
  4. 工具类实现:了解了通用转换器的设计

下一章预告:第11章将介绍空间查询与分析功能。

posted @ 2026-01-08 14:09  我才是银古  阅读(4)  评论(0)    收藏  举报