基于ArcGIS Engine + C#实现用户自定义动态电力符号

本文介绍如何使用ArcGISEngine+C#进行二次开发,使用户能够自定义电力设备符号。通过定义图元及其属性,实现复杂电力符号的绘制,并介绍了符号旋转方法及渲染方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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应用开发中,实现用户自定义设备符号,系统自动渲染。 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值