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。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM