当前位置:   article > 正文

根据经纬度判断点是否位于多边形内以及到多边形的距离_c++点到多边型的距离

c++点到多边型的距离

最近,在业务中遇到一个场景,需要根据经纬度,判断一个点是否位于多边形区域内,如果不在多边形内部,计算点到多边形的最短距离,即到多边形各个边的距离的最短值。

经过研究和参考网上的文章,最终实现了该功能。

一、定义多边形和点

  1. // 定义多边形,沿顺时针或逆时针方向,依次添加点的经纬度
  2. List<double[]> polygon = new ArrayList<>();
  3. polygon.add(new double[]{121.553793, 29.808325});
  4. polygon.add(new double[]{121.553793, 29.808329});
  5. polygon.add(new double[]{121.553799, 29.808329});
  6. polygon.add(new double[]{121.553799, 29.808325});
  7. // 定义点
  8. double[] point = new double[]{121.553792, 29.808325};

二、判断点是否在多边形内部

点在多边形边上,认为点不在多边形内部

  1. /**
  2. * 判断一个点是否在多边形内部;在多边形边上也不算是在多边形内部
  3. * @param polygon 经纬度点组成的多边形
  4. * @param point 经纬度点
  5. * @return 点是否在多边形内
  6. */
  7. public static boolean isInside(List<double[]> polygon, double[] point) {
  8. boolean inside = false;
  9. for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
  10. if (((polygon.get(i)[1] > point[1]) != (polygon.get(j)[1] > point[1])) &&
  11. (point[0] < (polygon.get(j)[0] - polygon.get(i)[0]) * (point[1] - polygon.get(i)[1]) /
  12. (polygon.get(j)[1] - polygon.get(i)[1]) + polygon.get(i)[0])) {
  13. inside = !inside;
  14. }
  15. }
  16. return inside;
  17. }

三、计算外部点到多边形最短距离

计算外部点到多边形的距离,分为以下几个步骤:

  • 点到多边形各个边的距离

        多边形各个边由多边形的点顺时针或者逆时针取相邻两个点,组成线段

  • 取点到边的距离的最小值
  1. /**
  2. * 计算点到多边形的最短距离
  3. * @param polygon 多边形各个点的经纬度
  4. * @param point 点
  5. * @return 点到多边形最短距离
  6. */
  7. public static double shortestDistance(List<double[]> polygon, double[] point) {
  8. double shortestDistance = Double.POSITIVE_INFINITY;
  9. for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
  10. double[] p1 = polygon.get(i);
  11. double[] p2 = polygon.get(j);
  12. double d = calcP2L(point, p1, p2);
  13. if (d < shortestDistance) {
  14. shortestDistance = d;
  15. }
  16. }
  17. return shortestDistance;
  18. }
  19. /**
  20. * 计算点到线段的距离
  21. * @param point 点的经度和纬度
  22. * @param point1 线段其中一个端点的经度和纬度
  23. * @param point2 线段另一个端点的经度和纬度
  24. * @return 点到线段的最短距离
  25. */
  26. public static double calcP2L(double[] point, double[] point1, double[] point2) {
  27. double x = point[0], y = point[1];
  28. double x1 = point1[0], y1 = point1[1];
  29. double x2 = point2[0], y2 = point2[1];
  30. double d1 = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
  31. if (d1 < 0) {
  32. return calcP2P(point, point1);
  33. }
  34. double d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
  35. if (d1 >= d2) {
  36. return calcP2P(point, point2);
  37. }
  38. double r = d1 / d2;
  39. double px = x1 + (x2 - x1) * r;
  40. double py = y1 + (y2 - y1) * r;
  41. double[] ppoint = new double[]{px, py};
  42. return calcP2P(point, ppoint);
  43. }
  44. /**
  45. * 计算两点间的球面距离
  46. * @param apoint a点经纬度
  47. * @param bpoint b点经纬度
  48. * @return 点到点的距离
  49. */
  50. public static double calcP2P(double[] apoint, double[] bpoint) {
  51. double alat = apoint[0];
  52. double alon = apoint[1];
  53. double blat = bpoint[0];
  54. double blon = bpoint[1];
  55. double R = 6378.137 * 1000;// 地球半径(米)
  56. // 判断点是在北半球还是南半球,本程序中输入的数据若为负则表示在南边球
  57. double distance = 0.0D;
  58. double _alat = alat * (Math.PI / 180);//弧度
  59. double _alon = alon * (Math.PI / 180);
  60. double _blat = blat * (Math.PI / 180);
  61. double _blon = blon * (Math.PI / 180);
  62. double c = Math.sin(_alat) * Math.sin(_blat) + Math.cos(_alat) * Math.cos(_blat) * Math.cos(_alon - _blon);// Java中三角函数角度以弧度制表示
  63. if (c > 1) {
  64. c = 1;
  65. }
  66. distance = Math.acos(c) * R; // 弧长公式:弧长 = 弧度 * 半径
  67. if (distance <= 0.01) { // GPS误差
  68. distance = 0.0D;
  69. }
  70. return distance * 1.9088; // 经过测试,distance和真实距离差 1.9088 倍,在这里扩大 1.9088 倍进行调整
  71. }

在主方法shortestDistance中,依次获取多边形的边p1、p2,调用calcP2L计算点到线段的距离;在calcP2L方法中,再调用calcP2P计算点到点的距离,获取点到点的距离,进而获取点到线段的距离,最终获取点到多边形的距离。

细节理论,后续补充。。。。。。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/562764
推荐阅读
相关标签
  

闽ICP备14008679号