Micaps3.2二次开发实例教程-11

实例六-让Micaps支持新数据类型-BLN地图数据

Micaps本身支持几十类数据,如果将所有类型数据的读写显示都模块都放在一起,那将带来如下问题:

  • 代码量太大,代码维护成问题;
  • Micaps以后可能还需要支持更多的数据格式,程序的升级扩充问题;
  • 各种数据支持代码也不能仅靠Micaps开发团队核心人员编写,团队开发问题;
  • 最后,各省还想直接显示他们自己的数据,二次开发问题;

Micaps3.2的策略是利用SharpDevelop的插件框架,将各种数据支持功能都以插件方式提供,一种数据格式一个插件。大家根据Micaps预定义好规则,独立开发插件,扩充性和团队开发问题都得到了解决。二次开发中也可以使用同样方法开发插件让Micaps支持特定的数据格式。

要实现这个功能,插件的代码里首先要解决两个问题:


  • 数据识别问题。当用户打开一个文件(链接、字符串等)后,如何让Micaps识别出数据类型,然后根据数据类型来决定怎么读文件、怎么绘图。

对这个问题,Sharpdevelop已经提供了框架,使用一种叫做DisplayBinding(显示绑定)的插件架构。每个显示绑定插件里首先要实现一个对文件类型的识别函数,Sharpdevelop将系统中所有显示绑定插件排成一个列表,如果自己能识别,则打开显示,不能识别则交个下一个数据支持插件处理。

  •  数据显示问题。读出了数据,如果是要填到地图上,如何与Micaps地图交互?

要将数据显示在地图上,那必然要和Micaps的地图交互。Micaps已提供大量可供调用类,包括图层、绘制函数等,这也是Micaps二次开发的难点,这些内容可查阅《Micaps3.2二次开发手册》。

这一节,我们编写插件为Micaps增加surfer的bln格式地图数据支持功能。

1、Addin文件:

  

<Pathname="/Workspace/DisplayBindings">
    <DisplayBinding id="SurferBln"
              type="Layer"
              class="SurferBln.SurferBlnDataBindings"/>
  </Path>

显示绑定的扩展点路径为"/Workspace/DisplayBindings";type="Layer"是Micaps新增的一种类型,它表示该数据将以地图图层方式显示;在显示绑定段里指定绑定的类名为"SurferBln.SurferBlnDataBindings",这个类将完成对数据类型的判断、数据显示等动作。

2、代码:

代码中主要是实现Addin文件里指定的SurferBln.SurferBlnDataBindings,该类必须实现接口ILayerDisplayBinding:

 public class SurferBlnDataBindings : ILayerDisplayBinding
    {
        #region ILayerDisplayBinding 成员
 
        /// <summary>
        /// 判读传入的文件名是否能被本插件打开
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns>可以打开:true,不能打开:false</returns>
        public bool CanCreateForFile(string filename)
        {
            //本插件能打开后缀为bln的文件
            return Path.GetExtension(filename).ToLower() == ".bln";
        }
 
        /// <summary>
        /// 创建bln图层并加入地图
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public ILayer CreateLayerForFile(OpenedFile file)
        {
            //取得当前视图,转换为Micaps地图视图
            var mainRenderView = WorkspaceSingleton.Workspace.ActiveViewContent as IMicapsMainView;
            //如果当前视图是地图,则加载图层
            if (mainRenderView != null)
            {
                //创建bln图层
                BlnChart Chart = new BlnChart();
                //用它创建Micaps图层绑定对象
                MicapsDataLayerWrapper layer = new MicapsDataLayerWrapper(Chart);
                //给图层的地图对象赋值
                Chart.Map = mainRenderView.Map;
                //加载数据
                layer.Load(file, file.OpenRead());
                file.CloseIfAllViewsClosed();
                layer.LayerName = Chart.Description();
                return layer;
            }
            return null;            
        } 
        #endregion
    }


ILayerDisplayBinding接口包含两个函数:

  • bool CanCreateForFile(string filename);用来判断该插件能打开的文件。
  • ILayer CreateLayerForFile(OpenedFile file);打开文件,创建图层。

    上面的代码里,BlnChart是我们新建的一个类,用来读取和显示bln文件。该类从C_ChartBase类继承,主要实现以下成员:
 
 
  • string ReadFile(string filename):读取解析bln文件。
  • void Draw(GLGraphics g):绘图。

<pre name="code" class="csharp">using System;
using System.Collections.Generic;
using System.Text;
using nmc.micaps3;
using System.Drawing;
using System.IO;

namespace SurferBln
{
    class BlnChart : C_ChartBase
    {

        private BlnProperty _Property = new BlnProperty();

        public override void AddLayer(System.Collections.ArrayList list)
        {
            LayerZOrder layer_order = new LayerZOrder();
            layer_order.obj = this;
            layer_order.zOrder = 31;
            list.Add(layer_order);
        }
        string _Description = "Surfer Bln格式数据";

        public override string Description()
        {
            return _Description;
        }

        public override void Draw(GLGraphics g)
        {
            float x, y;
            List<PointF> pts;
            foreach (MapModel mo in MapObjects)
            //判断地图元素类型,仅显示线状数据
            if (mo.ObjectType == ShapeType.PolyLine)
                {
                    pts = new List<PointF>();
                    foreach (PointF ptf in mo.Points)
                    {
                        map.MemTY(ptf.X, ptf.Y, out x, out y);
                        PointF xy = new PointF(x,y);
                        pts.Add(xy);
                    }
                    g.DrawLines(_Property.LineColor, pts.ToArray());
                }
            }
            //map.MemTY(107, 33, out x, out y);
            //g.DrawEllipse(_Property.LineColor, x, y, 300, 300);
        }

        public override object GetPropertyInstance()
        {
            return _Property;
        }

        public override DateTime NextDateTime()
        {
            throw new NotImplementedException();
        }

        public override DateTime PreviousDateTime()
        {
            throw new NotImplementedException();
        }

        public override string ReadDB(object parameter)
        {
            throw new NotImplementedException();
        }
        protected IList<MapModel> MapObjects = new List<MapModel>();

        public override string ReadFile(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (StreamReader ws = new StreamReader(fs, Encoding.Default))
                {
                    while (!ws.EndOfStream)
                    {
                        //数据行
                        string line = "";
                        //读取地图元素头,并跳过空行
                        do
                        {
                            line = ws.ReadLine();
                        }
                        while (string.IsNullOrEmpty(line));
                        //分隔数据行
                        string[] items = line.Split(", ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        //点数
                        int n = Convert.ToInt16(items[0]);
                        //地图元素
                        MapModel mo = new MapModel();
                        //地图元素头为两个
                        if (items.Length > 1)
                        {
                            int t = Convert.ToInt16(items[1]);
                            if (t == 1)
                            {
                                //线
                                mo.ObjectType = ShapeType.PolyLine;
                            }
                            else
                            {
                                //面
                                mo.ObjectType = ShapeType.Polygon;
                            }
                        }
                        else
                        {
                            //线
                            mo.ObjectType = ShapeType.PolyLine;
                        }
                        //地图元素点数
                        mo.Points = new System.Drawing.PointF[n];
                        //读取经纬度
                        for (int i = 0; i < n; i++)
                        {
                            PointF ptf = new PointF();
                            line = "";
                            //读入一行,并跳过空行
                            do
                            {
                                line = ws.ReadLine();
                            }
                            while (string.IsNullOrEmpty(line));
                            //分隔数据行
                            items = line.Split(", ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                            //有两项时
                            if (items.Length == 2)
                            {
                                //经纬度
                                ptf.X = Convert.ToSingle(items[0]);
                                ptf.Y = Convert.ToSingle(items[1]);
                                mo.Points[i] = ptf;
                            }
                        }
                        //加入到列表
                        MapObjects.Add(mo);
                    }
                }
                fs.Close();
            }
            _Description = Path.GetFileName(filename);
            return "Success";
        }

        public override string ReadXmlFile(string filename)
        {
            throw new NotImplementedException();
        }

        protected static int z_order = 31;
        public override int Z_Order
        {
            get
            {
                return z_order;
            }
            set
            {
                z_order = value;
            }
        }
    }

    /// <summary>
    /// 地图数据实体类
    /// </summary>
    public class MapModel //: DrawObject
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public MapModel()
        {
        }

        private ShapeType _ObjectType = 0;
        /// <summary>
        /// 对象类型
        /// </summary>
        public ShapeType ObjectType
        {
            get { return _ObjectType; }
            set { _ObjectType = value; }
        }

        private string _Id;
        /// <summary>
        /// 对象ID
        /// </summary>
        public string Id
        {
            get { return _Id; }
            set { _Id = value; }
        }

        private RectangleF _Rect;
        /// <summary>
        /// 对象最大矩形范围
        /// </summary>        
        public RectangleF Rect
        {
            get
            {
                return _Rect;
            }
            set { _Rect = value; }
        }

        private PointF[] _Points;
        /// <summary>
        /// 对象点数组
        /// </summary>
        public PointF[] Points
        {
            get { return _Points; }
            set { _Points = value; }
        }
    }

    /// <summary>
    /// 地图元素类型
    /// </summary>
    public enum ShapeType : int
    {
        /// <summary>
        /// 空
        /// </summary>
        Null = 0,
        /// <summary>
        /// 点
        /// </summary>
        Point = 1,
        /// <summary>
        /// 线
        /// </summary>
        PolyLine = 3,
        /// <summary>
        /// 面
        /// </summary>
        Polygon = 5,
    };
}


 

总结一下,显示自定义格式数据时,Addin文件从扩展点路径"/Workspace/DisplayBindings"扩展,指定数据绑定类,代码中,实现数据绑定类接口IlayerDisplayBinding的两个方法,一个方法判断我们的插件是否能识别打开的文件,当文件能打开时,将调用另一个方法打开文件建立新图层,另外,需要新建一个继承C_ChartBase的类,它实现读取文件和绘图功能。

下图为打开bln地图的效果,为了显示更清楚,我隐去了Micaps自带的基础地图:


       海南的bln县界与Micaps叠加:


       其实,Micaps3.2完全没必要自己再定义一套图层显示绑定,直接使用SharpDevelop的IdisplayBinding接口就行了,甚至写一个适配器直接使用Micaps3.1的原有插件。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值