背景
micaps二次开发中,比较重要的功能就是和主程序地图进行交互。交互分为两种:
- 向主程序地图区域添加元素;
-
获取主程序地图区域信息;
为了直观说明这个问题,这里给出micaps的主界面:
二次开发交互示意图
这里介绍一下,自己对获取主程序地图区域鼠标位置信息的理解 。
获取地图上鼠标位置
自定义一个交互的类 TyphoonPointSelectMapTool
internal class TyphoonPointSelectMapTool : MapTool
{
private lyTyphoonPresenter _presenter;
public TyphoonPointSelectMapTool(lyTyphoonPresenter presenter)
{
this._presenter = presenter;
}
public override void MouseDown(MouseButtonID button, int x, int y)
{
if (button == MouseButtonID.MB_Left)
{
this._presenter.OnMouseDown(button, x, y);
}
}
public override void MouseMove(MouseButtonID button, int x, int y)
{
this._presenter.OnMouseMove(x, y);
}
public override void MouseUp(MouseButtonID button, int x, int y)
{
this._presenter.OnMouseUp(button, x, y);
}
public override void MouseWheel(MouseButtonID button, int delta)
{
}
protected override void OnActionCompleted()
{
}
public override void OnActive()
{
}
public override void OnDeactive()
{
}
}
自定义presenter类
public void OnMouseUp(MouseButtonID button, int x, int y)
{
if (button == MouseButtonID.MB_Right)
{
this._showTempPoint = false;
this.FreeTempPointResource();
}
else
{
//左键是选择输入点
PointF point = this._presenter.ScrToGeography(x, y);
this._points.Add(point);
this._showTempPoint = true;
}
this.DisplayPoint(true);
}
至此,完成了获取主程序地图信息获取的功能编写
那么如何触发这个功能呢?
触发获取主程序地图信息功能
在二次开发界面上,触发需要获取主界面位置信息的按钮时,执行如下函数:
bool active = checkBoxMouseSelect.Checked;
if (active)
{
ServiceLocator.Current.GetInstance().DisableMapInputAction(CMA.MICAPS.Box2D.Input.InputActions.Pan);
}
else
{
ServiceLocator.Current.GetInstance().EnableMapInputAction(CMA.MICAPS.Box2D.Input.InputActions.Pan);
}
this.SetTyphoonMapTool(this._typhoonMapTool, active);
子函数:
private void SetTyphoonMapTool(IMouseInputHandler tool, bool register)
{
ToolAction action = register ? ((ToolAction)4) : ((ToolAction)5);
MapToolMessage message = new MapToolMessage(action);
message.CustomMouseHandler=tool;
MapToolMessage[] messageArray1 = new MapToolMessage[] { message };
ServiceLocator.Current.GetInstance().Publish(messageArray1);
}
显示点到主程序地图上
获取鼠标点后,能够将点位置实时显示到地图上,则可以快速响应用户的点击信息,这是一个很好的交互方式。
如何显示,目前,我还没有找到画点的方式,查阅了很多资料,寻找到一种折中的办法,效果一般。具体实现如下:
public void DisplayPoint(bool visible)
{
if (visible)
{
if (this._points.Count >0)
{
this.FreePointResource();
DisplayTempPoint(_points[0]);
// 这里仅仅显示了一个点信息;
}
}
else
{
this.FreePointResource();
this.FreeTempPointResource();
}
}
private void DisplayTempPoint(PointF point)
{
if ((this._points.Count != 0) && this._showTempPoint)
{
if (this._tempPoint == null)
{
this._tempPoint = new PointRenderable(8f, Color.Red);
this._tempPoint.Add(point.X,point.Y);
Device.Instance.ActiveScene.AddRenderable(this._tempPoint.MeshRenderable);
}
else
{
this._tempPoint.UpdatePostion(point.X, point.Y);
}
}
}
public IRenderable MeshRenderable
{
get
{
if (this._meshRenderable == null)
{
this._meshRenderable = this.CreateMeshRenderable();
}
return this._meshRenderable;
}
}
private CMA.MICAPS.Box2D.Graphics.MeshRenderable CreateMeshRenderable()
{
/*
绘制点到micaps界面上,必须考虑投影的影响。vertebuffer中存储的是
屏幕坐标,直接将经纬度放入,在屏幕中绘制出来的几乎不变
添加经纬度转换后,则可以正确绘制。
遗留问题:
绘制出来的是方块,还不知道怎么修改
*/
int num3;
int count = this._points.Count;
if (count == 0)
{
return null;
}
Mesh mesh = new Mesh();
mesh.MeshBuffer=new MeshBuffer();
MeshPart part = new MeshPart(0L);
mesh.AddPart(part);
Material2D materiald = new Material2D();
materiald.SurfaceState.point_size = _size;//.get_SurfaceState().point_size = this._size;
materiald.BackColor = _color;//.set_BackColor(this._color);
materiald.ForeColor = _color;
mesh.SetMaterial(materiald);
double num;
double num2;
IMapProjection projection = ServiceLocator.Current.GetInstance().CurrentMap.Projection;
for (int i = 0; i < count; i = num3 + 1)
{
PointF tf = this._points[i];
projection.FwdP((double)tf.X, (double)tf.Y, out num, out num2);
mesh.MeshBuffer.VertexBuffer.AppendFloat((float)num);
mesh.MeshBuffer.VertexBuffer.AppendFloat((float)num2);
num3 = i;
}
BufferOpInfo info = new BufferOpInfo
{
offset = 0,
count = count,
mode = 0
};
info.mode = 0;
part.BufferOpInfo=info;
return new CMA.MICAPS.Box2D.Graphics.MeshRenderable(mesh);
}
public void UpdatePostion(float worldx, float worldy)
{
double num;
double num2;
IMapProjection projection = ServiceLocator.Current.GetInstance().CurrentMap.Projection;
projection.FwdP((double)worldx, (double)worldy, out num, out num2);
VertexBuffer buffer = this._meshRenderable.Mesh.MeshBuffer.VertexBuffer;// ().MeshBuffer.VertexBuffer;
IntPtr destination = buffer.Lock();
float[] source = new float[] {(float) num, (float)num2 };
Marshal.Copy(source, 0, destination, 2);
buffer.Unlock();
this._meshRenderable.RefreshVertexBuffer();
}
这里需要强调一下,地图具有投影信息,要注意地理坐标和屏幕坐标的转换,转换用如下:
IMapProjection projection = ServiceLocator.Current.GetInstance().CurrentMap.Projection;
projection.FwdP((double)tf.X, (double)tf.Y, out num, out num2);
最初没有注意这个问题,鼠标所选的点在屏幕上基本上没有改变,困扰了很久。
以上是实现的主要函数。
效果如下:
效果图