【项目记录】-路灯监测 gmap.net
需求
2016年5月,客户要求在地图上显示路灯及数据,分析数据生成报表,以便查看分析路灯情况。
选型
国外项目就不考虑国内的地图了,开始想使用google的web地图,考虑到地图上标记物过多影响性能及使用体验,对gmap测试后,选用gmap.net。
开发

功能:
1.导入路灯及数据,在地图上添加、编辑、删除路灯,路灯数据软件修正、移除错误数据
2.地图上线时路灯及数据,数据以标记、曲线、表格方式显示
3.导出整个系统数据,下次可以将系统导出的文件导入进行查看;导出生成excel报表
4.多点测距;多边形方式进行选择查看,选择多边形内路灯情况
代码
计算2个坐标点距离
private static double EARTH_RADIUS = 6378137;//赤道半径(单位m)
/**
* 转化为弧度(rad)
* */
private static double rad(double d)
{
return d * Math.PI / 180.0;
}
/**
* 基于余弦定理求两经纬度距离
* @param lon1 第一点的精度
* @param lat1 第一点的纬度
* @param lon2 第二点的精度
* @param lat3 第二点的纬度
* @return 返回的距离,单位m
* */
public static double GetDistance(double lng1, double lat1, double lng2, double lat2)
{
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double radLng1 = rad(lng1);
double radLng2 = rad(lng2);
if (radLat1 < 0)
radLat1 = Math.PI / 2 + Math.Abs(radLat1);// south
if (radLat1 > 0)
radLat1 = Math.PI / 2 - Math.Abs(radLat1);// north
if (radLng1 < 0)
radLng1 = Math.PI * 2 - Math.Abs(radLng1);// west
if (radLat2 < 0)
radLat2 = Math.PI / 2 + Math.Abs(radLat2);// south
if (radLat2 > 0)
radLat2 = Math.PI / 2 - Math.Abs(radLat2);// north
if (radLng2 < 0)
radLng2 = Math.PI * 2 - Math.Abs(radLng2);// west
double x1 = EARTH_RADIUS * Math.Cos(radLng1) * Math.Sin(radLat1);
double y1 = EARTH_RADIUS * Math.Sin(radLng1) * Math.Sin(radLat1);
double z1 = EARTH_RADIUS * Math.Cos(radLat1);
double x2 = EARTH_RADIUS * Math.Cos(radLng2) * Math.Sin(radLat2);
double y2 = EARTH_RADIUS * Math.Sin(radLng2) * Math.Sin(radLat2);
double z2 = EARTH_RADIUS * Math.Cos(radLat2);
double d = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
//余弦定理求夹角
double theta = Math.Acos((EARTH_RADIUS * EARTH_RADIUS + EARTH_RADIUS * EARTH_RADIUS - d * d) / (2 * EARTH_RADIUS * EARTH_RADIUS));
double dist = theta * EARTH_RADIUS;
return dist;
}
获取方向角度
/// <summary>
/// 获取方向角度
/// </summary>
/// <param name="lon1"></param>
/// <param name="lat1"></param>
/// <param name="lon2"></param>
/// <param name="lat2"></param>
/// <returns></returns>
public static double GetDirection(double lon1, double lat1, double lon2, double lat2)
{
double x1 = lon1;
double y1 = lat1;
double x2 = lon2;
double y2 = lat2;
double pi = Math.PI;
double w1 = y1 / 180 * pi;
double j1 = x1 / 180 * pi;
double w2 = y2 / 180 * pi;
double j2 = x2 / 180 * pi;
double ret;
if (j1 == j2)
{
if (w1 > w2) ret = 270; //北半球的情况,南半球忽略
else if (w1 < w2) ret = 90;
else ret =-1;//位置完全相同
}
ret = 4 * Math.Pow(Math.Sin((w1 - w2) / 2), 2) - Math.Pow(Math.Sin((j1 - j2) / 2) * (Math.Cos(w1) - Math.Cos(w2)), 2);
ret = Math.Sqrt(ret);
double temp = (Math.Sin(Math.Abs(j1 - j2) / 2) * (Math.Cos(w1) + Math.Cos(w2)));
ret = ret / temp;
ret = Math.Atan(ret) / pi * 180;
if (j1 > j2) // 1为参考点坐标
{
if (w1 > w2) ret += 180;
else ret = 180 - ret;
}
else if (w1 > w2) ret = 360 - ret;
return ret;
//result.Text = Convert.ToString(ret);
//if ((ret <= 10) || (ret > 350)) angle.Text = "东";
//if ((ret > 10) && (ret <= 80)) angle.Text = "东北";
//if ((ret > 80) && (ret <= 100)) angle.Text = "北";
//if ((ret > 100) && (ret <= 170)) angle.Text = "西北";
//if ((ret > 170) && (ret <= 190)) angle.Text = "西";
//if ((ret > 190) && (ret <= 260)) angle.Text = "西南";
//if ((ret > 260) && (ret <= 280)) angle.Text = "南";
//if ((ret > 280) && (ret <= 350)) angle.Text = "东南";
}
判断坐标是否在多边形内
/// <summary>
/// 判断点是否在多边形内.
/// </summary>
/// <param name="checkPoint">要判断的点</param>
/// <param name="polygonPoints">多边形的顶点</param>
/// <returns></returns>
public static bool IsInPolygon(PointLatLng checkPoint, List<PointLatLng> polygonPoints)
{
int counter = 0;
int i;
double xinters;
PointLatLng p1, p2;
int pointCount = polygonPoints.Count;
p1 = polygonPoints[0];
for (i = 1; i <= pointCount; i++)
{
p2 = polygonPoints[i % pointCount];
if (checkPoint.Lat > Math.Min(p1.Lat, p2.Lat)//校验点的Y大于线段端点的最小Y
&& checkPoint.Lat <= Math.Max(p1.Lat, p2.Lat))//校验点的Y小于线段端点的最大Y
{
if (checkPoint.Lng <= Math.Max(p1.Lng, p2.Lng))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断).
{
if (p1.Lat != p2.Lat)//线段不平行于X轴
{
xinters = (checkPoint.Lat - p1.Lat) * (p2.Lng - p1.Lng) / (p2.Lat - p1.Lat) + p1.Lng;
if (p1.Lng == p2.Lng || checkPoint.Lng <= xinters)
{
counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0)
{
return false;
}
else
{
return true;
}
}
多点测距

多边形选择

关于测距
测距尝试过使用gmap提供的根据道路测距,发现还是不太准,所以还是选择了手动选择坐标点连线测距。
后记
该项目2018年初还增加了一些功能,开发过程中有不少次沟通和修改,主要就是一些gps和数据拆分、补全上的处理和报表算法上有些繁琐,项目目前暂时告一段落。
【项目记录】-路灯监测 gmap.net的更多相关文章
- IOS客户端Coding项目记录导航
IOS客户端Coding项目记录(一) a:UITextField设置出现清除按键 b:绘画一条下划线 表格一些设置 c:可以定义表头跟底部视图(代码接上面) d:隐藏本页的导航栏 e:UIEdge ...
- Unity Project Wizard (最近打开的项目记录)
最近打开工程列表 当用Unity打开过的项目越来越多之后,在最近打开项目记录框中就会变的很长,那么如何才能删除最近打开的记录呢? Unity4.x最近打开的工程记录 Unity5.x最近打开的工程记录 ...
- jenkins构建项目记录2(tag)
与jenkins构建项目记录1不同的是通过tag拉去对应版本代码 1.先安装创建(git parameter) 2.general设置 name可任意命名,下面源码管理设置时变量会引用到. 3.源码管 ...
- 【项目记录】-液化气配送app android版
15年底参与过甲方呼叫中心平台开发.液化气配送app android版要求1个月开发完成.开发此项目以前我只有过一周android的开发经验.(与甲方签署过保密协议,遵循职业道德有些敏感信息不能写.) ...
- 用spring+hibernate+struts 项目记录以及常用的用法进等
一.hibernate1. -----BaseDao------ // 容器注入 private SessionFactory sessionFactory; public void setSessi ...
- [项目记录] 用c语言完成的一个学生成绩管理系统
一.要求: 学生成绩管理系统 某班有最多不超过30人(具体人数由键盘输入)参加期末考试,最多不超过6门(具体门数由键盘输入).使用链表编程实现如下菜单驱动的学生成绩管理系统. 从文件读入每个学生个人信 ...
- [项目记录]一个.net下使用HAP实现的吉大校园通知网爬虫工具:OAWebScraping
第一章 简介 本文主要介绍了在.NET下利用优秀的HTML解析组件HtmlAgilityPack开发的一个吉林大学校内通知oa.jlu.edu.cn的爬取器.尽管.Net下解析HTML文件有很多种选择 ...
- vue 项目记录.路飞学城(一)
前情提要: 通过vue 搭建路飞学城记录 一:项目分析 二:项目搭建 1:创建项目 vue init webpack luffy 2:初始化项目 清除默认的HelloWorld.vue组件和APP. ...
- wc项目记录
1.Github项目地址:https://github.com/3116004700/ruanjiangongcheng 2.预估时间见PSP表格. 3.解题思路描述: 在看到这个项目的时候我就想到了 ...
随机推荐
- ASIHTTPRequest
ASIHTTPRequest,是一个直接在CFNetwork上做的开源项目,提供了一个比官方更方便更强大的HTTP网络传输的封装.
- JAVA 一句话技巧
1.拆分字符串 遇到特殊字符,比如:对‘$’符号,就应该使用‘\\$’,后总结可以加个方括号如 "[.]".2.遍历HASHMAP Iterator itr = map.keySe ...
- linux 中nvme 的中断申请及处理
/** * struct irq_desc - interrupt descriptor * @irq_data: per irq and chip data passed down to chip ...
- P1361 小M的作物
P1361 小M的作物 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号). 现在,第 ...
- TemplateMethod-模板模式
什么是Template Method模式 在父类中定义处理流程的框架,在子类中实现具体处理的模式就称为Template Mehtod模式.模板模式的关键是:子类可以置换掉父类的可变部分,但是子类却不可 ...
- Python之数学(math)和随机数(random)
math包包含了最基本的数学运算函数,如果想要更加高级的数学功能,可以使用标准库外的numpy和scipy库,他们不但支持数组和矩阵运算, 还有丰富的数学和物理方程可供使用 random包可以用来生成 ...
- ssm打印sql语句
在mybatis配置文件中添加<setting name="logImpl" value="STDOUT_LOGGING"/> <?xml v ...
- php之插入排序
<?phpfunction insertSort($arr) { //插入排序 $len = count($arr); for($i=1;$i<$len;$i++){ ...
- Core Animation 文档翻译 (第六篇)
高级动画技巧 配置属性动画或者关键帧动画的方式是多种多样的.需要同时执行多个动画或者顺序执行多个动画的APP,可以通过高级的方式同步这些动画的timing或者将这些动画绑定在一起.我们也可以使用其 ...
- python中的函数对象与闭包函数
函数对象 在python中,一切皆对象,函数也是对象 在python语言中,声明或定义一个函数时,使用语句: def func_name(arg1,arg2,...): func_suite 当执行流 ...