---
title: "Geofencing — Geolocation for Laravel | Roundly"
description: "Radius checks, point-in-polygon zones, bearings, midpoints and bounding boxes on Coordinates — pure PHP, no API calls."
url: https://roundly-consulting.com/open-source/docs/geolocation-for-laravel/geofencing
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Geolocation for Laravel](https://roundly-consulting.com/open-source/docs/geolocation-for-laravel.md)

# Geofencing

Coordinates carries a set of geofencing helpers. They are pure math — no provider, no network:

```php
use RoundlyConsulting\Geolocation\DataTransferObjects\Coordinates;

$here = new Coordinates(48.1486, 17.1077);
$there = new Coordinates(48.21, 16.37);

$here->near($there, radiusKm: 100);         // bool — Haversine distance ≤ 100 km
$here->within([$a, $b, $c, $d]);            // point-in-polygon, bool
$here->bearingTo($there);                   // initial bearing, degrees 0–360 clockwise from north
$here->midpointTo($there);                  // Coordinates on the great circle
$box = $here->boundingBox(radiusKm: 10);    // BoundingBox
$box->contains($point);                     // bool
```

## Method reference

| Method | Returns |
| --- | --- |
| `distanceTo(Coordinates): float` | Great-circle distance in metres (Haversine). |
| `near(Coordinates, float $radiusKm): bool` | Whether the other point lies within the radius. |
| `within(list<Coordinates>): bool` | Point-in-polygon (ray casting); each edge runs the short way round, so polygons across the antimeridian work. Fewer than 3 vertices returns false; a polygon enclosing a pole is not supported. |
| `bearingTo(Coordinates): float` | Initial bearing, 0–360° clockwise from north. |
| `midpointTo(Coordinates): Coordinates` | Geographic midpoint along the great circle, longitude normalised into -180..180. |
| `boundingBox(float $radiusKm): BoundingBox` | The smallest box holding every point within the radius. Wraps across ±180°; spans every longitude when the circle reaches a pole. |
| `BoundingBox::contains(Coordinates): bool` | Whether a point falls inside the box, wrapped boxes included. |
| `BoundingBox::crossesAntimeridian(): bool` | Whether the box wraps across ±180° (its south-west longitude is then greater than its north-east one). |

## Antimeridian and poles

The helpers work across the antimeridian and near the poles: midpointTo() normalises the longitude into -180..180, a bounding box that crosses ±180° wraps (crossesAntimeridian() is then true and its south-west longitude is greater than its north-east one), and a circle that reaches a pole spans every longitude. within() takes each polygon edge the shorter way round, so a polygon drawn across the antimeridian works. A polygon that encloses a pole is not supported.

## Polygon zones

Describe a zone by its vertices — the ring doesn’t need to repeat the first point:

```php
$deliveryZone = [
    new Coordinates(48.20, 17.00),
    new Coordinates(48.20, 17.20),
    new Coordinates(48.10, 17.20),
    new Coordinates(48.10, 17.00),   // no need to repeat the first vertex
];

$customer = new Coordinates(48.15, 17.11);

$customer->within($deliveryZone);   // true
```

## Bounding boxes

A BoundingBox is an axis-aligned rectangle — ideal as a cheap SQL pre-filter before an exact distance check:

```php
$box = (new Coordinates(48.1486, 17.1077))->boundingBox(radiusKm: 10);

$box->southWest;   // Coordinates — minimum latitude, western edge
$box->northEast;   // Coordinates — maximum latitude, eastern edge
$box->toArray();   // ['minLatitude' => ..., 'minLongitude' => ..., 'maxLatitude' => ..., 'maxLongitude' => ...]

// Near ±180° the box wraps: south-west longitude > north-east longitude
(new Coordinates(0.0, 179.99))->boundingBox(radiusKm: 10)->crossesAntimeridian();   // true
```

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/geolocation-for-laravel.md)
