如有插件定制需求或技术交流,欢迎联系QQ 975601416
写完了自己瞅了一眼都不想看,希望有需要的你能看懂。
先摆一张效果图:
下面进入主题,本篇先讲一下地图布局中的对象,正文中会对一些关键词用英文补充说明一下,这可不是作者在显摆,了解下功能的英文表述对查询帮助是很有帮助的。
直达链接:
PageLayout 页面布局视图,元素的容器
Page 版面,用于控制打印纸张
IElement接口 页面元素
IFrameElement接口 框架元素,图框、外图框即此
MapFrame 地图(map)的容器
FrameElement 地图外框
MapSurroundFrame 用于管理地图周边元素(MapSurround,比例尺、指北针、图例等)
ITextElement 标题等文字元素
先介绍一下主要对象类型——容器PageLayout与存放在容器中的Element元素。
ArcGis数据框有两个视图,“数据视图”(DataView)与“布局视图”(LayoutView)。制图是在“布局视图”里操作,在ArcObject里进行图框整饰就是操作“PageLayout”对象。
“PageLayout”对象实现了IGraphicsContainer接口,顾名思义,该接口提供了容器,用以存放、管理graphic elements。通过AddElement方法可以将元素(IElement)放入PageLayout,通过DeleteElement方法可以删除元素。
1 //PageLayout作为容器 2 IGraphicsContainer pGraphicsContainer = pPageLayout as IGraphicsContainer; 3 //IElement类型元素放入PageLayout,注意第二参zeorder固定为0(10.1,作者没有研究高版本API是否有改动)。 4 pGraphicsContainer.AddElement(element,0); 5 //删除元素,注意这个element是程序运行已经存在内存中的,放入PageLayout的对象 6 pGraphicsContainer.DeleteElement(element);
打印纸张的版面控制。
//单位,一般用厘米 pPageLayout.Page.Units = esriUnits.esriCentimeters; //传入double类型值,设置页面长、宽 pPageLayout.Page.PutCustomSize(width, height); //读取当前版面的长宽值 double width; double height; pPageLayout.Page.QuerySize(out width, out height);
在 ArcGIS 中显示在视图上的数据有两类:一类是地理要素数据,包括矢量要素数据、栅格数据、 Tin 等表面数据等,存储在 Geodatabase 或数据文件(如shapefile)中,它们是用于 GIS 分析制图的源数据;另一类是元素(Element),元素是一个地图除去要素数据外的部分,即在一幅地图中,除了地理数据外,其余的对象全部都是元素。
Element对象是一个庞大复杂的对象集合,它分为图形元素(GraphicElement)和框架元素(Frame Element)。图形元素主要包括 TextElement、 MarkerElement、 LineElement、 FillShapeElement、GroupElement 、 PictureElement 等 。 框 架 元 素 主 要 包 括 MapFrame 、MapSurroundFrame、 Table Frames 等。 这些元素都实现了IElement接口。
地图图框整饰的几个基本元素有图框(Frame)、标题(Title)、比例尺(Scale)、图例(Legend)、指北针(NorthArrow)、其他辅助要素(底部文字等)。
pageLayout中用于存放地图的MapFrame实现了IMapFrame接口,该接口继承自IFrameElement接口,外框线可以使用FrameElement对象实现。
图框细分应该会有内图框、外图框。
MapFrame是一个展示、存放Map图层要素(layers)的地方,直接切换到“布局视图”就可以看到它,内图框是MapFrame的边框。
内框MapFrame与PageLayout.Page的距离(上、下、侧)需要给定。图框肯定要从纸张边缘往里缩一定距离才是。
//根据与Page边的距离确定一个Envelpoe,通过它设置地图框架MapFrame的位置 IFrameElement pFrameElement = pGraphicsContainer.FindFrame(pActiveView.FocusMap);//pGraphicsContainer容器是什么?
IMapFrame pMapFrame = pFrameElement as IMapFrame;
IEnvelope pEnvelopeMapFrame = new EnvelopeClass();
pEnvelopeMapFrame.PutCoords(xmin, ymin, xmax, ymax);
IElement pElement = pFrameElement as IElement;
pElement.Geometry = pEnvelopeMapFrame;
外图框只用来展示一个粗线框,其几何图形可以是MapFrame的Envelpoe外扩一定距离形成的一个Envelpoe(这里称作pEnvelpoeOuter),将FrameElement的Geometry属性设置为pEnvelpoeOuter,将FrameElement对象的边框(Boder)的线型、宽度设置一下就做出来了。
//set Outer-border frame FrameElement frameElementOuter = new FrameElementClass(); IFrameElement pFrameElementOuter = frameElementOuter as IFrameElement; IElementProperties3 pElementProperties = pFrameElementOuter as IElementProperties3; pElementProperties.Name = "OuterBorder"; IEnvelope pEnvelpoeOuter = new EnvelopeClass(); pEnvelpoeOuter.PutCoords(xmin - 0.2, ymin - 0.2, xmax + 0.2, ymax + 0.2); frameElementOuter.Geometry = pEnvelpoeOuter; //set Outer-border line style ILineSymbol pLineSymbol = DisplayUtils.CartoLineSymbol(3.0, DisplayUtils.RGBColor(0, 0, 0)); ISymbolBorder pSymbolBorder = new SymbolBorderClass(); pSymbolBorder.LineSymbol = pLineSymbol; IFrameProperties pFramePropertiesOuter = pFrameElementOuter as IFrameProperties; pFramePropertiesOuter.Border = pSymbolBorder; return frameElementOuter;
MapSurroundFrame 地图周边元素,实现了IMapSurroundFrame接口,该接口同样继承自IFrameElement接口。
比例尺、图例、指北针是MapFrame的MapSurround对象,比例尺、图例是明显的与MapFrame相关,是随图层信息动态变化的。
比例尺:采用文本型比例尺,uid.Value = "esriCarto.ScaleText"。根据MapFrame的Envelpoe与PageLayout的Page的相对位置确定其放置的。
图例:uid.Value = "esriCarto.Legend"。根据MapFrame的Envelpoe确定其位置。
指北针: uid.Value = "esriCarto.MarkerNorthArrow"。根据MapFrame的Envelpoe确定其位置。其实质是一个字符,“运行”——输入“charmap”可以打开“字符映射表”,选择ESRI North字体,选择对应的字形可以看到其16进制的CharacterIndex,使用科学计算器计算出10进制的值就可以在程序中使用了。
public IElement AddNorthArrow(IPageLayout pPageLayout, double distanceToInnerBorder, double size, int characterIndex) { IUID uid = new UIDClass(); uid.Value = "esriCarto.MarkerNorthArrow"; IActiveView pActiveView = pPageLayout as IActiveView; IMapFrame pMapFrame = pGraphicsContainer.FindFrame(pActiveView.FocusMap) as IMapFrame; IMapSurroundFrame pMapSurroundFrame = pMapFrame.CreateSurroundFrame(uid as UID, null); pMapSurroundFrame.MapSurround.Name = "NorthArrow"; IMarkerNorthArrow pMarkerNorthArrow = pMapSurroundFrame.MapSurround as IMarkerNorthArrow; IMarkerSymbol pMarkerSymbol = pMarkerNorthArrow.MarkerSymbol; ICharacterMarkerSymbol pCharacterMarkerSymbol = pMarkerSymbol as ICharacterMarkerSymbol; pCharacterMarkerSymbol.CharacterIndex = characterIndex ; pCharacterMarkerSymbol.Size = size; pMarkerNorthArrow.MarkerSymbol = pCharacterMarkerSymbol; double xmin = pEnvelopeMapFrame.XMax - distanceToInnerBorder; double ymin = pEnvelopeMapFrame.YMax - distanceToInnerBorder; double xmax = pEnvelopeMapFrame.XMax - 1; double ymax = pEnvelopeMapFrame.YMax - 1; IEnvelope pEnvelope = new EnvelopeClass(); pEnvelope.PutCoords(xmin, ymin, xmax, ymax); IFillSymbol pFillSymbol = DisplayUtils.SimpleFillSymbol(esriSimpleFillStyle.esriSFSSolid, DisplayUtils.CartoLineSymbol(0, DisplayUtils.RGBColor()), DisplayUtils.RGBColor(255, 255, 255)); pMapSurroundFrame.Background = DisplayUtils.SymbolBackGRound(pFillSymbol ); IElement pNorthArrowElement = pMapSurroundFrame as IElement; pNorthArrowElement.Geometry = pEnvelope; return pNorthArrowElement; }
ITextElement 文字元素,用来设置标题与其他文字元素
标题:
根据MapFrame的Envelpoe与PageLayout.Page 的宽度(width)、高度(height)确定一个位于MapFrame上方且居中的Envelpoe(这里称作TitleEnvelpoe)。创建一个TextElementClass,设置其样式,然后将其Geometry属性设置为TitleEnvelpoe就可以了。
public IElement AddTitle(IPageLayout pPageLayout, string title,string font,double size) { ITextElement pTextElement = new TextElementClass(); pTextElement.Text = title; pTextElement.Symbol = DisplayUtils.TextSymbol(font, size,esriTextHorizontalAlignment.esriTHACenter,esriTextVerticalAlignment.esriTVACenter); double width; double height; pPageLayout.Page.QuerySize(out width, out height); double xmin = 0; double ymin = pEnvelopeMapFrame.YMax; double xmax = width; double ymax = height; IEnvelope pEnvelope = new EnvelopeClass(); pEnvelope.PutCoords(xmin, ymin, xmax, ymax); IElement pElement = pTextElement as IElement; IElementProperties3 pElementProperties3 = pElement as IElementProperties3; pElementProperties3.Name = "Title"; pElement.Geometry = pEnvelope; return pElement; }
底部文字:
也是是根据MapFrame的Envelpoe与PageLayout.Page的相对位置,分别确定出位于MapFrame左下角、右下角的两个Envelpoe,然后创建两个TextElementClass,设置其样式,分别塞到Envelpoe。