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

简介:

华立电网北京研发中心 阿文

ArcGIS Engine二次开发一般需要通过桌面产品来制作这些符号,然后通过专门的转换工具转换以后供AE使用。电力GIS应用当中,电力设备种类繁多,设备状态比较复杂,需要用不同的符号来表现电力设备的不通状态,此外电力技术的更新速度很快,新设备种类也不断推陈出新,用户往往要求提供符号定义工具以满足这些需求。本文以配电变压器为例,介绍一种使用ArcGIS Engine + C#二次开发模式下,可以让用户自己定义设备符号的一种方法。

一、符号定义

配电变压器符号如下图所示:


jpg.gif此主题相关图片如下:
20073810472079563.jpg

可以将这个符号分解成四个图元,两段线段,两个圆(圆弧)。用以下结构来描述图元:

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

可以编写一个绘制简单图元的绘图工具,方便用户绘制这些图元,绘制好的图元存成以上格式,存入到数据库中,以方便系统读入。


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:00

4.图元旋转

自定义符号需要按指定角度进行旋转,直线旋转的方法比较简单,以下介绍圆弧的旋转方法:

以圆弧所在圆所属矩形的左上角为例:


jpg.gif此主题相关图片如下:
20073810515311930.jpg

旋转前的坐标为(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






    本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/xiexiaokui/archive/2008/07/25/1251691.html ,如需转载请自行联系原作者
相关文章
|
2月前
|
C#
C#学习相关系列之常用符号介绍
C#学习相关系列之常用符号介绍
|
9月前
|
关系型数据库 MySQL C#
C# winform 一个窗体需要调用自定义用户控件的控件名称
给用户控件ucQRCode增加属性: //二维码图片 private PictureBox _pictureBoxFSHLQrCode; public PictureBox PictureBoxFSHLQrCode {   get { return _pictureBoxFSHLQrCode; }   set { this.pictureBoxFSHLQrCode = value; } } 在Form1窗体直接调用即可: ucQRCode uQRCode=new ucQRCode(); ucQRCode.PictureBoxFSHLQrCode.属性= 要复制或传给用户控件上的控件的值
48 0
|
22天前
|
C# C++
C# 自定义时间进度条
本文作者通过参考leslie_xin的一篇文章,成功创建了一个自定义的WinForms控件——时间进度条,该控件带有时间刻度和多种可定制的属性,如颜色、时间间隔等。作者在控件中加入了开始和结束时间,以及自适应的时间刻度间隔。控件能根据设置显示时间标签,并提供了事件处理,如值改变时的触发。代码中包含了计算时间刻度、绘制刻度线和时间标签的逻辑。作者强调了避免循环调用事件、使用OnXXX()形式的事件处理函数以及注意自定义控件中的属性和事件设计。
62 7
|
16天前
|
SQL 存储 关系型数据库
ArcGIS Engine连接ArcSDE SQL Server(获得所有SDE图层)
ArcGIS Engine连接ArcSDE SQL Server(获得所有SDE图层)
|
2月前
|
移动开发 JavaScript 安全
C# 实现微信自定义分享
C# 实现微信自定义分享
|
2月前
|
C#
C#学习相关系列之自定义遍历器
C#学习相关系列之自定义遍历器
|
10月前
|
编译器 C#
c# 自定义扩展方法
c# 自定义扩展方法
|
2月前
|
Python
ArcGIS中ArcMap通过Python程序脚本新建工具箱与自定义工具的方法
ArcGIS中ArcMap通过Python程序脚本新建工具箱与自定义工具的方法
|
定位技术
ArcGIS:如何对Shapefile文件进行符号系统修改、标注、合并、分割、拓扑编辑等?
ArcGIS:如何对Shapefile文件进行符号系统修改、标注、合并、分割、拓扑编辑等?
330 0
|
9月前
|
编译器 C#
C#中导入其它自定义的命名空间
c#中怎么导入其它自定义的命名空间首先要确保已经导入了想要导入的自定义的命名空间。如上图这时编译器应该会报错,此时就需要手动去添加引用了,cs文件默认没有添加引用,只是加载了想要导入的命名空间,但是没有添加引用,所以需要自己要手动添加引用。切记!然后会有一个对话框选择你想引用的命名空间,点击确定即可。注意:一般而言,C#中如果没有改变那么一般项目的类名都默认是Program,在引用时需要注...
81 1
C#中导入其它自定义的命名空间