• 【项目记录】-路灯光照分析系统 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和数据拆分、补全上的处理和报表算法上有些繁琐,项目目前暂时告一段落。

  • 相关阅读:
    【POJ2893&HDOJ6620】M &#215; N Puzzle(n*m数码判定)
    idea破解方法
    ORACLE:MERGE INTO
    DOS命令大全
    使用oracle 的 PL/Sql 定时执行一个存储过程
    spring RestTemplate用法详解
    Oracle截取字符串和查找字符串
    PLSQL Developer常用设置及快捷键
    IntelliJ IDEA设置自动导入包
    Git使用详细教程
  • 原文地址:https://www.cnblogs.com/july4/p/8478884.html
Copyright © 2020-2023  润新知