ConvertHandler.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Mead
  5. * Date: 2019/8/31
  6. * Time: 2:42 PM
  7. */
  8. namespace App\Handlers;
  9. /**
  10. * Created by PhpStorm.
  11. * User: 申大侠
  12. * Date: 2018/7/11
  13. * Time: 9:19
  14. */
  15. class ConvertHandler
  16. {
  17. private $PI = 3.14159265358979324;
  18. private $x_pi = 0;
  19. public function __construct()
  20. {
  21. $this->x_pi = 3.14159265358979324 * 3000.0 / 180.0;
  22. }
  23. /**
  24. * 判断一个坐标是否在圆内
  25. * 思路:判断此点的经纬度到圆心的距离 然后和半径做比较
  26. * 如果此点刚好在圆上 则返回true
  27. * @param $point ['longitude'=>'','latitude'=>''] array指定点的坐标
  28. * @param $circle array ['center'=>['longitude'=>'','latitude'=>''],'radius'=>''] 中心点和半径
  29. */
  30. function is_point_in_circle($point, $circle, $radius)
  31. {
  32. $distance = $this->distance($point['latitude'], $point['longitude'], $circle['latitude'], $circle['longitude']);
  33. if ($distance <= $radius) {
  34. return true;
  35. } else {
  36. return false;
  37. }
  38. }
  39. /**
  40. * 计算两个点之间的距离
  41. * @return float
  42. */
  43. function distance($latitudeA, $lonA, $latitudeB, $lonB)
  44. {
  45. $earthR = 6371000.;
  46. $x = cos($latitudeA * $this->PI / 180.) * cos($latitudeB * $this->PI / 180.) * cos(($lonA - $lonB) * $this->PI / 180);
  47. $y = sin($latitudeA * $this->PI / 180.) * sin($latitudeB * $this->PI / 180.);
  48. $s = $x + $y;
  49. if ($s > 1) $s = 1;
  50. if ($s < -1) $s = -1;
  51. $alpha = acos($s);
  52. $distance = $alpha * $earthR;
  53. return $distance;
  54. }
  55. /**
  56. * 判断一个坐标是否在一个多边形内(由多个坐标围成的)
  57. * 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
  58. * 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
  59. *
  60. */
  61. function is_point_in_polygon($point, $pts)
  62. {
  63. $N = count($pts);
  64. $boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
  65. $intersectCount = 0;//cross points count of x
  66. $precision = 2e-10; //浮点类型计算时候与0比较时候的容差
  67. $p1 = 0;//neighbour bound vertices
  68. $p2 = 0;
  69. $p = $point; //测试点
  70. $p1 = $pts[0];//left vertex
  71. for ($i = 1; $i <= $N; ++$i) {//check all rays
  72. // dump($p1);
  73. if ($p['longitude'] == $p1['longitude'] && $p['latitude'] == $p1['latitude']) {
  74. return $boundOrVertex;//p is an vertex
  75. }
  76. $p2 = $pts[$i % $N];//right vertex
  77. if ($p['latitude'] < min($p1['latitude'], $p2['latitude']) || $p['latitude'] > max($p1['latitude'], $p2['latitude'])) {//ray is outside of our interests
  78. $p1 = $p2;
  79. continue;//next ray left point
  80. }
  81. if ($p['latitude'] > min($p1['latitude'], $p2['latitude']) && $p['latitude'] < max($p1['latitude'], $p2['latitude'])) {//ray is crossing over by the algorithm (common part of)
  82. if ($p['longitude'] <= max($p1['longitude'], $p2['longitude'])) {//x is before of ray
  83. if ($p1['latitude'] == $p2['latitude'] && $p['longitude'] >= min($p1['longitude'], $p2['longitude'])) {//overlies on a horizontal ray
  84. return $boundOrVertex;
  85. }
  86. if ($p1['longitude'] == $p2['longitude']) {//ray is vertical
  87. if ($p1['longitude'] == $p['longitude']) {//overlies on a vertical ray
  88. return $boundOrVertex;
  89. } else {//before ray
  90. ++$intersectCount;
  91. }
  92. } else {//cross point on the left side
  93. $xinters = ($p['latitude'] - $p1['latitude']) * ($p2['longitude'] - $p1['longitude']) / ($p2['latitude'] - $p1['latitude']) + $p1['longitude'];//cross point of longitude
  94. if (abs($p['longitude'] - $xinters) < $precision) {//overlies on a ray
  95. return $boundOrVertex;
  96. }
  97. if ($p['longitude'] < $xinters) {//before ray
  98. ++$intersectCount;
  99. }
  100. }
  101. }
  102. } else {//special case when ray is crossing through the vertex
  103. if ($p['latitude'] == $p2['latitude'] && $p['longitude'] <= $p2['longitude']) {//p crossing over p2
  104. $p3 = $pts[($i + 1) % $N]; //next vertex
  105. if ($p['latitude'] >= min($p1['latitude'], $p3['latitude']) && $p['latitude'] <= max($p1['latitude'], $p3['latitude'])) { //p.latitude lies between p1.latitude & p3.latitude
  106. ++$intersectCount;
  107. } else {
  108. $intersectCount += 2;
  109. }
  110. }
  111. }
  112. $p1 = $p2;//next ray left point
  113. }
  114. if ($intersectCount % 2 == 0) {//偶数在多边形外
  115. return false;
  116. } else { //奇数在多边形内
  117. return true;
  118. }
  119. }
  120. }