PMA\libraries\gis\GISPolygon::getPointOnSurface PHP Метод

getPointOnSurface() публичный статический Метод

(for simple closed rings)
public static getPointOnSurface ( array $ring ) : array | void
$ring array array of points forming the ring
Результат array | void a point on the surface of the ring
    public static function getPointOnSurface($ring)
    {
        // Find two consecutive distinct points.
        for ($i = 0, $nb = count($ring) - 1; $i < $nb; $i++) {
            if ($ring[$i]['y'] != $ring[$i + 1]['y']) {
                $x0 = $ring[$i]['x'];
                $x1 = $ring[$i + 1]['x'];
                $y0 = $ring[$i]['y'];
                $y1 = $ring[$i + 1]['y'];
                break;
            }
        }
        if (!isset($x0)) {
            return false;
        }
        // Find the mid point
        $x2 = ($x0 + $x1) / 2;
        $y2 = ($y0 + $y1) / 2;
        // Always keep $epsilon < 1 to go with the reduction logic down here
        $epsilon = 0.1;
        $denominator = sqrt(pow($y1 - $y0, 2) + pow($x0 - $x1, 2));
        $pointA = array();
        $pointB = array();
        while (true) {
            // Get the points on either sides of the line
            // with a distance of epsilon to the mid point
            $pointA['x'] = $x2 + $epsilon * ($y1 - $y0) / $denominator;
            $pointA['y'] = $y2 + ($pointA['x'] - $x2) * ($x0 - $x1) / ($y1 - $y0);
            $pointB['x'] = $x2 + $epsilon * ($y1 - $y0) / (0 - $denominator);
            $pointB['y'] = $y2 + ($pointB['x'] - $x2) * ($x0 - $x1) / ($y1 - $y0);
            // One of the points should be inside the polygon,
            // unless epsilon chosen is too large
            if (GISPolygon::isPointInsidePolygon($pointA, $ring)) {
                return $pointA;
            }
            if (GISPolygon::isPointInsidePolygon($pointB, $ring)) {
                return $pointB;
            }
            //If both are outside the polygon reduce the epsilon and
            //recalculate the points(reduce exponentially for faster convergence)
            $epsilon = pow($epsilon, 2);
            if ($epsilon == 0) {
                return false;
            }
        }
    }

Usage Example

Пример #1
0
 /**
  * test for getPointOnSurface
  *
  * @param array $ring array of points forming the ring
  *
  * @dataProvider providerForTestGetPointOnSurface
  * @return void
  */
 public function testGetPointOnSurface($ring)
 {
     $this->assertEquals(
         $this->object->isPointInsidePolygon(
             $this->object->getPointOnSurface($ring),
             $ring
         ),
         true
     );
 }
All Usage Examples Of PMA\libraries\gis\GISPolygon::getPointOnSurface