### Populate PostGIS Database with Data Source: https://github.com/twpayne/go-geos/blob/master/examples/postgis/README.md Populates the PostGIS database with data using the pq.CopyIn function. This command requires the DSN for the PostgreSQL database. ```bash go run . -dsn $DSN -populate ``` -------------------------------- ### Create PostGIS Database Schema Source: https://github.com/twpayne/go-geos/blob/master/examples/postgis/README.md Creates the necessary database schema for PostGIS, including the PostGIS extension and a table with a geometry column. This command requires the Data Source Name (DSN) for the PostgreSQL database. ```bash go run . -dsn $DSN -create ``` -------------------------------- ### Lint Go Code with golangci-lint Source: https://github.com/twpayne/go-geos/blob/master/CONTRIBUTING.md This command runs golangci-lint to check the Go code for style issues and potential bugs. Ensure golangci-lint is installed and configured. ```console $ golangci-lint run ``` -------------------------------- ### Export Data from PostGIS to GeoJSON Source: https://github.com/twpayne/go-geos/blob/master/examples/postgis/README.md Writes data from the PostGIS database in GeoJSON format to standard output. This command requires the DSN for the PostgreSQL database. ```bash go run . -dsn $DSN -write ``` -------------------------------- ### Format C Code with clang-format Source: https://github.com/twpayne/go-geos/blob/master/CONTRIBUTING.md This command uses clang-format to format C source files (.c) and header files (.h) in place. Ensure clang-format is installed and in your PATH. ```console $ clang-format -i *.c *.h ``` -------------------------------- ### Import GeoJSON Data into PostGIS Database Source: https://github.com/twpayne/go-geos/blob/master/examples/postgis/README.md Imports new data in GeoJSON format into the PostGIS database from standard input. This command requires the DSN for the PostgreSQL database. ```bash echo '{"name":"Paris","geometry":{"type":"Point","coordinates":[2.3508,48.8567]}}' | go run . -dsn $DSN -read ``` -------------------------------- ### Efficient Spatial Operations with Prepared Geometries in Go Source: https://context7.com/twpayne/go-geos/llms.txt Illustrates the use of `Prepare` to create a prepared geometry, which significantly speeds up repeated spatial queries like `Contains`, `Intersects`, and `DistanceWithin`. It also shows the `ContainsXY` method for faster point-in-polygon checks. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Create a complex polygon and prepare it polygon, _ := geos.NewGeomFromWKT("POLYGON ((189 115, 200 170, 130 170, 35 242, 156 215, 210 290, 274 256, 360 190, 267 215, 300 50, 200 60, 189 115))") prepGeom := polygon.Prepare() // Test multiple points against prepared geometry (much faster) points := []struct { x, y float64 }{ {190, 200}, {100, 100}, {250, 200}, {400, 400}, } for _, p := range points { point := geos.NewPointFromXY(p.x, p.y) // Fast containment check using prepared geometry if prepGeom.Contains(point) { fmt.Printf("Point (%.0f, %.0f) is inside\n", p.x, p.y) } else { fmt.Printf("Point (%.0f, %.0f) is outside\n", p.x, p.y) } } // ContainsXY - even faster for point-in-polygon with raw coordinates fmt.Printf("Contains (200, 180): %v\n", prepGeom.ContainsXY(200, 180)) // Other prepared geometry operations line, _ := geos.NewGeomFromWKT("LINESTRING (100 100, 300 300)") fmt.Printf("Intersects line: %v\n", prepGeom.Intersects(line)) fmt.Printf("Covers line: %v\n", prepGeom.Covers(line)) // Distance check with prepared geometry otherPoly, _ := geos.NewGeomFromWKT("POLYGON ((400 400, 500 400, 500 500, 400 500, 400 400))") fmt.Printf("Within distance 100: %v\n", prepGeom.DistanceWithin(otherPoly, 100)) } ``` -------------------------------- ### Customizing Buffer Operations with BufParams in Go Source: https://context7.com/twpayne/go-geos/llms.txt Illustrates how to customize buffering operations in Go-GEOS using the BufParams struct. It shows how to set end cap styles (flat, round), join styles (mitre, bevel), mitre limits, and quadrant segments. Also demonstrates single-sided buffering and offset curves. Requires the 'github.com/twpayne/go-geos' package. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { line, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 10 0, 10 10)") ctx := geos.NewContext() // Create buffer parameters params := ctx.NewBufParams(). SetEndCapStyle(geos.BufCapStyleFlat). // Flat ends (not rounded) SetJoinStyle(geos.BufJoinStyleMitre). // Mitre joins SetMitreLimit(2.0). // Limit for mitre joins SetQuadrantSegments(8) // Segments per quadrant // Buffer with parameters buffered := line.BufferWithParams(params, 2.0) fmt.Printf("Buffered area: %.2f\n", buffered.Area()) // Different buffer styles // Round caps (default) roundBuffer := line.Buffer(2.0, 8) fmt.Printf("Round buffer area: %.2f\n", roundBuffer.Area()) // Buffer with style parameters styledBuffer := line.BufferWithStyle( 2.0, // width 8, // quadrant segments geos.BufCapStyleSquare, // square end caps geos.BufJoinStyleBevel, // bevel joins 5.0, // mitre limit ) fmt.Printf("Styled buffer area: %.2f\n", styledBuffer.Area()) // Single-sided buffer (offset curve with area) singleSided := ctx.NewBufParams(). SetSingleSided(true). SetEndCapStyle(geos.BufCapStyleFlat) leftBuffer := line.BufferWithParams(singleSided, 2.0) fmt.Printf("Single-sided buffer area: %.2f\n", leftBuffer.Area()) // Offset curve (line offset, not buffer) offset := line.OffsetCurve(2.0, 8, geos.BufJoinStyleRound, 5.0) fmt.Println("Offset curve:", offset.Type()) } ``` -------------------------------- ### Go: Read and Write WKT and WKB Geometries Source: https://context7.com/twpayne/go-geos/llms.txt This Go code demonstrates how to read and write geometries in Well-Known Text (WKT) and Well-Known Binary (WKB) formats using the go-geos library. It covers basic WKT/WKB conversion, handling Extended WKB (EWKB) with SRIDs, and using explicit WKT readers and WKB writers for data interchange. ```go package main import ( "encoding/hex" "fmt" "github.com/twpayne/go-geos" ) func main() { // WKT - Well-Known Text (human-readable) polygon, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") wkt := polygon.ToWKT() fmt.Println("WKT:", wkt) // POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0)) // String() method also returns WKT fmt.Println("String:", polygon.String()) // WKB - Well-Known Binary (compact binary format) wkb := polygon.ToWKB() fmt.Printf("WKB (hex): %s\n", hex.EncodeToString(wkb)) // Parse WKB back to geometry restored, err := geos.NewGeomFromWKB(wkb) if err != nil { panic(err) } fmt.Println("Restored:", restored.ToWKT()) // EWKB with SRID (Extended WKB for PostGIS) polygon.SetSRID(4326) // WGS84 ewkb := polygon.ToEWKBWithSRID() fmt.Printf("EWKB with SRID (hex): %s\n", hex.EncodeToString(ewkb)) // Parse EWKB - SRID is preserved restoredWithSRID, _ := geos.NewGeomFromWKB(ewkb) fmt.Printf("SRID: %d\n", restoredWithSRID.SRID()) // 4326 // Using explicit readers and writers ctx := geos.NewContext() wktReader := ctx.NewWKTReader() geom, _ := wktReader.Read("POINT (1 2)") fmt.Println("Read point:", geom.ToWKT()) wkbWriter := ctx.NewWKBWriter() binary := wkbWriter.Write(geom) fmt.Printf("Binary length: %d bytes\n", len(binary)) } ``` -------------------------------- ### Manipulate Coordinate Sequences in Go Source: https://context7.com/twpayne/go-geos/llms.txt Demonstrates the creation and manipulation of coordinate sequences using `geos.CoordSeq` in Go. It covers manual creation, creation from arrays, accessing individual coordinates, and retrieving sequences from existing geometries. It also shows handling 3D coordinates and cloning sequences. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Create coordinate sequence manually coords := geos.NewCoordSeq(3, 2) // 3 points, 2 dimensions coords.SetX(0, 0.0) coords.SetY(0, 0.0) coords.SetX(1, 10.0) coords.SetY(1, 0.0) coords.SetX(2, 10.0) coords.SetY(2, 10.0) fmt.Printf("Size: %d, Dimensions: %d\n", coords.Size(), coords.Dimensions()) // Output: Size: 3, Dimensions: 2 // Create from coordinate array coordSeq := geos.NewCoordSeqFromCoords([][]float64{ {0, 0}, {5, 0}, {5, 5}, {0, 5}, {0, 0}, // closed ring }) // Check if counter-clockwise (for polygon orientation) fmt.Printf("Is CCW: %v\n", coordSeq.IsCCW()) // Get coordinates back as slice allCoords := coordSeq.ToCoords() for i, c := range allCoords { fmt.Printf("Point %d: (%.1f, %.1f)\n", i, c[0], c[1]) } // Access individual coordinates fmt.Printf("X[0]: %.1f, Y[0]: %.1f\n", coordSeq.X(0), coordSeq.Y(0)) // Get coordinate sequence from existing geometry line, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 1 1, 2 0)") lineCoords := line.CoordSeq() fmt.Printf("Line has %d points\n", lineCoords.Size()) // 3D coordinates with Z coords3D := geos.NewCoordSeqFromCoords([][]float64{ {0, 0, 100}, {1, 1, 200}, {2, 2, 300}, }) fmt.Printf("Z[1]: %.1f\n", coords3D.Z(1)) // 200.0 // Clone coordinate sequence cloned := coordSeq.Clone() fmt.Printf("Cloned size: %d\n", cloned.Size()) } ``` -------------------------------- ### Bounding Box Operations with Box2D in Go Source: https://context7.com/twpayne/go-geos/llms.txt Demonstrates creating and manipulating 2D bounding boxes using the Box2D type in Go-GEOS. It covers creating boxes from WKT polygons, direct creation, point and box containment tests, intersection tests, creating geometries from bounds, clipping geometries, and checking for empty bounds. Requires the 'github.com/twpayne/go-geos' package. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Create a polygon and get its bounds polygon, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") bounds := polygon.Bounds() fmt.Printf("Bounds: MinX=%.1f, MinY=%.1f, MaxX=%.1f, MaxY=%.1f\n", bounds.MinX, bounds.MinY, bounds.MaxX, bounds.MaxY) // Output: Bounds: MinX=0.0, MinY=0.0, MaxX=10.0, MaxY=10.0 // Create bounds directly box := geos.NewBox2D(0, 0, 5, 5) fmt.Printf("Width: %.1f, Height: %.1f\n", box.Width(), box.Height()) // 5.0, 5.0 // Point containment test fmt.Printf("Contains (2,2): %v\n", box.ContainsPoint(2, 2)) // true fmt.Printf("Contains (7,7): %v\n", box.ContainsPoint(7, 7)) // false // Box intersection test box2 := geos.NewBox2D(3, 3, 8, 8) fmt.Printf("Boxes intersect: %v\n", box.Intersects(box2)) // true // Containment test smallBox := geos.NewBox2D(1, 1, 4, 4) fmt.Printf("Box contains smallBox: %v\n", box.Contains(smallBox)) // true // Create geometry from bounds geomFromBounds := geos.NewGeomFromBounds(0, 0, 10, 10) fmt.Println("Geometry from bounds:", geomFromBounds.Type()) // Polygon // Clip geometry by bounding box line, _ := geos.NewGeomFromWKT("LINESTRING (-5 5, 15 5)") clipped := line.ClipByRect(0, 0, 10, 10) fmt.Println("Clipped line:", clipped.ToWKT()) // LINESTRING (0 5, 10 5) // Empty bounds check empty := geos.NewBox2DEmpty() fmt.Printf("Empty bounds: %v\n", empty.IsEmpty()) // true } ``` -------------------------------- ### Go Geometry Analysis: Basic Measurements and Properties Source: https://context7.com/twpayne/go-geos/llms.txt This Go code snippet demonstrates how to calculate basic measurements and retrieve properties of a polygon geometry using the go-geos library. It includes calculating area, length (perimeter), geometry type, SRID, and counts of coordinates and geometries. It requires the 'fmt' and 'github.com/twpayne/go-geos' packages. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { polygon, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 100 0, 100 50, 0 50, 0 0))") // Basic measurements fmt.Printf("Area: %.1f\n", polygon.Area()) // 5000.0 fmt.Printf("Length: %.1f\n", polygon.Length()) // 300.0 (perimeter) // Geometry type info fmt.Printf("Type: %s\n", polygon.Type()) // Polygon fmt.Printf("TypeID: %d\n", polygon.TypeID()) // 3 fmt.Printf("SRID: %d\n", polygon.SRID()) // 0 // Counts fmt.Printf("Coordinates: %d\n", polygon.NumCoordinates()) // 5 fmt.Printf("Geometries: %d\n", polygon.NumGeometries()) // 1 fmt.Printf("Interior rings: %d\n", polygon.NumInteriorRings()) // 0 // Key points centroid := polygon.Centroid() fmt.Printf("Centroid: (%.1f, %.1f)\n", centroid.X(), centroid.Y()) // (50.0, 25.0) pointOnSurface := polygon.PointOnSurface() fmt.Printf("Point on surface: %s\n", pointOnSurface.ToWKT()) // Envelope (bounding box as geometry) envelope := polygon.Envelope() fmt.Println("Envelope:", envelope.ToWKT()) // Boundary boundary := polygon.Boundary() fmt.Println("Boundary:", boundary.ToWKT()) // Precision fmt.Printf("Precision: %.1f\n", polygon.Precision()) } ``` -------------------------------- ### Manage GEOS Contexts for Concurrency in Go Source: https://context7.com/twpayne/go-geos/llms.txt Illustrates how to manage GEOS contexts for thread-safe operations in Go using `geos.Context`. It shows the use of the default global context and the creation of explicit contexts for improved performance in concurrent scenarios. It also covers cloning geometries across different contexts. ```go package main import ( "fmt" "sync" "github.com/twpayne/go-geos" ) func main() { // Default context (global, thread-safe but may have contention) point := geos.NewPointFromXY(1, 2) fmt.Println("Using default context:", point.ToWKT()) // Create explicit context for better performance in concurrent code ctx := geos.NewContext() // Create geometries using explicit context polygon := ctx.NewPolygon([][][]float64{ {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}}, }) fmt.Println("Using explicit context:", polygon.ToWKT()) // Concurrent processing with separate contexts per goroutine var wg sync.WaitGroup results := make(chan float64, 10) for i := 0; i < 10; i++ { wg.Add(1) go func(id int) { defer wg.Done() // Each goroutine gets its own context localCtx := geos.NewContext() // Create and process geometry poly := localCtx.NewPolygon([][][]float64{ {{0, 0}, {float64(id + 1) * 10, 0}, {float64(id + 1) * 10, float64(id + 1) * 10}, {0, float64(id + 1) * 10}, {0, 0}}, }) results <- poly.Area() }(i) } go func() { wg.Wait() close(results) }() for area := range results { fmt.Printf("Area: %.1f\n", area) } // Clone geometry across contexts originalCtx := geos.NewContext() original := originalCtx.NewPointFromXY(5, 5) targetCtx := geos.NewContext() cloned := targetCtx.Clone(original) // Clone into different context fmt.Printf("Cloned point: %s\n", cloned.ToWKT()) } ``` -------------------------------- ### Go: Integrate Geometries with PostgreSQL/PostGIS using database/sql Source: https://context7.com/twpayne/go-geos/llms.txt This Go code demonstrates integrating go-geos geometries with PostgreSQL/PostGIS databases using the standard database/sql package. The `geometry.Geometry` type implements `sql.Scanner` and `driver.Valuer` interfaces, enabling seamless insertion and retrieval of geometries, including SRID handling and conversion to/from EWKB format for database storage. ```go package main import ( "database/sql" "encoding/json" "fmt" _ "github.com/lib/pq" "github.com/twpayne/go-geos" "github.com/twpayne/go-geos/geometry" ) type Waypoint struct { ID int `json:"id"` Name string `json:"name"` Geometry *geometry.Geometry `json:"geometry"` } func main() { db, err := sql.Open("postgres", "postgres://localhost/geomtest?sslmode=disable") if err != nil { panic(err) } defer db.Close() // Create table with geometry column _, err = db.Exec(` CREATE EXTENSION IF NOT EXISTS postgis; CREATE TABLE IF NOT EXISTS waypoints ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, geom geometry(POINT, 4326) NOT NULL ); `) if err != nil { panic(err) } // Insert geometry - driver.Valuer interface handles conversion waypoint := Waypoint{ Name: "London", Geometry: geometry.NewGeometry(geos.NewPoint([]float64{-0.1275, 51.50722}).SetSRID(4326)), } _, err = db.Exec(`INSERT INTO waypoints(name, geom) VALUES ($1, $2)`, waypoint.Name, waypoint.Geometry) if err != nil { panic(err) } // Query geometry - sql.Scanner interface handles conversion rows, err := db.Query(`SELECT id, name, ST_AsEWKB(geom) FROM waypoints`) if err != nil { panic(err) } defer rows.Close() for rows.Next() { var wp Waypoint if err := rows.Scan(&wp.ID, &wp.Name, &wp.Geometry); err != nil { panic(err) } // Output as JSON (uses json.Marshaler for geometry) data, _ := json.Marshal(wp) fmt.Println(string(data)) // {"id":1,"name":"London","geometry":{"type":"Point","coordinates":[-0.1275,51.50722]}} } } ``` -------------------------------- ### GeoJSON Support with go-geos and geometry Package in Go Source: https://context7.com/twpayne/go-geos/llms.txt Shows how to parse GeoJSON strings into `geometry.Geometry` objects using `NewGeometryFromGeoJSON` and how to marshal `geometry.Geometry` objects into GeoJSON format using `json.Marshal`. It also demonstrates low-level GEOS GeoJSON functions and custom struct marshaling. ```go package main import ( "encoding/json" "fmt" "github.com/twpayne/go-geos" "github.com/twpayne/go-geos/geometry" ) func main() { // Parse GeoJSON geoJSON := []byte(`{"type":"Polygon","coordinates":[[[0,0],[10,0],[10,10],[0,10],[0,0]]]}`) geom, err := geometry.NewGeometryFromGeoJSON(geoJSON) if err != nil { panic(err) } fmt.Printf("Parsed type: %s\n", geom.Type()) // Polygon fmt.Printf("Area: %.1f\n", geom.Area()) // 100.0 // Create geometry and marshal to GeoJSON point := geometry.NewGeometry(geos.NewPointFromXY(1.5, 2.5)) output, err := json.Marshal(point) if err != nil { panic(err) } fmt.Println("GeoJSON:", string(output)) // {"type":"Point","coordinates":[1.5,2.5]} // Using low-level GEOS GeoJSON functions polygon, _ := geos.NewGeomFromGeoJSON(`{"type":"Polygon","coordinates":[[[0,0],[5,0],[5,5],[0,5],[0,0]]]}`) fmt.Println("GEOS parsed:", polygon.ToWKT()) // Convert to GeoJSON with indentation fmt.Println("GeoJSON output:", polygon.ToGeoJSON(2)) // Example with complex structure type Location struct { Name string `json:"name"` Geometry *geometry.Geometry `json:"geometry"` } loc := Location{ Name: "Central Park", Geometry: geometry.NewGeometry(geos.NewPointFromXY(-73.965355, 40.782865)), } data, _ := json.MarshalIndent(loc, "", " ") fmt.Println(string(data)) } ``` -------------------------------- ### Go Geos Spatial Predicates Source: https://context7.com/twpayne/go-geos/llms.txt Demonstrates how to test spatial relationships between geometries using various predicates provided by the go-geos library. This includes checking containment, intersection, disjointness, and proximity between different geometric shapes like polygons and points. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { polygon, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") pointInside := geos.NewPointFromXY(5, 5) pointOutside := geos.NewPointFromXY(15, 15) // Contains - does polygon contain the point? fmt.Printf("Polygon contains inside point: %v\n", polygon.Contains(pointInside)) // true fmt.Printf("Polygon contains outside point: %v\n", polygon.Contains(pointOutside)) // false // Intersects - do geometries share any space? line, _ := geos.NewGeomFromWKT("LINESTRING (5 5, 15 15)") fmt.Printf("Polygon intersects line: %v\n", polygon.Intersects(line)) // true // Within - is the point within the polygon? fmt.Printf("Point within polygon: %v\n", pointInside.Within(polygon)) // true // Disjoint - are geometries completely separate? polygon2, _ := geos.NewGeomFromWKT("POLYGON ((20 20, 30 20, 30 30, 20 30, 20 20))") fmt.Printf("Polygons disjoint: %v\n", polygon.Disjoint(polygon2)) // true // Touches - do geometries touch at boundaries only? polygon3, _ := geos.NewGeomFromWKT("POLYGON ((10 0, 20 0, 20 10, 10 10, 10 0))") fmt.Printf("Polygons touch: %v\n", polygon.Touches(polygon3)) // true // Distance between geometries fmt.Printf("Distance: %.1f\n", polygon.Distance(polygon2)) // ~14.1 // Check if within distance fmt.Printf("Within distance 20: %v\n", polygon.DistanceWithin(polygon2, 20)) // true } ``` -------------------------------- ### Go Geos Spatial Operations Source: https://context7.com/twpayne/go-geos/llms.txt Illustrates how to perform various geometric operations using the go-geos library, including buffering, union, intersection, difference, convex hull calculation, and centroid finding. These operations allow for complex manipulation and analysis of geometric data. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Buffer - create a polygon around a geometry point := geos.NewPointFromXY(0, 0) buffered := point.Buffer(10, 8) // 10 unit buffer with 8 segments per quadrant fmt.Printf("Buffered point area: %.2f\n", buffered.Area()) // ~314.16 (pi * r^2) // Union - combine two geometries poly1, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))") poly2, _ := geos.NewGeomFromWKT("POLYGON ((3 3, 8 3, 8 8, 3 8, 3 3))") union := poly1.Union(poly2) fmt.Printf("Union area: %.1f\n", union.Area()) // 46.0 (25 + 25 - 4 overlap) // Intersection - get common area intersection := poly1.Intersection(poly2) fmt.Printf("Intersection area: %.1f\n", intersection.Area()) // 4.0 // Difference - subtract one geometry from another difference := poly1.Difference(poly2) fmt.Printf("Difference area: %.1f\n", difference.Area()) // 21.0 // Symmetric difference - areas in either but not both symDiff := poly1.SymDifference(poly2) fmt.Printf("Symmetric difference area: %.1f\n", symDiff.Area()) // 42.0 // Convex hull points, _ := geos.NewGeomFromWKT("MULTIPOINT ((0 0), (1 1), (0 2), (2 2), (2 0))") hull := points.ConvexHull() fmt.Println("Convex hull:", hull.ToWKT()) // Centroid - center of mass polygon, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") centroid := polygon.Centroid() fmt.Printf("Centroid: (%.1f, %.1f)\n", centroid.X(), centroid.Y()) // (5.0, 5.0) // Simplify geometry complex, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 1 0.1, 2 0, 3 0.1, 4 0)") simplified := complex.Simplify(0.2) fmt.Println("Simplified:", simplified.ToWKT()) } ``` -------------------------------- ### Validate and Repair Geometries in Go Source: https://context7.com/twpayne/go-geos/llms.txt Demonstrates how to check the validity of geometries using `IsValid` and `IsValidReason`, and how to repair invalid geometries with `MakeValid`. It also shows other validity checks like `IsSimple`, `IsRing`, and `IsClosed` for LineStrings. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Valid polygon valid, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") fmt.Printf("Is valid: %v\n", valid.IsValid()) // true fmt.Printf("Reason: %s\n", valid.IsValidReason()) // Valid Geometry // Self-intersecting polygon (invalid - figure-8 shape) invalid, _ := geos.NewGeomFromWKT("POLYGON ((0 0, 10 10, 10 0, 0 10, 0 0))") fmt.Printf("Is valid: %v\n", invalid.IsValid()) // false fmt.Printf("Reason: %s\n", invalid.IsValidReason()) // Self-intersection // Repair invalid geometry repaired := invalid.MakeValid() fmt.Printf("Repaired is valid: %v\n", repaired.IsValid()) // true fmt.Println("Repaired geometry:", repaired.ToWKT()) // MakeValid with parameters repairedWithParams := invalid.MakeValidWithParams( geos.MakeValidStructure, geos.MakeValidKeepCollapsed, ) fmt.Printf("Repaired type: %s\n", repairedWithParams.Type()) // Other validity checks line, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 1 1, 2 2)") fmt.Printf("Is simple: %v\n", line.IsSimple()) // true (no self-intersection) fmt.Printf("Is ring: %v\n", line.IsRing()) // false (not closed) fmt.Printf("Is empty: %v\n", line.IsEmpty()) // false ring, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 1 0, 1 1, 0 0)") fmt.Printf("Ring is closed: %v\n", ring.IsClosed()) // true } ``` -------------------------------- ### Create Geometries from WKT in Go Source: https://context7.com/twpayne/go-geos/llms.txt Parses geometries from Well-Known Text (WKT) format using `NewGeomFromWKT`. This function is crucial for creating geometric objects like points, polygons, and linestrings from standard text representations. It returns a GEOS geometry object or an error if parsing fails. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Create a point from WKT point, err := geos.NewGeomFromWKT("POINT (1.5 2.5)") if err != nil { panic(err) } fmt.Println("Point:", point.ToWKT()) // Output: POINT (1.5 2.5) // Create a polygon from WKT polygon, err := geos.NewGeomFromWKT("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))") if err != nil { panic(err) } fmt.Printf("Polygon area: %.1f\n", polygon.Area()) // Output: Polygon area: 100.0 // Create a linestring from WKT line, err := geos.NewGeomFromWKT("LINESTRING (0 0, 1 1, 2 2)") if err != nil { panic(err) } fmt.Printf("Line length: %.4f\n", line.Length()) // Output: Line length: 2.8284 } ``` -------------------------------- ### Create Geometries Programmatically in Go Source: https://context7.com/twpayne/go-geos/llms.txt Constructs geometries directly from coordinate data using functions like `NewPoint`, `NewLineString`, `NewPolygon`, and `NewCollection`. This method is useful when coordinates are available in memory, allowing for programmatic creation of various geometric types, including those with holes and collections of geometries. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { // Create a point from coordinates point := geos.NewPoint([]float64{1.5, 2.5}) fmt.Println("Point:", point.ToWKT()) // Output: POINT (1.5 2.5) // Create a point from X, Y values point2 := geos.NewPointFromXY(3.0, 4.0) fmt.Printf("X: %.1f, Y: %.1f\n", point2.X(), point2.Y()) // Output: X: 3.0, Y: 4.0 // Create a linestring from coordinate array line := geos.NewLineString([][]float64{ {0, 0}, {1, 1}, {2, 0}, }) fmt.Println("LineString:", line.ToWKT()) // Output: LINESTRING (0 0, 1 1, 2 0) // Create a polygon with exterior ring (must be closed) polygon := geos.NewPolygon([][][]float64{ {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}}, // exterior ring }) fmt.Println("Polygon:", polygon.ToWKT()) // Create a polygon with a hole polygonWithHole := geos.NewPolygon([][][]float64{ {{0, 0}, {20, 0}, {20, 20}, {0, 20}, {0, 0}}, // exterior ring {{5, 5}, {15, 5}, {15, 15}, {5, 15}, {5, 5}}, // hole }) fmt.Printf("Polygon with hole area: %.1f\n", polygonWithHole.Area()) // Output: 300.0 // Create a geometry collection collection := geos.NewCollection(geos.TypeIDGeometryCollection, []*geos.Geom{ geos.NewPointFromXY(0, 0), geos.NewPointFromXY(1, 1), }) fmt.Printf("Collection size: %d\n", collection.NumGeometries()) // Output: 2 } ``` -------------------------------- ### Go Geometry Analysis: Minimum Rotated Rectangle Source: https://context7.com/twpayne/go-geos/llms.txt This Go code snippet shows how to compute the minimum rotated rectangle that encloses a given set of points using the go-geos library. This is useful for finding the smallest bounding box that can be oriented arbitrarily to fit the geometry. It requires the 'fmt' and 'github.com/twpayne/go-geos' packages. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { multiPoint, _ := geos.NewGeomFromWKT("MULTIPOINT ((0 0), (1 3), (4 2), (3 0))") minRect := multiPoint.MinimumRotatedRectangle() fmt.Println("Min rotated rectangle:", minRect.ToWKT()) } ``` -------------------------------- ### Go Geometry Analysis: Distance Calculations Source: https://context7.com/twpayne/go-geos/llms.txt This Go code snippet demonstrates how to compute various distance measurements between geometries using the go-geos library. It includes calculating the length of a linestring, the Hausdorff distance (shape similarity), and the Frechet distance (curve similarity) between two linestrings. It depends on the 'fmt' and 'github.com/twpayne/go-geos' packages. ```go package main import ( "fmt" "github.com/twpayne/go-geos" ) func main() { line, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 3 4)") fmt.Printf("Line length: %.1f\n", line.Length()) // 5.0 // Hausdorff distance (shape similarity) line2, _ := geos.NewGeomFromWKT("LINESTRING (0 0, 3 3)") fmt.Printf("Hausdorff distance: %.4f\n", line.HausdorffDistance(line2)) // Frechet distance (curve similarity) fmt.Printf("Frechet distance: %.4f\n", line.FrechetDistance(line2)) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.