Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Geo Laravel Package

brick/geo

brick/geo is a PHP geometry library for working with points, lines, polygons, and other shapes. Provides common spatial operations, parsing/formatting, and robust value objects to model geo data cleanly in applications and services.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require brick/geo
    

    Add to composer.json if using a monorepo or constrained environment:

    "require": {
        "brick/geo": "^2.0"
    }
    
  2. Basic Usage Create a point in the simplest form:

    use Brick\Geo\Point;
    
    $point = Point::fromDegrees(40.7128, -74.0060); // NYC coordinates
    echo $point; // "POINT (40.7128 -74.0060)"
    
  3. Key Classes to Explore

    • Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon
    • GeometryCollection
    • Circle (for radius-based queries)
  4. First Use Case: Distance Calculation

    $pointA = Point::fromDegrees(40.7128, -74.0060);
    $pointB = Point::fromDegrees(34.0522, -118.2437); // LA
    $distance = $pointA->distance($pointB); // Returns distance in meters
    

Implementation Patterns

Core Workflows

1. Coordinate Conversion

  • Degrees ↔ Radians
    $point = Point::fromDegrees(40.7128, -74.0060);
    $radians = $point->toRadians();
    
  • WGS84 ↔ UTM
    use Brick\Geo\Coordinate\Coordinate;
    $utm = $point->toUtm(); // Returns UTM zone and coordinates
    

2. Geometry Operations

  • Buffering (Creating a Polygon Around a Point)
    $buffered = $point->buffer(1000); // 1km radius polygon
    
  • Intersection/Union
    $polygon1 = Polygon::fromPoints([...]);
    $polygon2 = Polygon::fromPoints([...]);
    $intersection = $polygon1->intersection($polygon2);
    
  • Contains/Within
    if ($polygon->contains($point)) { ... }
    if ($point->within($polygon)) { ... }
    

3. Geohashing

  • Generate a geohash for a point:
    $geohash = $point->geohash(); // e.g., "dr5reg"
    
  • Reverse geohash to bounds:
    $bounds = Geohash::bounds("dr5reg");
    

4. Projections

  • Convert between coordinate systems (e.g., WGS84 ↔ Web Mercator):
    $webMercator = $point->toWebMercator();
    

Integration Tips

Database Integration (PostGIS)

  • Storing Geometries Use ST_GeomFromText in PostgreSQL with the geometry column type:
    $geometry = $polygon->toText(); // "POLYGON ((...))"
    DB::table('locations')->insert(['geom' => $geometry]);
    
  • Querying Geometries
    $results = DB::table('locations')
        ->whereRaw('ST_Contains(geom, ST_GeomFromText(?))', [$point->toText()])
        ->get();
    

API Responses

  • Serialize geometries to GeoJSON:
    $geoJson = $polygon->toGeoJson();
    return response()->json(['geometry' => $geoJson]);
    

Caching Geometries

  • Cache complex geometries (e.g., polygons) to avoid recomputation:
    $cachedPolygon = Cache::remember("polygon_{$key}", now()->addHours(1), function () {
        return $this->buildComplexPolygon();
    });
    

Batch Processing

  • Use GeometryCollection for bulk operations:
    $collection = GeometryCollection::fromGeometries([$point1, $line1, $polygon1]);
    $totalLength = $collection->totalLength(); // Sum of all lengths
    

Gotchas and Tips

Pitfalls

1. Precision Issues

  • Floating-point inaccuracies can cause contains() checks to fail. Use a small epsilon for comparisons:
    if ($polygon->contains($point, 0.00001)) { ... }
    
  • Prefer within() for point-in-polygon checks when precision is critical.

2. Coordinate Order Matters

  • Polygons must have coordinates ordered clockwise or counter-clockwise (use Polygon::fromPoints() carefully).
  • Use Polygon::isValid() to check:
    if (!$polygon->isValid()) {
        $polygon = $polygon->buffer(0); // Fix invalid polygons
    }
    

3. UTM Zone Ambiguity

  • Points near UTM zone boundaries (e.g., ±180° longitude) may throw exceptions. Handle with:
    try {
        $utm = $point->toUtm();
    } catch (InvalidArgumentException $e) {
        // Fallback to a nearby zone or use degrees
    }
    

4. GeoJSON vs. WKT

  • toGeoJson() and toText() (WKT) may produce different representations. Validate output:
    $wkt = $polygon->toText();
    $geoJson = $polygon->toGeoJson();
    assert($wkt !== $geoJson); // Expected: formats differ
    

5. Performance with Large Datasets

  • Avoid loading entire MultiPolygon collections into memory. Use spatial indexes (e.g., PostGIS) for filtering first.

Debugging Tips

1. Visualizing Geometries

  • Use GeoJSON.io to validate geometries:
    $geoJson = $geometry->toGeoJson();
    file_put_contents('debug.json', json_encode($geoJson));
    
  • For quick CLI checks:
    echo $polygon->toText() . "\n";
    

2. Logging Geometry Operations

  • Log WKT representations for debugging:
    \Log::debug('Polygon WKT:', ['wkt' => $polygon->toText()]);
    

3. Common Exceptions

  • InvalidArgumentException: Invalid coordinates (e.g., latitude > 90°).
  • RuntimeException: Unsupported operations (e.g., buffering a LineString).

Extension Points

1. Custom Projections

  • Extend Projection for niche use cases:
    class CustomProjection extends Projection {
        public function forward(Coordinate $coordinate): Coordinate { ... }
        public function inverse(Coordinate $coordinate): Coordinate { ... }
    }
    

2. Geometry Factories

  • Create domain-specific factories:
    class CityBoundaryFactory {
        public static function createFromZipCodes(array $zipCodes): Polygon { ... }
    }
    

3. Spatial Indexing

  • Integrate with libraries like PHP-Spatial for advanced indexing:
    $index = new RTree();
    $index->insert($polygon, $polygon->getBounds());
    

4. Event Listeners for Geometry Changes

  • Use traits to track modifications:
    trait LogsGeometryChanges {
        private $originalWkt;
    
        public function __construct() {
            $this->originalWkt = $this->toText();
        }
    
        public function modified(): bool {
            return $this->toText() !== $this->originalWkt;
        }
    }
    

5. Serialization Hooks

  • Override toArray() for custom serialization:
    class CustomPoint extends Point {
        public function toArray(): array {
            return [
                'latitude' => $this->latitude->degrees,
                'longitude' => $this->longitude->degrees,
                'altitude' => $this->altitude?->degrees,
            ];
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky