基於ArcGIS Engine + C#實現用戶自定義動態電力符號

ArcGIS Engine二次開發一般需要通過桌面產品來製作這些符號,然後通過專門的轉換工具轉換以後供AE使用。電力GIS應用當中,電力設備種類繁多,設備狀態比較複雜,需要用不同的符號來表現電力設備的不通狀態,此外電力技術的更新速度很快,新設備種類也不斷推陳出新,用戶往往要求提供符號定義工具以滿足這些需求。本文以配電變壓器爲例,介紹一種使用ArcGIS Engine + C#二次開發模式下,可以讓用戶自己定義設備符號的一種方法。
一、符號定義
配電變壓器符號如下圖所示:

可以將這個符號分解成四個圖元,兩段線段,兩個圓(圓弧)。用以下結構來描述圖元:

 

public struct MetaData
         {
              public int Typ;                // 圖形類型 3:圓弧,0:線段
              public double Scale;           // 縮放
              public int OffsX ;             // 偏移(x)
              public int OffsY;              // 偏移(y)
              public double Angle;           // 旋轉
              public int x1;                 // 圖元的第一點位置(x)
              public int y1;                 // 圖元的第一點位置(y)
              public int x2;                 // 圖元的第二點位置(x)
              public int y2;                 // 圖元的第二點位置(y)
              public int x3;                 // 圖元的第三點位置(x)
              public int y3;                 // 圖元的第三點位置(y)
              public int x4;                 // 圖元的第四點位置(x)
              public int y4;                 // 圖元的第四點位置(y)
     } // 線段:第一點:起點座標, 第二點:終點座標, 第三點, 第四點爲空

 

       // 圓弧:第一點:圓弧所在圓所屬矩形的左上角, 第二點:圓弧所在圓所屬矩形的左右下角,第三點:圓弧起點;第四點:圓弧終點

      // 圓弧方向爲逆時針,對於圓x3,y3,x4,y4重合

各圖元的座標如下:


Typ
x1
y1
X2
Y2
x3
Y3
X4
Y4
第一點
3
20
-70
160
70
90
-70
90
-70
第二點
3
100
-70
240
70
100
0
100
0
第三點
0
0
0
20
0
0
0
0
0
第四點
0
240
0
260
0
0
0
0
0

可以編寫一個繪製簡單圖元的繪圖工具,方便用戶繪製這些圖元,繪製好的圖元存成以上格式,存入到數據庫中,以方便系統讀入。

一、自定義、實現符號類MyMarkerSymbol:
1.類的定義:
自定義符號需要實現以下四個接口:
IMarkerSymbol
ISymbol
IClone
IpersistVariant

MyMarkerSymbol類定義爲:

 

    public class MyMarkerSymbol :IMarkerSymbol,ISymbol,IClone,IPersistVariant
{
         public MyMarkerSymbol() 
         { 
              //base.New(); 
              Class_Initialize_Renamed(); 
    }
}

構造函數,需將符號的角度傳入。

     
public MyMarkerSymbol(double ange) 
     { 
              //base.New(); 
              Class_Initialize_Renamed(); 
              m_Angle = ange;
}
//成員變量
     private int m_lPen; 
     private int m_lOldPen; 
     private int m_lHDC; 
     private double m_Angle;
     private int m_SymbolIndex;
     private ESRI.ArcGIS.Display.IDisplayTransformation m_pDispTrans;
    
private int m_lSize;


2.接口函數的實現:
要實現自定義符號需要實現這四個接口的多個函數,最重要的是ImarkerSymbol的三個函數:SetupDCDrawResetDC
SetupDC用於設置畫筆畫刷、顏色等信息。

     
public void SetupDC(int hDC, ITransformation transformation)
     {
              // TODO:  添加 MyMarkerSymbol.SetupDC 實現
              m_lPen = CreatePen(0, 2, System.Convert.ToInt32(m_pColor.RGB)); 
              m_lOldPen = SelectObject(hDC, m_lPen); 
              m_lHDC = hDC; 
              m_pDispTrans = (IDisplayTransformation)transformation; 
    }
hDC爲畫布句柄。

ResetDC函數,繪製完成後,進行資源釋放和狀態回覆。

 

         public void ResetDC()
         {
              // TODO:  添加 MyMarkerSymbol.ResetDC 實現
              SelectObject(m_lHDC, m_lOldPen); 
              DeleteObject(m_lPen); 
              m_pDispTrans = null
              m_lHDC = 0; 
    }

Draw函數實現符號的繪製工作:

 

public void Draw(IGeometry Geometry)
         {
              // TODO:  添加 MyMarkerSymbol.Draw 實現
              if (Geometry == null
              { 
                   return
              } 
              ESRI.ArcGIS.Geometry.IPoint pPt; 
              pPt = (IPoint)Geometry; 
              int x; 
              int y; 
              if (m_pDispTrans == null
              { 
                   x = (int)pPt.X; 
                   y = (int)pPt.Y; 
              } 
              else 
              { 
                   m_pDispTrans.FromMapPoint(pPt, out x, out y); 
              } 
              DrawMetas(x,y);
    }
3.DrawMetas實現:
需要在畫布上繪製兩條直線合兩個圓,可以通過調用Windows API函數來實現:

 

[System.Runtime.InteropServices.DllImport("gdi32")]

 

 

         private static extern bool LineTo (int hdc,int x,int y );

 

 

         [System.Runtime.InteropServices.DllImport("gdi32")]

 

 

         public static extern bool MoveToEx(int hdc,int x,int y,LPPOINT lpPoint);

 

 

         [System.Runtime.InteropServices.DllImport("gdi32")]

 

 

         public static extern bool Arc

 

 

              (int hdc,int X1,int Y1, int X2,int Y2,int X3, int Y3,int X4,int Y4);

 

 


4.圖元旋轉

自定義符號需要按指定角度進行旋轉,直線旋轉的方法比較簡單,以下介紹圓弧的旋轉方法:

以圓弧所在圓所屬矩形的左上角爲例:

旋轉前的座標爲(x0,y0),旋轉後的座標爲(x1,y1),計算出旋轉半徑r,alpha,則:

x1 = r*Math.Cos( alpha - mAngle );

    y1 = r*Math.Sin( alpha - mAngle );

其他各定點也可以用同樣方法計算。

計算出各頂點後調用以下方法繪製圓弧即可:

Arc(m_lHDC,(int)(x1),(int)(y1),(int)(x2),(int)(y2),    (int)(x3),(int)(y3),(int)(x4),(int)(y4));

對於直線段可以用以下方法繪製即可:

LPPOINT prePos=new LPPOINT();

     MoveToEx(m_lHDC,(int)x1,(int)y1,prePos);

     LineTo(m_lHDC,(int)x2,(int)y2);

三、調用符號

1.  使用IsimpleRenderer接口渲染:

        //定義render

IsimpleRenderer pSimpleRenderer = new SimpleRendererClass();

//定義自定義符號

MyMarkerSymbol mMyMarkerSymbol = new MyMarkerSymbol();

//渲染

IGeoFeatureLayer m_pGeoFeatureLayer;
pSimpleRenderer.Symbol = (ISymbol) mMyMarkerSymbol;

m_pGeoFeatureLayer = (IGeoFeatureLayer)ly;

m_pGeoFeatureLayer.Renderer = (IFeatureRenderer)pSimpleRenderer;

2.  使用IUniqueValueRenderer接口渲染:
IuniqueValueRenderer pRender = new UniqueValueRendererClass();      

        iAngleField = pFields.FindField("ANGLE");

        for (int i=0;i< pFeatCls.FeatureCount(pQueryFilter) ;i++)

        {

                   pFeat = pFeatCursor.NextFeature();

                   string x = null;

                   x = pFeat.get_Value(iField).ToString() ;

                   dAngle = (double)pFeat.get_Value(iAngleField);

                   SymbolIndex = int.Parse(pFeat.get_Value(iSymIndexField).ToString());

                   MyMarkerSymbol sym = new MyMarkerSymbol(dAngle);

                   pRender.AddValue( x,x, (ISymbol)msy);

         }        

pLyr.Renderer = (IFeatureRenderer)pRender;


以上介紹只能實現比較簡單的動態符號,但只要完善其中的函數,就可以實現各種複雜的電力符號,應用到Arcgis Engine應用開發中,實現用戶自定義設備符號,系統自動渲染。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章