AE开发之地图浏览20210517 地图的放大缩小漫游、书签的制作、记忆视窗范围、调试代码方法

回顾

什么时候用什么对象
主要类:抽象类 组件类 普通类

抽象类无法new,普通类也无法new进行创建,只有是组件类才可以创建,创建的就是一个对象,定义变量的时候是类的名称,用类名去定义对象,前面都是用接口去定义,Imap去做Map,对象已经存在了,但是面前是面向接口编程,这时候暴露出啦的都是对象的接口,操作和使用通过接口去实现。

这样的话好处是:子类继承父类,同时继承接口,统一接口去实现在子类中实现,但是在工作空间工厂之类的操作时候,new的时候是不同的工作空间工厂。

组件类父类是普通类时候,只能new子类,然后用子类的接口去进行不同的操作,如工作空间的创立。

workspace是在OpenFromFile执行的时候,就去创建的了这个对象,暴露出来的接口是Iworkspace接口,有了这个接口,可以用他的属性方法去做操作,对其属性去访问,实际上是访问的该工作空间下的所有数据集,返回的是数据集的集合,排列,集合,后面是要做什么呢?

是让它回到最开始,然后利用next再次访问数据集,可能有很多不同的类,实际上在这个过程中也用到了许多的对象。我们虽然看不到,但是可以通过其接口进行操作。

new一个CAD workspacefactory

接口查询,可以看成类型的强制转换,但是有一个提示:强制转化的时候,要保证这个类存在这两个接口,不能由一个workspace接口强制到一个不存在的接口

 private void openCADToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "dwg file|*.dwg";//前面是一个提示,弹出的描述,后面是过滤
            dlg.Multiselect = false;
            dlg.Title = "Open dwg file";
            //调用对话框
            if (dlg.ShowDialog() == DialogResult.OK)
            {

                string pathfile = dlg.FileName;
                int index = pathfile.LastIndexOf('\\');//找到最后一个斜杠的位置
                string path = pathfile.Substring(0, index);//从0开始去取,一直取到最后一个
                string name = pathfile.Substring(index + 1);

                IWorkspaceFactory pWF = new ESRI.ArcGIS.DataSourcesFile.CadWorkspaceFactory();//利用工厂对象去生成一个CAD文件的工作空间
                IWorkspace pW = pWF.OpenFromFile(path, 0);    //打开对应的文件夹路径
                                                              // IFeatureWorkspace pFW = (IFeatureWorkspace)pW;
                                                              //IFeatureClass pFeatueClass =
                ICadDrawingWorkspace pCadwrk = pW as ICadDrawingWorkspace;
                ICadDrawingDataset pCadDraw = pCadwrk.OpenCadDrawingDataset(name);
                ICadLayer pCadlayer = new CadLayerClass();
                pCadlayer.CadDrawingDataset = pCadDraw;



                //CadLayerClass pCadlayer= pCadwrk.OpenCadDrawingDataset(name);

                ILayer player = new CadLayer();
                ICadLayer pcadl = player as ICadLayer;
                pcadl.CadDrawingDataset = pCadDraw;
                axMapControl1.AddLayer(pcadl);//player prasterlayer都是指向同一个对象,但是这个地方需要一个ILayer接口
                axMapControl1.Refresh();//刷新

}

在这里插入图片描述

加载fileGDB文件地理数据库(在personalgeodatabase基础上)

在这里插入图片描述
在这里插入图片描述
在personalGDB基础上,修改工作空间工厂和文件过滤器。

dlg.Filter = " File GDB|*.gdb";//前面是一个提示,弹出的描述,后面是过滤


 IWorkspaceFactory pWorkFct = new FileGDBWorkspaceFactory();

大型数据库,arcSDE加载模式,创建一个SDE的workspacefactory

做地图浏览

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
1.创建后无内容,需要去加载,我们可以取一个地图的内容存过来。

 pMapDoc.Save();//找到地图,把地图内容给取下来,取下来放到哪里去呢?

2.所以要用new的方法,但是创建后,现在还是空的,我们要把地图文档名称取下来。怎么取下来呢?

①查看是不是当前地图文档就有名称了,创建一个filename

 string fileName = axMapControl1.DocumentFilename;

预示着,地图控件,有一个地图文档的文件名称,也就是磁盘下文档的存放路径。

如果有这个路径,就可以通过这个路径进行存储了

②如果地图文档名是空的,不用Openfiledialog,而是用savefiledialog,可以再去找到这个名称,再去存放

            if(fileName==null)
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.Filter = "Map Document|*.mxd";
                //可以添加tital等东西属性,课下查
                if(dlg.ShowDialog()==DialogResult.OK)
                {
                    fileName = dlg.FileName;
                
                }
            }

3.地图存放,存谁的内容呢?
应该是mapcontrol上面的这个地图,这个内容放在哪里呢?
先是要访问这个内容。

ReplaceContents

用于当前地图文档,用接口传进来的内容,替代当前显示的这个内容,这个contents代表一个对象一个内容,我们要把它更新进来,现在这个地图可以用axmapcontrol去访问这个地图,但我们要的不是map,而是一个Imxdcontents接口,需要去查map对象去查

map在carto类库里面。

可以通过强制转换得到IMxdDocument接口

if(fileName!=null)
            {
                IMap pMap = axMapControl1.Map;
                IMxdContents mxdContents = (IMxdContents)pMap;
                IMapDocument pMapDoc = new MapDocument();
                //创建出对象,暴露出接口了
                //pMapDoc.Save();//找到地图,把地图内容给取下来,取下来放到哪里去呢?
                pMapDoc.ReplaceContents(mxdContents);
            }

这时候,mapdocument对象当中就有这个接口了,我们的目的是存起来,实际上我们要判定一下。

new过程就是在磁盘下,制定位置创建文档,创建完后需要通过save方法,去存储。

 pMapDoc.Save(true,true);

第一个参数:true相对路径,false是绝对路径
第二个true是指需要创建一个图标标识

尝试加入判断是否存在的代码(ppt)

 private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string fileName = axMapControl1.DocumentFilename;//预示着,地图控件,有一个地图文档的文件名称,也就是磁盘下文档的存放路径。
            if(fileName==null)
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.Filter = "Map Document|*.mxd";
                //可以添加tital等东西属性,课下查
                if(dlg.ShowDialog()==DialogResult.OK)
                {
                    fileName = dlg.FileName;
                
                }
            }
            if(fileName!=null)
            {
                IMap pMap = axMapControl1.Map;
                IMxdContents mxdContents = (IMxdContents)pMap;
                IMapDocument pMapDoc = new MapDocument();
                //创建出对象,暴露出接口了
                //pMapDoc.Save();//找到地图,把地图内容给取下来,取下来放到哪里去呢?


                pMapDoc.New(fileName);
                pMapDoc.ReplaceContents(mxdContents);
                pMapDoc.Save(true,true);//true1相对路径,false是绝对路径,第二个true是指需要创建一个图标标识
            }
        }

如果进行代码调试,知道bug在哪里

断点设置

在这里插入图片描述
在这里插入图片描述

逐句调试

菜单栏上面有【调试】,可以设置为逐语句调试

结束调试

点击【继续】,或者逐句到最后

地图的放大缩小漫游

放大 zoom in

//先把地图缩小,再在地图上去显示,地图范围存到哪里去了呢

1.存地图范围,用什么去表达呢?

IEnvelope pEnv= axMapControl1.Extent;

2.调整地图范围,x y的比例和是否按比例去放大。

private void zoomInToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //先把地图缩小,再在地图上去显示,地图范围存到哪里去了呢
           IEnvelope pEnv= axMapControl1.Extent;
            pEnv.Expand(0.5,0.5,true);//第一个参数是x,第二个参数是y,第三个参数是是否按比例
            //放大两倍
            axMapControl1.Extent = pEnv;
            axMapControl1.Refresh();
        }

查IEnvelop对象

https://blog.csdn.net/duck04551/article/details/6604338

IEnvelope是指地物的外接矩形,用来表示地物图形的大体位置和形状,一般可用于检索地物,判断地物间的拓扑关系,可以使得检索、判断的速度加快,因为有了IEnvelope,可以首先判断该外接矩形是否在检索范围内,而判断一个外接矩形是比较简单的。

Envelope也称包络线,是一个矩形区域,是每个几何形体的最小外接矩形。

每个Geometry都拥有一个Envelope,包括Envelope自身。IEnv是包络线对象的主要接口,定义了XMax、XMin、YMax、YMin、Height和Width等属性,用于获取或设置一个存在的包络线对象的空间坐标。

IEnvelope接口也提供了一些方法,如Expand、offset、CenterAt、PutCoords等。Expand方法用于按比例缩放包络线的范围,产生一个新的包络线对象;offset是一个偏移方法,通过一个给定的(X,y)移动包络线;CenterAt方法则通过改变包络线的中心点来移动包络线;PutCoords方法饿公国指定的坐标点来构造包络线。

接口的属性和方法:

IEnvelope接口的长宽属性Height和Width属性(读写,可以通过该属性获取或设置该边框的长和宽)

IEnvelope接口的4个顶点属性UpperLeft、UpperRight、LowerLeft和LowerRight(读写,返回IPoint类型的四个顶点,比直接获得最值坐标更加方便严谨)

IEnvelope接口的最值坐标属性XMax、XMin、YMax和YMin(读写,可以通过该属性获取或设置该边框的四个顶点的坐标)

IEnvelope接口的CenterAt(pPoint) (方法,将这个矩形的边框移动到参数pPoint的位置,但是其他属性不变,如它的Width和Height)

IEnvelope接口的Union (inEnvelope ) (方法,将参数输入的几何边框和调用该方法的几何边框求并集,并将结果赋值给第一个边框,即调用此方法的object)

IEnvelope接口的Intersect (inEnvelope ) (方法,返回与输入参数相交的区域的几何边框,并将结果赋值给第一个边框,即调用此方法的object)

IEnvelope接口的PutCoords (XMin, YMin,XMax,YMax) (方法,将新建的一个边框的4个极坐标设置为输入的参数)

IEnvelope接口的QueryCoords (XMin, YMin,XMax,YMax)(方法,将已有的一个边框的4个极坐标输出到参数当中以备后用)

IEnvelope接口的Expand (dx, dy, asRatio) (方法,按照输入的dx与dy参数来放大或者缩小当前的边框,用与对ArcMap窗体的中心放大或缩小,或者点击屏幕获得点击点的坐标,并将中心点设置成点击点,并进行一定比例的放大或者缩小)

IEnvelope接口的Offset (X, Y) (方法,将已有的一个边框的按照输入参数的大小来进行水平竖直的移动)

geometry类库(几何类库)

https://blog.csdn.net/BIT_SKY/article/details/50056605

一、Geometry类的层次
几何类定义了下述层次:

· Geometry(非实例化)

· Point(可实例化的)

· Curve(非实例化)

· LineString(可实例化的)

· Line

· LinearRing

· Surface(非实例化)

· Polygon(可实例化的)

· GeometryCollection(可实例化的)

· MultiPoint(可实例化的)

· MultiCurve(非实例化)

· MultiLineString(可实例化的)

· MultiSurface(非实例化)

· MultiPolygon(可实例化的)

不能在非实例化类中创建对象。能够在可实例化类中创建对象。所有类均有属性,可实例化类还可以包含声明(定义有效类实例的规则)。

Geometry是一种基本类。它是一种抽象类。Geometry的可实例化子类限制为可在2维坐标空间中存在的0、1、2维几何对象。所有的可实例化几何类是这样定义的,从而使得几何类的实例从拓扑意义上讲是闭合的(也就是说,所有定义的几何类包含其边界)。

基本Geometry类具有关于Point、Curve、Surface和GeometryCollection的子类:

· Point表示0维对象。

· Curve表示1维对象,具有子类LineString,以及次级子类Line和LinearRing。

· Surface是为2维对象设计的,具有子类Polygon。

· GeometryCollection具有特殊的0维、1维和2维类集合,名为MultiPoint、MultiLineString和MultiPolygon,分别用于为对应的Points、LineStrings和Polygons集合进行几何建模。MultiCurve和MultiSurface是作为抽象超类引入的,它们归纳了用于处理Curves和Surfaces的集合接口。

Geometry、Curve、Surface、MultiCurve和MultiSurface定义为非实例化类。它们为其子类定义了公用方法集合,而且是为扩展而包含在内的。

Point、LineString、Polygon、GeometryCollection、MultiPoint、MultiLineString和MultiPolygon定义为可实例化类。

二、类Geometry
Geometry是层次结构的根类。它是一种非实例化类,但具有很多属性,这些属性对由任何Geometry子类创建的所有几何值来说是共同的。下面介绍了这些属性(尤其是具有自己特殊属性的子类)。

Geometry属性

Geometry值具有下述属性:

· 其type(类型)。每个geometry属于层次结构中可实例化类之一。

· 其SRID,或空间参考ID。该值确定了用于描述定义几何对象的坐标空间的空间坐标系统。

在MySQL中,SRID值仅是与geometry值相关的整数值。所有计算均是在欧几里得几何系(平面)中进行的。

· 它在其空间坐标系统中的coordinates(坐标),表示为双精度数值(8字节)。所有的非空几何对象至少包含一对坐标(X、Y)。空几何对象不含坐标。

坐标与SRID相关。例如,在不同的坐标系内,两个对象之间的距离会有所不同,即使这两个对象具有相同的坐标也同样。这是因为,平面坐标系中的距离和地心坐标系(地球表面上的坐标)中的距离是不同的事项。

· 其interior(内部)、boundary(边界)和exterior(外部)。

每个几何对象均占据空间中的某一位置。几何对象的exterior(外部)指的是未被该对象占据的所有空间。其interior(内部)指的是被该对象占据的空间。其boundary(边界)指的是几何对象内部和外部之间的界面。

· 其MBR(最小边界矩形)或包络面。这是一种边界几何值,由最小和最大坐标(X,Y)构成。

· ((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))

· 无论值是简单的或非简单的。类型(LineString、MultiPoint、MultiLineString)的几何值或是简单的,或是非简单的。每个类型决定了其自己的简单或非简单声明。

· 无论值是封闭的或非封闭的。类型(LineString、MultiPoint)的几何值或是封闭的,或是非封闭的。每个类型决定了其自己的封闭或非封闭声明。

· 无论值是空的或非空的。如果没有任何点,几何对象是空的。空几何对象的内部、外部和边界未定义(也就是说,它们由Null值表示)。空的几何对象定义为总是简单的,面积为0。

· 其dimension(维数)。几何对象的维数为−1、0、1或2:

o −1用于空几何对象。

o 0用于无长度、无面积的几何对象。

o 1用于具有非0长度和0面积的几何对象。

o 2用于具有非0面积的几何对象。

Point对象的维数为0。LineString对象的维数为1。Polygon对象的维数为2。MultiPoint、MultiLineString和MultiPolygon对象的维数与构成它们的元素的维数相同。

三、类Point
Point(点)指的是代表坐标空间中单个位置的几何类。

Point示例

· 想像一张具有众多城市的大世界地图。每个Point对象可代表1个城市。

· 在城市地图上,Point对象可代表1个公共汽车站。

Point属性

· X-坐标值。

· Y-坐标值。

· Point定义为0维几何对象。

· Point的边界为空集合。

缩小 zoom out

private void zoomOutToolStripMenuItem_Click(object sender, EventArgs e)
        {
             IEnvelope pEnv = axMapControl1.Extent;
            pEnv.Expand(1.5, 1.5, true);//第一个参数是x,第二个参数是y,第三个参数是是否按比例
            axMapControl1.Extent = pEnv;
            axMapControl1.Refresh();
        }

drag zoom in 显示拉框范围,实现拉框放大

1.在地图控件中拉框,拉框会激发MouseDown等事件,拉框就在这些事件中操作

2.在mapControl双击,就会自动跳转到axMapControl1_OnMouseDown事件

3.怎么去拉框呢?

 axMapControl1.TrackRectangle();

4.怎么去接收拉框的范围呢?

 IEnvelope pEnv = axMapControl1.TrackRectangle();

5、如果点击,却没有拉框,或者拉出的是一个直线,则返回对象为空。需要去判断。

if(pEnv==null||pEnv.IsEmpty||pEnv.Width==0)
            //IsEmpty返回是否非空,是个属性。
            //如果高度为0,可能拉出的是一条直线,同理宽度为0
            {
                return;
            }   

6.把拉框范围赋给地图控件
7.刷新

8、设置属性或者字段,判断拉框是为了放大还是缩小,由于不需要外部访问,所以设置为属性即可。

namespace MapControl2
{


    public partial class Form1 : Form
    {
        private string toolAction;
    }
}

9.在MouseDown事件中进行判断,可以用分支语句switch进行判断。

            switch (toolAction)
            {
                case "Drag zoom in"://对大小写敏感,可以直接复制,减少出错
                    IEnvelope pEnv = axMapControl1.TrackRectangle();
                    if (pEnv == null || pEnv.IsEmpty || pEnv.Width == 0)
                    //IsEmpty返回是否非空,是个属性。
                    //如果高度为0,可能拉出的是一条直线,同理宽度为0
                    {
                        return;
                    }
                    axMapControl1.Extent = pEnv;
                    axMapControl1.Refresh();
                    break;
                case "grag zoom out":
                    IEnvelope pEnv = axMapControl1.TrackRectangle();
                    break;
                case "pan":
                    IEnvelope pEnv = axMapControl1.TrackRectangle();
                    break;
            }

值得注意的是:
①对大小写敏感

 case "Drag zoom in"://对大小写敏感,可以直接复制,减少出错

②形式:

case ... :
break;

10.放大缩小倍数的确定,可以用拉框的宽和高,和已知图框的宽高进行比值,得到新地图的范围。

先创一个范围。

 case "grag zoom out":
                    IEnvelope pEnv = axMapControl1.TrackRectangle();
                    if (pEnv == null || pEnv.IsEmpty || pEnv.Width == 0)
                    //IsEmpty返回是否非空,是个属性。
                    //如果高度为0,可能拉出的是一条直线,同理宽度为0
                    {
                        return;
                    }
                    double x_scal = axMapControl1.Extent.Width / pEnv.Width;
                    double y_scal = axMapControl1.Extent.Height / pEnv.Height;

11.算新窗口的高度和宽度。

 double width = axMapControl1.Extent.Width * x_scal;
                    double higth = axMapControl1.Extent.Height * y_scal;

12.找新窗口的x y 的最小值。

double x_min = pEnv.XMin-(pEnv.XMin- axMapControl1.Extent.XMin)*x_scal;
                    double y_min = pEnv.YMin -(pEnv.YMin - axMapControl1.Extent.YMin) * y_scal;
                 

13.找新窗口X Y的最大值

在这里插入代码片

14.重设置工作范围

 pEnv.PutCoords(x_min, y_min, x_max, y_max);

显示整个地图范围

private void fullMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            axMapControl1.Extent = axMapControl1.FullExtent;
            axMapControl1.Refresh();
        }

漫游 PAN

 case "pan":
                    axMapControl1.Pan();
                    axMapControl1.Refresh();

记忆视窗范围。(如快速回到上一个视窗范围)

1.谁去记忆,放到哪里去呢?
(范围的堆栈,在哪里呢?)

 IExtentStack pStack= axMapControl1.ActiveView.ExtentStack;//视窗范围的堆栈
           

2.判断是返回前视窗还是后视窗。

        private void formMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
           IExtentStack pStack= axMapControl1.ActiveView.ExtentStack;//视窗范围的堆栈
           if(pStack.CanRedo())
            {
                pStack.Undo();//回到前视窗
                axMapControl1.Refresh();
            }

        }

        private void backMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IExtentStack pStack = axMapControl1.ActiveView.ExtentStack;//视窗范围的堆栈
            if (pStack.CanRedo())
            {
                pStack.Redo();//回到后视窗
                axMapControl1.Refresh();
            }
        }
查ExtentStack

https://blog.csdn.net/mazhiyuan1981/article/details/110494541
https://blog.csdn.net/chh19941125/article/details/89211342
http://zhihu.geoscene.cn/question/12013

堆栈(Stack)代表了一个后进先出的对象集合。

当您需要对各项进行后进先出的访问时,则使用堆栈。

当您在列表中添加一项,称为推入元素,也叫压栈,当您从列表中移除一项时,称为弹出元素,也叫出栈。

【问题分析】:
Reset之后IExtentStack.Count变成0,而只有当IExtentStack.Count变成2时才能执行Undo操作,因此需要两次平移操作才能将其增长成2。

解释:Count代表了堆栈中的记录数量,Undo操作必须要在堆栈数量大于等于2时才能执行,因为回退后还是需要显示一个状态的,不可能显示成null。
而Reset函数将堆栈清空,因此此时需要连续执行两次压栈才能再执行出栈。

【解决办法】:
在执行Reset后紧接着执行一次pExtStack.Do方法即可。

感兴趣区 “书签”

1.在解决方案里面添加窗体应用

注意命名特点:
upIM窗体

2.添加label,添加textbox,添加button
在这里插入图片描述
3.标签存在哪里?什么时间去进行标签的存放?

点击OK的时候进行存放。
标签名称在textBox当中。

所以要在button1进行操作。
访问控件的active,涉及到窗口的关联,传过来之前的窗口,需要定义一个属性。

在最初窗口添加一个菜单项,去调用新的窗口
4、

  private void addBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 frm = new Form2();
            frm.PMapView = axMapControl1.Map;
            frm.ShowDialog();
        }

IAOIBookmark标签对象

https://blog.csdn.net/hyman_c/article/details/53102013

location属性,记忆当前视图窗口的位置,要存放到这里去,name是标签名称。

这两个属性,大家要适用。

常见问题

引用需要using,仅仅添加引用是对整个项目的应用。

11

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值