zoukankan      html  css  js  c++  java
  • 基于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重合
    View Code

    各图元的坐标如下:

     

    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);

        }

    3DrawMetas实现:

    需要在画布上绘制两条直线合两个圆,可以通过调用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应用开发中,实现用户自定义设备符号,系统自动渲染。如有更好方法请赐教hongwu.tan@hotmail.com

    你们的评论、反馈,及对你们有所用,是我整理材料和博文写作的最大的鼓励和唯一动力。欢迎讨论和关注!
    没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。
  • 相关阅读:
    entrySet()
    DBCC DBREINDEX重建索引提高SQL Server性能
    ASP中调用存储过程、语法、写法-sql server数据
    这个月一直很忙,没时间写点心得,就放点周末去玩的照片吧
    JQuery 中,使文本框获得焦点的方法
    数据库系统不能自动删除备份的原因之一
    C# 中的常用正则表达式总结
    删除在建表时SQL SERVER2000指定PRIMARY KEY引起的 聚合索引
    IIS7入门之旅:(1)appcmd命令的使用
    IIS7入门之旅:(2)如何实现和加载自定义的Basic Authentication模块
  • 原文地址:https://www.cnblogs.com/arxive/p/14320780.html
Copyright © 2011-2022 走看看