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

来源:互联网 发布:淘宝店招怎么做全屏 编辑:程序博客网 时间:2024/06/09 12:47

实例六-让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的原有插件。

原创粉丝点击