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

news/2025/1/12 8:41: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的原有插件。


http://www.ppmy.cn/news/869706.html

相关文章

MII(2)

本文主要分析MII/RMII/SMII&#xff0c;以及GMII/RGMII/SGMII接口的信号定义&#xff0c;及相关知识&#xff0c;同时本文也对RJ-45接口进行了总结&#xff0c;分析了在10/100模式下和1000M模式下的设计方法。 MII接口提供了MAC与PHY之间、PHY与STA(Station Management)之间的互…

CSDN博文大赛火爆开启

俗话说的好&#xff0c;程序员会写博&#xff0c;谁也挡不住&#xff01; 是不是每个开发者都能写出好博文&#xff0c;这个很难说&#xff0c;但可以肯定的是&#xff0c;能写出好博文的&#xff0c;一定是优秀的程序员&#xff01; 写作即思考&#xff0c;养成写博文的习惯…

MiCTeX MiniFAQ

来自&#xff1a; instanton的个人空间【 2007-5-15 】 MiCTeX MiniFAQ 1. 什么是MiCTeX? 它和CTeX、CTeX套装是什么关系&#xff1f; MiCTeX是本人为了方便使用MiKTeX 2.5及其后版本的新特性而构建的一个中文TeX套装。它可以读作“My CTeX”、“MiKTeX”或者“Micro TeX”&…

MIPI CSI-2

欲观原文&#xff0c;请君移步 1 MIPI简介 MIPI 是 Mobile Industry Processor Interface&#xff08;移动行业处理器接口&#xff09;的缩写。MIPI 联盟是一个开放的会员制组织。2003年7月&#xff0c;由美国德州仪器&#xff08;TI&#xff09;、意法半导体&#xff08;ST&am…

mipi2spi

timescale 1ns / 1ps module SPI_Master# ( parameter CLK_FREQ 50, /* 模块时钟输入&#xff0c;单位为MHz */ parameter SPI_CLK 1000, /* SPI时钟频率&#xff0c;单位为KHz */ parameter …

Xilinx ZYNQ 7000 HDMI

High-Definition Multimedia Interface (HDMI) 参考xilinx application note XAPP460 HDMI来自High-Definition Multimedia Interface 高分辨率多媒体接口&#xff0c;多媒体一般包含图像和声音。 Transition Minimized Differential Signaling (TMDS) 是HDMI的物理层。 TMDS…

MS2130 HDMI转USB3.0

1.内部集成USB3.0控制器和数据收发模块、HDMI RX 模块和音视频处理模块 2.USB音频默认48KHz 立体声输出 3. 支持HDMI 1.4b&#xff0c; HDCP 1.4 &#xff0c;DVI 1.0 4.支持RGB444、YCBCR422、YCBCR444、 YCBCR420 color space&#xff0c;支持deep color 24/30/36 位模式…

1.2.1 Minix

《鸟哥的Linux私房菜 基础学习篇&#xff08;第三版&#xff09;》第1章Linux是什么&#xff0c;本章介绍为何Linux可以免除专利软件之争&#xff0c;并且了解到Linux为何可以同时在个人计算机与大型主机上面大放光彩。本节为大家介绍Minix。 1.2 Torvalds的Linux开发 我们前面…