PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/Algorithms/Graph/Prim/php_classes/point.class.php

https://github.com/samklr/AlgorithmsNYC
PHP | 166 lines | 118 code | 32 blank | 16 comment | 29 complexity | a871d8dbc86d5bc1d733acbc7f4f2c59 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. class Point {
  3. public $guid;
  4. public $x;
  5. public $y;
  6. static $distanceTable = array();
  7. static $angleTable = array();
  8. static $anglePolarTable = array();
  9. function __construct( $coordX, $coordY, $guid = null ) {
  10. $this->x = $coordX;
  11. $this->y = $coordY;
  12. $this->guid = $guid;
  13. if( is_null( $this->guid ) ) {
  14. $this->guid = str_pad( $coordX, 0, '0', STR_PAD_LEFT ).','.str_pad( $coordY, 0, '0', STR_PAD_LEFT );
  15. }
  16. }
  17. public function __toString() {
  18. return $this->guid;
  19. }
  20. static function distance( $point1, $point2 ) {
  21. //if( !isset( self::$distanceTable[ $point1->guid ][ $point2->guid ] ) ) {
  22. $a = $point2->x - $point1->x;
  23. $b = $point2->y - $point1->y;
  24. $distance = round( sqrt( pow( $a, 2 ) + pow( $b, 2 ) ), 1 );
  25. self::$distanceTable[ $point1->guid ][ $point2->guid ] = $distance;
  26. self::$distanceTable[ $point2->guid ][ $point1->guid ] = $distance;
  27. //}
  28. return self::$distanceTable[ $point1->guid ][ $point2->guid ];
  29. }
  30. static function getDistanceTable() {
  31. return self::$distanceTable;
  32. }
  33. static function angle( $pointA, $pointB, $pointC ) {
  34. if( ! isset( self::$angleTable[ $pointA->guid . ';' . $pointB->guid . ';' . $pointC->guid ] ) ) {
  35. $AB = Point::distance( $pointA, $pointB );
  36. $BC = Point::distance( $pointB, $pointC );
  37. $AC = Point::distance( $pointC, $pointA );
  38. // Al-Khashi theorem
  39. self::$angleTable[ $pointA->guid.';'.$pointB->guid.';'.$pointC->guid ] =
  40. rad2deg( acos( ( pow( $AB, 2 ) + pow( $BC, 2 ) - pow( $AC, 2 ) ) / ( 2 * $AB * $BC ) ) );
  41. }
  42. return self::$angleTable[ $pointA->guid.';'.$pointB->guid.';'.$pointC->guid ];
  43. }
  44. /* Polar angle difference between $pointA and $pointC, $pointB is the origin, $pointA is 0 angle */
  45. static function anglePolar( $pointA, $pointB, $pointC ) {
  46. if( ! isset( self::$anglePolarTable[ $pointA->guid . ';' . $pointB->guid . ';' . $pointC->guid ] ) ) {
  47. $Ax = $pointA->x - $pointB->x;
  48. $Ay = $pointA->y - $pointB->y;
  49. $Cx = $pointC->x - $pointB->x;
  50. $Cy = $pointC->y - $pointB->y;
  51. if( $Ax <= 0 && pow( $Ay, 2 ) == 0 ) {
  52. $Apolar = 180;
  53. }else {
  54. $Apolar = rad2deg( 2 * atan( $Ay / ( $Ax + sqrt( pow( $Ax, 2 ) + pow( $Ay, 2 ) ) ) ) );
  55. }
  56. if( $Cx + sqrt( pow( $Cx, 2 ) + pow( $Cy, 2 ) ) == 0 ) {
  57. $Cpolar = 180;
  58. }else {
  59. $Cpolar = rad2deg( 2 * atan( $Cy / ( $Cx + sqrt( pow( $Cx, 2 ) + pow( $Cy, 2 ) ) ) ) );
  60. }
  61. $result = $Cpolar - $Apolar;
  62. if( $result < 0 ) $result += 360;
  63. self::$anglePolarTable[ $pointA->guid.';'.$pointB->guid.';'.$pointC->guid ] = $result;
  64. }
  65. return self::$anglePolarTable[ $pointA->guid.';'.$pointB->guid.';'.$pointC->guid ];
  66. }
  67. static function aireTriangle( $pointA, $pointB, $pointC ) {
  68. $AB = Point::distance( $pointA, $pointB );
  69. $BC = Point::distance( $pointB, $pointC );
  70. $AC = Point::distance( $pointC, $pointA );
  71. return sqrt( ( $AB + $BC + $AC) * ( - $AB + $BC + $AC ) * ( $AB - $BC + $AC ) * ( $AB + $BC - $AC ) ) / 4;
  72. }
  73. static function isCrossing( $pointA, $pointB, $pointC, $pointD ) {
  74. //var_dump( "isCrossing", $pointA->guid, $pointB->guid, $pointC->guid, $pointD->guid );
  75. $isCrossing = false;
  76. if(
  77. $pointA == $pointC && $pointB == $pointD ||
  78. $pointA == $pointD && $pointB == $pointC ) {
  79. // All identical points
  80. $isCrossing = true;
  81. }elseif(
  82. $pointA != $pointC && $pointB != $pointD &&
  83. $pointA != $pointD && $pointB != $pointC
  84. ) {
  85. // If only one point id identical => not crossing
  86. // Division by zero protection
  87. $v1 = ($pointA->x == $pointB->x);
  88. $v2 = ($pointC->x == $pointD->x);
  89. if( ! ($v1 && $v2) ) {
  90. if( $v1 ) {
  91. // AB is vertical
  92. $aCD = ($pointD->y - $pointC->y) / ($pointD->x - $pointC->x);
  93. $bCD = $pointC->y - $aCD * $pointC->x;
  94. $commonY= $aCD * $pointA->x + $bCD;
  95. $isCrossing =
  96. $commonY > min( $pointA->y, $pointB->y ) &&
  97. $commonY < max( $pointA->y, $pointB->y ) &&
  98. $commonY > min( $pointC->y, $pointD->y ) &&
  99. $commonY < max( $pointC->y, $pointD->y );
  100. }elseif( $v2 ) {
  101. // CD is vertical
  102. $aAB = ($pointB->y - $pointA->y) / ($pointB->x - $pointA->x);
  103. $bAB = $pointA->y - $aAB * $pointA->x;
  104. $commonY= $aAB * $pointC->x + $bAB;
  105. $isCrossing =
  106. $commonY > min( $pointA->y, $pointB->y ) &&
  107. $commonY < max( $pointA->y, $pointB->y ) &&
  108. $commonY > min( $pointC->y, $pointD->y ) &&
  109. $commonY < max( $pointC->y, $pointD->y );
  110. }else {
  111. // a : directional coefficient / b : origin oodonnée
  112. $aAB = ($pointB->y - $pointA->y) / ($pointB->x - $pointA->x);
  113. $aCD = ($pointD->y - $pointC->y) / ($pointD->x - $pointC->x);
  114. // AB and CD are not parallel
  115. if( $aAB != $aCD ) {
  116. $bAB = $pointA->y - $aAB * $pointA->x;
  117. $bCD = $pointC->y - $aCD * $pointC->x;
  118. // X coordinate of the extended line crossing
  119. $commonX = ( $bCD - $bAB ) / ( $aAB - $aCD );
  120. // Lines are crossing between the given points
  121. $isCrossing =
  122. $commonX > min( $pointA->x, $pointB->x ) &&
  123. $commonX < max( $pointA->x, $pointB->x ) &&
  124. $commonX > min( $pointC->x, $pointD->x ) &&
  125. $commonX < max( $pointC->x, $pointD->x );
  126. }
  127. }
  128. }
  129. }
  130. //var_dump( $isCrossing );
  131. //if( $isCrossing ) var_dump( "isCrossing", $pointA->guid, $pointB->guid, $pointC->guid, $pointD->guid );
  132. return $isCrossing;
  133. }
  134. }