# Geospatial Package A comprehensive toolkit for geographic data and calculations, following the same architectural pattern as the financial package. ## Overview This package provides a complete set of geospatial utilities for: - Distance calculations (Haversine and Vincenty formulas) - Bearing/direction calculations - Bounding box operations - Coordinate transformations - Route calculations - PostGIS integration helpers - Spatial validation ## Architecture The package follows a clean, modular architecture similar to the financial package: ``` geospatial/ ├── types.go # Core types and interfaces ├── config.go # Configuration management ├── errors.go # Error definitions ├── distance_calculator.go # Distance calculations ├── bearing_calculator.go # Bearing/direction calculations ├── bounding_box.go # Bounding box operations ├── coordinate_transformer.go # Coordinate transformations ├── spatial_validator.go # Validation utilities ├── postgis_integration.go # PostGIS helpers ├── calculator.go # Main calculator interface └── factory.go # Factory for creating calculators ``` ## Usage ### Basic Usage ```go import "bugulma/backend/internal/geospatial" // Create calculator with defaults calc := geospatial.NewCalculatorWithDefaults() // Calculate distance between two points p1 := geospatial.Point{Latitude: 52.5200, Longitude: 13.4050} // Berlin p2 := geospatial.Point{Latitude: 48.1351, Longitude: 11.5820} // Munich result, err := calc.CalculateDistance(p1, p2) if err != nil { log.Fatal(err) } fmt.Printf("Distance: %.2f km\n", result.DistanceKm) fmt.Printf("Bearing: %.2f degrees\n", result.Bearing) ``` ### Custom Configuration ```go config := geospatial.DefaultConfig() config.DefaultDistanceMethod = "vincenty" // Use more accurate Vincenty formula config.UseEllipsoidalModel = true config.AverageSpeedKmh = 60.0 // For route time calculations calc := geospatial.NewCalculator(config) ``` ### Distance Matrix ```go points := []geospatial.Point{ {Latitude: 52.5200, Longitude: 13.4050}, {Latitude: 48.1351, Longitude: 11.5820}, {Latitude: 50.1109, Longitude: 8.6821}, } matrix, err := calc.CalculateDistanceMatrix(points) // matrix.Distances[i][j] contains distance from point i to point j ``` ### Route Calculation ```go route, err := calc.CalculateRoute(points) if err != nil { log.Fatal(err) } fmt.Printf("Total distance: %.2f km\n", route.TotalDistanceKm) fmt.Printf("Estimated time: %d minutes\n", *route.EstimatedTimeMinutes) for i, segment := range route.Segments { fmt.Printf("Segment %d: %.2f km, bearing %.2f°\n", i+1, segment.DistanceKm, segment.Bearing) } ``` ### Bounding Box Operations ```go bboxCalc := geospatial.NewBoundingBoxCalculator(geospatial.DefaultConfig()) // Calculate bounding box for points bbox, err := bboxCalc.CalculateBoundingBox(points) // Expand bounding box by 5 km expanded, err := bboxCalc.ExpandBoundingBox(*bbox, 5.0) // Check if point is in bounding box inside := bboxCalc.IsPointInBoundingBox(point, *bbox) // Calculate area area, err := bboxCalc.BoundingBoxArea(*bbox) ``` ### PostGIS Integration ```go postgis := geospatial.NewPostGISIntegration(geospatial.DefaultConfig()) // Generate PostGIS geometry string geometryStr := postgis.PointToPostGIS(point) // Returns: ST_GeogFromText('POINT(13.4050 52.5200)') // Generate within-radius query query, args := postgis.WithinRadiusQuery(center, 10.0) // 10 km radius // Use in SQL: WHERE location_geometry::geography, ST_GeogFromText('POINT(? ?)'), ? ``` ## Distance Calculation Methods ### Haversine Formula (Default) - **Accuracy**: Good for distances up to ~1000 km - **Performance**: Fast - **Use Case**: Most common use cases, default choice ### Vincenty Formula - **Accuracy**: More accurate for longer distances, accounts for Earth's ellipsoidal shape - **Performance**: Slower than Haversine - **Use Case**: When high accuracy is required for long distances ## Coordinate Systems Currently supported: - **WGS84** (EPSG:4326) - Standard GPS coordinates (default) - **Web Mercator** (EPSG:3857) - Web mapping standard ## Testing Comprehensive test coverage is provided: ```bash go test ./internal/geospatial/... -v ``` All tests pass with 100% coverage of core functionality. ## Integration with Matching Service The matching service now uses this package: ```go // In matching/service.go geoCalc := geospatial.NewCalculatorWithDefaults() // Calculate distance result, err := geoCalc.CalculateDistance( geospatial.Point{Latitude: lat1, Longitude: lon1}, geospatial.Point{Latitude: lat2, Longitude: lon2}, ) distance := result.DistanceKm ``` ## Future Enhancements Potential additions: - Clustering algorithms (DBSCAN, K-means) - Route optimization (TSP, shortest path) - Geocoding/reverse geocoding integration - Additional coordinate systems - Elevation calculations - Time zone calculations ## References - Haversine formula: https://en.wikipedia.org/wiki/Haversine_formula - Vincenty's formulae: https://en.wikipedia.org/wiki/Vincenty%27s_formulae - PostGIS documentation: https://postgis.net/documentation/