zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    前端开发-模块化开发框架RequireJS-1 初识requirejs
    需整理
    SSM
    iomanip
    new与delete使用方法
    分析setting源代码获取sd卡大小
    第一次正式小用Redis存储
    blob storage第一次亲密接触
    第一次使用ashx,被震惊
    Redis中的异步Async
  • 原文地址:https://www.cnblogs.com/yzhyingcool/p/10065605.html
Copyright © 2011-2022 走看看