运行效果如下:在桌面程序中访问高德地图,通过cs代码调用高德js接口实现多边形区域动态添加;通过鼠标点击事件实现当前位置经纬度采集并传递给cs代码,判断点击位置是否在指定的区域内。
项目结构如下:
核心代码如下:
窗口代码:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Web.Script.Serialization;
//----------------------------------------------------------------------
//demo:集成webbrowser空间,实现windows桌面程序访问高德地图,
// 基于高德地图的一些简单操作(地图上添加多边形区域、点击获取坐标等)
//
// 1、测试cs程序与html的互操作(cs调用js方法、js调用cs方法)
// 2、测试指定点是否在指定的多边形区域内
//
//----------------------------------------------------------------------
namespace testPointInPolygon
{
[ComVisibleAttribute(true)]//允许cs代码与js代码的互操作
public partial class Form1 : Form
{
private PointInPolygon pip;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 公有方法,供js调用
/// </summary>
/// <param name="strPos"></param>
public void GetMapPos(string strPos)
{
string[] pos = strPos.Split(‘,‘);
this.txtPointX.Text = pos[0];
this.txtPointY.Text = pos[1];
}
private void button2_Click(object sender, EventArgs e)
{
if (pip is null)
{
MessageBox.Show("请先添加区域。");
return;
}
bool bFlag = pip.IsPointInPolygon(double.Parse(this.txtPointX.Text), double.Parse(this.txtPointY.Text));
if (bFlag)
{
MessageBox.Show("指定点在区域内。");
}
else
{
MessageBox.Show("指定点不在区域内。");
}
}
//构建多边形测试数据
private List<PointXY> BuildPointList()
{
List<PointXY> listPoint = new List<PointXY>();
PointXY point;
point = new PointXY();
point.PointX = 116.27582;
point.PointY = 39.968792;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.27479;
point.PointY = 39.884015;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.29024;
point.PointY = 39.831305;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.465334;
point.PointY = 39.833151;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.486277;
point.PointY = 39.846859;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.48971;
point.PointY = 39.955108;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.443705;
point.PointY = 39.988523;
listPoint.Add(point);
point = new PointXY();
point.PointX = 116.294016;
point.PointY = 39.983788;
listPoint.Add(point);
return listPoint;
}
private void Form1_Load(object sender, EventArgs e)
{
// 防止 WebBrowser 控件打开拖放到其上的文件。
webBrowser1.AllowWebBrowserDrop = false;
// 防止 WebBrowser 控件在用户右击它时显示其快捷菜单.
webBrowser1.IsWebBrowserContextMenuEnabled = false;
// 以防止 WebBrowser 控件响应快捷键。
webBrowser1.WebBrowserShortcutsEnabled = false;
// 以防止 WebBrowser 控件显示脚本代码问题的错误信息。
webBrowser1.ScriptErrorsSuppressed = true;
// 这个属性比较重要,可以通过这个属性,把后台代码中的数据,传递到JS中,供内嵌的网页使用
webBrowser1.ObjectForScripting = this;
//打开本地指定html
webBrowser1.Navigate(Application.StartupPath + "\\html\\OprMap.html");
}
private void button3_Click(object sender, EventArgs e)
{
List<PointXY> list = this.BuildPointList();
pip = new PointInPolygon(list);
List<object> lo = new List<object>();
for (int i = 0; i < list.Count; i++)
{
object o = "[" + list[i].PointX + "," + list[i].PointY + "]";
lo.Add(o);
}
JavaScriptSerializer jss = new JavaScriptSerializer();
string strPos = jss.Serialize(lo).Replace(‘"‘,‘ ‘);
//string strPos = "[[116.403322, 39.920255],[116.410703, 39.897555],[116.402292, 39.892353],[116.389846, 39.891365]]";
//调用js中的方法
webBrowser1.Document.InvokeScript("DrawPolygon", new object[] { strPos });
}
}
}
html代码:
js代码:
指定点是否在指定区域内:
using System;
using System.Collections.Generic;
using System.Linq;
namespace testPointInPolygon
{
public class PointInPolygon
{
private List<double> _PolygonX, _PolygonY;//指定多边形的点的X坐标集合、Y坐标集合
private double _MaxX, _MinX, _MaxY, _MinY;//指定多边形的点的最大X坐标、最小X坐标、最大Y坐标、最小Y坐标
private int _PolygonPointNumber;//多边形区域的点数
/// <summary>
/// 初始化区域的点坐标集合
/// </summary>
/// <param name="points">组成区域的点坐标集合</param>
public PointInPolygon(List<PointXY> PolygonPoints)
{
_PolygonX = new List<double>();
_PolygonY = new List<double>();
for (int i = 0; i < PolygonPoints.Count; i++)
{
_PolygonX.Add(PolygonPoints[i].PointX);
_PolygonY.Add(PolygonPoints[i].PointY);
}
_PolygonPointNumber = PolygonPoints.Count;
PolygonPoints = PolygonPoints.OrderBy(ss => (ss.PointX)).ToList();
_MinX = PolygonPoints.First().PointX;
_MaxX = PolygonPoints.Last().PointX;
PolygonPoints = PolygonPoints.OrderBy(ss => (ss.PointY)).ToList();
_MinY = PolygonPoints.First().PointY;
_MaxY = PolygonPoints.Last().PointY;
}
/// <summary>
/// 指定的点是否在区域内
/// </summary>
/// <param name="PointX">指定点X坐标</param>
/// <param name="PointY">指定点Y坐标</param>
/// <returns></returns>
public bool IsPointInPolygon(double PointX, double PointY)
{
//如果x、y坐标超出区域的最小最大坐标,直接返回false
if (PointX < _MinX || PointX > _MaxX || PointY < _MinY || PointY > _MaxY)
return false;
int i, j, count = 0;
for (i = 0, j = _PolygonPointNumber - 1; i < _PolygonPointNumber; j = i++)
{
if (((_PolygonY[i] > PointY) != (_PolygonY[j] > PointY)) &&
(PointX < (_PolygonX[j] - _PolygonX[i]) * (PointY - _PolygonY[i]) / (_PolygonY[j] - _PolygonY[i]) + _PolygonX[i]))
{
count++;
}
}
if (count % 2 == 1)
{
//单数在区域内
return true;
}
else
{
//双数在区域外
return false;
}
}
}
[Serializable]
public class PointXY
{
public double PointX;
public double PointY;
}
}