天天看點

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

湖北疫情資料專題顯示系統

代碼github位址:

https://github.com/yunwei37/COVID-19-ArcEngine

新型冠狀病毒肺炎(COVID-19,簡稱“新冠肺炎”)疫情肆虐全球多個國家,2020年3月11日,世界衛生組織 (WHO) 正式宣布将新冠肺炎列為全球性大流行病。在全球抗擊新型冠狀病毒疫情的過程中,産生了前所未有的大規模疫情資料,利用大資料分析技術和方法能夠協助發現病毒傳染源、監測疫情發展、調配救援物資,進而更好地進行疫情防控工作。空間資料分析作為大資料分析的重要組成,将資料智能處理、直覺展示和互動分析有機地結合,使機器智能和人類智慧深度融合、優勢互補,為疫情防控中的分析、指揮和決策提供有效依據和指南。

簡介:

本系統基于ArcEngine進行開發,支援武漢疫情地圖根據不同日期的展示、操作以及添加圖例、導出為多種格式,支援屬性資料的編輯和查詢,支援指定時間區段統計疫情與軌迹分析功能;可以直覺地展示出疫情的發展态勢,為疫情分析和防控工作作出更好的決策參考。

程式功能設計與展示:

開始界面布局:

進入程式顯示的開始界面:

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統
  • 視窗上方為菜單欄,包含檔案、查詢、屬性編輯、地圖導出等标簽;
  • 菜單欄的檔案選項包含打開MXD檔案、shapefile檔案,可以根據選擇的日期來渲染每日疫情地圖,也可以通過疫情統計按鈕打開疫情統計視窗;
  • 下方頁面包含空間展示和屬性資料兩個标簽,分别展示地圖和屬性資料;
  • 地圖包含左側的TOC和右側的地圖顯示視窗;
  • 顯示視窗可以切換資料視圖和頁面視圖;

每日疫情地圖:

可以根據選擇的日期來渲染每日疫情地圖,通過分層渲染的方式來表現疫情人數的多少;支援各種正常的地圖操作,如放大縮小平移等等;

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

行進軌迹繪制:

可以根據行進軌迹資料檔案,選取時間段繪制軌迹并分析經過的地市和疫情狀況:

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

空間查詢:

本系統支援多種查詢方式,包含點選查詢、矩形、多邊形、圓等多種空間查詢,并可以檢視相應選擇集:

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統
ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

地圖導出

本系統支援導出為多種格式,如jpg/tif/pdf等;可以在頁面視圖中實時檢視所要導出的圖形;并支援添加圖例等。

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

屬性資料:

本系統支援檢視資料集和進行屬性資料的編輯;

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

疫情統計:

支援根據時間段顯示疫情的統計資料,包含總量和變化量;

ArcEngine + DevPress GIS二次開發:開源湖北疫情互動式資料分析、地圖輸出、專題可視化系統湖北疫情資料專題顯示系統

附加功能:

  • 支援記錄檔記錄功能,便于對程式的錯誤進行排查;

程式具體實作

資料存儲與操作方式:

  • 将湖北市域圖形資料存儲在shp檔案中,通過加載shp按鈕進行載入;
  • 選擇網易的疫情實時動态播報平台作為資料源,其位址如下: https://wp.m.163.com/163/page/news/virus_report/index.html?nw=1&anw=1 通過爬蟲請求擷取資料(從1.1日至5.31日),經過資料清洗後儲存為csv檔案;
  • 在具有公網ip位址的 windows server 上搭建mysql資料庫,将确診人數資料存入資料庫中,連接配接資料庫擷取确診資料資訊;可以便于後續在伺服器上繼續更新資料;
  • 建立了DAO層,将資料庫的增删改查等操作封裝在工具類中,和具體程式業務邏輯分隔開來,其中包含了三個類:
    • SqlHelper

      :建立資料庫連接配接、執行資料庫指令、 建立MySqlDataReader對象:
    其中定義的接口:
    public MySqlConnection getMySqlCon();
    public int getMySqlCom(string M_str_sqlstr, params MySqlParameter[] parameters);
    public DataTable getMySqlRead(string M_str_sqlstr, params MySqlParameter[] parameters);           
    • sqlDataFormat

      :進行資料格式的修改:
    public static string dataFormat(string str);           
    • OperateDatabase

      :定義了資料庫增加、删除、修改、查找的接口;
    public static int Insert(string TableName,ArrayList arr);
    public static DataTable select(string TableName, ArrayList arr);
    public static int Update(string TableName, ArrayList arr,ArrayList arr_where);
    public static int Delete(string TableName, ArrayList arr_where);           

程式子產品設計與檔案組織:

程式可以分為以下幾個子產品:

  1. 輔助類:

包含和資料庫操作相關的DAO層、圖例附加屬性定義和日志子產品;除了上述描述的資料操作類以外,還有:

- EnumMapSurroundType:圖例附加屬性定義類
- Log: 日志子產品類
           
  1. 地圖操作相關:

    主要包含地圖操作(平移、縮放),地圖渲染,以及地圖導出等功能;

    • Form1:地圖展示和操作相關的實作;
    • GisClass:包含了打開MXD檔案、shp檔案,以及地圖渲染的一些輔助函數;
  2. 屬性操作相關

    包含在地圖上進行空間查詢屬性、在屬性表中進行屬性編輯等;

    • Form1:屬性表編輯和展示等操作
    • SeletionForm:進行屬性查詢
    • AddForm:添加資料
  3. 疫情資料統計子產品:

    包含對疫情的統計圖表生成操作;

    • StaticsForm類

從界面美觀的角度考慮,我們采用了DevExpress進行開發;DevExpress是一個比較有名的界面控件套件,提供了一系列的界面控件套件的DotNet界面控件。

視窗:

  • 主窗體類為

    Form1.cs

  • 進行屬性查詢選擇窗體類為

    SeletionForm.cs

  • 統計圖表類為

    StaticsForm.cs

  • 添加資料類為

    AddForm.cs

主要功能實作流程與方法

  1. 地圖展示和正常地圖操作:
    • 采用ArcEngine的mapControl控件進行地圖展示:
    • 采用ArcEngine的ToolbarControl控件完成正常的地圖操作,如放大、縮小、平移、全圖;
    • 加載shp/mxd檔案:

打開mxd檔案:

private void openMxd_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
     {
         String MxdPath=GisClass.OpenMxd();
         axMapControl1.LoadMxFile(MxdPath);
     }

 public static string OpenMxd()
     {
         string MxdPath = "";
         OpenFileDialog OpenMXD = new OpenFileDialog();
         OpenMXD.Title = "打開地圖";
         OpenMXD.InitialDirectory = "E:";

         OpenMXD.Filter = "Map Documents (*.mxd)|*.mxd";
         if (OpenMXD.ShowDialog() == DialogResult.OK)
         {
             MxdPath = OpenMXD.FileName;
         }
         return MxdPath;
     }           

打開shp檔案:

public static string[] OpenShapeFile()
    {
        string[] ShpFile = new string[2];
        OpenFileDialog OpenShpFile = new OpenFileDialog();
        OpenShpFile.Title = "打開Shape檔案";
        OpenShpFile.InitialDirectory = "E:";
        OpenShpFile.Filter = "Shape檔案(*.shp)|*.shp";

        if (OpenShpFile.ShowDialog() == DialogResult.OK)
        {
            string ShapPath = OpenShpFile.FileName;
            //利用"\\"将檔案路徑分成兩部分
            int Position = ShapPath.LastIndexOf("\\");

            string FilePath = ShapPath.Substring(0, Position);
            string ShpName = ShapPath.Substring(Position + 1);
            ShpFile[0] = FilePath;

            ShpFile[1] = ShpName;

        }
        else
        {
            return null;
        }
        return ShpFile;
    }           
  1. 每日疫情分布顯示:
    • 通過打開shp檔案按鈕加載

      市域.shp

      ,再周遊圖層擷取湖北市域空間資料;如未加載,系統會報錯如下:
      //周遊,尋找市域圖層
      for (int i = 0; i < this.axMapControl1.Map.LayerCount; i++) {
         ILayer layer1 = this.axMapControl1.Map.get_Layer(i);
         if (layer1.Name == "市域")
         {
             layer = layer1 as IFeatureLayer;
             break;
         }
      }
      if (layer == null) {
         MessageBox.Show("請打開市域圖層");
         return;
      }            
    • 點選每日疫情按鈕,首先擷取圖層的相應字段,然後根據選擇的日期在資料庫中進行查詢,擷取疫情資料;
      //擷取圖層字段,沒有則添加一個num字段
      IFeatureClass featureClass = layer.FeatureClass;
      int isExist=featureClass.FindField("num");
      if (isExist == -1) { 
         //添加一個字段
         IFields pFields = featureClass.Fields;
         IFieldsEdit pFieldsEdit = pFields as IFieldsEdit;
         IField fld = new FieldClass();
         IFieldEdit2 fldE = fld as IFieldEdit2;
         fldE.Name_2 = "num";
         fldE.AliasName_2 = "數量";
         fldE.Type_2 = esriFieldType.esriFieldTypeSingle;
         featureClass.AddField(fld);
      }
      //給字段指派
      IFeatureCursor pFtCursor = featureClass.Search(null, false);
      IFeature pFt = pFtCursor.NextFeature();
      int index1 = pFt.Fields.FindField("num");
      IDataset dataset = (IDataset)featureClass;
      IWorkspace workspace = dataset.Workspace;
      IWorkspaceEdit workspaceEdit = (IWorkspaceEdit)workspace;
      workspaceEdit.StartEditing(true);
      workspaceEdit.StartEditOperation();
      while (pFt != null) {
         int index = pFt.Fields.FindField("code");
         String code = pFt.get_Value(index).ToString();
      
         DataRow[] drs=dt.Select("CODE=" + code);
         DataTable dtNew = dt.Clone();
         for (int i = 0; i < drs.Length; i++)
         {
             dtNew.ImportRow(drs[i]);
      
         }
         String num = dtNew.Rows[0]["AllConfiemed"].ToString();
         if (num == "") {
             num = "0";
         }
      
         pFt.set_Value(index1,  Convert.ToInt32(num));
         pFt.Store();
         pFt = pFtCursor.NextFeature();
      }           
    • 根據擷取的資料對圖層進行渲染
      GisClass.ClassRender(this.axMapControl1.ActiveView, layer, 6, "num");           
  2. 空間查詢操作:
    • 通過點選圖形按鈕,繪制多邊形、圓、矩形等;
    如繪制多邊形:先設定繪制類型為多邊形,再建立一個多邊形元素,設定相應屬性,在pGraphicsContainer中添加該多邊形;然後滑鼠點選時追蹤多邊形,并局部重新整理map
    private void drawPolygon_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            this.type = 1;
            IPolygonElement polygonElement = new PolygonElementClass();
            pElement = polygonElement as IElement;
            ISimpleFillSymbol simpleFill = new SimpleFillSymbolClass();
            simpleFill.Style = esriSimpleFillStyle.esriSFSNull;
            simpleFill.Color = GisClass.GetRgbColor(255,0,0);
            //設定邊線顔色
            ILineSymbol lineSymbol = new SimpleLineSymbol();
            lineSymbol.Color = GisClass.GetRgbColor(255, 0, 0);
            IFillShapeElement shapeEle = pElement as IFillShapeElement;
    
            simpleFill.Outline = lineSymbol;
            shapeEle.Symbol = simpleFill;
            pGraphicsContainer.AddElement(pElement, 0);
        
          
        }
        private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e{
        .......
                if (this.type == 1)
                {
    
                    IGeometry Polygon = axMapControl1.TrackPolygon();
                    pElement.Geometry = Polygon;
                    axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewBackground, null, null);
                }
        ......
        }           
    • 通過點選查詢,對所選範圍執行空間查詢操作,對地圖上查詢到的部分進行高亮顯示;
      private void query_btn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
          {
              ArrayList arr = new ArrayList();
              DataTable dt = OperateDatabase.select("data", arr);
              this.gridControl1.DataSource = dt;
              this.tabControl2.SelectedIndex = 1;
          }
      
                 
    • 點選進行屬性查詢,打開屬性表;
      private void shapeQuery_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
          {
              axMapControl1.Map.ClearSelection();
              IGraphicsContainer graphicsContainer = axMapControl1.Map as IGraphicsContainer;
              graphicsContainer.Reset();
              IElement element = graphicsContainer.Next();
              //擷取圖形幾何資訊
              if (element == null) {
                  MessageBox.Show("請在工具欄選擇繪制矩形,多邊形,或者圓");
                  return;
              }
              IGeometry geometry = element.Geometry;
              axMapControl1.Map.SelectByShape(geometry,null,false);
              //進行部分重新整理顯示最新要素
              axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection,null,axMapControl1.ActiveView.Extent);
          }
                 
  3. 屬性資料編輯:
    • 在屬性資料的頁面中,可以點選查詢、增加、删除等按鈕進行屬性資料的編輯;
    修改單元格内容:
    //擷取修改的單元格
            string CellValue = this.gridView1.GetFocusedValue().ToString();
            //擷取單元格的列名
            string ColumnName = this.gridView1.FocusedColumn.FieldName;
            //擷取所在列的id
            DataRow dr = this.gridView1.GetDataRow(e.RowHandle);
            string id = dr["id"].ToString();
            //修改
            ArrayList arr = new ArrayList();
            if (ColumnName == "name" || ColumnName == "YMD")
            {
                arr.Add(ColumnName + ":'" + CellValue + "'");
            }
            else
            {
                arr.Add(ColumnName + ":" + CellValue);               
            }
            ArrayList arr_where = new ArrayList();
            arr_where.Add("id:" + id);
            int result = OperateDatabase.Update("data", arr, arr_where);
            if (result == 0)
            {
                MessageBox.Show("該值修改失敗");
            }           
添加資料:
           
private void add_btn_Click(object sender, EventArgs e)
    {
        ArrayList arr = new ArrayList();
        arr.Add("code:"+this.textBox_code.Text);
        arr.Add("name:'" + this.textBox_name.Text+"'");
        arr.Add("YMD:'" + this.date_edit.Text+"'");
        arr.Add("AllConfiemed:" + this.spinEdit_AllConfiemed.Text);
        arr.Add("CurConfirmeed:" + this.spinEdit_CurConfirmeed.Text);
        arr.Add("Cured:" + this.spinEdit_Cured.Text);
        arr.Add("Death:" + this.spinEdit_Death.Text);
        int result = OperateDatabase.Insert("data",arr);
        if (result == 1)
        {
            MessageBox.Show("添加成功");
            return;
        }else {
            MessageBox.Show("添加失敗");
            return;
        }
    }           
屬性查詢結果:

在屬性查詢結果中是以樹的方式展示不同圖層的查詢結果:
           
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        this.gridView1.Columns.Clear();
        currentLayer = e.Node.Tag as IFeatureLayer;
        if (currentLayer == null) {
            return;
        }
        IFeatureSelection featureSelection = currentLayer as IFeatureSelection;
        //擷取選中得要素幾何
        ISelectionSet selectionSet = featureSelection.SelectionSet;
        //擷取字段
        IFields fields = currentLayer.FeatureClass.Fields;
        DataTable dt = new DataTable();
        for (int i = 0; i < fields.FieldCount; i++) {
            dt.Columns.Add(fields.get_Field(i).Name);
        }
        //擷取整個資料集
        ICursor cursor;
        selectionSet.Search(null,false,out cursor);
        //擷取每個要素
        IFeatureCursor featureCursor = cursor as IFeatureCursor;
        //周遊
        IFeature feature = featureCursor.NextFeature();
        String[] strs;
        while (feature != null) {
            strs = new String[fields.FieldCount];
            for (int i = 0; i < fields.FieldCount; i++) {
                strs[i] = feature.get_Value(i).ToString();
            }
            dt.Rows.Add(strs);
            feature = featureCursor.NextFeature();
        }
        this.gridControl1.DataSource = dt;
       
    }           
    • 在首頁面上點選疫情統計,可顯示查詢視窗,其中可完成對于疫情統計圖表的生成和檢視;
      private void statics_btn_Click(object sender, EventArgs e)
          {
              //查詢起始日期的數字
              if (this.dateEdit_start.Text == "" || this.dateEdit_target.Text == "") {
                  MessageBox.Show("請填寫起止日期");
                  return;
              }
              ArrayList arr1 = new ArrayList();
              arr1.Add("YMD:'" + this.dateEdit_start.Text + "'");
              DataTable dt1 = OperateDatabase.select("data",arr1);
              ArrayList arr2 = new ArrayList();
              arr1.Add("YMD:'" + this.dateEdit_target.Text + "'");
              DataTable dt2 = OperateDatabase.select("data", arr1);
              Series s1 = this.chartControl1.Series[0];
              s1.DataSource = dt1;
              s1.ArgumentDataMember = "name";
              s1.ValueDataMembers[0] = "CurConfirmeed";
          }           
  1. 軌迹分析:
    • 通過日期框進行日期區間的選擇;
    • 軌迹資料已存放在資料庫中,通過sql查詢載入軌迹資料:
    • 進行軌迹查詢:
    • 繪制軌迹:
      if (this.start_time.EditValue == "" || this.end_time.EditValue == "") {
             MessageBox.Show("請選擇起止日期");
             return;
         }
         SqlHelper help = new SqlHelper();
         String sql = "select * from route where tm between '" + this.start_time.EditValue + "' and '" + this.end_time.EditValue+"'";
         DataTable dt = help.getMySqlRead(sql);
         ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbol();
         simpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
         IColor color = GisClass.GetRgbColor(0,255,0);
         simpleMarkerSymbol.Color = color;
         ILineElement lineElement = new LineElementClass();
         IElement ele1 = lineElement as IElement;
         ISegment pSegment;
         ILine pLine=null;
         object o = Type.Missing;
         ISegmentCollection pPath = new PathClass();
         for (int i = 0; i < dt.Rows.Count; i++) {
      
             IMarkerElement markerEle = new MarkerElementClass();
             IElement ele=markerEle as IElement;
             IPoint point = new PointClass();
             markerEle.Symbol = simpleMarkerSymbol;
             point.PutCoords(Double.Parse(dt.Rows[i]["x"].ToString()),Double.Parse(dt.Rows[i]["y"].ToString()));
             ele.Geometry = point;
             pGraphicsContainer.AddElement(ele,0);
             //逐段添加線
             if (i > 0 && i < dt.Rows.Count) {
                 IPoint point1 = new PointClass();
                 point1.PutCoords(Double.Parse(dt.Rows[i-1]["x"].ToString()), Double.Parse(dt.Rows[i-1]["y"].ToString()));
                 pLine = new LineClass();
                 pLine.PutCoords(point1, point);
                 pSegment = pLine as ISegment;
                 pPath.AddSegment(pSegment, ref o, ref o);
             }
           
            
             axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewBackground, null, null);
         }
         IGeometryCollection pPolyline = new PolylineClass();
         pPolyline.AddGeometry(pPath as IGeometry, ref o, ref o);
         IPolyline polyline = pPolyline as IPolyline;
         //擷取範圍
         IEnvelope ev = polyline.Envelope;
         this.axMapControl1.ActiveView.Extent = ev;
         ele1.Geometry = pPolyline as IPolyline;
         pGraphicsContainer.AddElement(ele1, 0);           
  2. 每日疫情圖輸出:
    • 添加圖例:可為地圖添加指北針、比例尺等;
    添加指北針:
    void addNorthArrow(IPageLayout pPageLayout, IEnvelope pEnv, IActiveView pActiveView)
        {
            if (pPageLayout == null || pActiveView == null)
            {
                return;
            }
         
    
            ESRI.ArcGIS.esriSystem.IUID uid = new ESRI.ArcGIS.esriSystem.UIDClass();
            uid.Value = "esriCarto.MarkerNorthArrow";
    
            ESRI.ArcGIS.Carto.IGraphicsContainer graphicsContainer = pPageLayout as ESRI.ArcGIS.Carto.IGraphicsContainer; 
            ESRI.ArcGIS.Carto.IActiveView activeView = pPageLayout as ESRI.ArcGIS.Carto.IActiveView; 
            ESRI.ArcGIS.Carto.IFrameElement frameElement = graphicsContainer.FindFrame(pActiveView.FocusMap);
            ESRI.ArcGIS.Carto.IMapFrame mapFrame = frameElement as ESRI.ArcGIS.Carto.IMapFrame; // Dynamic Cast
            ESRI.ArcGIS.Carto.IMapSurroundFrame mapSurroundFrame = mapFrame.CreateSurroundFrame(uid as ESRI.ArcGIS.esriSystem.UID, null); // Dynamic Cast
            ESRI.ArcGIS.Carto.IElement element = mapSurroundFrame as ESRI.ArcGIS.Carto.IElement; // Dynamic Cast
            element.Geometry = pEnv;
            element.Activate(activeView.ScreenDisplay);
            graphicsContainer.AddElement(element, 0);
            ESRI.ArcGIS.Carto.IMapSurround mapSurround = mapSurroundFrame.MapSurround;
    
            // Change out the default north arrow
            ESRI.ArcGIS.Carto.IMarkerNorthArrow markerNorthArrow = mapSurround as ESRI.ArcGIS.Carto.IMarkerNorthArrow; // Dynamic Cast
            ESRI.ArcGIS.Display.IMarkerSymbol markerSymbol = markerNorthArrow.MarkerSymbol;
            ESRI.ArcGIS.Display.ICharacterMarkerSymbol characterMarkerSymbol = markerSymbol as ESRI.ArcGIS.Display.ICharacterMarkerSymbol; // Dynamic Cast
            characterMarkerSymbol.CharacterIndex = 200; // change the symbol for the North Arrow
            markerNorthArrow.MarkerSymbol = characterMarkerSymbol;
        }           
添加比例尺:           
public void makeScaleBar(IActiveView pActiveView, IPageLayout pPageLayout, IEnvelope pEnv)
    {
        IGraphicsContainer container = pPageLayout as IGraphicsContainer;
        // 獲得MapFrame  
        IFrameElement frameElement = container.FindFrame(pActiveView.FocusMap);
        IMapFrame mapFrame = frameElement as IMapFrame;
        //根據MapSurround的uid,建立相應的MapSurroundFrame和MapSurround  
        UID uid = new UIDClass();
        uid.Value = "esriCarto.AlternatingScaleBar";
        IMapSurroundFrame mapSurroundFrame = mapFrame.CreateSurroundFrame(uid, null);
        //設定MapSurroundFrame中比例尺的樣式  
        IMapSurround mapSurround = mapSurroundFrame.MapSurround;
        IScaleBar markerScaleBar = ((IScaleBar)mapSurround);
        markerScaleBar.LabelPosition = esriVertPosEnum.esriBelow;
        markerScaleBar.UseMapSettings();
        //QI,确定mapSurroundFrame的位置  
        IElement element = mapSurroundFrame as IElement;

        element.Geometry = pEnv;
        //使用IGraphicsContainer接口添加顯示  
        container.AddElement(element, 0);
        pActiveView.Refresh();  
    }
    #endregion                
  • 點選輸出按鈕,可将疫情圖輸出為多種格式:

    如導出為圖檔:

    private void ExportMapToImage()
        {
            try
            {
                SaveFileDialog pSaveDialog = new SaveFileDialog();
                pSaveDialog.FileName = "";
                pSaveDialog.Filter = "JPG圖檔(*.JPG)|*.jpg|tif圖檔(*.tif)|*.tif|PDF文檔(*.PDF)|*.pdf";
                if (pSaveDialog.ShowDialog() == DialogResult.OK)
                {
                    double iScreenDispalyResolution =this.axPageLayoutControl1.ActiveView.ScreenDisplay.DisplayTransformation.Resolution;// 擷取螢幕分辨率的值
                    IExporter pExporter = null;
                    if (pSaveDialog.FilterIndex == 1)
                    {
                        pExporter = new JpegExporterClass();
                    }
                    else if (pSaveDialog.FilterIndex == 2)
                    {
                        pExporter = new TiffExporterClass();
                    }
                    else if (pSaveDialog.FilterIndex == 3)
                    {
                        pExporter = new PDFExporterClass();
                    }
                    pExporter.ExportFileName = pSaveDialog.FileName;
                    pExporter.Resolution = (short)iScreenDispalyResolution; //分辨率
                    tagRECT deviceRect = this.axPageLayoutControl1.ActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame();
                    IEnvelope pDeviceEnvelope = new EnvelopeClass();
                    pDeviceEnvelope.PutCoords(deviceRect.left, deviceRect.bottom, deviceRect.right, deviceRect.top);
                    pExporter.PixelBounds = pDeviceEnvelope; // 輸出圖檔的範圍
                    ITrackCancel pCancle = new CancelTrackerClass();//可用ESC鍵取消操作
                    this.axPageLayoutControl1.ActiveView.Output(pExporter.StartExporting(), pExporter.Resolution, ref deviceRect, this.axPageLayoutControl1.ActiveView.Extent, pCancle);
                    Application.DoEvents();
                    pExporter.FinishExporting();
                }
    
            }
            catch (Exception Err)
            {
                MessageBox.Show(Err.Message, "輸出圖檔", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }           
    除了導出為圖檔之外,支援多種其他格式,如pdf、jpg等

組員構成及分工:

  • : 屬性資料相關編輯與空間查詢操作、每日疫情分布顯示與疫情統計;
  • : 資料結構和資料庫設計與實施,地圖操作實作,軌迹分析與查詢,地圖輸出;
  • : 地圖展示,屬性資料、疫情分布顯示等功能的完善和bug修複,以及文檔撰寫;

遺留的一些問題與思考

  • 進行查詢需要操作的步驟較多,後續可以繼續優化;
  • 可以适當豐富疫情統計功能;
  • 從此次課程項目中也确實學到了許多,了解了一個GIS應用程式的完整開發流程;