项目说明:
在windowsMobile6.0的平台下,做GPS掌上地图定位程序。需要实现查询GPS定位点周围一定范围内的天然气管线的信息。
功能要求:
1、地图上以定位点为中心,半径R,画一个空心圆。
2、查询圆内的天然气管线,如果存在管线,将管线主要信息放置在listview中显示。
3、单击listview中具体每条管线信息时在地图上绘制出这条管线和圆心的最短距离的线段,并绘制出线段长度。
解决方案;
1、在地图的Pait事件中进行绘制圆,主要用到 函数DrawEllipse;
///定义一个封闭的范围,然后再范围中绘制圆。
//注意要绘制空心圆,只需要将画刷的颜色置为空。
Envelope el = new Envelope(gpsManager.SearchLocation.Coordinate, gpsManager.Range*2, gpsManager.Range*2);
e.Display.DrawEllipse(new Pen(Color.Black), new SolidBrush(Color.Empty), el);
2、判断和圆相交的管线,arcgismobile10中没有提供折线与圆相交的函数,但是有折线与矩形相交的判断函数。先用arcgismobile10中提供
的函数查询出与圆所在的矩形框相交的管线,在重这些管线中帅选出真正与圆相交的管线。
折线与圆相交,就是线段与圆相交。这个问题就变成求线段要与圆的相交问题。
如果线段上的点到圆心的距离小于圆半径,则这条线段与圆相交或在圆内。
线段与圆相交或在圆内有三中情况。
设线段的两个端为A,B,圆心为P,圆半径R
1、如果角APB为锐减或直角,点p到线段AB的垂足D在线段AB上,如果PD的长度小于R则线段AB与圆相交或在圆内。
2、如果角ABP为钝角,点p到线段AB的垂足D在线段AB的延长线上,如果PD的长度小于R则线段AB与圆相交或在圆内。如果AB*AB+BP*BP 角ABP为钝角 3、如果角BAP为钝角,点p到线段AB的垂足D在线段BA的延长线上,如果PD的长度小于R则线段AB与圆相交或在圆内。如果AP*AP+AB*AB 角BAP为钝角 关于三角形垂足的求法分两个方面考虑: 1、垂线PD的斜率存在。 2、垂线PD的斜率不存在。 补充一下几何知识:设AB的斜率K1,PD的斜率K2,则K1*K2=-1. AB的斜率可以通过两点式求得。这通过公是可求出PD的斜率K2. 根据线段PD的公司y=k2*x+a;,将P的坐标带入,求出b,这PD的线段公式已知。 联立AB的公式和PD公式,求出交点D的坐标。 具体代码如下: private List /// /// ESRI.ArcGIS.Mobile.Map map1, ListView dataGrid1) GpsLocation.Coordinate.Y); // if no geometry /// SearchLocation.Coordinate.Y - begintcoor.Y) / (1 / k + k)); SearchLocation.Coordinate.Y); /// /// gpsManager.Position.Heading , 20); gpsManager.SearchLocation.Coordinate); .SearchLocation .Coordinate .X )/2,(gpsManager .SelectGeometry [index ].NearCoor .Y +gpsManager .SearchLocation.Coordinate .Y )/2); m", new Font(FontFamily.GenericSerif , 14, FontStyle.Regular), Color.Black, Color.Blue, cor, ESRI.ArcGIS.Mobile.TextAlignment.MiddleLeft);
public List
{
get
{
return _selectGeomety;
}
set
{
_selectGeomety =value ;
}
}
/// 是否画搜索范围
///
public bool DrawRange
{
get;
set;
}
/// 查找搜索范围内的管线
///
/// 地图缓存
/// 地图
public void FindFeaturesInEnvelope(ESRI.ArcGIS.Mobile.MobileServices.MobileCache mobileCache1,
{
//根据坐标点创建一个Envelope矩形
if (GpsLocation != null)
{
SelectGeometry.Clear();
SearchLocation = new ESRI.ArcGIS.Mobile.Geometries.Point(GpsLocation.Coordinate.X,
Envelope envelope = new Envelope(SearchLocation.Coordinate, Range*2, Range*2);
//得到地图的第一个图层
FeatureLayer featureLayer = mobileCache1.Layers["line_polyline"] as FeatureLayer;
if (featureLayer == null)
return;
//创建了一个查询实例过滤器。查询过滤器为Envelop的矩形,
//过滤器会查询这个矩形内包含的要素。
QueryFilter spatialQueryFilter = new QueryFilter(envelope, GeometricRelationshipType.Intersect);
//设置这个图层进行空间查询
FeatureDataTable featureDataTable = featureLayer.GetDataTable(spatialQueryFilter);
//如果功能层的数据表没有行返回
if (featureDataTable.Rows.Count == 0)
{
MessageBox.Show("未发现管线!");
DrawRange = false;
return;
}
else
{
DrawRange = true;
for (int i = 0; i < featureDataTable.Rows.Count; i++)
{
Geometry geo = featureDataTable.Rows[i][featureDataTable.GeometryColumnIndex] as Geometry;
if (!FindNearestPointInEvelope(geo))
{
featureDataTable.Rows.RemoveAt(i);
i--;
}
}
}
if (featureDataTable.Rows.Count > 0)
{
//返回查询后要素的几何形状
Geometry geometry = featureDataTable.Rows[0][featureDataTable.GeometryColumnIndex] as Geometry;
if (geometry == null)
return;
//地图根据这个几何图形进行闪烁,闪烁5次,每次150毫秒。
map1.FlashGeometry(new Pen(Color.Red), new SolidBrush(Color.Yellow), 15, 150, 5, geometry);
dataGrid1.Items.Clear();
foreach (FeatureDataRow row in featureDataTable.Rows)
{
string []str=new string [4];
str[0]=row ["TYPE"].ToString ();
str[1]=row["Name"].ToString ();
str[2]=row["Describe"].ToString ();
str[3]=row["LineLength"].ToString ();
ListViewItem lvItem = new ListViewItem
(
str
);
dataGrid1.Items.Add(lvItem);
}
}
}
else
{
MessageBox.Show("卫星未定位!");
}
}
/// 判断给定的几何图形是否与闭合框相交,并将相交的几何图形和信息加入列表中
///
/// 已经与闭合选择框相交的图形
public bool FindNearestPointInEvelope(Geometry geo)
{
//标志给定的几何图形有与给点的圆相交的点或者有在园内的线段
bool isCorossOrContain = false;
Coordinate nearestPoint = new Coordinate();
double nearestDistance = Range ;
foreach (CoordinateCollection coordcol in geo.Parts)
{
if (coordcol.Count > 1)
{
for (int i = 0; i < coordcol.Count - 1; i++)
{
Coordinate begintcoor = coordcol[i];
Coordinate endcoor = coordcol[i + 1];
Coordinate footPoint = new Coordinate();
Coordinate tempnearestPoint = new Coordinate();
double tempnearestDistance = 0;
double k = (endcoor.Y - begintcoor.Y) / (endcoor.X - begintcoor.X);
if (k == 0) //垂线斜率不存在情况
{
footPoint.X = SearchLocation.Coordinate.X;
footPoint.Y = begintcoor.Y;
}
else
{
footPoint.X = (float)((k * begintcoor.X + SearchLocation.Coordinate.X / k +
footPoint.Y = (float)(-1 / k * (footPoint.X - SearchLocation.Coordinate.X) +
}
//点begintcoor和点endcoor之间线段长
double c = GetDistance(begintcoor, endcoor);
//点begintcoor和定位点之间的线段长
double a = GetDistance(begintcoor, SearchLocation.Coordinate);
//点endcoor和定位点之间的线段长
double b = GetDistance(endcoor, SearchLocation.Coordinate);
//垂足点和定位的之间的长度
double h = GetDistance(footPoint, SearchLocation.Coordinate);
if (c * c + b * b < a * a)
{
tempnearestPoint = new Coordinate(endcoor.X, endcoor.Y);
tempnearestDistance = b;
}
else if (c * c + a * a < b * b)
{
tempnearestPoint = new Coordinate(begintcoor.X, begintcoor.Y);
tempnearestDistance = a;
}
else
{
tempnearestPoint = new Coordinate(footPoint.X, footPoint.Y);
tempnearestDistance = h;
}
if (tempnearestDistance <= Range)
{
isCorossOrContain = true;
if (tempnearestDistance <= nearestDistance)
{
nearestPoint = new Coordinate(tempnearestPoint.X, tempnearestPoint.Y);
nearestDistance = tempnearestDistance;
}
}
}
}
}
if (isCorossOrContain)
{
GeometryExtend geoe = new GeometryExtend();
geoe.Geo = geo;
geoe.NearCoor = new Coordinate(nearestPoint.X, nearestPoint.Y);
geoe.NearDistance = nearestDistance;
SelectGeometry.Add(geoe);
}
return isCorossOrContain;
}
/// 或得两点坐标的长度
///
///
///
///
public double GetDistance(Coordinate p1, Coordinate p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}
/// 地图上绘制导航符号
///
///
///
private void map1_Paint(object sender, ESRI.ArcGIS.Mobile.MapPaintEventArgs e)
{
if (gpsManager.GpsLocation == null || gpsManager.GpsLocation.IsEmpty)
return;
CoordinateCollection collect =gpsManager.GetCoordinationCollection(this.map1,gpsManager.GpsLocation,
e.Display.DrawPolygon(new Pen(Color.Black), new SolidBrush(Color.Red), collect);
if (gpsManager.DrawRange)
{
Envelope el = new Envelope(gpsManager.SearchLocation.Coordinate, gpsManager.Range*2, gpsManager.Range*2);
e.Display.DrawEllipse(new Pen(Color.Black), new SolidBrush(Color.Empty), el);
if (listviewLineData.SelectedIndices.Count > 0)
{
int index = listviewLineData.SelectedIndices[0];
e.Display.DrawLine(new Pen(Color.Black), gpsManager.SelectGeometry[index].NearCoor,
Coordinate cor=new Coordinate ((gpsManager .SelectGeometry[index ].NearCoor.X +gpsManager
e.Display.DrawText("距离:" + Math.Round(gpsManager.SelectGeometry[index].NearDistance, 2).ToString() + "
}
}
}