第03章-核心架构与类库设计

第03章:核心架构与类库设计

3.1 SharpMap 整体架构

3.1.1 架构概览

SharpMap 采用分层架构设计,各层职责明确,耦合度低:

┌─────────────────────────────────────────────────────────────────────────┐
│                          表现层 (Presentation Layer)                      │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│  │     MapBox      │  │    MapImage     │  │  Custom Control │         │
│  │   (WinForms)    │  │   (WinForms)    │  │     (WPF)       │         │
│  └────────┬────────┘  └────────┬────────┘  └────────┬────────┘         │
└───────────┼─────────────────────┼────────────────────┼──────────────────┘
            │                     │                    │
            └──────────────┬──────┴────────────────────┘
                           ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          核心层 (Core Layer)                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│  │       Map       │──│     Layers      │──│     Styles      │         │
│  │   (地图对象)    │  │    (图层集合)   │  │    (样式系统)   │         │
│  └────────┬────────┘  └────────┬────────┘  └────────┬────────┘         │
│           │                    │                    │                   │
│  ┌────────┴────────┐  ┌────────┴────────┐  ┌────────┴────────┐         │
│  │    Rendering    │  │   Thematics     │  │  Transformations│         │
│  │    (渲染器)     │  │   (主题渲染)    │  │   (坐标变换)    │         │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘         │
└─────────────────────────────────────────────────────────────────────────┘
                           ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          数据层 (Data Layer)                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐         │
│  │   IProvider     │  │  FeatureDataSet │  │    Geometry     │         │
│  │  (数据提供者)   │  │   (要素数据)    │  │    (几何对象)   │         │
│  └────────┬────────┘  └────────┬────────┘  └────────┬────────┘         │
│           │                    │                    │                   │
│  ┌────────┴────────────────────┴────────────────────┴────────┐         │
│  │                    Provider 实现                            │         │
│  │  ShapeFile │ PostGIS │ Ogr │ WMS │ MsSql │ GeoJSON │ ...  │         │
│  └───────────────────────────────────────────────────────────┘         │
└─────────────────────────────────────────────────────────────────────────┘

3.1.2 核心命名空间

SharpMap 的主要命名空间及其功能:

命名空间 功能描述
SharpMap 核心类型,包含 Map 类
SharpMap.Layers 图层类型定义
SharpMap.Data 数据模型和数据集
SharpMap.Data.Providers 数据提供者实现
SharpMap.Styles 样式和符号定义
SharpMap.Rendering 渲染器和渲染逻辑
SharpMap.Rendering.Thematics 主题渲染
SharpMap.CoordinateSystems 坐标系统
SharpMap.Utilities 工具类
SharpMap.Forms WinForms 控件

3.1.3 类图概览

                           ┌─────────────────┐
                           │       Map       │
                           │ (地图容器)      │
                           └────────┬────────┘
                                    │
                    ┌───────────────┼───────────────┐
                    │               │               │
                    ▼               ▼               ▼
           ┌────────────┐  ┌────────────┐  ┌────────────┐
           │   Layers   │  │ Background │  │  Variable  │
           │ Collection │  │   Layers   │  │   Layers   │
           └─────┬──────┘  └─────┬──────┘  └─────┬──────┘
                 │               │               │
                 └───────────────┼───────────────┘
                                 │
                    ┌────────────┴────────────┐
                    │                         │
                    ▼                         ▼
            ┌─────────────┐          ┌─────────────┐
            │    Layer    │          │  IProvider  │
            │  (抽象基类) │          │  (数据接口) │
            └──────┬──────┘          └──────┬──────┘
                   │                        │
    ┌──────────────┼──────────────┐         │
    │              │              │         │
    ▼              ▼              ▼         ▼
┌─────────┐ ┌───────────┐ ┌─────────┐  ┌─────────┐
│Vector   │ │  Label    │ │  Tile   │  │ShapeFile│
│Layer    │ │  Layer    │ │  Layer  │  │Provider │
└─────────┘ └───────────┘ └─────────┘  └─────────┘

3.2 Map 类详解

3.2.1 Map 类定义

Map 类是 SharpMap 的核心类,负责管理地图的所有组件:

namespace SharpMap
{
    public class Map : IDisposable
    {
        // 构造函数
        public Map();
        public Map(Size size);
        
        // 主要属性
        public Size Size { get; set; }
        public Color BackColor { get; set; }
        public int SRID { get; set; }
        public Envelope Envelope { get; set; }
        public double Zoom { get; set; }
        public Coordinate Center { get; set; }
        public double MinimumZoom { get; set; }
        public double MaximumZoom { get; set; }
        public double PixelSize { get; }
        public double PixelWidth { get; }
        public double PixelHeight { get; }
        public double MapScale { get; }
        
        // 图层集合
        public LayerCollection Layers { get; }
        public LayerCollection BackgroundLayer { get; }
        public LayerCollection VariableLayers { get; }
        
        // 主要方法
        public Image GetMap();
        public void ZoomToExtents();
        public void ZoomToBox(Envelope envelope);
        public Coordinate ImageToWorld(PointF point);
        public PointF WorldToImage(Coordinate point);
        
        // 坐标转换
        public ICoordinateTransformation CoordinateTransformation { get; set; }
        
        // 资源释放
        public void Dispose();
    }
}

3.2.2 Map 属性详解

尺寸和外观属性

// 创建地图
var map = new Map(new Size(800, 600));

// 设置背景颜色
map.BackColor = Color.LightBlue;

// 获取/设置地图大小
map.Size = new Size(1024, 768);

// 获取像素大小(地图单位/像素)
double pixelSize = map.PixelSize;
double pixelWidth = map.PixelWidth;
double pixelHeight = map.PixelHeight;

空间属性

// 设置空间参考
map.SRID = 4326;  // WGS84

// 获取/设置地图范围
Envelope extent = map.Envelope;
map.Envelope = new Envelope(-180, 180, -90, 90);

// 获取/设置中心点
Coordinate center = map.Center;
map.Center = new Coordinate(116.4, 39.9);

// 获取/设置缩放级别
double zoom = map.Zoom;
map.Zoom = 10000;  // 地图单位

// 缩放限制
map.MinimumZoom = 0.1;
map.MaximumZoom = 1000000;

比例尺

// 获取当前地图比例尺
double scale = map.MapScale;
Console.WriteLine($"当前比例尺:1:{scale:N0}");

// 设置特定比例尺
map.Zoom = map.GetMapHeight(scale);

3.2.3 图层集合管理

// 普通图层集合(按添加顺序渲染)
map.Layers.Add(vectorLayer);
map.Layers.Insert(0, baseLayer);
map.Layers.Remove(layer);
map.Layers.Clear();

// 背景图层集合(先渲染)
map.BackgroundLayer.Add(tileLayer);

// 动态图层集合(每次重绘都重新获取数据)
map.VariableLayers.Add(realtimeLayer);

// 遍历图层
foreach (ILayer layer in map.Layers)
{
    Console.WriteLine($"图层:{layer.LayerName}");
}

// 按名称获取图层
var layer = map.Layers.FirstOrDefault(l => l.LayerName == "States");

3.2.4 坐标转换方法

// 像素坐标转地理坐标
PointF screenPoint = new PointF(400, 300);
Coordinate worldPoint = map.ImageToWorld(screenPoint);
Console.WriteLine($"地理坐标:{worldPoint.X}, {worldPoint.Y}");

// 地理坐标转像素坐标
Coordinate geoPoint = new Coordinate(116.4, 39.9);
PointF pixelPoint = map.WorldToImage(geoPoint);
Console.WriteLine($"像素坐标:{pixelPoint.X}, {pixelPoint.Y}");

3.2.5 渲染方法

// 渲染地图到 Image
Image mapImage = map.GetMap();

// 保存为文件
mapImage.Save("output.png", ImageFormat.Png);
mapImage.Save("output.jpg", ImageFormat.Jpeg);

// 渲染到 Graphics
using (var bitmap = new Bitmap(800, 600))
using (var graphics = Graphics.FromImage(bitmap))
{
    map.RenderMap(graphics);
    bitmap.Save("output.png");
}

3.3 图层类体系

3.3.1 ILayer 接口

namespace SharpMap.Layers
{
    public interface ILayer : ICloneable
    {
        // 基本属性
        string LayerName { get; set; }
        bool Enabled { get; set; }
        int SRID { get; set; }
        Envelope Envelope { get; }
        
        // 可见性
        double MinVisible { get; set; }
        double MaxVisible { get; set; }
        
        // 坐标转换
        ICoordinateTransformation CoordinateTransformation { get; set; }
        
        // 渲染
        void Render(Graphics g, Map map);
    }
}

3.3.2 Layer 抽象基类

namespace SharpMap.Layers
{
    public abstract class Layer : ILayer, IDisposable
    {
        // 构造函数
        protected Layer(string layerName);
        
        // 属性
        public virtual string LayerName { get; set; }
        public virtual bool Enabled { get; set; }
        public virtual int SRID { get; set; }
        public abstract Envelope Envelope { get; }
        public virtual double MinVisible { get; set; }
        public virtual double MaxVisible { get; set; }
        public virtual double VisibilityUnits { get; set; }
        
        // 坐标转换
        public ICoordinateTransformation CoordinateTransformation { get; set; }
        public ICoordinateTransformation ReverseCoordinateTransformation { get; set; }
        
        // 抽象方法
        public abstract void Render(Graphics g, Map map);
        
        // 释放资源
        public virtual void Dispose();
    }
}

3.3.3 VectorLayer 类

VectorLayer 是最常用的图层类型,用于渲染矢量数据:

namespace SharpMap.Layers
{
    public class VectorLayer : Layer
    {
        // 构造函数
        public VectorLayer(string layerName);
        public VectorLayer(string layerName, IProvider dataSource);
        
        // 数据源
        public IProvider DataSource { get; set; }
        
        // 样式
        public VectorStyle Style { get; set; }
        
        // 主题渲染
        public ITheme Theme { get; set; }
        
        // 平滑模式
        public SmoothingMode SmoothingMode { get; set; }
        
        // 剪裁
        public bool ClippingEnabled { get; set; }
        
        // 重写方法
        public override Envelope Envelope { get; }
        public override void Render(Graphics g, Map map);
        
        // 执行点击查询
        public FeatureDataSet ExecuteIntersectionQuery(Envelope envelope);
        public FeatureDataSet ExecuteIntersectionQuery(Geometry geometry);
    }
}

VectorLayer 使用示例

// 创建矢量图层
var vectorLayer = new VectorLayer("Countries");

// 设置数据源
vectorLayer.DataSource = new ShapeFile("countries.shp", true);

// 设置样式
vectorLayer.Style = new VectorStyle
{
    Fill = new SolidBrush(Color.LightGreen),
    Outline = new Pen(Color.DarkGreen, 1),
    EnableOutline = true,
    PointColor = Brushes.Red,
    PointSize = 10
};

// 设置平滑模式
vectorLayer.SmoothingMode = SmoothingMode.AntiAlias;

// 启用剪裁
vectorLayer.ClippingEnabled = true;

// 设置可见比例尺范围
vectorLayer.MinVisible = 1000;
vectorLayer.MaxVisible = 10000000;

// 添加到地图
map.Layers.Add(vectorLayer);

3.3.4 LabelLayer 类

LabelLayer 用于在地图上渲染文字标注:

namespace SharpMap.Layers
{
    public class LabelLayer : Layer
    {
        // 构造函数
        public LabelLayer(string layerName);
        
        // 数据源
        public IProvider DataSource { get; set; }
        
        // 标注列
        public string LabelColumn { get; set; }
        
        // 样式
        public LabelStyle Style { get; set; }
        
        // 主题
        public ITheme Theme { get; set; }
        
        // 标注委托(动态生成标注文本)
        public GetLabelMethod LabelStringDelegate { get; set; }
        
        // 优先级列(用于标注冲突解决)
        public string PriorityColumn { get; set; }
        
        // 旋转列
        public string RotationColumn { get; set; }
        
        // 多行标注
        public MultipartGeometryBehaviourEnum MultipartGeometryBehaviour { get; set; }
        
        // 平滑模式
        public SmoothingMode SmoothingMode { get; set; }
        public TextRenderingHint TextRenderingHint { get; set; }
    }
    
    // 标注委托类型
    public delegate string GetLabelMethod(FeatureDataRow row);
}

LabelLayer 使用示例

// 创建标注图层
var labelLayer = new LabelLayer("Country Labels");

// 设置数据源(通常与矢量图层相同)
labelLayer.DataSource = vectorLayer.DataSource;

// 设置标注字段
labelLayer.LabelColumn = "NAME";

// 设置样式
labelLayer.Style = new LabelStyle
{
    Font = new Font("Arial", 12, FontStyle.Bold),
    ForeColor = Color.Black,
    BackColor = new SolidBrush(Color.FromArgb(200, 255, 255, 255)),
    HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center,
    VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Middle,
    Offset = new PointF(0, 0),
    Halo = new Pen(Color.White, 2),
    CollisionDetection = true,
    CollisionBuffer = new SizeF(5, 5)
};

// 使用委托动态生成标注文本
labelLayer.LabelStringDelegate = (row) =>
{
    string name = row["NAME"].ToString();
    double area = Convert.ToDouble(row["AREA"]);
    return $"{name}\n({area:N0} km²)";
};

// 设置优先级(高优先级的标注更容易显示)
labelLayer.PriorityColumn = "POPULATION";

// 添加到地图
map.Layers.Add(labelLayer);

3.3.5 TileLayer 类

TileLayer 用于显示瓦片地图服务:

// 需要安装 SharpMap.Layers.BruTile 包
using SharpMap.Layers;
using BruTile;
using BruTile.Web;

// 创建 OpenStreetMap 瓦片源
var osmTileSource = new HttpTileSource(
    new GlobalSphericalMercator(),
    "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
    new[] { "a", "b", "c" },
    "OSM");

// 创建瓦片图层
var tileLayer = new TileLayer(osmTileSource, "OpenStreetMap");

// 添加到背景图层
map.BackgroundLayer.Add(tileLayer);

3.3.6 GdalRasterLayer 类

GdalRasterLayer 用于显示栅格数据(需要 SharpMap.Extensions):

using SharpMap.Layers;

// 创建栅格图层
var rasterLayer = new GdalRasterLayer("Satellite", "satellite.tif");

// 设置透明度
rasterLayer.Transparency = 0.5f;

// 设置透明色
rasterLayer.TransparentColor = Color.Black;

// 添加到地图
map.Layers.Add(rasterLayer);

3.4 数据提供者体系

3.4.1 IProvider 接口

namespace SharpMap.Data.Providers
{
    public interface IProvider : IDisposable
    {
        // 连接状态
        string ConnectionID { get; }
        bool IsOpen { get; }
        void Open();
        void Close();
        
        // 空间参考
        int SRID { get; set; }
        
        // 数据范围
        Envelope GetExtents();
        
        // 查询方法
        Collection<Geometry> GetGeometriesInView(Envelope envelope);
        Collection<uint> GetObjectIDsInView(Envelope envelope);
        Geometry GetGeometryByID(uint oid);
        
        // 要素查询
        void ExecuteIntersectionQuery(Envelope envelope, FeatureDataSet ds);
        void ExecuteIntersectionQuery(Geometry geometry, FeatureDataSet ds);
        FeatureDataRow GetFeature(uint oid);
        
        // 要素数量
        int GetFeatureCount();
    }
}

3.4.2 常用数据提供者

ShapeFile 提供者

using SharpMap.Data.Providers;

// 创建 ShapeFile 提供者
var provider = new ShapeFile("data.shp");
var provider2 = new ShapeFile("data.shp", true);  // 使用文件索引
var provider3 = new ShapeFile("data.shp", true, true);  // 使用空间索引

// 检查属性
Console.WriteLine($"文件路径:{provider.Filename}");
Console.WriteLine($"要素数量:{provider.GetFeatureCount()}");
Console.WriteLine($"数据范围:{provider.GetExtents()}");

// 获取属性表结构
provider.Open();
var table = provider.GetSchemaTable();
foreach (DataColumn column in table.Columns)
{
    Console.WriteLine($"字段:{column.ColumnName} ({column.DataType})");
}
provider.Close();

PostGIS 提供者

using SharpMap.Data.Providers;

// 创建 PostGIS 提供者
string connectionString = "Host=localhost;Database=gisdb;Username=user;Password=pass";
var provider = new PostGIS(connectionString, "tablename", "geom", "gid");

// 设置 SRID
provider.SRID = 4326;

// 设置要查询的字段
provider.DefinitionQuery = "status = 'active'";

// 使用
var layer = new VectorLayer("PostGIS Data", provider);

OGR 提供者(需要 GDAL):

using SharpMap.Data.Providers;

// 创建 OGR 提供者
var provider = new Ogr("data.geojson");
var provider2 = new Ogr("data.kml", 0);  // 指定图层索引

// 支持的格式包括:GeoJSON, KML, GML, GPX, CSV 等

3.4.3 自定义数据提供者

using System.Collections.ObjectModel;
using SharpMap.Data;
using SharpMap.Data.Providers;
using NetTopologySuite.Geometries;

public class CustomProvider : IProvider
{
    private bool _isOpen;
    private List<Geometry> _geometries;
    private List<Dictionary<string, object>> _attributes;
    
    public CustomProvider()
    {
        _geometries = new List<Geometry>();
        _attributes = new List<Dictionary<string, object>>();
    }
    
    public string ConnectionID => "Custom";
    
    public bool IsOpen => _isOpen;
    
    public int SRID { get; set; } = 4326;
    
    public void Open()
    {
        _isOpen = true;
    }
    
    public void Close()
    {
        _isOpen = false;
    }
    
    public void AddFeature(Geometry geometry, Dictionary<string, object> attributes)
    {
        _geometries.Add(geometry);
        _attributes.Add(attributes);
    }
    
    public Envelope GetExtents()
    {
        if (_geometries.Count == 0)
            return new Envelope();
            
        var env = new Envelope();
        foreach (var geom in _geometries)
        {
            env.ExpandToInclude(geom.EnvelopeInternal);
        }
        return env;
    }
    
    public Collection<Geometry> GetGeometriesInView(Envelope envelope)
    {
        var result = new Collection<Geometry>();
        foreach (var geom in _geometries)
        {
            if (envelope.Intersects(geom.EnvelopeInternal))
            {
                result.Add(geom);
            }
        }
        return result;
    }
    
    public Collection<uint> GetObjectIDsInView(Envelope envelope)
    {
        var result = new Collection<uint>();
        for (int i = 0; i < _geometries.Count; i++)
        {
            if (envelope.Intersects(_geometries[i].EnvelopeInternal))
            {
                result.Add((uint)i);
            }
        }
        return result;
    }
    
    public Geometry GetGeometryByID(uint oid)
    {
        if (oid < _geometries.Count)
            return _geometries[(int)oid];
        return null;
    }
    
    public void ExecuteIntersectionQuery(Envelope envelope, FeatureDataSet ds)
    {
        var table = new FeatureDataTable();
        
        // 添加字段
        if (_attributes.Count > 0)
        {
            foreach (var key in _attributes[0].Keys)
            {
                table.Columns.Add(key);
            }
        }
        
        // 添加要素
        for (int i = 0; i < _geometries.Count; i++)
        {
            if (envelope.Intersects(_geometries[i].EnvelopeInternal))
            {
                var row = table.NewRow();
                row.Geometry = _geometries[i];
                
                if (i < _attributes.Count)
                {
                    foreach (var kvp in _attributes[i])
                    {
                        row[kvp.Key] = kvp.Value;
                    }
                }
                
                table.AddRow(row);
            }
        }
        
        ds.Tables.Add(table);
    }
    
    public void ExecuteIntersectionQuery(Geometry geometry, FeatureDataSet ds)
    {
        ExecuteIntersectionQuery(geometry.EnvelopeInternal, ds);
    }
    
    public FeatureDataRow GetFeature(uint oid)
    {
        // 实现获取单个要素
        throw new NotImplementedException();
    }
    
    public int GetFeatureCount()
    {
        return _geometries.Count;
    }
    
    public void Dispose()
    {
        _geometries.Clear();
        _attributes.Clear();
    }
}

// 使用自定义提供者
var customProvider = new CustomProvider();

// 添加一些测试数据
var factory = new GeometryFactory();
customProvider.AddFeature(
    factory.CreatePoint(new Coordinate(116.4, 39.9)),
    new Dictionary<string, object> { { "Name", "Beijing" }, { "Population", 21540000 } }
);
customProvider.AddFeature(
    factory.CreatePoint(new Coordinate(121.5, 31.2)),
    new Dictionary<string, object> { { "Name", "Shanghai" }, { "Population", 24280000 } }
);

// 使用提供者创建图层
var layer = new VectorLayer("Custom Data", customProvider);

3.5 样式系统

3.5.1 VectorStyle 类

namespace SharpMap.Styles
{
    public class VectorStyle : Style
    {
        // 填充
        public Brush Fill { get; set; }
        
        // 边框
        public Pen Outline { get; set; }
        public bool EnableOutline { get; set; }
        
        // 线
        public Pen Line { get; set; }
        
        // 点
        public Brush PointColor { get; set; }
        public float PointSize { get; set; }
        public PointSymbolizer Symbol { get; set; }
        
        // 默认样式
        public static VectorStyle Default { get; }
        public static VectorStyle CreateRandomStyle();
    }
}

样式示例

// 多边形样式
var polygonStyle = new VectorStyle
{
    Fill = new SolidBrush(Color.FromArgb(150, 100, 200, 100)),
    Outline = new Pen(Color.DarkGreen, 2),
    EnableOutline = true
};

// 渐变填充
var gradientStyle = new VectorStyle
{
    Fill = new LinearGradientBrush(
        new Rectangle(0, 0, 100, 100),
        Color.LightBlue,
        Color.DarkBlue,
        45f),
    Outline = new Pen(Color.Navy, 1),
    EnableOutline = true
};

// 线样式
var lineStyle = new VectorStyle
{
    Line = new Pen(Color.Red, 3)
    {
        DashStyle = DashStyle.Dash,
        StartCap = LineCap.Round,
        EndCap = LineCap.ArrowAnchor
    }
};

// 点样式
var pointStyle = new VectorStyle
{
    PointColor = Brushes.Red,
    PointSize = 12
};

// 使用图标符号
var symbolStyle = new VectorStyle
{
    Symbol = new ImageSymbol(Image.FromFile("marker.png"))
};

3.5.2 LabelStyle 类

namespace SharpMap.Styles
{
    public class LabelStyle : Style
    {
        // 字体
        public Font Font { get; set; }
        
        // 颜色
        public Color ForeColor { get; set; }
        public Brush BackColor { get; set; }
        
        // 光晕效果
        public Pen Halo { get; set; }
        
        // 对齐方式
        public HorizontalAlignmentEnum HorizontalAlignment { get; set; }
        public VerticalAlignmentEnum VerticalAlignment { get; set; }
        
        // 偏移
        public PointF Offset { get; set; }
        
        // 旋转
        public float Rotation { get; set; }
        
        // 碰撞检测
        public bool CollisionDetection { get; set; }
        public SizeF CollisionBuffer { get; set; }
        
        // 对齐枚举
        public enum HorizontalAlignmentEnum { Left, Center, Right }
        public enum VerticalAlignmentEnum { Top, Middle, Bottom }
    }
}

标注样式示例

var labelStyle = new LabelStyle
{
    // 字体设置
    Font = new Font("Microsoft YaHei", 10, FontStyle.Regular),
    ForeColor = Color.Black,
    
    // 背景
    BackColor = new SolidBrush(Color.FromArgb(200, 255, 255, 200)),
    
    // 光晕效果(提高可读性)
    Halo = new Pen(Color.White, 3),
    
    // 对齐
    HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center,
    VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Bottom,
    
    // 偏移
    Offset = new PointF(0, -10),
    
    // 碰撞检测
    CollisionDetection = true,
    CollisionBuffer = new SizeF(10, 10)
};

3.6 渲染器体系

3.6.1 渲染流程

Map.GetMap()
    │
    ▼
遍历 BackgroundLayer
    │
    ▼
遍历 Layers
    │
    ├──► VectorLayer.Render()
    │        │
    │        ▼
    │    获取可视范围内的几何
    │        │
    │        ▼
    │    应用样式/主题
    │        │
    │        ▼
    │    渲染几何到 Graphics
    │
    ├──► LabelLayer.Render()
    │        │
    │        ▼
    │    获取标注数据
    │        │
    │        ▼
    │    碰撞检测
    │        │
    │        ▼
    │    渲染标注文本
    │
    └──► TileLayer.Render()
             │
             ▼
         计算需要的瓦片
             │
             ▼
         获取/缓存瓦片
             │
             ▼
         渲染瓦片到 Graphics
    │
    ▼
遍历 VariableLayers
    │
    ▼
返回 Image

3.6.2 自定义渲染

public class CustomVectorLayer : VectorLayer
{
    public CustomVectorLayer(string layerName) : base(layerName)
    {
    }
    
    public override void Render(Graphics g, Map map)
    {
        // 设置渲染质量
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
        
        // 获取可视范围
        var envelope = map.Envelope;
        
        // 获取数据
        var geometries = DataSource.GetGeometriesInView(envelope);
        
        // 自定义渲染逻辑
        foreach (var geometry in geometries)
        {
            RenderGeometry(g, map, geometry);
        }
    }
    
    private void RenderGeometry(Graphics g, Map map, Geometry geometry)
    {
        if (geometry is Point point)
        {
            var screenPoint = map.WorldToImage(point.Coordinate);
            
            // 绘制自定义符号
            DrawCustomMarker(g, screenPoint);
        }
        else if (geometry is LineString line)
        {
            // 绘制线
            var points = line.Coordinates.Select(c => 
                map.WorldToImage(c)).ToArray();
            
            using (var pen = new Pen(Color.Blue, 2))
            {
                g.DrawLines(pen, points);
            }
        }
        else if (geometry is Polygon polygon)
        {
            // 绘制多边形
            var points = polygon.ExteriorRing.Coordinates.Select(c => 
                map.WorldToImage(c)).ToArray();
            
            using (var brush = new SolidBrush(Color.FromArgb(100, 0, 100, 200)))
            using (var pen = new Pen(Color.DarkBlue, 1))
            {
                g.FillPolygon(brush, points);
                g.DrawPolygon(pen, points);
            }
        }
    }
    
    private void DrawCustomMarker(Graphics g, PointF point)
    {
        float size = 20;
        var rect = new RectangleF(
            point.X - size / 2, 
            point.Y - size / 2, 
            size, 
            size);
        
        using (var brush = new SolidBrush(Color.Red))
        {
            g.FillEllipse(brush, rect);
        }
        
        using (var pen = new Pen(Color.White, 2))
        {
            g.DrawEllipse(pen, rect);
        }
    }
}

3.7 本章小结

本章详细介绍了 SharpMap 的核心架构和类库设计:

  1. 整体架构:了解了 SharpMap 的分层架构设计
  2. Map 类:深入学习了 Map 类的属性、方法和使用方式
  3. 图层体系:掌握了 VectorLayer、LabelLayer、TileLayer 等图层类型
  4. 数据提供者:学习了 IProvider 接口和常用数据提供者
  5. 样式系统:了解了 VectorStyle 和 LabelStyle 的配置方法
  6. 渲染流程:理解了 SharpMap 的渲染机制

3.8 参考资源


下一章预告:第04章将深入讲解 Map 对象的高级用法,包括地图导航、视图控制、事件处理等内容。

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