Point::isCrossing PHP Method

isCrossing() static public method

static public isCrossing ( $pointA, $pointB, $pointC, $pointD )
    static function isCrossing($pointA, $pointB, $pointC, $pointD)
    {
        //var_dump( "isCrossing", $pointA->guid, $pointB->guid, $pointC->guid, $pointD->guid );
        $isCrossing = false;
        if ($pointA == $pointC && $pointB == $pointD || $pointA == $pointD && $pointB == $pointC) {
            // All identical points
            $isCrossing = true;
        } elseif ($pointA != $pointC && $pointB != $pointD && $pointA != $pointD && $pointB != $pointC) {
            // If only one point id identical => not crossing
            // Division by zero protection
            $v1 = $pointA->x == $pointB->x;
            $v2 = $pointC->x == $pointD->x;
            if (!($v1 && $v2)) {
                if ($v1) {
                    // AB is vertical
                    $aCD = ($pointD->y - $pointC->y) / ($pointD->x - $pointC->x);
                    $bCD = $pointC->y - $aCD * $pointC->x;
                    $commonY = $aCD * $pointA->x + $bCD;
                    $isCrossing = $commonY > min($pointA->y, $pointB->y) && $commonY < max($pointA->y, $pointB->y) && $commonY > min($pointC->y, $pointD->y) && $commonY < max($pointC->y, $pointD->y);
                } elseif ($v2) {
                    // CD is vertical
                    $aAB = ($pointB->y - $pointA->y) / ($pointB->x - $pointA->x);
                    $bAB = $pointA->y - $aAB * $pointA->x;
                    $commonY = $aAB * $pointC->x + $bAB;
                    $isCrossing = $commonY > min($pointA->y, $pointB->y) && $commonY < max($pointA->y, $pointB->y) && $commonY > min($pointC->y, $pointD->y) && $commonY < max($pointC->y, $pointD->y);
                } else {
                    // a : directional coefficient / b : origin oodonnée
                    $aAB = ($pointB->y - $pointA->y) / ($pointB->x - $pointA->x);
                    $aCD = ($pointD->y - $pointC->y) / ($pointD->x - $pointC->x);
                    // AB and CD are not parallel
                    if ($aAB != $aCD) {
                        $bAB = $pointA->y - $aAB * $pointA->x;
                        $bCD = $pointC->y - $aCD * $pointC->x;
                        // X coordinate of the extended line crossing
                        $commonX = ($bCD - $bAB) / ($aAB - $aCD);
                        // Lines are crossing between the given points
                        $isCrossing = $commonX > min($pointA->x, $pointB->x) && $commonX < max($pointA->x, $pointB->x) && $commonX > min($pointC->x, $pointD->x) && $commonX < max($pointC->x, $pointD->x);
                    }
                }
            }
        }
        //var_dump( $isCrossing );
        //if( $isCrossing ) var_dump( "isCrossing", $pointA->guid, $pointB->guid, $pointC->guid, $pointD->guid );
        return $isCrossing;
    }

Usage Example

 /**
  * Checks the presence of a point in the polygon
  * Returns :
  * 0 : Point not in polygon
  * 1 : Point in polygon
  * 2 : Point is a node of the polygon
  * 
  * @see http://stackoverflow.com/questions/217578/point-in-polygon-aka-hit-test
  */
 public function includes(Point $point)
 {
     $return = 0;
     //Whole area check : does it include the center ?
     $includes_point = false;
     $origin = new Point(-1, -1);
     $airePointAKey = count($this->points) - 1;
     for ($airePointBKey = 0; $airePointBKey < count($this->points); $airePointBKey++) {
         if ($point->guid == $this->points[$airePointBKey]->guid) {
             $return = 2;
             break;
         }
         if (Point::isCrossing($origin, $point, $this->points[$airePointAKey], $this->points[$airePointBKey])) {
             $includes_point = !$includes_point;
         }
         $airePointAKey++;
         if ($airePointAKey == count($this->points)) {
             $airePointAKey = 0;
         }
     }
     if ($return == 0) {
         $return = (int) $includes_point;
     }
     return $return;
 }