C#2008+ArcGIS Mobile实现路口定位
第一步:在道路图层中,通过模糊查询获取道路列表,并选取所需的道路,C#代码如下:
代码
1 /// <summary>
2 /// 模糊查询道路
3 /// </summary>
4 /// <param name="_name">道路名关键字</param>
5 /// <param name="_ms">待操作的mobileservice</param>
6 /// <param name="_layername">操作的图层名</param>
7 /// <param name="_lb">填充结果的ListBox</param>
8 /// <param name="_lg">获取的geometry集合</param>
9 public static void SearchRoadList(string _name, MobileService _ms, string _layername, ListBox _lb,out List<Geometry> _lg)
10 {
11 _lb.Items.Clear();
12 if (String.IsNullOrEmpty(_name))
13 {
14 _lg = null;
15 return;
16 }
17
18 MobileServiceLayer msl = _ms.Layers[_layername] as MobileServiceLayer;
19 FeatureLayer fl = msl as ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer;
20 string qstr = "NAME Like '%" + _name + "%'";//过滤内容
21
22 QueryFilter qf = new QueryFilter(qstr, true);//过滤器
23
24 using (FeatureDataReader fdr = fl.GetDataReader(qf))
25 {
26 _lg = new List<Geometry>();
27 while (fdr.Read())
28 {
29 Geometry geo = fdr.GetGeometry() as ESRI.ArcGIS.Mobile.Geometries.Geometry;
30 _lg.Add(geo);
31 string id = Convert.ToString(fdr["OBJECTID"]);
32 string name = Convert.ToString(fdr["NAME"]);
33 _lb.Items.Add(id + "-" + name);
34 }
35 }
36 if (_lb.Items.Count == 0)
37 {
38 MessageBox.Show("搜寻结果为空!", "提示");
39 }
40
41
42 }
2 /// 模糊查询道路
3 /// </summary>
4 /// <param name="_name">道路名关键字</param>
5 /// <param name="_ms">待操作的mobileservice</param>
6 /// <param name="_layername">操作的图层名</param>
7 /// <param name="_lb">填充结果的ListBox</param>
8 /// <param name="_lg">获取的geometry集合</param>
9 public static void SearchRoadList(string _name, MobileService _ms, string _layername, ListBox _lb,out List<Geometry> _lg)
10 {
11 _lb.Items.Clear();
12 if (String.IsNullOrEmpty(_name))
13 {
14 _lg = null;
15 return;
16 }
17
18 MobileServiceLayer msl = _ms.Layers[_layername] as MobileServiceLayer;
19 FeatureLayer fl = msl as ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer;
20 string qstr = "NAME Like '%" + _name + "%'";//过滤内容
21
22 QueryFilter qf = new QueryFilter(qstr, true);//过滤器
23
24 using (FeatureDataReader fdr = fl.GetDataReader(qf))
25 {
26 _lg = new List<Geometry>();
27 while (fdr.Read())
28 {
29 Geometry geo = fdr.GetGeometry() as ESRI.ArcGIS.Mobile.Geometries.Geometry;
30 _lg.Add(geo);
31 string id = Convert.ToString(fdr["OBJECTID"]);
32 string name = Convert.ToString(fdr["NAME"]);
33 _lb.Items.Add(id + "-" + name);
34 }
35 }
36 if (_lb.Items.Count == 0)
37 {
38 MessageBox.Show("搜寻结果为空!", "提示");
39 }
40
41
42 }
这里除了获取名称以外,也获取了道路的ID,这是因为在实际的数据中可能会有多条道路Polyline的Name相同,但ID不同,下面主要是通过ID定位道路
在ListBox有查询结果,选择道路后,可以从上面的List<Geometry> _lg中获取对应的Geometry,下面另外附了一段代码,是通过ID获取道路的Geometry的:
代码
1 /// <summary>
2 /// 根据ID获取道路的Geometry
3 /// </summary>
4 /// <param name="_roadid">道路ID</param>
5 /// <param name="_layername">道路操作图层</param>
6 /// <param name="_ms">要操作的MobileService</param>
7 /// <returns></returns>
8 public static ESRI.ArcGIS.Mobile.Geometries.Geometry GetGeometry(string _roadid, string _layername, MobileService _ms)
9 {
10 MobileServiceLayer msl = _ms.Layers[_layername] as MobileServiceLayer;
11 FeatureLayer fl = msl as FeatureLayer;
12 string qstr = "OBJECTID=" + _roadid;
13 QueryFilter qf = new QueryFilter(qstr, true);
14 ESRI.ArcGIS.Mobile.Geometries.Geometry G = null;
15 try
16 {
17 using (FeatureDataReader fdr = fl.GetDataReader(qf))
18 {
19 while (fdr.Read())
20 {
21 G = fdr.GetGeometry() as ESRI.ArcGIS.Mobile.Geometries.Geometry;
22 return G;
23 }
24 }
25 return G = null;
26 }
27 catch (Exception ex)
28 {
29 MessageBox.Show(ex.Message, "错误");
30 return G = null;
31 }
32 }
2 /// 根据ID获取道路的Geometry
3 /// </summary>
4 /// <param name="_roadid">道路ID</param>
5 /// <param name="_layername">道路操作图层</param>
6 /// <param name="_ms">要操作的MobileService</param>
7 /// <returns></returns>
8 public static ESRI.ArcGIS.Mobile.Geometries.Geometry GetGeometry(string _roadid, string _layername, MobileService _ms)
9 {
10 MobileServiceLayer msl = _ms.Layers[_layername] as MobileServiceLayer;
11 FeatureLayer fl = msl as FeatureLayer;
12 string qstr = "OBJECTID=" + _roadid;
13 QueryFilter qf = new QueryFilter(qstr, true);
14 ESRI.ArcGIS.Mobile.Geometries.Geometry G = null;
15 try
16 {
17 using (FeatureDataReader fdr = fl.GetDataReader(qf))
18 {
19 while (fdr.Read())
20 {
21 G = fdr.GetGeometry() as ESRI.ArcGIS.Mobile.Geometries.Geometry;
22 return G;
23 }
24 }
25 return G = null;
26 }
27 catch (Exception ex)
28 {
29 MessageBox.Show(ex.Message, "错误");
30 return G = null;
31 }
32 }
第二步,分析处理两个道路的Geometry,得到路口,并在图中高亮显示出来,C#代码如下,我的表述能力不怎么好,希望通过代码来弥补
代码
1 /// <summary>
2 /// 高亮显示路口
3 /// </summary>
4 /// <param name="mainroadid">主路的道路ID</param>
5 /// <param name="crossroadid">跨越道路ID</param>
6 /// <param name="layername">操作的图层名</param>
7 /// <param name="ms">操作的MobileService</param>
8 /// <param name="mp">操作的MobileMap</param>
9 /// <param name="cc">搜集到的CoordinateCollection</param>
10 /// <param name="IsMacth">是否超过一个路口</param>
11 public static void HightLightRoadCorner(Geometry mainGeo,Geometry crossGeo, string layername, MobileService ms, ESRI.ArcGIS.Mobile.Map mp, out CoordinateCollection cc, bool IsTouch)
12 {
13 try
14 {
15 //Geometry mainGeo = GetGeometry(mainroadid, layername, ms);
16 if (mainGeo == null)
17 {
18 MessageBox.Show("不能获取对应道路,请检查", "提示");
19 cc = null;
20 return;
21 }
22
23 //Geometry crossGeo = GetGeometry(crossroadid, layername, ms);
24 if (crossGeo == null)
25 {
26 MessageBox.Show("不能获取第二条道路,请检查", "提示");
27 cc = null;
28 return;
29 }
30 GeometricRelationshipType _type;
31 if (IsTouch == true)
32 _type = GeometricRelationshipType.Touch;//两条道路有两个或以上的路口
33 else
34 _type = GeometricRelationshipType.Cross;//两条道路有一个路口
35
36 bool IsCross = mainGeo.Relate(crossGeo, _type);//判断两者是否相交
37
38 if (IsCross == true)
39 {
40 IList<CoordinateCollection> crossRoadParts = crossGeo.Parts;
41 IList<Coordinate> crossRoadCoordinate = crossRoadParts[0];
42 CoordinateCollection tmpCollect = new CoordinateCollection();
43
44 if (crossRoadCoordinate.Count != 0)
45 {
46 for (int i = 0; i < crossRoadCoordinate.Count; i++)
47 {
48 ESRI.ArcGIS.Mobile.Geometries.Point tmppoint = new ESRI.ArcGIS.Mobile.Geometries.Point(crossRoadCoordinate[i]);
49
50 if (tmppoint.Within(mainGeo))
51 {
52 if (IsTouch == true)//有两个或以上交叉路口
53 {
54 Coordinate c = tmppoint.GetExtent().GetCenter();
55 tmpCollect.Add(c);
56 HighLightOnlyRoadCorner(tmppoint, mp, ms, layername);
57 }
58 else
59 {
60 cc=tmpCollect = null;
61 HighLightOnlyRoadCorner(tmppoint, mp, ms, layername);
62 return;
63 }
64
65 }
66
67 }
68 }
69 //if (tmpCollect.Count == 0)
70 // cc = null;
71 //else
72 // cc = tmpCollect;
73 cc = tmpCollect;
74
75 }
76 else
77 {
78 MessageBox.Show("两条道路不能相交,不能确定路口!", "提示");
79 cc = null;
80 return;
81 }
82 }
83 catch
84 {
85 cc = null;
86 }
87
88 }
2 /// 高亮显示路口
3 /// </summary>
4 /// <param name="mainroadid">主路的道路ID</param>
5 /// <param name="crossroadid">跨越道路ID</param>
6 /// <param name="layername">操作的图层名</param>
7 /// <param name="ms">操作的MobileService</param>
8 /// <param name="mp">操作的MobileMap</param>
9 /// <param name="cc">搜集到的CoordinateCollection</param>
10 /// <param name="IsMacth">是否超过一个路口</param>
11 public static void HightLightRoadCorner(Geometry mainGeo,Geometry crossGeo, string layername, MobileService ms, ESRI.ArcGIS.Mobile.Map mp, out CoordinateCollection cc, bool IsTouch)
12 {
13 try
14 {
15 //Geometry mainGeo = GetGeometry(mainroadid, layername, ms);
16 if (mainGeo == null)
17 {
18 MessageBox.Show("不能获取对应道路,请检查", "提示");
19 cc = null;
20 return;
21 }
22
23 //Geometry crossGeo = GetGeometry(crossroadid, layername, ms);
24 if (crossGeo == null)
25 {
26 MessageBox.Show("不能获取第二条道路,请检查", "提示");
27 cc = null;
28 return;
29 }
30 GeometricRelationshipType _type;
31 if (IsTouch == true)
32 _type = GeometricRelationshipType.Touch;//两条道路有两个或以上的路口
33 else
34 _type = GeometricRelationshipType.Cross;//两条道路有一个路口
35
36 bool IsCross = mainGeo.Relate(crossGeo, _type);//判断两者是否相交
37
38 if (IsCross == true)
39 {
40 IList<CoordinateCollection> crossRoadParts = crossGeo.Parts;
41 IList<Coordinate> crossRoadCoordinate = crossRoadParts[0];
42 CoordinateCollection tmpCollect = new CoordinateCollection();
43
44 if (crossRoadCoordinate.Count != 0)
45 {
46 for (int i = 0; i < crossRoadCoordinate.Count; i++)
47 {
48 ESRI.ArcGIS.Mobile.Geometries.Point tmppoint = new ESRI.ArcGIS.Mobile.Geometries.Point(crossRoadCoordinate[i]);
49
50 if (tmppoint.Within(mainGeo))
51 {
52 if (IsTouch == true)//有两个或以上交叉路口
53 {
54 Coordinate c = tmppoint.GetExtent().GetCenter();
55 tmpCollect.Add(c);
56 HighLightOnlyRoadCorner(tmppoint, mp, ms, layername);
57 }
58 else
59 {
60 cc=tmpCollect = null;
61 HighLightOnlyRoadCorner(tmppoint, mp, ms, layername);
62 return;
63 }
64
65 }
66
67 }
68 }
69 //if (tmpCollect.Count == 0)
70 // cc = null;
71 //else
72 // cc = tmpCollect;
73 cc = tmpCollect;
74
75 }
76 else
77 {
78 MessageBox.Show("两条道路不能相交,不能确定路口!", "提示");
79 cc = null;
80 return;
81 }
82 }
83 catch
84 {
85 cc = null;
86 }
87
88 }
下面是写的两个相关的函数
代码
1 /// <summary>
2 /// 判断点是否在指定区域内
3 /// </summary>
4 /// <param name="_g">geometry</param>
5 /// <param name="_ev">指定区域</param>
6 /// <returns></returns>
7 public static bool PointInEnvelop(Geometry _g, Envelope _ev)
8 {
9 Coordinate cd = _g.GetExtent().GetCenter();
10 double evcenterx = _ev.XCenter;
11 double evcentery = _ev.YCenter;
12 double minx = evcenterx - _ev.Width / 2;
13 double maxx = evcenterx + _ev.Width / 2;
14 double miny = evcentery - _ev.Height / 2;
15 double maxy = evcentery + _ev.Height / 2;
16
17 if (cd.X > minx && cd.X < maxx && cd.Y > miny && cd.Y < maxy)
18 {
19 return true;
20 }
21 else
22 {
23 return false;
24 }
25 }
26
27 /// <summary>
28 /// 定位路口单点
29 /// </summary>
30 /// <param name="cornerpoint">路口点</param>
31 /// <param name="mp">地图控件</param>
32 /// <param name="layername">图层名</param>
33 public static void HighLightOnlyRoadCorner(ESRI.ArcGIS.Mobile.Geometries.Point cornerpoint, ESRI.ArcGIS.Mobile.Map mp,MobileService ms,string layername)
34 {
35 Envelope newEnvelope = mp.GetExtent();
36 MobileServiceLayer msl = ms.Layers[layername] as MobileServiceLayer;
37 FeatureLayer fl = msl as ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer;
38 if (fl.InScaleRange(mp.Scale))
39 {
40 if (PointInEnvelop(cornerpoint as Geometry,newEnvelope))
41 {
42 mp.FlashGeometry(new Pen(Color.Blue, 2.0F), new SolidBrush(Color.Red), 15, 500, 15, cornerpoint);
43 }
44 else
45 {
46 Coordinate tmpcd = cornerpoint.GetExtent().GetCenter();
47 Envelope tmpel = new Envelope(tmpcd, 250, 250);
48 mp.SetExtent(tmpel);
49 mp.FlashGeometry(new Pen(Color.Blue, 2.0F), new SolidBrush(Color.Red), 20, 500, 20, cornerpoint);
50 }
51
52 }
53 else
54 {
55 Coordinate tmpcd = cornerpoint.GetExtent().GetCenter();
56 Envelope tmpel = new Envelope(tmpcd, 250, 250);
57 mp.SetExtent(tmpel);
58 mp.FlashGeometry(new Pen(Color.Blue, 2.0F), new SolidBrush(Color.Red), 20, 500, 20, cornerpoint);
59
60 }
61 }
62 }
2 /// 判断点是否在指定区域内
3 /// </summary>
4 /// <param name="_g">geometry</param>
5 /// <param name="_ev">指定区域</param>
6 /// <returns></returns>
7 public static bool PointInEnvelop(Geometry _g, Envelope _ev)
8 {
9 Coordinate cd = _g.GetExtent().GetCenter();
10 double evcenterx = _ev.XCenter;
11 double evcentery = _ev.YCenter;
12 double minx = evcenterx - _ev.Width / 2;
13 double maxx = evcenterx + _ev.Width / 2;
14 double miny = evcentery - _ev.Height / 2;
15 double maxy = evcentery + _ev.Height / 2;
16
17 if (cd.X > minx && cd.X < maxx && cd.Y > miny && cd.Y < maxy)
18 {
19 return true;
20 }
21 else
22 {
23 return false;
24 }
25 }
26
27 /// <summary>
28 /// 定位路口单点
29 /// </summary>
30 /// <param name="cornerpoint">路口点</param>
31 /// <param name="mp">地图控件</param>
32 /// <param name="layername">图层名</param>
33 public static void HighLightOnlyRoadCorner(ESRI.ArcGIS.Mobile.Geometries.Point cornerpoint, ESRI.ArcGIS.Mobile.Map mp,MobileService ms,string layername)
34 {
35 Envelope newEnvelope = mp.GetExtent();
36 MobileServiceLayer msl = ms.Layers[layername] as MobileServiceLayer;
37 FeatureLayer fl = msl as ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer;
38 if (fl.InScaleRange(mp.Scale))
39 {
40 if (PointInEnvelop(cornerpoint as Geometry,newEnvelope))
41 {
42 mp.FlashGeometry(new Pen(Color.Blue, 2.0F), new SolidBrush(Color.Red), 15, 500, 15, cornerpoint);
43 }
44 else
45 {
46 Coordinate tmpcd = cornerpoint.GetExtent().GetCenter();
47 Envelope tmpel = new Envelope(tmpcd, 250, 250);
48 mp.SetExtent(tmpel);
49 mp.FlashGeometry(new Pen(Color.Blue, 2.0F), new SolidBrush(Color.Red), 20, 500, 20, cornerpoint);
50 }
51
52 }
53 else
54 {
55 Coordinate tmpcd = cornerpoint.GetExtent().GetCenter();
56 Envelope tmpel = new Envelope(tmpcd, 250, 250);
57 mp.SetExtent(tmpel);
58 mp.FlashGeometry(new Pen(Color.Blue, 2.0F), new SolidBrush(Color.Red), 20, 500, 20, cornerpoint);
59
60 }
61 }
62 }
希望以上代码对大家使用ArcGIS Mobile进行道路定位有所帮助,如果有什么问题,可以与我联系~~~~
在实际操作过程中,可能两条道路会有两个路口甚至更多,举个例子:在上海,桂林路与桂林西街,桂林东街都有两个路口~
不过我上面的代码还有一个不算是Bug的Bug,就是在定位两个路口,甚至是两个路口以上的路口时,设置Mainroad和Crossroad时会有不同的结果,如果有高手能发现问题,请指出,兄弟在此谢过了!!!!!!!!!!