转:http://www.cnblogs.com/dachie/archive/2010/08/17/1801598.html
4.5.2 实例7:创建测量长度和面积自定义工具... 13
4.7.2 实例9:给定坐标向图层上自动添加图元... 17
4.15.2 实例16:在MapX系统中嵌入多媒体数据... 33
5.1.2.Oracle spatial组件的引入... 35
5.2 循序渐进学习Oracle Spatial在MapX中的应用... 36
5.2.2 准备由Oracle Spatial存储的图层文件... 36
5.2.5用程序实现MapX图元到oracle数据库的上载... 42
5.2.6 用程序实现oracle数据表数据下载至MapX中显示... 44
7.2 .NET Framework 的主要组件和功能... 92
第四章 MapX与C#实例
这一章我们通过若干专题来介绍用C#如何开发MapX应用程序。
4.1 MapX图层建立
4.1.1 MapX数据与地图的组织结构
MapX地图是由一个一个图层合成而来。 MapX 将其所有基础信息以 MapInfo表的形式组织起来;每一表都是一组 MapInfo 文件,用来在地图中建立一个图层。
这一组MapInfo文件包括:
.<Somefile>.tab:图层属性结构定义文件,该文件描述 MapInfo 表的结构。它是描述包含数据文件格式的小文本文件。
.<Somefile>.dat(.mdb、.aid 或 .dbf):图层属性记录文件,这些文件包含表格数据.可用记事本或相应的数据库管理软件打开浏览数据。
.<Somefile>.map:图层空间记录文件,该文件描述空间图形对象(如果该表没有任何地图对象,则该文件将不存在)。
.<Somefile>.id:图层索引文件,该文件是将数据与空间对象相链接的交叉引用文件(如果该表没有任何地图对象,则该文件将不存在)。
.<Somefile>.ind:它是索引文件.通过该索引文件,您可以使用 Find 对象搜索地图对象。
要创建图层就要了解这些内部机理,方能思路清晰。下面是一个创建自定义层的例子。
4.1.2 实例1:建立/添加一个用户自定义图层
4.1.2.1 程序功能
在地图上建立一个用户自定义的图层,该图层上的每个图元包括图元编号、图元名称、图元描述、图元坐标等属性,并且生成一个数据集与该图层绑定。
4.1.2.2 程序实现
public bool NewUserLayer(string layerName)
//新建自定义图层,若存在则添加到图层集中
{
MapXLib.Layer layer;
MapXLib.Fields flds=new MapXLib.FieldsClass();
flds.AddStringField("source",50,false);
flds.AddStringField("name",50,false);
flds.AddStringField("identity",50,false);
flds.AddStringField("description",50,false);
flds.AddStringField("foundTime",50,false);
flds.AddFloatField("objX",false);
flds.AddFloatField("objY",false);
MapXLib.LayerInfo layerInfo;
layerInfo=new MapXLib.LayerInfoClass(); layerInfo.AddParameter("FileSpec",@appDirectory+"\\"+layerName+".tab");
layerInfo.AddParameter("Name",layerName);
layerInfo.AddParameter("Fields",flds);
layerInfo.AddParameter("AutoCreateDataset",1);
layerInfo.AddParameter("DatasetName","ds"+layerName);
if (!File.Exists(@appDirectory+"\\"+layerName+".tab"))
{
layerInfo.Type=MapXLib.LayerInfoTypeConstants.miLayerInfoTypeNewTable;
}
else
{
layerInfo.Type=MapXLib.LayerInfoTypeConstants.miLayerInfoTypeTab;
}
try
{
layer = axMap1.Layers.Add(layerInfo,1);
axMap1.Refresh();
return true;
}
catch
{
return false;
}
}
4.1.2.3 程序说明
(1)flds是MapXLib.Fields对象,即图层的属性字段集,将来会出现在.tab文件中。用new MapXLib.FieldsClass()来实例化一个新的Fields对象。在对任何对象进行引用前,必须先实例化该对象。
AddStringField, AddFloatField是Fields字段集对象的两个方法,分别用来定义字符串字段及浮点型字段,并添加到Fields字段集对象中。有关AddStringField(),AddFloatField()的语法请参考MapX文档。
(2)MapXLib.LayerInfo对象是用来增加新层的一个非常好的方法,在layerInfo中具体定义该层的一些参数。
l layerInfo.AddParameter("FileSpec",@appDirectory+"\\userDrawLayer.tab"):指定该层的存放路径。@为转义字符, appDirectory为应用程序目录变量,可用Directory.GetCurrentDirectory()来得到。 userDrawLayer.tab为该层的.tab文件名。
l layerInfo.AddParameter("Name","userDrawLayer"):指定该层的名字”userDrawLayer”,名字将会出现在图层控制对话框中。
l layerInfo.AddParameter("Fields",flds):指定该图层的属性字段集对象,即上面新定义的MapXLib.Fields对象。
l layerInfo.AddParameter("AutoCreateDataset",1):指定是否自动产生数据集,1自动产生,0不产生。有关数据集的概念,在后续部分再重点作介绍。
l layerInfo.AddParameter("DatasetName","dsUserLayer");指定数据集的名字“dsUserLayer”。
l layerInfo.Type属性:指定新层的类型。MapXLib.LayerInfoTypeConstants.miLayerInfoTypeNewTable:指定产生一新层。 MapXLib.LayerInfoTypeConstants.miLayerInfoTypeTab:指定一存在的图层。
l axMap2.Layers.Add(layerInfo,1)语句:增加layerInfo所定义的新层,其中“1”代表增加至图层最上面。
这样就得到一个名为userdrawlayer的图层,并且得到一个名为dsUserLayer的数据集与该图层自动绑定。利用这种方法建立数据集非常方便,也非常好用。在一般情况下都可满足系统的需求。该数据集可理解为一张表格,该表格的结构即为上面定义的flds字段集对象,该表格中的每一个记录对应图层上每一个图元的属性记录。
编号 |
名称 |
描述 |
经度 |
纬度 |
01 |
北京市 |
中华人民共和国国首都 |
.. |
.. |
… |
… |
… |
… |
… |
(3)LabelProperties用来说明如何用数据集中的数据标注图层上每一个图元。
layer.LabelProperties.Dataset:指定数据集对象。
layer.LabelProperties.DataField:指定用数据集中哪个字段值标注图元。
layer.LabelProperties.Position:指定标注位置。
layer.LabelProperties.Style.TextFont.Size:指定标注的字体及大小等。
layer.LabelProperties.Offset:指定标注离图元中心的距离。
下面我们就可以在刚建立好的图层上描绘自己的内容了。
4.1.3 在MapX中使用栅格图层
4.1.3.1什么是栅格图象?
栅格图象是由多行微小的点(象素)组成的一种计算机化的图象。如果手头有扫描仪及扫描软件,可以通过扫描一幅纸张地图来创建栅格图象。完成地图扫描并将其保存于文件中后,即可在MapInfo中显示该文件。
有多种不同的栅格图象文件格式。MapInfo能够处理以下格式的栅格图象文件:JPEG、GIF、TIFF、PCX、BMP、TGA(Targa)和BIL(SPOT卫星图片)。
4.1.3.2什么是配准栅格图象?
配准一幅栅格图象时,要输入地图坐标(如经度/纬度),并指定栅格图象上与该坐标对应的点。因为栅格图象文件不包含地理坐标信息,所以要在MapInfo Professional中显示栅格图象前必须进行配准,以使MapInfo Professional在显示图象时能够完成地理计算,如计算距离和面积等。
在MapInfo Professional中首次打开一幅栅格图象时,MapInfo Professional显示“配准栅格图象”对话框。填写该对话框以告知MapInfo Professional如何配准图象。MapInfo Professional将栅格图象配准信息保存在表文件中以供以后使用。下一次打开该栅格图象表时就不必再进行配准了。这样,只须对栅格图象进行一次配准。
栅格图层的应用在地理信息系统中也有重要作用。一般作为背景使用,特别是可作为鹰眼图的背景使用,可防止在改变视图时引起的刷新。
4.1.3.3配准栅格图像
若还没有在MapInfo Professional中显示过某个栅格图象,执行下述步骤配准该图象:
(1) 选择“文件”>“打开”,“打开”对话框出现。
(2) 从“文件类型”下拉列表中选择“栅格图象”。MapInfo Professional显示栅格图象文件清单。
(3) 选择要打开的栅格图象文件并选择“打开”。弹出一个MapInfo Professional对话框,点击“配准”按钮。MapInfo Professional显示“图象配准”对话框。该栅格图象的一个预览出现在对话框的下半段。
(4) 通过选择“投影”按钮并完成“选择投影”对话框来设定该图象的地图投影。配准栅格文件时,初始的投影方式就是表的缺省投影。
如果通过扫描纸张地图创建栅格图象,该纸张地图应包含所用的地图投影信息。如果不能确定地图投影,使用缺省地图投影(经/纬度)。缺省地图投影方式是由“地图窗口参数设置”中的“缺省投影”设置的。如果不清楚的话,可以使用经纬度。
(5) 把鼠标光标移到对话框下半段的预览图象上,并移到一个已知地图坐标(例如经/纬度)的点,再单击鼠标按钮。MapInfo Professional显示“增加控制点”对话框。
(6) 通过输入对应于在地图图象上单击位置的地图坐标,完成“增加控制点”对话框。
记住,本初子午线以西的任何位置有负的经度,赤道以南的任何位置有负的纬度。因此,西经73度对应于X值-73。
如果以度为单位输入坐标,必须输入小数度而不是度/分/秒。
(7) 重复步骤5和6,直到输入最少三个控制点。要保证精确结果,输入五或六个控制点。所增加的每个控制点有助于MapInfo Professional把地球坐标同栅格图象上的位置联系起来。理想地,在图象的每个角至少有一个控制点。
所需的控制点数依赖于栅格图象的性质。如果不能确定地图投影或正在使用没有实际地图投影的图象,例如航空照片,也许要输入二十或更多控制点。
(8) 完成增加控制点后选择“确定”。MapInfo Professional把该栅格图象显示在地图窗口中。
完成“图象配准”对话框后,MapInfo Professional把配准信息保存到一个表文件(.tab)中。这样我们就可以象利用普通Mapinfo表文件一样来用这个栅格图层了。
4.1.4 实例2:栅格图层的建立
4.1.4.1 程序功能
装载一栅格图层到图层集合的最低层。
4.1.4.2 程序实现
public bool LoadRasterLayer(string layerName)
{
int layerNumber=axMap1.Layers.Count;
try
{
axMap1.Layers.Add(layerName+".tab",layerNumber+1);
return true;
}
catch
{
return false;
}
}
4.1.4.3 程序说明
装载栅格图层与载载普通图层一样,用同样的语法结构Layers.Add()。
4.2 图元自动标注
对一个图元加上标注可直观的给用户识别地图上的每一个地理对象,在MapX中可设置自动标注图元和手工标注图元。
4.2.1 实例3:给图层加上自动标注功能
4.2.1.1 程序实现
private void autoLabel(string layerName)
{
MapXLib.Layer layer=axMap1.Layers._Item(layerName);
MapXLib.Dataset ds=axMap1.DataSets._Item(“ds”+layerName);
layer.LabelProperties.Dataset =ds;
layer.LabelProperties.DataField =ds.Fields._Item(“name”);
layer.LabelProperties.Position=MapXLib.PositionConstants.miPositionBC;
layer.LabelProperties.Style.TextFont.Size=10;
layer.LabelProperties.Offset=4;
layer.AutoLabel =true;
}
4.2.1.2 程序说明
(1)程序中假定layer层在生成时已生成与之绑定的数据集,其名称为”ds”+layerName。具体作法请参见实例新建自定义图层。
(2)用LabelProperties对象来定义标注的内容,字体,位置等。例子中用数据集的name字段的内容来标注图元,标注位置在图元下方偏移4个单位,字体大小为10。
(3)layer.AutoLabel =true打开自动标注功能,若要关闭所有标注可简单地置标注的visible属性为false。
4.3 MapX地图集
4.3.1 什么是MapX地图集(Geoset)?
地图集即图层的的集合,MapX控件的Geoset属性即为要打开的地图集对象。地图集对象的扩展名为.gst。它可由MapX所带的工具Geoset Manager来生成,请读者自己一试。
Geoset 保留地图图层及其设置的集合,以便于您使用。Geoset 是由同一地理区域的标准 MapInfo 格式地图文件 (.tab) 组成的数据集,因此命名为 Geoset。Geoset 可以帮助您避免在每次要作为示例地图处理图层时要分别打开和显示这些图层的耗时的工作。
.gst 是包含若干元数据关键字的文本文件,告诉 MapX 显示哪些表以及如何显示它们。
在打开一个 Geoset 时,它自动默认显示打开在 Geoset 中包括的所有文件。开发人员可以更改该默认显示以满足自身的要求。Geoset 的设置包括投影、默认缩放、对象的自动加标签、缩放图层以及在打开时表是否可见。MapX 也将打开开发人员指定的任何单个 (.tab) 地图文件。Geoset 是出于方便目的提供的,不是 MapX 行使功能所必需的。
4.3.2 实例4:打开已存在的地图集文件
4.3.3.1 程序功能
在硬盘中选择一个地图集文件.gst,然后在MapX中打开,并保存地图的初始属性如初始时的缩放比例及中心位置等。
4.3.3.2 程序实现
openFileDialog1.DefaultExt ="*.gst";
openFileDialog1.Filter="geoset file (*.gst)|*.gst";
openFileDialog1.ShowDialog();
if (openFileDialog1.FileName=="")
return;
axMap1.GeoSet=openFileDialog1.FileName;
mapZoom=axMap1.Zoom;
mapCenterX=axMap1.CenterX;
mapCenterY=axMap1.CenterY;
4.3.2.3 程序说明:
例程中由openFileDialog可在运行中任意打开所需的地图集对象,然后把该地图集文件名赋给地图的GeoSet属性即可。后面三行是用于保存地图集的初始缩放比例及中心位置,以便能够在运行过程中随时恢复到起始视图状态下。
4.3.3 实例5:保存地图集
4.3.3.1 程序功能
在新建或添加一个图层后,地图集改变,在此时应保存改变后的地图集,以方便下次一次性打开所有图层,发挥geoset的作用。下面的程序实现这一功能。
4.3.3.2 程序实现
string geosetFileName="";
saveFileDialog1.InitialDirectory=@appDirectory;
saveFileDialog1.Filter = "geoset files (*.gst)|*.gst";
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
geosetFileName=saveFileDialog2.FileName;
else
return;
axMap1.SaveMapAsGeoset(axMap1.Title.ToString(),@geosetFileName);
4.3.3.3 程序说明
(1)appDirectory为应用程序目录变量,可用Directory.GetCurrentDirectory()来得到;
(2)saveFileDialog对话框来得到地图集的文件名及路径;
(3)saveMapAsGeoset()方法来保存地图集,其语法为void SaveMapAsGeoset ( System.String name,System.String fileSpec)
4.4 内置工具的使用
大多数地图绘制应用程序提供各种工具来协助完成常见的绘图任务(例如在地图上绘制线条)和导航任务(例如放大)。MapX 提供若干常见地图绘制工具,并且您还可以创建自己的定制工具。
4.4.1 使用标准工具
使用 MapX,您可以很容易地将常见工具栏按钮并入应用程序中。MapX 提供对若干常见地图绘制工具的内置支持,可实现大部分地图功能,包括:
• 令用户更改地图的比例和/ 或位置的导航工具(放大、缩小、平移、居中)。
• 让用户单击地图图元以给它加标签的加标签工具。
• 为用户提供各种方法来选择地图图元的一组选择工具。
• 对象创建工具,用于创建新的地图图元。
提供对修改键(SHIFT 键、CTRL 键)的内置支持的选择工具:使用选择工具的同时按住 SHIFT 键;该工具将取消选择图元;使用选择工具的同时按住 CTRL,该工具会将图元添加到选择中。只要按下修改键 MapX 就会自动显示不同的光标(加号或减号出现在该光标旁),以便用户可以理解该键的用途。
下面列出内置工具常量:
miArrowTool = 1000: 单击标题或注释此外,在可编辑图层中移动选
定图元或调整选定图元的大小。
miPanTool = 1001:漫游工具
miCenterTool = 1002:使…成为中心工具
miZoomInTool = 1003:地图放大工具
miZoomOutTool = 1004 :地图缩小工具
miSymbolTool = 1005:符号注释工具
miTextTool = 1006:文本注释工具
miSelectTool = 1007 :图元选择工具
miRadiusSelectTool = 1008 :扇形选择工具
miRectSelectTool = 1009 :矩形选择工具
miPolygonSelectTool = 1010:多边形选择工具
miLabelTool = 1011:标注工具
miAddLineTool = 1012:画线工具
miAddPolylineTool = 1013:画折线工具
miAddRegionTool = 1014:画区域工具
miAddPointTool = 1015:画点图元工具
4.4.3 实例6:内置标准工具的使用
4.4.3.1 程序功能
实现地理信息系统中常见的工具栏按钮功能,并入应用程序中。
4.4.3.2 程序实现
//放大按钮
axMap2.CurrentTool=ToolConstants.miZoomInTool;
//恢复到初始视图按钮
axMap2.ZoomTo(this.mapZoom,this.mapCenterX,this.mapCenterY);
//漫游按钮
axMap2.CurrentTool=MapXLib.ToolConstants.miPanTool;
//增加点图元按钮
MapXLib.Style style=new MapXLib.StyleClass();
style.PickSymbol();
axMap2.DefaultStyle =style;
layerInsertion.Editable=true;
axMap2.Layers.InsertionLayer=layerInsertion;
axMap2.CurrentTool=MapXLib.ToolConstants.miAddPointTool;
//增加折线图元按钮
MapXLib.Style stylePolyLine=new MapXLib.StyleClass();
stylePolyLine.PickLine();
axMap2.DefaultStyle =stylePolyLine;
layerInsertion.Editable=true;
axMap2.Layers.InsertionLayer=layerInsertion;
axMap2.CurrentTool=MapXLib.ToolConstants.miAddPolylineTool;
//增加区域图元按钮
MapXLib.Style styleRegion=new MapXLib.StyleClass();
styleRegion.PickRegion();
axMap2.DefaultStyle =styleRegion;
layerInsertion.Editable=true;
axMap2.Layers.InsertionLayer=layerInsertion;
axMap2.CurrentTool=MapXLib.ToolConstants.miAddRegionTool;
4.4.2.3 程序说明
(1)currentTool属性用来选择当前工具;
(2)在上面增加图元的例程中, style.PickSymbol ()方法用来取得新图元的样式,包括大小.线型.颜色.填充方案等,以增加程序的灵活性;
(3)特别注意在增加图元时,不仅要设置当前图层为可编辑,而且要把当前层指定为图层集合的可插入层,即要指定图层集的insertionLayer属性。
4.5自定义工具
MapX内置工具给我们编程提供了很大的方便,但在一些情况下还远远不能满足用户需求,在这种情况下,我们就要进行自定义工具了。
4.5.1 创建自定义工具
在您为任何应用程序创建一个定制工具时,通常要执行三步:
(1) 创建工具。
(2) 编写工具处理程序(工具实际执行功能的代码)。
(3) 使用该工具(令用户开始使用工具)。
4.5.2 实例7:创建测量长度和面积自定义工具
在GIS系统中,长度及面积的测量是一项重要功能,它也是典型的自定义工具的使用的例子,各种书中都有相应介绍,在这里就在c#下创建自定义长度测量及面积测量工具的例程介绍如下。
4.5.3.1 程序功能
创建两个自定义工具:测量长度及测量面积。
4.5.3.2 程序实现
//首先声明长度测量及面积测量工具常量
private const int miGetLength =100;//自定义用户工具:测量长度
private const int miGetArea =101;//自定义用户工具:测量面积
//然后创建长度测量及面积测量工具
axMap2.CreateCustomTool(miGetLength,MapXLib.ToolTypeConstants.miToolTypePoly,MapXLib.CursorConstants.miCrossCursor,MapXLib.CursorConstants.miCrossCursor,MapXLib.CursorConstants.miCrossCursor,false);
axMap2.CreateCustomTool(miGetArea,MapXLib.ToolTypeConstants.miToolTypePolygon,MapXLib.CursorConstants.miCrossCursor,MapXLib.CursorConstants.miCrossCursor,MapXLib.CursorConstants.miCrossCursor,false);
//最后在PolyToolUsed实现两个工具
private void axMap1_PolyToolUsed(object sender, AxMapXLib.CMapXEvents_PolyToolUsedEvent e)
{
if(e.toolNum==miGetLength)
{
MapXLib.Points pts=(MapXLib.Points)e.points;
MapXLib.Point pt1,pt2;
double d=0.0;
for(int i=1;i<pts.Count;i++)
{
pt1=pts._Item(i);
pt2=pts._Item(i+1);
d+=axMap2.Distance(pt1.X,pt1.Y,pt2.X,pt2.Y);
}
statusBarPanel2.Text="距离:"+d.ToString();
}
else if(e.toolNum==miGetArea)
{
MapXLib.Points pts=(MapXLib.Points)e.points;
MapXLib.FeatureFactory dd=axMap2.FeatureFactory;
MapXLib.Style style=axMap2.DefaultStyle;
statusBarPanel2.Text="面积:"+dd.CreateRegion(pts,style).Area.ToString();
}
}
4.5.2.3 程序说明
注意:这些代码一定要在polytoolused事件中实现,因为每种工具使用都要在多点下才能完成。这里用了Distance及Area来获得其长度和面积,其它代码请读者自己仔细品味,相信读者会读懂它,不再做解释。
4.6 MapX地图符号样式的定制
在mapinfo中,图元分为点线面三种,每种图元都有自己的样式库。我们用内置工作miAddLine,miAddPoint,miAddRegion时,都是使用各自的默认样式画出相应的点线面图元。我们可以在画之前更改其样式,以达到自己所需要的样式。这就是我们前面画图元时首先调用style.pickSymbol(),style.pickLine(),style.pickRegion()的原因,也可以在图层对话框中更改其样式,图层对话框的调用方法为layerDialog();
然而,mapinfo所带样式库还是非常有局限,不可能提供所有的符号和样式,来满足各行各业的应用。如果能够对符号库进行扩充那么就非常完美了。可喜的是mapinfo professinal自带的mapbasic程序symbol.mbx可以帮助我们完成这一工作。下面给出点符号样式的扩充方法:
如图在mapinfo中运行mapbasic程序,选择symbol.mbx。
工具菜单下将会出现“创建新符号”,单击子菜单“新建一个”,出现符号编辑器,对新符号创建完成后按保存出现保存成功对话框。
注意:本人用的是mapinfo professional 7.0,若为以前的版本,可能会有所不同,具体请参考相关资料。
Mapinfo也支持位图形式的点符号,位图作为一个点显示在图层某个位置上。位图存放在"Program Files\Common Files\MapInfo Shared\MapX Common\CUSTSYMB"子目录下。MapX存放在”Program Files\MapInfo\MapX 5.0\CUSTSYMB”子目录下。我们只需要得到符号的位图文件然后存在CUSTSYMB下就可完成位图号的扩充。这样,我们基本可以达到需要什么就能画什么的程度。
4.7在图层上添加自定义图元
下面我们实现这样一个功能,在例程1新建的图层上画一个位图形式的点符号。分两种情况:(1)给出点的位置坐标,自动出现在图层上;(2)未给出位置坐标,由用户在图层上用鼠标点击出现。Form上有若干文本输入框,用于输入图元各信息number(图元编号),caption(图元名称),descr(图元描述),下面一确定按钮点击出现:
4.7.1 实例8:鼠标点击向图层上添加图元
4.7.1.1 程序功能
4.7.1.2 程序实现
private const int miAddSymbol =106;//自定义用户工具:添加用户图元到图层,在类的变量声明部分定义
axMap2.CreateCustomTool(miAddSymbol,MapXLib.ToolTypeConstants.miToolTypePoint,MapXLib.CursorConstants.miSizeAllCursor,MapXLib.CursorConstants.miSizeAllCursor,MapXLib.CursorConstants.miSizeAllCursor,false);//创建该自定义工具,在form load事件中定义
private void axMap1_ToolUsed(object sender, AxMapXLib.CMapXEvents_ToolUsedEvent e)
//在toolUsed实现该添加点图元自定义工具
{
if(e.toolNum==miAddSymbol)
{
//取得点击外的位置坐标
x=e.x1;
y=e.y1;
MapXLib.Point pnt=new MapXLib.PointClass();
MapXLib.RowValue rv=new MapXLib.RowValueClass();
MapXLib.RowValues rvs=new MapXLib.RowValuesClass();
MapXLib.Feature ftr;
MapXLib.FeatureFactory feaFac;
MapXLib.Style newStyle=new MapXLib.StyleClass();
feaFac = axMap2.FeatureFactory;
//定义点图元的样式
newStyle.SymbolType =MapXLib.SymbolTypeConstants.miSymbolTypeBitmap;//指定为位图样式
newStyle.SymbolBitmapSize=20;//指定图元大小
newStyle.SymbolBitmapName=bitmapfilename;//指定位图文件名
newStyle.SymbolBitmapTransparent=true;//指定位图透明,和图层融为一体
axMap2.AutoRedraw = false;
userLayer.Editable =true;
pnt.Set(x,y);
ftr= feaFac.CreateSymbol(pnt,newStyle);//用featuerFactory生成该位图图元
//******************************************************
//以下代码通过rowvalue和rowvalues来为新建图元设置所有属性
//******************************************************
dsUserLayer=axMap2.Layers._Item(1).DataSets._Item(1);//例程1中自动生成的dataset.
fldsUserLayer=dsUserLayer.Fields;
rv.Dataset =dsUserLayer;
for(int j=1;j<=fldsUserLayer.Count;j++)
{
if(j==1)
{
rv.Field=fldsUserLayer._Item(j);
rv.Value=number.ToString();
}
if(j==2)
{
rv.Field=fldsUserLayer._Item(j);
rv.Value=caption;
}
if(j==3)
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =descr;
}
if(j==4)
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =x;
}
if(j==5)
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =y;
}
rvs.Add(rv);
}
userLayer.AddFeature(ftr,rvs);//向图层增加该图元
userLayer.Refresh();
}
//下面是对确认按钮的编程,调用刚才实现的miAddSybol用户自定义工具
public void addUserSymbol(string infoBitmapname,string infoNumber,string infoCaption,string infoDescr)//
{
bitmapfilename=infoBitmapname;
number=infoNumber;
caption=infoCaption;
descr=infoDescr;
axMap2.CurrentTool=(MapXLib.ToolConstants)miAddSymbol;
}
另外一种不需自定义用内置的miAddTool添加。
4.7.2 实例9:给定坐标向图层上自动添加图元
4.7.3.1 程序功能
4.7.3.2 程序实现
这种情况下不需要自定义miAddSymbol工具,直接编程实现,代码大致相同,示例如下:
public void AddUserSymbol(ref FeatureInfo featureInfo,string layerName)
//增加到userlayer后插入oracle表中,userName必须为工作层
{
try
{
MapXLib.Point pnt=new MapXLib.PointClass();
MapXLib.RowValue rv=new MapXLib.RowValueClass();
MapXLib.RowValues rvs=new MapXLib.RowValuesClass();
MapXLib.Feature ftr;
MapXLib.FeatureFactory feaFac;
MapXLib.Layer layer=axMap1.Layers._Item(layerName);
MapXLib.Style newStyle=new MapXLib.StyleClass();
feaFac = axMap1.FeatureFactory;
newStyle.SymbolType =MapXLib.SymbolTypeConstants.miSymbolTypeBitmap;
newStyle.SymbolBitmapSize=20;
if (featureInfo.identity=="1")
{ newStyle.SymbolBitmapColor=(uint)MapXLib.ColorConstants.miColorBlue;
newStyle.SymbolBitmapOverrideColor=true;
}
else if(featureInfo.identity=="2")
{
newStyle.SymbolBitmapColor=(uint)MapXLib.ColorConstants.miColorGreen;
newStyle.SymbolBitmapOverrideColor=true;
}
else
{ newStyle.SymbolBitmapColor=(uint)MapXLib.ColorConstants.miColorRed ;
newStyle.SymbolBitmapOverrideColor=true;
}
newStyle.SymbolBitmapName=featureInfo.symbolFileName;
newStyle.SymbolBitmapTransparent=true;
axMap1.AutoRedraw = false;//禁止图层自动刷新
layer.Editable =true;
pnt.Set(featureInfo.point_x,featureInfo.point_y);
ftr= feaFac.CreateSymbol(pnt,newStyle);
//******************************************************
//以下代码通过rowvalue和rowvalues来为新建图元设置所有属性
//******************************************************
MapXLib.Dataset dsUserLayer;
MapXLib.Fields fldsUserLayer;
dsUserLayer=axMap1.DataSets._Item("ds"+layerName);
fldsUserLayer=dsUserLayer.Fields;
rv.Dataset =dsUserLayer;
//MI_PRINX索引构成规则:number前2位加yymmddhhmmss
DateTime myDataTime=DateTime.Now;
if (featureInfo.source==null) featureInfo.source="6";
string rownumber=featureInfo.source.PadLeft (2,\'0\')+myDataTime.Year.ToString()+myDataTime.Month.ToString()
+myDataTime.Day.ToString()+myDataTime.Hour.ToString()+myDataTime.Minute.ToString()+myDataTime.Second.ToString();
for(int j=1;j<=fldsUserLayer.Count;j++)
{
if(fldsUserLayer._Item(j).Name.ToUpper() =="MAINID")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value=featureInfo.featureID;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="SOURCE")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value=featureInfo.source;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="NAME")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value=featureInfo.name;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="IDENTITY")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =featureInfo.identity;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="DESCRIPTION")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =featureInfo.description;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="FOUNDTIME")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =featureInfo.foundTime;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="MEDIA")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =featureInfo.media;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="X")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =featureInfo.point_x;
}
if(fldsUserLayer._Item(j).Name.ToUpper() =="Y")
{
rv.Field=fldsUserLayer._Item(j);
rv.Value =featureInfo.point_y;
}
rvs.Add(rv);
}
layer.AddFeature(ftr,rvs);
layer.Refresh();
this.InsertIntoOracle(featureInfo,rownumber,ftr.Style,"symbol",ftr,layerName);
DeleteAllfeatures(userLayerName);
}
catch{}
axMap1.AutoRedraw = true;
}
4.7.2.3 程序说明
1.位图必须放在custSymb子目录下,且位图不支持24位以上真彩色, 大小最大48点。
2.本例程不仅画出了位图图元,还给出了设置图元属性的方法: (1)指定rowvaluer 数据集:rv.dataset= dsUserLayer; (2)通过rowvalue.field指定要修改的字段: rv.Field=fldsUserLayer._Item(j);
(3)通过rowvalue.value指定该字段的值: rv.Value=caption;
(4)把每个rowvalue增加到rowvalues集合中去,该rowvalues代表该图元的所用属性;
(5)利用图层的addfeature(feature,rowvalues)方法增加新的图元。
这样我们可以用记事打开相应图层的.dat文件查看我们增加的新图元的所有属性。
4.8 获得图元属性
在地理信息系统获取某个图元的属性是最基本的功能之一,实现起来也比较简单。
4.8.1实例10:获取选定图元的属性
4.8.1.1 程序功能
用内置选择工具选择某一图元,然后返回该图元的所有属性。
4.8.1.2 程序实现
public string[] GetSymbolProperty(string layerName)
{
MapXLib.Layer layer=null;
MapXLib.Dataset ds=null;
MapXLib.Fields fields=null;
try
{
layer=axMap1.Layers._Item(layerName);
ds=axMap1.DataSets._Item("ds"+layerName);
fields=ds.Fields;
symbolInfo=new string[fields.Count];
}
catch
{
return null;
}
foreach(MapXLib.Feature ftr in layer.Selection)
{
for(int i=1;i<=fields.Count;i++)
{
layer.KeyField=fields._Item(i).Name;
symbolInfo[i-1]=ftr.KeyValue.ToString();
}
}
return symbolInfo;
4.8.1.3 程序说明
1.属性值的获得:首先设置图层的KeyField关键字段属性:layer.KeyField= ds.Fields._Item(j).Name;
然后利用图元的keyvalue即可得到图元该字段的值: ftr.KeyValue
2.循环所有字段就取得图元的所有属性:
for(int i=1;i<=fields.Count;i++)
3.在本例中将所有属性全转化为string类型存于字符串数组symbolInfo[]中。
4.9 图元的选取
图元选取利用MapX内置的各种选取工具即可,我们对地图的操作往往都是针对地图上所选取的图元进行的,所以许多操作都要在这个选取上作文章了。
图元的选取利用selection集合,非常方便,同selectionchanaged事件结合可以做很多令人兴奋的效果。下面举得例子是利用selection集合及selectionchanged事件实现类似infoTip的功能,即当鼠标指在当前选中图元上时,会自动出现该图元的所有提示.这个功能当然可以用图层的labelproperty属性和数据集绑定实现,但我觉得下面的方法会更好。
4.9.1 实例11:实现InfoTip功能
//too1tip属性定义,在form load事件中
toolTip1.AutoPopDelay = 5000;
toolTip1.InitialDelay = 1000;
toolTip1.ReshowDelay = 500;
toolTip1.ShowAlways = true;
// SelectionChanged事件中实现提示功能
private void axMap1_SelectionChanged(object sender, System.EventArgs e)
{
MapXLib.Layer layer=axMap2.Layers._Item(1);
MapXLib.Dataset ds=axMap2.DataSets._Item(1);
foreach(MapXLib.Feature ftr in layer.Selection)
{
selectedFea=ftr;
string msg="";
for(int j=1;j<=ds.Fields.Count;j++)
{
layer.KeyField =ds.Fields._Item(j).Name;
symbolProperty[j-1]=ftr.KeyValue.ToString();
msg+= layer.KeyField+":"+ symbolProperty[j-1]+"\n";
}
toolTip1.SetToolTip(this.axMap1,msg);
}
}
注: (1)symbolProperty[]为一字符串数组,存储图元所有属性。
(2)例子中用了c#工具箱中的toolTip对象,巧妙的实现了信息提示.关于tooltip对象详细说明建议读者查帮助。
4.10 图元属性的修改
4.10.1 实例12:修改图元属性
4.10.1.1 程序功能
修改已知图元的属性。
4.10.1.2 程序实现
public void modiUserSymbol(MapXLib.Feature ftr,string infoNumber,string infoCaption, string infoDescr,double xIn,double yIn)
{
if (ftr==null) return;
number=infoNumber;
caption=infoCaption;
descr=infoDescr;
x=xIn;
y=yIn;
MapXLib.RowValues rvs=new MapXLib.RowValuesClass();
MapXLib.Layer layer=axMap2.Layers._Item(1);
MapXLib.Dataset ds=axMap2.DataSets._Item("dsUserLayer");
for(int j=1;j<=ds.Fields.Count;j++)
{
layer.KeyField =ds.Fields._Item(j).Name;
if (j==1)
ftr.KeyValue=number;
if (j==2)
ftr.KeyValue=caption;
if (j==4)
ftr.KeyValue=descr;
if (j==6)
ftr.KeyValue=x.ToString();
if (j==7)
ftr.KeyValue=y.ToString();
ftr.Update(true,rvs);
}
MessageBox.Show("目标属性修改成功!");
}
图元属性修改用图元的update方法。
4.11 实例13:图元的查询
图层的search(strWhere, , [Variables])方法中以方便的实现图元的查询,具有类似SQL查询的强大能力。其中参数strWhere为检索图元的条件表达式,相当于sql的where子句。该语句执行结果返回查找到的图元集合。
下面的例程实现一个万能模糊查询,即给定一个查找关键字keyStr,然后可查出图元属性中包含有有关键字keyStr的图元,而不管是哪个属性字段。
public void searchSymbols(string keyStr)
{
MapXLib.Features ftrs;
MapXLib.Features ftrs1;
MapXLib.Layer layer=axMap2.Layers._Item(1);
layer.Selection.ClearSelection();//清空selection集合
MapXLib.Variables vs=new MapXLib.VariablesClass();
ftrs=layer.Search("objName LIKE"+" "+"\"%"+keyStr+"%\"",vs);
//查找名称属性中包含keyStr的的图元,并存于ftrs集合中
ftrs1=layer.Search("objNumber LIKE"+" "+"\"%"+keyStr+"%\"",vs);
//查找编号属性中包含keyStr的的图元,并存于ftrs1集合中
ftrs.Add(ftrs1);//把ftrs1集合合并到ftrs集合中
MessageBox.Show("共有满足条件的图元"+ftrs.Count.ToString()+"个!");
layer.Selection.Add(ftrs);
//把查找到的所有图元存到selection集合中,以便使其高亮显示,处于选中状态。
}
4.12 实例14:鹰眼图的实现
鹰眼图的实现能使电子地图在功能及界面上锦上添花,各种媒体上都有一些介绍,下面介绍用C#实现的鹰眼图功能。
4.12.1 程序实现
//初始时,产生鹰眼图矩形框绘画层
private void mapsmall()
{
if (!File.Exists(@appDirectory+"\\mapSmall.tab"))
m_Layer=mapSmall.Layers.CreateLayer("RectLayer",@appDirectory+
"\\mapSmall.tab",1,32,mapSmall.NumericCoordSys);
else
m_Layer = mapSmall.Layers.Add(@appDirectory+"\\mapSmall.tab",1);
m_Layer.Editable=true;
mapSmall.Layers.InsertionLayer=m_Layer;
}
private void axMap1_MapViewChanged(object sender, System.EventArgs e)
{
if(mapSmall==null) return;
MapXLib.Feature tempFea;
MapXLib.Feature m_Fea;
MapXLib.FeatureFactory feaFact;
feaFact=mapSmall.FeatureFactory;
MapXLib.Points tempPnts=new MapXLib.PointsClass();
MapXLib.Style tempStyle=new MapXLib.StyleClass();
MapXLib.Features ftrs;
ftrs=m_Layer.AllFeatures;
double MapX=0,mapY=0,mapWidth=0,mapHeight=0,MapX1=0,mapY1=0;
float screenX,screenY,screenWidth,screenHeight,screenX1,screenY1;
screenX=axMap2.Bounds.X;
screenY=axMap2.Bounds.Y;
screenWidth=axMap2.Bounds.Width;
screenHeight=axMap2.Bounds.Height;
screenX1=screenX+screenWidth;
screenY1=screenY+screenHeight;
axMap2.ConvertCoord(ref screenX,ref screenY,ref MapX,ref mapY,
MapXLib.ConversionConstants.miScreenToMap);
axMap2.ConvertCoord(ref screenX1,ref screenY1,ref MapX1,ref mapY1,
MapXLib.ConversionConstants.miScreenToMap);
mapWidth=MapX1-MapX;
mapHeight=mapY1-mapY;
if (ftrs.Count==0)
{ tempStyle.RegionPattern=MapXLib.FillPatternConstants.miPatternNoFill; tempStyle.RegionColor=(uint)MapXLib.ColorConstants.miColorRed;
tempStyle.RegionBorderColor=255;
MapXLib.Points pts=new MapXLib.PointsClass();
pts.AddXY(MapX,mapY,1);
pts.AddXY(MapX+mapWidth,mapY,2);
pts.AddXY(MapX+mapWidth,mapY+mapHeight,3);
pts.AddXY(MapX,mapY+mapHeight,4);
tempFea = feaFact.CreateRegion(pts,tempStyle);
m_Fea = m_Layer.AddFeature(tempFea,new MapXLib.RowValuesClass());
m_Layer.Refresh();
mapSmall.AutoRedraw = true;
}
else
{
m_Fea=ftrs._Item(1);
m_Fea.Parts._Item(1).RemoveAll();
m_Fea.Parts._Item(1).AddXY(MapX,mapY,1);
m_Fea.Parts._Item(1).AddXY(MapX+mapWidth,mapY,2);
m_Fea.Parts._Item(1).AddXY(MapX+mapWidth,mapY+mapHeight,3);
m_Fea.Parts._Item(1).AddXY(MapX,mapY+mapHeight,4);
m_Fea.Update(true,new MapXLib.RowValuesClass());
m_Layer.Refresh();
mapSmall.AutoRedraw = true;
}
}
void axMap2_MouseDownEvent(object sender,AxMapXLib.CMapXEvents_MouseDownEvent e)
{
if(mapLarge==null)return;
double MapX=0;
double MapY=0;
axMap2.ConvertCoord(ref e.x,ref e.y,ref MapX,ref MapY,
MapXLib.ConversionConstants.miScreenToMap);
mapLarge.CenterX=MapX;
mapLarge.CenterY=MapY;
}
4.12.3程序说明
(1)由主图视图改变影响鹰眼图矩形框的重绘,代码实现在主图的viewchanged事件中。
(2)在鹰眼图中单击鼠标,把单击处的位置点作为主图的中心点重绘主图。代码实现在鹰眼图的mousedownevent事件中。
(3)M_layer为鹰眼图中绘制矩形框的图层。
(4)mapSmall代表鹰眼图控件,mapLarge代表主图控件。
(5)主图与鹰眼图同步的关键是主图的可视区域地理范围与鹰眼图的矩形框所包含的地理范围一样。 首先得到主图的Boundsr的各个顶点的屏幕坐标用函数axMap1.ConvertCoord()将bounds的各顶点屏幕坐标转化为地理坐标。最后在鹰眼图中根据主图中各顶点的地理坐标画出矩形区域。
(6)注意convertCoord()函数的用法,请参考相关资料,注意其中第五个参数的用法。
请读者仔细领会其中的机理。本例子只给了视图范围同步问题,没有给出编辑同步问题,即在主图中增加一个图元,在鹰眼图中同步增加一个点。留给读者自己练习,相信一定不会难住聪明的读者。
4.13 数据绑定
数据绑定的问题是MapX很重要的一个内容,是MapX具有生命力的重要体现。有了数据绑定,我们可以给地图赋予意义,可以给基于地理位置的空间对象以各种意义,满足各行各业的需要。然而,就是这个数据绑定,在C#下用得确不尽人意,这再一次体现了MapX对.net的支持不力。但是我们可以避过对我们不利的地方,来解决这个问题。下面就本人成功实现的一些数据绑定的例子,介绍如下:
(1)用layerinfo对象增加层时自动产生与之绑定的数据集 其中相应语句为
layerInfo.AddParameter("AutoCreateDataset",1);
layerInfo.AddParameter("DatasetName","dsUserLayer");
具体参见例程1部分。利用这种方法简单也非常方便,可以满足大部分应用。
(2)利用axMap1.DataSets.Add方法建立数据绑定
程序代码摘要如下:
//定义Fields字段集
MapXLib.Fields flds=new MapXLib.FieldsClass(); flds.Add("objNumber","objNumber",MapXLib.AggregationFunctionConstants.miAggregationIndividual,MapXLib.FieldTypeConstants.miTypeString);
flds.Add("objName","objName",MapXLib.AggregationFunctionConstants.miAggregationIndividual,MapXLib.FieldTypeConstants.miTypeString);
flds.Add
请发表评论