加载地图数据的几种方法(AE + C#)

时间:2022-09-09 19:26:38
  
任何系统都离不开数据的加载,下边就 AE 中几种常用的数据加载做一个列举。以便查阅:
 
1、加载个人数据库
个人数据库是保存在 Access 中的数据库。其加载方式有两种:通过名字和通过属性加载(也许不只这两种, AE 中实现同一功能可以有多种方式)。
A 、通过设置属性加载个人数据库。
首先通过 IPropertySet 接口定义要连接数据库的一些相关属性,在个人数据库中为数据库的路径,例如:
IPropertySet  Propset = new PropertySetClass();  
           Propset.SetProperty("DATABASE",@"D:/test/Ao/data/sh/MapData.mdb" );
       当定义完属性并设置属性后就可以进行打开数据库的操作了,在 ArcEngine 开发中存在 IWorkspaceFactory IFeatureWorkspace IFeatureClass IFeatureLayer 等几个常用的用于打开和操作数据空间地物的接口。 IWorkspaceFactory 是一个用于创建和打开工作空间的接口,它是一个抽象的接口,我们在具体应用时要用对应的工作空间实例化它,如下 :
IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
如果我们打开的是 SDE 数据库就要用 SdeWorkspaceFactoryClass 实例化 Fact 。当我们完成了工作空间的实例化后就可以根据上边设置的属性打开对应的 Access 数据库了。打开方式如下:
         IFeatureWorkspace Workspace = Fact.Open(Propset,0) as IFeatureWorkspace;
打开 Access 工作空间后接下来的事情是做什么了,很简单,找到对应的地物类,赋给相应的层,通过 MapControl 控件添加对应的层,然后刷新地图。以下为添加某一层的代码:
        IFeatureClass Fcls = Workspace.OpenFeatureClass("District");
       IFeatureLayer Fly = new FeatureLayerClass();
       Fly.FeatureClass = Fcls;
       MapCtr.Map.AddLayer (Fly);
       MapCtr.ActiveView.Refresh();
其中 District 为地物类的名字, MapCtr AE MapControl 的对象。上边的通过属性设置加载数据空间的方式还可以用于 SDE 数据库,在 SDE 数据库加载时会介绍。
以下为通过设置属性加载 Access 数据库的完整 C# 代码:
public void AddAccessDBByPro()
{
       IPropertySet  Propset = new PropertySetClass();  
       Propset.SetProperty("DATABASE",@"D:/test/Ao/data/sh/MapData.mdb" );
       IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
       IFeatureWorkspace Workspace = Fact.Open(Propset,0) as IFeatureWorkspace;
          
       IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
       IFeatureLayer Fly = new FeatureLayerClass();
       Fly.FeatureClass = Fcls;
  
       MapCtr.Map.AddLayer(Fly);
       MapCtr.ActiveView.Refresh();
}
B 、通过数据库名字加载个人数据库
在这我先把完整的代码写出来,让您先跟上边的代码做个对比。以下为完整的代码:
public void AddAccessDBByName()
{
      IWorkspaceName  pWorkspaceName = new WorkspaceNameClass() ;
    pWorkspaceName.WorkspaceFactoryProgID = "esriDataSourcesGDB.AccessWorkspaceFactory";
      pWorkspaceName.PathName = @"D:/test/Ao/data/sh/MapData.mdb";
      IName n = pWorkspaceName as IName ;
      IFeatureWorkspace Workspace = n.Open() as IFeatureWorkspace;
                                                              
     IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
     IFeatureLayer Fly = new FeatureLayerClass();
     Fly.FeatureClass = Fcls;
     MapCtr.Map.AddLayer (Fly);
     MapCtr.ActiveView.Refresh();
}
细心的人已经注意到,打开 Access 工作空间后接下来的代码是一样的,都是找到对应的地物类,赋给相应的层,通过 MapControl 控件添加对应的层,然后刷新地图。现在讲解一下上边的代码,首先是创建一个个人数据库工作空间名 , 在指定工作空间名的 ProgID ,以确定打开的是什么类型的工作空间,例如在打开 Access 个人数据库时使用的是下边的代码:
  IWorkspaceName  pWorkspaceName = new WorkspaceNameClass() ;
pWorkspaceName.WorkspaceFactoryProgID = "esriDataSourcesGDB.AccessWorkspaceFactory";
pWorkspaceName.PathName = @"D:/test/Ao/data/sh/MapData.mdb";
属性 WorkspaceFactoryProgID 可以确保工作空间是 AccessWorkspaceFactory ,即个人数据库,同时指定要打开数据库的路径。为了打开数据库,我们通过 AE 的类图可以发现打开工作空间必须使用 IName 接口(个人认为,不一定正确,可以思考一下看有其他办法没有),所以接着定义 IName 对象,并把工作空间名转换成 IName 类型并赋值给 IName 对象,然后通过 IName 对象的 Open() 方法打开相应的工作空间 , 代码如下:
IName n = pWorkspaceName as IName ;
IFeatureWorkspace Workspace = n.Open () as IFeatureWorkspace;
接下来的事情就是上边提到。
2 、加载 SDE 数据库
什么是 SDE 数据库?这个问题要详细地讲解将花费大量的时间,但我可以告诉你 SDE 空间数据库可以是任何关系数据库。 ESRI 公司为了使空间数据能保存在关系数据库中,并且能很好的查询相关的空间属性而开发的一个中间件,使用 SDE 能很好的将空间数据保存在关系数据库中。如 Orcale SQL Server 等。 SDE 具体细节的了解请查找相关的资料,这里只介绍怎么连接 SDE 数据库。 SDE 数据库的联机分为直接连接和通过 SDE 连接。当服务器的性能比较好的时候可以采用 SDE 连接,否则采用直接连接,这样可以减轻服务器的任务。建议采用直接连接,其实, SDE 连接方式和直接连接的方式只是一个属性参数设置的问题。跟个人数据库采用属性连接的方式一样,先定义一个属性对象,然后设置属性参数,接着定义一个工作空间并用 SdeWorkspaceFactoryClass() 实例化它,接着加在加载图层 , 至于加载图层的代码,与加载个人数据库中图层的方法一样,其实不只加载这两种数据类型,加载其他类型的数据时也是采用相同的方法加载图层,只是工作空间采用不同的实例而已,下边为完整的对吗 ”//” 后的为注析 :
public void AddSDELayer(bool ChkSdeLinkModle)
{
     // 定义一个属性
     IPropertySet  Propset = new PropertySetClass();  
     if ( ChkSdeLinkModle==true ) // 采用 SDE 连接
     {  
            // 设置数据库服务器名,服务器所在的 IP 地址
           Propset.SetProperty ("SERVER", "192.168.2.41");
            // 设置 SDE 的端口,这是安装时指定的,默认安装时 "port:5151"
           Propset.SetProperty ("INSTANCE", "port:5151");
            //SDE 的用户名
           Propset.SetProperty ("USER", "sa");
            // 密码
           Propset.SetProperty ("PASSWORD", "sa");
          // 设置数据库的名字 , 只有 SQL Server  Informix 数据库才需要设置
           Propset.SetProperty ("DATABASE", "sde");
           //SDE 的版本 , 在这为默认版本
           Propset.SetProperty ("VERSION", "SDE.DEFAULT");
     }
     else // 直接连接
     {
           // 设置数据库服务器名 , 如果是本机可以用 "sde:sqlserver:."
           Propset.SetProperty ("INSTANCE", "sde:sqlserver:zhpzh");
            //SDE 的用户名
           Propset.SetProperty ("USER", "sa");
            // 密码
           Propset.SetProperty ("PASSWORD", "sa");
          // 设置数据库的名字 , 只有 SQL Server  Informix 数据库才需要设置             
          Propset.SetProperty ("DATABASE", "sde");
          //SDE 的版本 , 在这为默认版本
          Propset.SetProperty ("VERSION", "SDE.DEFAULT");
    }
    // 定义一个工作空间 , 并实例化为 SDE 的工作空间
    IWorkspaceFactory Fact = new SdeWorkspaceFactoryClass();
    // 打开 SDE 工作空间 , 并转化为地物工作空间
    IFeatureWorkspace Workspace = (IFeatureWorkspace )Fact.Open(Propset,0);
    /* 定义一个地物类 , 并打开 SDE 中的管点地物类 , 写的时候一定要写全 . SDE 中有一个管点层 , 你不能写成 IFeatureClass Fcls = Workspace.OpenFeatureClass (" 管点 "); 这样 , 一定要写成下边的样子 .*/
       IFeatureClass Fcls = Workspace.OpenFeatureClass ("sde.dbo. 管点 ");
            
       IFeatureLayer Fly = new FeatureLayerClass ();
       Fly.FeatureClass = Fcls;
       MapCtr.Map.AddLayer (Fly);
       MapCtr.ActiveView.Refresh ();
    }
不知道注意到了没有 , 直接连接跟 SDE 连接的最大的不同是直接连接不要设置端口,同时他们的参数设置也不一样,好好注意参数的设置。

3、加载 CAD 图层
CAD 图层的加载可以分为:分图层加载和整幅图加载
A 分图层加载
我们可以把 CAD 图分为点、线、面、标注加载到 MapControl 中,跟加载其他数据一样,首先要定义一个工作空间,并用 CadWorkspaceFactoryClass ()实例化它,当得到了工作空间后就可以打开相应的工作空间,然后再打开指定的层类型。下边为完整的代码:
  public void AddCADByLayer()
    {
       // 定义工作空间,并用 CadWorkspaceFactoryClass() 实例化它
    IWorkspaceFactory Fact = new CadWorkspaceFactoryClass();
    // 打开相应的工作空间,并赋值给要素空间, OpenFromFile ()
    // 中的参数为 CAD 文件夹的路径
IFeatureWorkspace Workspace = Fact.OpenFromFile(@"I:/test/",0)  as IFeatureWorkspace;       
       /* 打开线要素类,如果要打开点类型的要素,需要把下边的代码该成:
   IFeatureClass Fcls = Workspace.OpenFeatureClass ("modle.dwg:point");
由此可见 modle.dwg CAD 图的名字,后边加上要打开的要素类的类型,中间用冒号隔开,大家可以想想多边形和标注是怎么打开的。 */
     IFeatureClass Fcls = Workspace.OpenFeatureClass ("modle.dwg:polyline");             
       IFeatureLayer Fly = new FeatureLayerClass ();
       Fly.FeatureClass = Fcls;
MapCtr.Map.AddLayer (Fly);
       MapCtr.ActiveView.Refresh ();
}
B 整幅 CAD 图的加载
当我们要加载整幅 CAD 图时,需要使用下边的代码,这跟加载地物类有一定的区别,详细地介绍请看代码中的注析:
public void AddWholeCAD()
{
       * 下边的两行代码是定义一个 CAD 工作空间,然后打开它,但这次不是赋值给
     IFeatureWorkspace 对象 , 而是赋值给 IWorkspace 定义的对象 */
IWorkspaceFactory Fact = new CadWorkspaceFactoryClass();
       IWorkspace Workspace = Fact.OpenFromFile(@"I:/test/",0);     
   // 定义一个 CAD 画图空间,并把上边打开的工作空间赋给它
       ICadDrawingWorkspace dw =  Workspace as ICadDrawingWorkspace;
   // 定义一个 CAD 的画图数据集,并且打开上边指定的工作空间中一幅 CAD
   // 然后赋值给 CAD 数据集
       ICadDrawingDataset ds = dw.OpenCadDrawingDataset ("modle.DWG");
   // 通过 ICadLayer 类,把上边得到的 CAD 数据局赋值给 ICadLayer 类对象的
   //CadDrawingDataset 属性
       ICadLayer CadLayer = new  CadLayerClass();
       CadLayer.CadDrawingDataset = ds;
        // 利用 MapControl 加载 CAD
       MapCtr.Map.AddLayer (CadLayer);
     MapCtr.ActiveView.Refresh ();
}
通过上边的代码和相关的解析,大家可能对整幅 CAD 图的加载有一个了解,但要具体搞清楚它的含义,也不那么容易。这留给大家去慢慢体会,在这我谈谈我自己的体会,但不一定正确。要打开数据集,首先要打开它的工作空间,至于什么是工作空间,我也说不太明白,但我的理解是,如果数据是保存在文件中的,工作空间大概就是它对应的文件夹,如果是数据库中的数据,我想大概就是对应的数据库。打开数据空间后,在这因为是整幅 CAD 图加载,所以跟以前的有点不同,这也就是相当整个 CAD 图就是一个数据集,所以要转到 CAD 画图的工作空间,然后把 CAD 图作为 CAD 数据集打开。为了在 MapControl 中加载 CAD 层,必须使用 ICadLayer 控件的对象,因为 MapCtr.Map.AddLayer () 方法中只能是 ICadLayer 的对象。