ArcGis 制图——地图图框整饰的插件式实现(一)C#

如有插件定制需求或技术交流,欢迎联系QQ 975601416

写完了自己瞅了一眼都不想看,希望有需要的你能看懂。

先摆一张效果图:


 下面进入主题,本篇先讲一下地图布局中的对象,正文中会对一些关键词用英文补充说明一下,这可不是作者在显摆,了解下功能的英文表述对查询帮助是很有帮助的。

 直达链接:

PageLayout 页面布局视图,元素的容器

Page  版面,用于控制打印纸张

IElement接口 页面元素

IFrameElement接口 框架元素,图框、外图框即此

MapFrame 地图(map)的容器

FrameElement 地图外框

MapSurroundFrame  用于管理地图周边元素(MapSurround,比例尺、指北针、图例等)

ITextElement 标题等文字元素

 


先介绍一下主要对象类型——容器PageLayout与存放在容器中的Element元素。

PageLayout对象

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);

Page对象

打印纸张的版面控制。

//单位,一般用厘米
pPageLayout.Page.Units = esriUnits.esriCentimeters;
//传入double类型值,设置页面长、宽
pPageLayout.Page.PutCustomSize(width, height);
//读取当前版面的长宽值
double width;
double height;
pPageLayout.Page.QuerySize(out width, out height);

 IElement元素

在 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)、其他辅助要素(底部文字等)。

IFrameElement框架元素

pageLayout中用于存放地图的MapFrame实现了IMapFrame接口,该接口继承自IFrameElement接口,外框线可以使用FrameElement对象实现。

图框细分应该会有内图框、外图框。

MapFrame对象 内框

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;

FrameElement对象 外框

外图框只用来展示一个粗线框,其几何图形可以是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。

原文地址:https://www.cnblogs.com/yzhyingcool/p/10065605.html