在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
基于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重合
各图元的坐标如下:
可以编写一个绘制简单图元的绘图工具,方便用户绘制这些图元,绘制好的图元存成以上格式,存入到数据库中,以方便系统读入。 2楼
tanhw 发表于:2007-3-8 10:49:00
一、自定义、实现符号类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的三个函数:SetupDC,Draw和ResetDC。 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); 3楼
tanhw 发表于:2007-3-8 10:53:004.图元旋转 自定义符号需要按指定角度进行旋转,直线旋转的方法比较简单,以下介绍圆弧的旋转方法: 以圆弧所在圆所属矩形的左上角为例: 旋转前的坐标为(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应用开发中,实现用户自定义设备符号,系统自动渲染。如有更好方法请赐教([email protected]) |
请发表评论