## Introduction

phpgeo is a small PHP library which provides abstractions to geographical coordinates (including support for different ellipsoids), polylines ("GPS Tracks"), polygons, bounds, and more. phpgeo allows you to perform different calculations with these abstractions, as distances, track lengths, etc.

phpgeo is developed by Marcus Jaschen and all contributors.

The project is hosted on Github:

### Privacy

The privacy statement for this documentation site can be found here: Datenschutzerklärung

## Requirements

phpgeo requires at least PHP 7.0.

Older PHP versions are supported in releases up to phpgeo 1.3.8.

## Installation

To install phpgeo, simply "require" it using Composer:

`php composer.phar require mjaschen/phpgeo`

## Development

### Run Tests

phpgeo provides unit tests with a quite good coverage. For an easy usage, the test command is wrapped as a Composer script:

`composer ci:tests`

Of course it’s possible to run PHPUnit directly:

`php vendor/bin/phpunit`

To test against another PHP version you can use Docker. The following command runs the tests using PHP 7.1:

`docker run -it --rm --name phpgeo-phpunit -v "$PWD":/usr/src/phpgeo -w /usr/src/phpgeo php:7.1-cli php vendor/bin/phpunit` Or using PHP 7.2: `docker run -it --rm --name phpgeo-phpunit -v "$PWD":/usr/src/phpgeo -w /usr/src/phpgeo php:7.2-cli php vendor/bin/phpunit`

Besides the unit tests, static test runners are also provided. Run the lint command to ensure the sources don’t contain any syntax error:

`composer ci:lint`

A static code analysis with Psalm is configured as well:

`composer ci:psalm`

It’s possible to run all tests at once:

`composer ci`

### API Documentation

Detailed API documentation is available.

## Geometries

phpgeo provides several geometry classes:

• `Coordinate`

• `Line`

• `Polyline`

• `Polygon`

A Coordinate represents a geographic location, i. e. it contains a latitude and a longitude - together with an so called Ellipsoid.

A Line consists of two coordinates, while polylines and polygons are built from two or more coordinates.

### Coordinate

The `Coordinate` class is the most important class of phpgeo and provides the base for all features. It’s a representation of a geographic location and consists of three parts:

• Geographic Latitude

• Geographic Longitude

• Ellipsoid

Geographic latitude and longitude values are float numbers between -90.0 and 90.0 (degrees latitude) and -180.0 and 180.0 (degrees longitude).

The Ellipsoid is a representation of an approximated shape of the earth and is abstracted in its own Ellipsoid class.

### Line

A line consists of two points, i. e. instances of the `Coordinate` class.

#### Length

The `Line` class provides a method to calculate its own length. The method expects an instance of a class which implements the `DistanceInterface`.

``````<?php

use Location\Coordinate;
use Location\Distance\Haversine;
use Location\Line;

$line = new Line( new Coordinate(52.5, 13.5), new Coordinate(52.6, 13.4) );$length = $line->getLength(new Haversine()); (1) printf("The line has a length of %.3f meters\n",$length);``````
 1 `Haversine` is one of the currently two available classes for distance calculation. The other one is named `Vincenty`.

The code above will produce the output below:

`The line has a length of 13013.849 meters`

#### Bearing

The bearing of an instance can be calculated using the `getBearing()` method. An instance of `BearingInterface` must be provided as method argument.

``````<?php

use Location\Bearing\BearingEllipsoidal;
use Location\Coordinate;
use Location\Line;

$line = new Line( new Coordinate(52.5, 13.5), new Coordinate(52.6, 13.4) );$bearing = $line->getBearing(new BearingEllipsoidal()); (1) printf("The line has a bearing of %.2f degrees\n",$bearing);``````
 1 `BearingEllipsoidal` is one of the currently two available classes for bearing calculation. The other one is named `BearingSpherical`.

The code above will produce the output below:

`The line has a bearing of 328.67 degrees`

This ist the so called initial bearing. There exist another bearing angle, called the final bearing. It can be calculated as well:

``````<?php

use Location\Bearing\BearingEllipsoidal;
use Location\Coordinate;
use Location\Line;

$line = new Line( new Coordinate(52.5, 13.5), new Coordinate(52.6, 13.4) );$bearing = $line->getFinalBearing(new BearingEllipsoidal()); printf("The line has a final bearing of %.2f degrees\n",$bearing);``````

The code above will produce the output below:

`The line has a final bearing of 328.59 degrees`

### Polyline

A polyline consists of an ordered list of locations, i. e. instances of the `Coordinate` class.

#### Create a polyline

To create a polyline, just instantiate the class and add points:

``````<?php

use Location\Coordinate;
use Location\Polyline;

$polyline = new Polyline();$polyline->addPoint(new Coordinate(52.5, 13.5));
$polyline->addPoint(new Coordinate(54.5, 12.5));$polyline->addPoint(new Coordinate(55.5, 14.5));
?>``````

It’s possible to add points to the end of the polyline at every time.

#### Segments

It’s possible to get a list of polyline segments. Segments are returned as an array of `Line` instances.

``````<?php

use Location\Coordinate;
use Location\Polyline;

$track = new Polyline();$track->addPoint(new Coordinate(52.5, 13.5));
$track->addPoint(new Coordinate(54.5, 12.5));$track->addPoint(new Coordinate(55.5, 14.5));

foreach ($track->getSegments() as$segment) {
printf(
"Segment length: %0.2f kilometers\n",
($segment->getLength(new Haversine()) / 1000) ); }`````` The code above will produce the output below: ```Segment length: 232.01 kilometers Segment length: 169.21 kilometers``` #### Length Length calculation is described in the Distance and Length section. #### Reverse Direction It’s possible to get a new instance with reversed direction while the original polyline stays unchanged: ``````<?php use Location\Coordinate; use Location\Polyline;$track = new Polyline();
$track->addPoint(new Coordinate(52.5, 13.5));$track->addPoint(new Coordinate(54.5, 12.5));

$reversed =$track->getReverse();

print_r($reversed);`````` The code above will produce the output below: ```Location\Polyline Object ( [points:protected] => Array ( [0] => Location\Coordinate Object ( [lat:protected] => 54.5 [lng:protected] => 12.5 [ellipsoid:protected] => Location\Ellipsoid Object ( [name:protected] => WGS-84 [a:protected] => 6378137 [f:protected] => 298.257223563 ) ) [1] => Location\Coordinate Object ( [lat:protected] => 52.5 [lng:protected] => 13.5 [ellipsoid:protected] => Location\Ellipsoid Object ( [name:protected] => WGS-84 [a:protected] => 6378137 [f:protected] => 298.257223563 ) ) ) )``` ### Polygon A polygon consists of an ordered list of locations, i. e. instances of the `Coordinate` class. It’s very similar to a polyline, but its start and end points are connected. #### Create a polygon To create a polygon, just instantiate the class and add points: ``````<?php use Location\Coordinate; use Location\Polygon;$polygon = new Polygon();
$polygon->addPoint(new Coordinate(52.5, 13.5));$polygon->addPoint(new Coordinate(54.5, 12.5));
$polygon->addPoint(new Coordinate(55.5, 14.5)); ?>`````` It’s possible to add points to the end at every time. #### Get list of points `getPoints()` is used to get the list of points, the number of points can be retrieved by calling `getNumberOfPoints()`: ``````<?php use Location\Coordinate; use Location\Formatter\Coordinate\DMS; use Location\Polygon;$polygon = new Polygon();
$polygon->addPoint(new Coordinate(52.5, 13.5));$polygon->addPoint(new Coordinate(54.5, 12.5));
$polygon->addPoint(new Coordinate(55.5, 14.5)); printf("The polygon consists of %d points:\n",$polygon->getNumberOfPoints());

foreach ($polygon->getPoints() as$point) {
echo $point->format(new DMS()) . PHP_EOL; }`````` The code above will produce the output below: ```The polygon consists of 3 points: 52° 30′ 00″ 013° 30′ 00″ 54° 30′ 00″ 012° 30′ 00″ 55° 30′ 00″ 014° 30′ 00″``` #### Segments It’s possible to get a list of polygon segments. Segments are returned as an array of `Line` instances. ``````<?php use Location\Coordinate; use Location\Distance\Haversine; use Location\Polygon;$polygon = new Polygon();
$polygon->addPoint(new Coordinate(52.5, 13.5));$polygon->addPoint(new Coordinate(54.5, 12.5));
$polygon->addPoint(new Coordinate(55.5, 14.5)); foreach ($polygon->getSegments() as $line) { printf("%0.3f m\n",$line->getLength(new Haversine()));
}``````

The code above will produce the output below:

```232011.020 m
169207.795 m
339918.069 m```

#### Length/Perimeter

Length calculation is described in the Distance and Length section.

#### Area

It’s possible to calculate the area of an polygon. The result is given in square meters (m²).

 The calculation gives inaccurate results. For relatively small polygons the error should be less than 1 %.
``````<?php

use Location\Coordinate;
use Location\Polygon;

$formatter = new \Location\Formatter\Coordinate\DecimalDegrees(' ', 10);$polygon = new Polygon();
$polygon->addPoint(new Coordinate(0.0000000000, 0.0000000000));$polygon->addPoint(new Coordinate(0.0000000000, 0.0008983153));
$polygon->addPoint(new Coordinate(0.0009043695, 0.0008983153));$polygon->addPoint(new Coordinate(0.0009043695, 0.0000000000));

printf(
'Polygon Area = %f m², Perimeter = %f m%s',
$polygon->getArea(),$polygon->getPerimeter(new \Location\Distance\Vincenty()),
PHP_EOL
);``````

The code above produces the output below:

`Polygon Area = 10044.905261 m², Perimeter = 400.000000 m`

#### Geofence

It’s possible to check if a geometry object (point, line, polyline, polygon) lies inside a polygon. The documentation can be found in the Geofence section.

#### Reverse Direction

It’s possible to get a new instance with reversed direction while the original polygon stays unchanged:

``````<?php

use Location\Coordinate;
use Location\Polygon;
use Location\Formatter\Coordinate\DecimalDegrees;

$polygon = new Polygon();$polygon->addPoint(new Coordinate(52.5, 13.5));
$polygon->addPoint(new Coordinate(64.1, - 21.9));$polygon->addPoint(new Coordinate(40.7, - 74.0));
$polygon->addPoint(new Coordinate(33.9, - 118.4));$reversed = $polygon->getReverse(); foreach ($reversed->getPoints() as $point) { echo$point->format(new DecimalDegrees(', ')) . PHP_EOL;
}``````

The code above produces the output below:

```33.90000, -118.40000
40.70000, -74.00000
64.10000, -21.90000
52.50000, 13.50000```

### Ellipsoid

An ellipsoid is a mathematically defined approximation of the earth’s surface.

An ellipsoid is defined by two parameters:

• the semi-major axis a (equatorial radius)

• the semi-minor axis b (polar radius)

a and b together define the flattening of the ellipsoid f:

$f = \frac{a-b}{a}$

 phpgeo’s ellipsoids are defined by a and 1/f instead of a and b. That’s not a problem because each of the three values can be calculated from the other two.

phpgeo supports arbitrary ellipsoids. WGS-84 is used as default when no other ellipsoid is given. For day-to-day calculations it’s not needed to care about ellipsoids in the most cases.

It’s possible to create an instance of the Ellipsoid class either by specifing a name or by providing the three parameters name, a, and 1/f.

``````use Location\Ellipsoid;

$ellipsoid = Ellipsoid::createDefault('WGS-84'); (1) printf( "%s: a=%f; b=%f; 1/f=%f\n",$ellipsoid->getName(),
$ellipsoid->getA(),$ellipsoid->getB(),
$ellipsoid->getF() );$ellipsoid = new Ellipsoid('GRS-80', 6378137, 298.257222); (2)

printf(
"%s: a=%f; b=%f; 1/f=%f\n",
$ellipsoid->getName(),$ellipsoid->getA(),
$ellipsoid->getB(),$ellipsoid->getF()
);``````
 1 Create ellipsoid instance from one of the default configurations 2 Create custom ellipsoid by providing name, a, and 1/f

The code above will produce the output below:

```WGS-84: a=6378137.000000; b=6356752.314245; 1/f=298.257224
GRS-80: a=6378137.000000; b=6356752.314133; 1/f=298.257222```

Please take a look into the `Ellipsoid` source file for a list of pre-defined ellipsoids.

## Calculations

### Distance and Length

#### Distance Between Two Coordinates (Vincenty’s Formula)

Use the calculator object directly:

``````<?php

use Location\Coordinate;
use Location\Distance\Vincenty;

$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit

$calculator = new Vincenty(); echo$calculator->getDistance($coordinate1,$coordinate2);``````

The code above will produce the output below:

`128130.850`

or call the `getDistance()` method of a Coordinate object by injecting a calculator object:

``````<?php

use Location\Coordinate;
use Location\Distance\Vincenty;

$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit

echo $coordinate1->getDistance($coordinate2, new Vincenty());``````

The code above will produce the output below:

`128130.850`

#### Distance Between Two Coordinates (Haversine Formula)

There exist different methods for calculating the distance between two points. The Haversine formula is much faster than Vincenty’s method but less precise:

``````<?php

use Location\Coordinate;
use Location\Distance\Haversine;

$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit

echo $coordinate1->getDistance($coordinate2, new Haversine());``````

The code above will produce the output below:

`128384.515`

#### Length of a Polyline

phpgeo has a polyline implementation which can be used to calculate the length of a GPS track or a route. A polyline consists of at least two points. Points are instances of the `Coordinate` class.

For more details about polylines/GPS tracks see the Polyline section.

``````<?php

use Location\Coordinate;
use Location\Polyline;
use Location\Distance\Vincenty;

$track = new Polyline();$track->addPoint(new Coordinate(52.5, 13.5));
$track->addPoint(new Coordinate(54.5, 12.5)); echo$track->getLength(new Vincenty());``````

#### Perimeter of a Polygon

The perimeter is calculated as the sum of the length of all segments. The result is given in meters.

``````<?php

use Location\Distance\Vincenty;
use Location\Coordinate;
use Location\Polygon;

$polygon = new Polygon();$polygon->addPoint(new Coordinate(10, 10));
$polygon->addPoint(new Coordinate(10, 20));$polygon->addPoint(new Coordinate(20, 20));
$polygon->addPoint(new Coordinate(20, 10)); echo$polygon->getPerimeter(new Vincenty());``````

The code above will produce the output below:

`4355689.472`

### Bearing and Destination

phpgeo can be used to calculate the bearing between two points and to get a destination point for a given start point together with a bearing angle and a distance.

Multiple calculation algorithms are supported. Currently phpgeo provides methods for calculations with a spherical earth model and with an ellipsoidal model. The spherical calculations are very fast, compared to the ellipsoidal methods. The ellipsoidal algorithms are a bit more precise on the other hand.

#### Bearing between two points

Given two points, it’s possible to calculate the bearing angled between those points.

phpgeo can calculate the initial bearing (bearing as seen from the first point) and the final bearing (bearing as seen approaching the destination point).

##### Calculation with a spherical earth model
``````<?php

use Location\Bearing\BearingSpherical;
use Location\Coordinate;

$berlin = new Coordinate(52.5, 13.5);$london = new Coordinate(51.5, -0.12);

$bearingCalculator = new BearingSpherical();$startTime = microtime(true);
var_dump($bearingCalculator->calculateBearing($berlin, $london)); var_dump($bearingCalculator->calculateFinalBearing($berlin,$london));
$endTime = microtime(true); printf("Time elapsed: %0.6f s\n", ($endTime - $startTime));`````` The code above will produce the following output: ```double(268.60722336693) double(257.85494586285) Time elapsed: 0.000285 s``` ##### Calculation with an ellipsoidal earth model ``````<?php use Location\Bearing\BearingEllipsoidal; use Location\Coordinate;$berlin = new Coordinate(52.5, 13.5);
$london = new Coordinate(51.5, -0.12);$bearingCalculator = new BearingEllipsoidal();

$startTime = microtime(true); var_dump($bearingCalculator->calculateBearing($berlin,$london));
var_dump($bearingCalculator->calculateFinalBearing($berlin, $london));$endTime = microtime(true);
printf("Time elapsed: %0.6f s\n", ($endTime -$startTime));``````

The code above will produce the following output:

```double(268.62436347111)
double(257.87203657292)
Time elapsed: 0.000304 s```

Both calculations finish in roughly the same time. One would expect the second calculation to be clearly slower than the first one. It seems the exit condition for the iteration is reached quite fast. There might exist other conditions where the ellipsoidal calculation is noticeable slower.

#### Destination point for given bearing and distance

As an example, starting from Berlin, calculate the destination point in 56.1 km distance with an initial bearing of 153 degrees:

``````<?php
use Location\Bearing\BearingEllipsoidal;
use Location\Bearing\BearingSpherical;
use Location\Coordinate;
use Location\Formatter\Coordinate\DecimalDegrees;

$berlin = new Coordinate(52.5, 13.5);$bearingSpherical = new BearingSpherical();
$bearingEllipsoidal = new BearingEllipsoidal();$destination1 = $BearingSpherical->calculateDestination($berlin, 153, 56100);
$destination2 =$bearingEllipsoidal->calculateDestination($berlin, 153, 56100); echo "Spherical: " .$destination1->format(new DecimalDegrees()) . PHP_EOL;
echo "Ellipsoidal: " . $destination2->format(new DecimalDegrees()) . PHP_EOL;`````` The code above will produce the output below: ```Spherical: 52.04988 13.87628 Ellipsoidal: 52.05020 13.87126``` Oh, look, what a beautiful spot on earth it is. ;-) #### Final Bearing for a calculated destination phpgeo can calculate the final bearing angle for a given starting point, an initial bearing, and the distance to the destination. ``````<?php use Location\Bearing\BearingEllipsoidal; use Location\Coordinate; use Location\Formatter\Coordinate\DecimalDegrees;$berlin = new Coordinate(52.5, 13.5);

$bearingEllipsoidal = new BearingEllipsoidal();$finalBearing = $bearingEllipsoidal->calculateDestinationFinalBearing($berlin, 153, 56100);

var_dump($finalBearing);`````` The code above will produce the output below: `float(153.29365182147)` ### Perpendicular Distance The perpendicular distance is defined as the shortest distance between a point and a line (in the two-dimensional plane) respectively between a point and a great circle on a spherical surface. With phpgeo it is possible to calculate the perpendicular distance between a point (instance of the `Coordinate` class) and a line (instance of the `Line` class). A line is defined by two coordinates, exactly as a great circle — both are interchangeable in this case. ``````<?php use Location\Coordinate; use Location\Line; use Location\Utility\PerpendicularDistance;$point = new Coordinate(52.44468, 13.57455);
$line = new Line( new Coordinate(52.4554, 13.5582), new Coordinate(52.4371, 13.5623) );$pdCalc = new PerpendicularDistance();

printf(
"perpendicular distance: %.1f meters\n",
$pdCalc->getPerpendicularDistance($point, $line) );`````` The code above will produce the output below: `perpendicular distance: 936.7 meters` ### Geofence phpgeo has a polygon implementation which can be used to determinate if a geometry (point, line, polyline, polygon) is contained in it or not. A polygon consists of at least three points.  The calculation gives wrong results if the polygons crosses the 180/-180 degrees meridian. ``````<?php use Location\Coordinate; use Location\Polygon;$geofence = new Polygon();

$geofence->addPoint(new Coordinate(-12.085870,-77.016261));$geofence->addPoint(new Coordinate(-12.086373,-77.033813));
$geofence->addPoint(new Coordinate(-12.102823,-77.030938));$geofence->addPoint(new Coordinate(-12.098669,-77.006476));

$outsidePoint = new Coordinate(-12.075452, -76.985079);$insidePoint = new Coordinate(-12.092542, -77.021540);

var_dump($geofence->contains($outsidePoint)); // returns bool(false) the point is outside the polygon
var_dump($geofence->contains($insidePoint)); // returns bool(true) the point is inside the polygon``````

### Transformations and Processing

#### Simplifying a polyline

Polylines can be simplified to save storage space or bandwidth.

phpgeo provides two implementations for simplifying a polyline.

The first implementation uses the Ramer–Douglas–Peucker algorithm (also known as Douglas-Peucker algorithm). The other implementation examines the bearings of the polyline segments and removes a segment when its bearing angle is similar to the bearing angle of its predecessor segment. I named it the Delta-Bearing algorithm.

##### Ramer-Douglas-Peucker Algorithm
``````<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\DecimalDegrees;
use Location\Polyline;
use Location\Processor\Polyline\SimplifyDouglasPeucker;

$polyline = new Polyline();$polyline->addPoint(new Coordinate(10.0, 10.0));
$polyline->addPoint(new Coordinate(20.0, 20.0));$polyline->addPoint(new Coordinate(30.0, 10.0));

$processor = new SimplifyDouglasPeucker(1500000); (1)$simplified = $processor->simplify($polyline);

foreach ($simplified->getPoints() as$point) {
echo $point->format(new DecimalDegrees()) . PHP_EOL; }``````  1 remove all points which perpendicular distance is less than 1,500,000 meters (1,500 km) from the surrounding points. The code above produces the output below: ```10.00000 10.00000 30.00000 10.00000``` ##### Delta-Bearing Algorithm ``````<?php use Location\Coordinate; use Location\Formatter\Coordinate\DecimalDegrees; use Location\Polyline; use Location\Processor\Polyline\SimplifyBearing;$polyline = new Polyline();
$polyline->addPoint(new Coordinate(10.0, 10.0));$polyline->addPoint(new Coordinate(20.0, 20.0));
$polyline->addPoint(new Coordinate(30.0, 10.0));$processor = new SimplifyBearing(90); (1)

$simplified =$processor->simplify($polyline); foreach ($simplified->getPoints() as $point) { echo$point->format(new DecimalDegrees()) . PHP_EOL;
}``````
 1 The constructor argument is the minimum required angle between two adjacent polyline segments so that no points will be removed. If the bearing angle difference is less that the given value, the middle point will be removed from the resulting polyline.

The code above produces the output below:

```10.00000 10.00000
30.00000 10.00000```

The following image shows both a polyline and its simplified version. The simplification was done with the Delta-Bearing Algorithm with a threshold angle of 20 degrees. The original polyline is painted in blue, the simplified polyline is magenta.

## Formatting and Output

### Coordinates

You can format a coordinate in different styles.

#### Decimal Degrees

``````<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\DecimalDegrees;

$coordinate = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit echo$coordinate->format(new DecimalDegrees());``````

The code above produces the output below:

`    19.82066 -155.46807`

The separator string between latitude and longitude can be configured via constructor argument, as well as the number of decimals (default value is 5 digits):

``````<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\DecimalDegrees;

$coordinate = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit echo$coordinate->format(new DecimalDegrees(', ', 3));``````

The code above produces the output below:

`    19.821, -155.468`

#### Degrees/Minutes/Seconds (DMS)

``````<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\DMS;

$coordinate = new Coordinate(18.911306, -155.678268); // South Point, HI, USA$formatter = new DMS();

echo $coordinate->format($formatter) . PHP_EOL;

$formatter->setSeparator(", ") ->useCardinalLetters(true) ->setUnits(DMS::UNITS_ASCII); echo$coordinate->format($formatter) . PHP_EOL;`````` The code above produces the output below: ``` 18° 54′ 41″ -155° 40′ 42″ 18° 54' 41" N, 155° 40' 42" W``` #### Decimal Minutes This format is commonly used in the Geocaching community. ``````<?php use Location\Coordinate; use Location\Formatter\Coordinate\DecimalMinutes;$coordinate = new Coordinate(43.62310, -70.20787); // Portland Head Light, ME, USA

$formatter = new DecimalMinutes(); echo$coordinate->format($formatter) . PHP_EOL;$formatter->setSeparator(", ")
->useCardinalLetters(true)
->setUnits(DecimalMinutes::UNITS_ASCII);

echo $coordinate->format($formatter) . PHP_EOL;``````

The code above produces the output below:

```    43° 37.386′ -070° 12.472′
43° 37.386' N, 070° 12.472' W```

#### GeoJSON

``````<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\GeoJSON;

$coordinate = new Coordinate(18.911306, -155.678268); // South Point, HI, USA echo$coordinate->format(new GeoJSON());``````

The code above produces the output below:

``{"type":"Point","coordinates":[-155.678268,18.911306]}``
 Float values processed by `json_encode()` are affected by the ini-setting `serialize_precision`. You can change the number of decimal places in the JSON output by changing that ini-option, e. g. with `ini_set('serialize_precision', 8)`.

### Polylines

You can format a polyline in different styles.

#### GeoJSON

``````<?php

use Location\Coordinate;
use Location\Polyline;
use Location\Formatter\Polyline\GeoJSON;

$polyline = new Polyline;$polyline->addPoint(new Coordinate(52.5, 13.5));
$polyline->addPoint(new Coordinate(62.5, 14.5));$formatter = new GeoJSON;

echo $formatter->format($polyline);``````

The code above produces the output below:

``{"type":"LineString","coordinates":[[13.5,52.5],[14.5,62.5]]}``
 Float values processed by `json_encode()` are affected by the ini-setting `serialize_precision`. You can change the number of decimal places in the JSON output by changing that ini-option, e. g. with `ini_set('serialize_precision', 8)`.

### Polygons

You can format a polygon in different styles.

#### GeoJSON

``````<?php

use Location\Coordinate;
use Location\Polygon;
use Location\Formatter\Polygon\GeoJSON;

$polygon = new Polygon;$polygon->addPoint(new Coordinate(10, 20));
$polygon->addPoint(new Coordinate(20, 40));$polygon->addPoint(new Coordinate(30, 40));
$polygon->addPoint(new Coordinate(30, 20));$formatter = new GeoJSON;

echo $formatter->format($polygon);``````

The code above produces the output below:

``{"type":"Polygon","coordinates":[[20,10],[40,20],[40,30],[20,30]]}``
 Float values processed by `json_encode()` are affected by the ini-setting `serialize_precision`. You can change the number of decimal places in the JSON output by changing that ini-option, e. g. with `ini_set('serialize_precision', 8)`.

## Parsing and Input

### Coordinates Parser

phpgeo comes with a parser for several types of coordinate formats. The parser works as a factory which creates an instance of the `Coordinate` class.

#### Supported Formats

Decimal Degrees with or without cardinal letters, with or without a comma as separator, with or without whitespace between values and cardinal letters:

```52.5, 13.5
52.5 13.5
-52.5 -13.5
52.345 N, 13.456 E
N52.345 E13.456```

Decimal Minutes with or without cardinal letters, with or without degree and minute signs, with or without a comma as separator, with or without whitespace between values and cardinal letters:

```N52° 12.345, E13° 34.567
52° 12.345′ N, E13° 34.567′ E
52 12.345, 013 34.567
-52 12.345, -013 34.567```

The unit test shows some more examples.

#### Example

``````use Location\Factory\CoordinateFactory;
use Location\Formatter\Coordinate\DecimalDegrees;

$point = CoordinateFactory::fromString('52° 13.698′ 020° 58.536′'); echo$point->format(new DecimalDegrees());``````
`52.22830 20.97560`