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

    你们的评论、反馈,及对你们有所用,是我整理材料和博文写作的最大的鼓励和唯一动力。欢迎讨论和关注!
    没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。
  • 相关阅读:
    古谚、评论与论断、名篇与名言
    重读《西游记》
    重读《西游记》
    命名之法 —— 时间、季节、地点
    命名之法 —— 时间、季节、地点
    文言的理解 —— 古时的称谓、别称、别名
    文言的理解 —— 古时的称谓、别称、别名
    Oracle GoldenGate for Oracle 11g to PostgreSQL 9.2.4 Configuration
    瀑布 敏捷 文档
    POJ 1325 ZOJ 1364 最小覆盖点集
  • 原文地址:https://www.cnblogs.com/arxive/p/14320780.html
Copyright © 2011-2022 走看看