台风风场数据一般包括X、Y、U和V,分别表示经度、纬度、东西方向速度和南北方向速度。简单的绘制,可以在一个GraphicsLayer中根据这几个属性值绘制箭头。开始我想的是自己动态生成各种Symbol,但现在还没法实现。现在用的方法的主要思路是根据X和Y确定箭头的末端位置p1,通过U和V确定箭头的大小(为了在地图上可见,可以乘以一个常数来放大)length,并且根据|V/U|的反正切值算出箭头与东西方向的夹角theta,这样就能根据length和theta计算箭头的顶点位置p2。取length/8(取多少自己感觉吧)为箭头两翼的长度h,并设箭头两翼的夹角为pi/3(还是感觉),那箭头一翼与箭身的夹角就是pi/6。这样就能根据p2、h、theta和pi/6,计算出箭头的左右两翼末端的坐标pL和pR。根据箭头的不同朝向,计算具体的参数值。
具体代码如下(Vector类中就包含了四个属性XYUV):
private void displayCurrent(List<vector> vectors)
{
var wm = new SpatialReference(3857);
foreach (var vector in vectors)
{
var length = Math.Sqrt(vector.U * vector.U + vector.V * vector.V) * 5000;
var theta = Math.Atan(Math.Abs(vector.V / vector.U));
var p1 =
(MapPoint)_webMercator.FromGeographic(new MapPoint(vector.X, vector.Y, new SpatialReference(4326)));
var h = length / 8;
double alphaL, alphaR;
MapPoint p2 = null;
MapPoint pR = null;
MapPoint pL = null;
if (vector.U > 0 && vector.V > 0)
{
p2 = new MapPoint(p1.X + length * Math.Cos(theta), p1.Y + length * Math.Sin(theta), wm);
alphaR = Math.PI / 2 - theta - Math.PI / 6;
alphaL = theta - Math.PI / 6;
pR = new MapPoint(p2.X - h * Math.Sin(alphaR), p2.Y - h * Math.Cos(alphaR), wm);
pL = new MapPoint(p2.X - h * Math.Cos(alphaL), p2.Y - h * Math.Sin(alphaL), wm);
}
else if (vector.U > 0 && vector.V < 0)
{
p2 = new MapPoint(p1.X + length * Math.Cos(theta), p1.Y - length * Math.Sin(theta), wm);
alphaR = theta - Math.PI / 6;
alphaL = Math.PI / 2 - theta - Math.PI / 6;
pR = new MapPoint(p2.X - h * Math.Cos(alphaR), p2.Y + h * Math.Sin(alphaR), wm);
pL = new MapPoint(p2.X - h * Math.Sin(alphaL), p2.Y + h * Math.Cos(alphaL), wm);
}
else if (vector.U < 0 && vector.V > 0)
{
p2 = new MapPoint(p1.X - length * Math.Cos(theta), p1.Y + length * Math.Sin(theta), wm);
alphaR = theta - Math.PI / 6;
alphaL = Math.PI / 2 - theta - Math.PI / 6;
pR = new MapPoint(p2.X + h * Math.Cos(alphaR), p2.Y - h * Math.Sin(alphaR), wm);
pL = new MapPoint(p2.X + h * Math.Sin(alphaL), p2.Y - h * Math.Cos(alphaL), wm);
}
else if (vector.U < 0 && vector.V < 0)
{
p2 = new MapPoint(p1.X - length * Math.Cos(theta), p1.Y - length * Math.Sin(theta), wm);
alphaR = Math.PI / 2 - theta - Math.PI / 6;
alphaL = theta - Math.PI / 6;
pR = new MapPoint(p2.X + h * Math.Sin(alphaR), p2.Y + h * Math.Cos(alphaR), wm);
pL = new MapPoint(p2.X + h * Math.Cos(alphaL), p2.Y + h * Math.Sin(alphaL), wm);
}
var arrow = new ESRI.ArcGIS.Client.Geometry.Polyline();
var path1 = new ESRI.ArcGIS.Client.Geometry.PointCollection { p1, p2 };
arrow.Paths.Add(path1);
var path2 = new ESRI.ArcGIS.Client.Geometry.PointCollection { pL, p2, pR };
arrow.Paths.Add(path2);
_currentLayer.Graphics.Add(new Graphic
{
Geometry = arrow,
Symbol = new SimpleLineSymbol(Colors.Black, 1),
});
}
}
效果如下:
做这个是因为师姐毕业论文中要用,而且自己以后肯定也会用到,毕竟都是一个方向的。参考以前毕业师姐写过的代码,完善了一下,就用ArcGIS API for Silverlight做了个例子。



