• 组件GIS 1 地图操作


    v20200614:TOC右键菜单“栅格图层”和“矢量图层”区别显示;获取属性表代码小优化;

    v20200622:内容调整,重写优化;(该死的强迫症)

    1.1 纲要

    1.1.1 思维导图

    地图操作

    1.1.2 接口、类、枚举

    • AxMapControl,AxPageLayoutControl,AxTOCControl,axLicenseControl,IHookHelper(ESRI.ArcGIS.Controls)/(ESRI.ArcGIS.AxControls)
    • IMapDocument,IActiveView,IMap,ILayer,IFeatureLayer,IRasterLayer,IExtentStack(ESRI.ArcGIS.Carto)
    • IWorkspaceFactory,IWorkspace,IFeatureWorkspace,IEnumDataset,IDataset,IFeatureDataset,IFeatureClass,esriDatasetType(ESRI.ArcGIS.Geodatabase)
    • IObjectCopy,esriUnits(ESRI.ArcGIS.esriSystem)
    • ICommand,ITool,ISystemMouseCursor,esriSystemMouseCursor(ESRI.ArcGIS.SystemUI)
    • IEnvelope(ESRI.ArcGIS.Geometry)
    • IDisplayTransformation(ESRI.ArcGIS.Display)

    1.2 布局

    利用TabControl、ToolStrip、SplitContainer、StatusStrip控件划分菜单区、图层管理区、视图区、状态栏。再加上ArcGIS的MapControl、PageLayoutControl、TOCControl、LicenseControl。最后在Program.cs内添加Runtime许可代码ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);

    每一个TabPage内镶嵌MenuStrip(支持快捷键,没有分割线,没有label控件)或者ToolStrip(不支持快捷键);每一个菜单项图标标来源于项目资源文件。

    主界面

    image-20200622094637112

    1.3 文件管理

    image-20200622144235628

    1.3.1 数据加载

    axMapControl控件提供axMapControl.AddLayer(); axMapControl.AddLayerFromFile(); axMapControl.AddShapeFile();三种方法。.shp .lyr文件可以直接调用方法传入路径即可,栅格数据需要调用IRasterLayer.CreateFromFilePath(FileName); 方法获取栅格图层,然后调用axMapControl.AddLayer()即可。

    加载.shp矢量数据

    if (ofdAddShp.ShowDialog() == DialogResult.OK)
    {
        string[] fileName = ofdAddShp.SafeFileNames;//无路径文件名
        string path = System.IO.Path.GetDirectoryName(ofdAddShp.FileName);//得到文件夹路径
        for (int i = 0; i < fileName.Length; i++)
            axMapControl.AddShapeFile(path, fileName[i]);
    }
    

    加载栅格数据

    if (ofdAddRaster.ShowDialog() == DialogResult.OK)
    {
        for (int i = 0; i < ofdAddRaster.FileNames.Length; i++)
        {
            IRasterLayer pRasterLayer = new RasterLayerClass();
            pRasterLayer.CreateFromFilePath(ofdAddRaster.FileNames[i]);
            axMapControl.AddLayer(pRasterLayer);
        }
    }
    

    1.3.2 地图文档的新建、打开、保存

    mxd新建

    IMap map = new MapClass();
    axMapControl.Map = map;
    

    mxd打开

    if (ofdOpenMxd.ShowDialog() == DialogResult.OK)
        axMapControl.LoadMxFile(ofdOpenMxd.FileName);
    

    mxd保存

    string sMxdFileName = axMapControl.DocumentFilename;
    if (sMxdFileName == null || sMxdFileName == string.Empty)
    {
        string sRelPath = Application.StartupPath + @"........Data";
        string sAbsPath = System.IO.Path.GetFullPath(sRelPath);
        SaveFileDialog pSaveFileDialog = new SaveFileDialog();
        pSaveFileDialog.Title = "请选择保存路径";
        pSaveFileDialog.InitialDirectory = sAbsPath;
        pSaveFileDialog.OverwritePrompt = true;
        pSaveFileDialog.Filter = "ArcMap文档(*.mxd)|*.mxd|ArcMap模板(*.mxt)|*.mxt";
        if (pSaveFileDialog.ShowDialog() == DialogResult.OK)
            sMxdFileName = pSaveFileDialog.FileName;
        else
            return;
    }
    IMapDocument pMapDocument = new MapDocumentClass();
    pMapDocument.New(sMxdFileName);
    pMapDocument.ReplaceContents(axMapControl.Map as IMxdContents);
    pMapDocument.Save();
    MessageBox.Show("保存地图文档成功!");
    

    mxd另存为

    string sRelPath = Application.StartupPath + @"........Data";
    string sAbsPath = System.IO.Path.GetFullPath(sRelPath);
    SaveFileDialog pSaveFileDialog = new SaveFileDialog();
    pSaveFileDialog.Title = "请选择保存路径";
    pSaveFileDialog.InitialDirectory = sAbsPath;
    pSaveFileDialog.OverwritePrompt = true;
    pSaveFileDialog.Filter = "ArcMap文档(*.mxd)|*.mxd|ArcMap模板(*.mxt)|*.mxt";
    if (pSaveFileDialog.ShowDialog() == DialogResult.OK)
    {
        IMapDocument pMapDocument = new MapDocumentClass();
        pMapDocument.New(pSaveFileDialog.FileName);
        pMapDocument.ReplaceContents(axMapControl.Map as IMxdContents);
        pMapDocument.Save();
        MessageBox.Show("保存地图文档成功!");
    }
    

    1.3.3 打开数据库

    首先要理解工作空间的概念,一个数据库就是一个工作空间,工作空间内存储数据集,数据集内部存储要素类、关系类、栅格数据等。

    img img

    将打开数据库内部数据封装成一个方法(在BasicClass):

    public static void AddLayersFromDataset(IWorkspace pWorkspace, AxMapControl axMapControl)
    {
        try
        {
            IEnumDataset pEnumDataset = pWorkspace.get_Datasets(esriDatasetType.esriDTAny);
            pEnumDataset.Reset();
            IDataset pDataset = pEnumDataset.Next();
            while (pDataset != null)
            {
                switch (pDataset.Type)
                {
                    case esriDatasetType.esriDTFeatureClass:    //要素类
                        {
                            IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
                            IFeatureClass pFeaCls = pFeatureWorkspace.OpenFeatureClass(pDataset.Name);
                            IFeatureLayer pFeaLyr = new FeatureLayerClass();
                            pFeaLyr.FeatureClass = pFeaCls;
                            axMapControl.Map.AddLayer(pFeaLyr);
                        }
                        break;
                    case esriDatasetType.esriDTFeatureDataset:  //要素集
                        {
                            IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
                            IFeatureDataset pFeaDataset = pFeatureWorkspace.OpenFeatureDataset(pDataset.Name);
                            IEnumDataset pEnumFeatureDataset = pFeaDataset.Subsets;
                            pEnumFeatureDataset.Reset();
                            IDataset pDatasetNew = pEnumFeatureDataset.Next();
                            while (pDatasetNew != null)
                            {
                                if (pDatasetNew is IFeatureClass)
                                {
                                    IFeatureClass pFeaCls = pFeatureWorkspace.OpenFeatureClass(pDatasetNew.Name);
                                    IFeatureLayer pFeaLyr = new FeatureLayerClass();
                                    pFeaLyr.FeatureClass = pFeaCls;
                                    axMapControl.Map.AddLayer(pFeaLyr);
                                }
                                pDatasetNew = pEnumFeatureDataset.Next();
                            }
                        }
                        break;
                    case esriDatasetType.esriDTRasterDataset:   //栅格集
                        MessageBox.Show("还没写哦!");
                        break;
                    case esriDatasetType.esriDTTable:           //表格
                        MessageBox.Show("还没写哦!");
                        break;
                    case esriDatasetType.esriDTTopology:        //拓扑
                        MessageBox.Show("还没写哦!");
                        break;
                    default:
                        MessageBox.Show("还没写哦!");
                        break;
                }
                pDataset = pEnumDataset.Next();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    

    1.4 地图浏览

    image-20200622144254091

    平移:在菜单点击事件修改axMapControl.MousePointer属性,在axMapControl的鼠标按下事件内调用axMapControl.Pan();

    缩放:自定义封装Tool类实现ITool和ICommad接口

    历史视图:自定义封装Command类实现ICommand接口

    书签:调用ArcGIS组件类库

    注:ICommand实现命令,不需要与axMapControl交互;ITool需要与axMapControl交互,绑定了axMapControl的键盘、鼠标事件。

    1.4.1 ICommand接口实现

    以“前一视图”为例,新建一个类继承ICommand(ESRI.ArcGIS.SystemUI)接口,显式实现接口,OnCreate(object Hook)传入axMapControl控件Object属性,OnClick()实现功能,历史视图是通过IActiveView.ExtentStack视图堆栈实现的。

    public void OnCreate(object Hook)
    {
        hookHelper = new HookHelperClass();
        hookHelper.Hook = Hook;
        extentStack = hookHelper.ActiveView.ExtentStack;
        if (hookHelper.ActiveView == null)
            hookHelper = null;
    }
    
    public void OnClick()
    {
        if (extentStack.CanUndo())
            extentStack.Undo();
        else
            enabled = false;
    }
    
    //调用
    ICommand cmd = new ExtentBackCommand();
    cmd.OnCreate(axMapControl.Object);
    cmd.OnClick();
    

    1.4.2 ITool接口实现

    注:可以配合ICommand使用

    放大功能

    //鼠标指针样式
    public int Cursor
    {
        get
        {
            ISystemMouseCursor pMouse = new SystemMouseCursorClass();
            pMouse.Load(esriSystemMouseCursor.esriSystemMouseCursorZoomIn);
            return pMouse.Cursor;
        }
    }
    
    public void OnMouseDown(int button, int shift, int x, int y)
    {
        if (button == 2) return;
        //框选
        IEnvelope pEnv = mapControl.TrackRectangle();
        //点选
        if (pEnv.IsEmpty || pEnv.Width == 0 || pEnv.Height == 0)
        {
            pEnv = mapControl.Extent;
            pEnv.Expand(0.5, 0.5, true);
        }
        mapControl.Extent = pEnv;
        mapControl.Refresh();
    }
    
    //调用
    ICommand tool = new MapZoomInTool();
    tool.OnCreate(axMapControl.Object);
    axMapControl.CurrentTool = tool as ITool;
    

    1.4.3 组件库类调用

    "ControlXXXXX"(ESRI.ArcGIS.Controls)形式的类

    1.4.4 视图同步

    用IDisplayTransformation装axMapControl.Extent视图,用IObjectCopy拷贝地图

    IActiveView pActiveView = (IActiveView)axPageLayoutControl.ActiveView.FocusMap;
    IDisplayTransformation displayTransformation = pActiveView.ScreenDisplay.DisplayTransformation;
    displayTransformation.VisibleBounds = axMapControl.Extent;
    IObjectCopy pObjectCopy = new ObjectCopyClass();
    object copyMap = pObjectCopy.Copy(axMapControl.Map);//复制地图到copiedMap中
    object copyToMap = axPageLayoutControl.ActiveView.FocusMap;
    pObjectCopy.Overwrite(copyMap, ref copyToMap); //复制地图
    

    1.4.5 鼠标坐标

    响应axMapControl_OnMouseMove事件

    sMapUnits = BasicClass.GetMapUnit(axMapControl.Map.MapUnits);
    statusBarLblCoor.Text = string.Format("{0:#.###} {1:#.###} {2}", e.mapX, e.mapY, sMapUnits);
    

    其中地图单位获取(封装在BasicClass内)

    public static string GetMapUnit(esriUnits mapUnit)
    {
        string sMapUnit = string.Empty;
        switch (mapUnit)
        {
            case esriUnits.esriCentimeters:
                sMapUnit = "厘米";
                break;
            case esriUnits.esriDecimalDegrees:
                sMapUnit = "十进制";
                break;
            case esriUnits.esriDecimeters:
                sMapUnit = "分米";
                break;
            case esriUnits.esriFeet:
                sMapUnit = "尺";
                break;
            case esriUnits.esriInches:
                sMapUnit = "英寸";
                break;
            case esriUnits.esriKilometers:
                sMapUnit = "千米";
                break;
            case esriUnits.esriMeters:
                sMapUnit = "米";
                break;
            case esriUnits.esriMiles:
                sMapUnit = "英里";
                break;
            case esriUnits.esriMillimeters:
                sMapUnit = "毫米";
                break;
            case esriUnits.esriNauticalMiles:
                sMapUnit = "海里";
                break;
            case esriUnits.esriPoints:
                sMapUnit = "点";
                break;
            case esriUnits.esriUnitsLast:
                sMapUnit = "UnitsLast";
                break;
            case esriUnits.esriUnknownUnits:
                sMapUnit = "未知单位";
                break;
            case esriUnits.esriYards:
                sMapUnit = "码";
                break;
            default:
                sMapUnit = "未知单位";
                break;
        }
        return sMapUnit;
    }
    

    1.4.6 比例尺

    实时显示当前比例尺

    响应axMapControl_OnAfterScreenDraw事件:menuCboMapScale.Text = string.Format("1:{0:#}", axMapControl.MapScale);

    手动输入比例尺

    键盘代码KeyValue请参考:CSDN:C# KeyValue列表

    响应menuCboMapScale_KeyPress事件

    if (e.KeyChar == 13)    //Enter
    {
        bool isColon = menuCboMapScale.Text.Contains(":");
        if (isColon)
        {
            string[] strArray = menuCboMapScale.Text.Split(':');
            axMapControl.MapScale = double.Parse(strArray[1]);
        }
        else
            axMapControl.MapScale = double.Parse(menuCboMapScale.Text);
        axMapControl.Refresh();
    }
    

    国家标准比例尺

    1:100,1:500,1:1000,1:2000,1:5000,1:1万,1:2万,1:5万,1:10万,1:25万,1:50万,1:100万

    响应menuCboMapScale_SelectedIndexChanged事件

    string sMapScale = menuCboMapScale.SelectedItem.ToString();
    string[] sArray = sMapScale.Split(':');//冒号分隔
    axMapControl.MapScale = double.Parse(sArray[1].Trim(','));//去除逗号
    axMapControl.Refresh();
    

    1.5 图层管理

    1.5.1 右键菜单

    添加contextMenuStrip控件,在axTOCControl的OnMouseDown事件内写代码

    if (e.button == 2)//右键
    {
        esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
        IBasicMap pBasicMap = null;
        object unk = null;
        object data = null;
        axTOCControl.HitTest(e.x, e.y, ref item, ref pBasicMap, ref pLyr, ref unk, ref data);
        if (item == esriTOCControlItem.esriTOCControlItemLayer)
        {
            if (pLyr is IFeatureLayer)  //矢量图层
            {
                pFeaLyr = pLyr as IFeatureLayer;
                btnAttributeTable.Visible = true;
                btnLayerSelected.Visible = true;
                btnLayerSelectable.Visible = true;
                btnLayerUnSelectable.Visible = true;
                btnLayerOutput.Visible = true;
                btnLayerSelectable.Enabled = !pFeaLyr.Selectable;
                btnLayerUnSelectable.Enabled = pFeaLyr.Selectable;
                btnLayerSelected.Enabled = pFeaLyr.Selectable;
            }
            else  //栅格图层
            {
                btnAttributeTable.Visible = false;
                btnLayerSelected.Visible = false;
                btnLayerSelectable.Visible = false;
                btnLayerUnSelectable.Visible = false;
                btnLayerOutput.Visible = false;
            }
            contextMenu.Show(Control.MousePosition);
        }
    }
    

    右键菜单

    1.5.2 图层定位

    将图层的“兴趣区”赋值给地图控件的视图属性,axMapControl.Extent = pFeaLyr.AreaOfInterest;

    1.6 交互优化

    软件没有数据时,一些功能是禁用的。

    响应axMapControl_OnAfterScreenDraw事件:

    //1 激活相关控件
    //1.1 地图浏览
    bool isData = false;//存在数据?
    isData = axMapControl.LayerCount > 0 ? true : false;
    barMapBrowse.Enabled = isData;
    //1.2 选择查询
    barSelect.Enabled = isData;
    //1.3 空间编辑
    barEditor.Enabled = isData;
    //1.4 历史视图
    bool canUndo = axMapControl.ActiveView.ExtentStack.CanUndo();
    btnExtentBack.Enabled = canUndo;
    bool canRedo = axMapControl.ActiveView.ExtentStack.CanRedo();
    btnExtentForward.Enabled = canRedo;
    

    主界面图标,响应FormMain_Load

    //添加图标
    IntPtr Hicon = Properties.Resources.GenericGlobeLarge_B_16.GetHicon();
    Icon newIcon = Icon.FromHandle(Hicon);
    this.Icon = newIcon;
    

    源码链接:组件GIS

  • 相关阅读:
    hdu5289 RMQ+二分
    poj1459 最大流Dinic
    poj2391 最大流+拆点
    poj1087&&hdu1526 最大流
    NOI2004 郁闷的出纳员
    Treap入门(转自NOCOW)
    poj 2892
    vijos 1512
    对拍程序
    poj 3264
  • 原文地址:https://www.cnblogs.com/liuwenzhen/p/13095610.html
Copyright © 2020-2023  润新知