Arcgis API for Flex 1.3的功能虽然很强,但如何让Flex去完成C/S系统中的拓扑分析这些大量计算和分析的任务?目前FLEX端还很难完成这样的分析计算(如果您有什么好的实现,还望不吝赐教)。
最近一直在做一个水利方面的WEBGIS系统,其中就有河道地形的断面分析。
想了很多办法,都不能很好的解决这个问题,最后还是使用Engine在后台完成断面分析后回传断面数据生成断面曲线的方式完成了这个功能,在效率上和C/S系统的基本差不多,并没有觉得慢。下面就来说说实现的思路。
先看看效果图
基本条件:
1.服务器:Gis Server + IIS
2.后台:.NET + FluorineFx框架 + Engine
3.通信方式:FLEX与后台通信方式又很多,这里采用AMF通信。
基本思路
利用Arcgis API For Flex + Flex 实现地图前台浏览和基本操作,当用户选择切割断面工具的时候绘制一个断面线段(这个随便是多线段还是直线),这个时候会取到这个线段的点集,把这个点集传到后台,Engine用这些点集完成与DEM的拓扑分析并返回结果给FLEX端,最后FLEX生成断面曲线。
具体实现
1. VO映射:
确定有哪些值对象,并做好映射。
A : FLEX做断面切割后传递给.NET的点集——Point(有两个属性:x,y坐标)
B : Engine完成分析回传给FLEX的断面曲线数据——CutDemLine(displayName:曲线的名称,List<DemPoint> demPointCollection:断面曲线数据)。这里还有个DemPoint(distance:距离切割线起点的长度,height:高程)值对象,也就是断面曲线上一个点对象。
DemPoint.as
2 {
3 [RemoteClass(alias="Jinhe.VO.DemPoint")]
4 public class DemPoint
5 {
6 public var distance:Number;
7 public var height:Number;
8 }
9 }
10
11
DemPoint.cs
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace Jinhe.VO
6 {
7 /// <summary>
8 /// DEM 上的点的值
9 /// </summary>
10 public class DemPoint
11 {
12 private double _distance;
13 /// <summary>
14 /// 距离切割线起点的长度
15 /// </summary>
16 public double distance
17 {
18 set
19 {
20 _distance = value;
21 }
22 get
23 {
24 return _distance;
25 }
26 }
27
28 private double _height;
29 /// <summary>
30 /// 该点的高程
31 /// </summary>
32 public double height
33 {
34 set
35 {
36 _height = value;
37 }
38 get
39 {
40 return _height;
41 }
42 }
43 }
44 }
45
CutDemLine.as
2 {
3 import mx.collections.ArrayCollection;
4
5 [RemoteClass(alias="Jinhe.VO.CutDemLine")]
6 public class CutDemLine
7 {
8 public var displayName:String;
9 public var demPointCollection:ArrayCollection;
10 }
11 }
CutDemLine.cs
using System.Collections.Generic;
using System.Text;
namespace Jinhe.VO
{
/// <summary>
/// 切割DEM 生成的断面数据曲线
/// </summary>
public class CutDemLine
{
private string _displayName;
/// <summary>
/// 断面曲线的名称
/// </summary>
public string displayName
{
set
{
_displayName = value;
}
get
{
return _displayName;
}
}
private List<DemPoint> _demPointCollection;
/// <summary>
/// 断面曲线数据
/// </summary>
public List<DemPoint> demPointCollection
{
set
{
_demPointCollection = value;
}
get
{
if (_demPointCollection == null)
_demPointCollection = new List<DemPoint>();
return _demPointCollection;
}
}
}
}
2. FLEX端切割和绘制断面曲线
主要的MXML部分:
<mx:HBox width="100%"
horizontalAlign="center">
<mx:ComboBox id="selectBox"
dataProvider="{demData}"
change="changeHandler(event)"/>
<mx:Button height="25" enabled="false" id="drawLineBtn"
label="切割" click="clickHandler(event)"
icon="@Embed(source='../assets/images/icons/i_draw_line.png')"/>
<mx:Button height="25"
label="打印预览" id="printBtn" click="printBtn_clickHandler(event)"
icon="@Embed(source='../assets/images/icons/i_print.png')"/>
</mx:HBox>
<mx:Label id="myState" text="" />
<mx:HBox height="90%" id="chart"
width="100%">
<mx:LineChart id="line" showDataTips="true" fontSize="14" color="#000000" dataTipFunction="dataTipFunction" seriesFilters="{[]}"
height="100%"
width="100%" >
<mx:backgroundElements>
<mx:GridLines direction="both"
horizontalTickAligned="true"
verticalTickAligned="true">
<mx:horizontalFill>
<mx:SolidColor color="haloBlue" alpha="0.3" />
</mx:horizontalFill>
<mx:horizontalAlternateFill>
<mx:SolidColor color="haloSilver" alpha="0.3" />
</mx:horizontalAlternateFill>
<mx:verticalFill>
<mx:SolidColor color="haloBlue" alpha="0.3" />
</mx:verticalFill>
<mx:verticalAlternateFill>
<mx:SolidColor color="haloSilver" alpha="0.3" />
</mx:verticalAlternateFill>
</mx:GridLines>
</mx:backgroundElements>
<mx:verticalAxis>
<mx:LinearAxis displayName="高程" title="高程" />
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:LinearAxis displayName="距离" title="距离" />
</mx:horizontalAxis>
</mx:LineChart>
<mx:Legend dataProvider="{line}" color="#00000" legendItemClass="Jinhe.Class.BigFontLegendItem" />
</mx:HBox>
断面切割线完成以后调用.NET拓扑分析方法,在NET返回结果后绘制断面曲线
2 {
3
4 var lineGeometry:Polyline = event.graphic.geometry as Polyline;
5 graphicsLayer.clear();
6 var gra:Graphic = new Graphic(lineGeometry);
7 var lineSym:SimpleLineSymbol = new SimpleLineSymbol("solid",0xff0000, 1,2);
8 gra.symbol = lineSym;
9 graphicsLayer.add(gra);
10 measurePt = lineGeometry.extent.center;
11 addDrawLabel("断面");
12 var points:Array = [];
13
14 //线段在当前的DEM范围内
15 var isAtSelectExtent:Boolean=true;
16
17 for each (var mapPoint:MapPoint in lineGeometry.paths[0])
18 {
19
20 if (selectExtent.contains(mapPoint))
21 {
22
23 var point:com.esri.solutions.flexviewer.vo.Point=new com.esri.solutions.flexviewer.vo.Point();
24 point.x=mapPoint.x;
25 point.y=mapPoint.y;
26 points.push(point);
27 }
28 else
29 {
30 isAtSelectExtent=false;
31 break;
32 }
33
34 }
35
36
37
38 if(isAtSelectExtent)
39 {
40 var filePathList:Array = selectBox.selectedItem.raster as Array;
41
42 var j:int =filePathList.length;
43 var lineArray:Array = [];
44 line.series = lineArray;
45 var colorIndex:int = 0;//颜色索引
46 var colorArray:Array = [0xff6c00,0x1200ff,0x04b000,0x0046b0,0xff0000,0x030031];
47 for(var i:int = 0; i< j; i++)
48 {
49 var displayName:String = filePathList[i].label;
50 myState.text = "正在计算"+displayName+"断面曲线,请稍候..."
51 var responder:IResponder = new mx.rpc.Responder(onResult,onFault);
52 netDal.CutDem(points,String(filePathList[i].source),displayName).addResponder(responder);
53 netDal.CutDem(points,String(filePathList[i].source),displayName);
54
55
56 function onResult(result:ResultEvent):void
57 {
58 if(result.result)
59 {
60 var lineSeries:LineSeries = new LineSeries();
61 lineSeries.xField = "distance";
62 lineSeries.yField = "height";
63 var lineStroke:Stroke = new Stroke(colorArray[colorIndex], 3);
64 colorIndex++;
65 lineSeries.setStyle("lineStroke", lineStroke);
66
67 lineSeries.setStyle("form","curve");
68
69
70 lineSeries.displayName = (result.result as CutDemLine).displayName;
71 lineSeries.dataProvider = (result.result as CutDemLine).demPointCollection;
72 lineArray.push(lineSeries);
73 line.series = lineArray;
74 myState.text = "";
75 }
76 }
77 }
78
79 }
80 else
81 {
82 mx.controls.Alert.show("您的切割线不是全部在所选择的河段内,请您选择正确的河段!");
83 }
84
85 }
86
3.后台完成拓扑分析
A :提供FLEX可访问的切割断面分析方法
[RemotingService()]
public class DAL{}
{
DataTable dt = CutDem(points, filePath);
if (dt != null)
{
int lenght = dt.Rows.Count;
CutDemLine cutDemLine = new CutDemLine();
cutDemLine.displayName = name;
for (int i = 0; i < lenght; i++)
{
DemPoint demPoint = new DemPoint();
demPoint.distance =Convert.ToDouble(dt.Rows[i]["distance"]);
demPoint.height = Convert.ToDouble(dt.Rows[i]["height"]);
cutDemLine.demPointCollection.Add(demPoint);
}
return cutDemLine;
}
else
{
return null;
}
}
[DataTableType("Jinhe.RemotingCenter.DAL")]
public DataTable CutDem(List<Jinhe.VO.Point> points, string filePath)
{
if (points != null)
{
string path = Config.getInstance().demRootPath + filePath;
return Jinhe.ArcEngine.CutDem.CutDemAndGetDt(points, path);
}
else
{
return null;
}
}
B: 创建点集并与DEM图做拓扑分析
{
IPointCollection pc = new PolylineClass();
object obj = Type.Missing;
for (int i = 0; i < points.Count; i++)
{
IPoint tempPoint = new PointClass();
//ESRI.ArcGIS.Geometry.Point point = new ESRI.ArcGIS.Geometry.Point();
tempPoint.X = points[i].x;
tempPoint.Y = points[i].y;
pc.AddPoint(tempPoint, ref obj, ref obj);
}
//节点抽稀
// pc = jznfit(pc);
return getDTByDemCutLine(pc, filePath);
}
DEM图与点集的拓扑分析方法:
//DEM切割
public static DataTable getDTByDemCutLine(IPointCollection pPointCollection, string demFullPath)
{}
只有两个参数,其中demFullPath是DEM文件路径
关于这个拓扑分析的方法我是从同事C/S系统中抽出来的,所以在这里就不提供了
本文是原创内容,若转载用显眼文字加以说明并提供本文的链接,谢谢!