需求

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的更多相关文章

  1. IOS客户端Coding项目记录导航

    IOS客户端Coding项目记录(一) a:UITextField设置出现清除按键 b:绘画一条下划线  表格一些设置 c:可以定义表头跟底部视图(代码接上面) d:隐藏本页的导航栏 e:UIEdge ...

  2. Unity Project Wizard (最近打开的项目记录)

    最近打开工程列表 当用Unity打开过的项目越来越多之后,在最近打开项目记录框中就会变的很长,那么如何才能删除最近打开的记录呢? Unity4.x最近打开的工程记录 Unity5.x最近打开的工程记录 ...

  3. jenkins构建项目记录2(tag)

    与jenkins构建项目记录1不同的是通过tag拉去对应版本代码 1.先安装创建(git parameter) 2.general设置 name可任意命名,下面源码管理设置时变量会引用到. 3.源码管 ...

  4. 【项目记录】-液化气配送app android版

    15年底参与过甲方呼叫中心平台开发.液化气配送app android版要求1个月开发完成.开发此项目以前我只有过一周android的开发经验.(与甲方签署过保密协议,遵循职业道德有些敏感信息不能写.) ...

  5. 用spring+hibernate+struts 项目记录以及常用的用法进等

    一.hibernate1. -----BaseDao------ // 容器注入 private SessionFactory sessionFactory; public void setSessi ...

  6. [项目记录] 用c语言完成的一个学生成绩管理系统

    一.要求: 学生成绩管理系统 某班有最多不超过30人(具体人数由键盘输入)参加期末考试,最多不超过6门(具体门数由键盘输入).使用链表编程实现如下菜单驱动的学生成绩管理系统. 从文件读入每个学生个人信 ...

  7. [项目记录]一个.net下使用HAP实现的吉大校园通知网爬虫工具:OAWebScraping

    第一章 简介 本文主要介绍了在.NET下利用优秀的HTML解析组件HtmlAgilityPack开发的一个吉林大学校内通知oa.jlu.edu.cn的爬取器.尽管.Net下解析HTML文件有很多种选择 ...

  8. vue 项目记录.路飞学城(一)

    前情提要: 通过vue 搭建路飞学城记录  一:项目分析 二:项目搭建 1:创建项目 vue init webpack luffy 2:初始化项目 清除默认的HelloWorld.vue组件和APP. ...

  9. wc项目记录

    1.Github项目地址:https://github.com/3116004700/ruanjiangongcheng 2.预估时间见PSP表格. 3.解题思路描述: 在看到这个项目的时候我就想到了 ...

随机推荐

  1. java.lang.NoClassDefFoundError: javax/mail/Authenticator

    摘录自:http://stackoverflow.com/questions/1630002/java-lang-noclassdeffounderror-javax-mail-authenticat ...

  2. ASP.net core 2.0.0 中 asp.net identity 2.0.0 的基本使用(一)—修改数据库连接

    开发环境:vs2017  版本:15.3.5 项目环境:.net framework 4.6.1    模板asp.net core 2.0  Web应用程序(模型视图控制器) 身份验证:个人用户账号 ...

  3. JavaScript小结

    语法小结 /** * Created by M.C on 2017/5/26. */ /*弹框*/ //var message = "Hello world"; //alert(m ...

  4. Python--socketserve源码分析(一)

    class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass 实现原理: s =socketserver.ThreadingTCPServer(参 ...

  5. Log4j源码解析--Appender接口解析

    本文转自上善若水的博客,原文出处:http://www.blogjava.net/DLevin/archive/2012/07/10/382676.html.感谢作者的无私的分享. Appender负 ...

  6. junit设计模式--组合模式

    Composite,英语翻译下,复合,组合. 组合模式有时候又叫做部分-整体模式,它使我们在树形结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户 ...

  7. MYSQL 5.7 修改密码、登录问题

    mysql5.7 关于密码问题 报错: ERROR 1862 (HY000): Your password has expired. To log in you must change it usin ...

  8. MyISAM 存储引擎的特点及优化方法

      MyISAM:   MyISAM 管理非事务表.是ISAM 的扩展格式.除了提供ISAM里所没有的索引的字段管理等的大量功能.MyISAM 还使用一种表格锁定的机制.来优化多个并发的读写操作.My ...

  9. C#高性能大容量SOCKET并发(八):通讯协议

    协议种类 开发Socket程序有两种协议类型,一种是用文本描述的,类似HTTP协议,定义字符集,好处是兼容性和调试方便,缺点是解析文本会损耗一些性能:一种是用Code加结构体,定义字节顺序,好处是性能 ...

  10. eclipse修改默认workspace

    1.进入 Window > Preferences > General > Startup and Shutdown 选中 Prompt for workspace on start ...