GEOS Buffer 
What is GEOS buffer? 
The GEOS buffer function creates a new geometry that represents all points within a specified distance of the input geometry. This is useful for creating zones of influence, safety margins, or areas of interest around geometric features.
For example, creating a buffer around a point:
import GeometryOps as GO
import GeoInterface as GI
using Makie
using CairoMakie
# Create a point and buffer it
point = GI.Point(0, 0)
buffered = GO.buffer(GO.GEOS(), point, 1.0)  # 1 unit bufferGeoInterface.Wrappers.Polygon{false, false}(POLYGON ((1 0, 0.9807852804032304 -0.1950903220161282, 0.9238795325112867 -0.3826834323650898, 0.8314696123025452 -0.5555702330196022, 0.7071067811865476 -0.7071067811865475, 0.5555702330196023 -0.8314696123025452, 0.3826834323650898 -0.9238795325112867, 0.1950903220161283 -0.9807852804032304, 0 -1, -0.1950903220161282 -0.9807852804032304, -0.3826834323650897 -0.9238795325112867, -0.555570233019602 -0.8314696123025455, -0.7071067811865475 -0.7071067811865476, -0.8314696123025453 -0.5555702330196022, -0.9238795325112867 -0.3826834323650899, -0.9807852804032304 -0.1950903220161286, -1 0, -0.9807852804032304 0.1950903220161284, -0.9238795325112868 0.3826834323650897, -0.8314696123025455 0.555570233019602, -0.7071067811865477 0.7071067811865475, -0.5555702330196022 0.8314696123025452, -0.3826834323650903 0.9238795325112865, -0.1950903220161287 0.9807852804032303, 0 1, 0.1950903220161283 0.9807852804032304, 0.38268343236509 0.9238795325112866, 0.5555702330196018 0.8314696123025455, 0.7071067811865474 0.7071067811865477, 0.8314696123025452 0.5555702330196022, 0.9238795325112865 0.3826834323650904, 0.9807852804032303 0.1950903220161287, 1 0)))Implementation 
The implementation uses GEOS's bufferWithStyle function through LibGEOS.jl. It supports various buffer styles:
- Cap styles: round, flat, square 
- Join styles: round, mitre, bevel 
- Mitre limit for sharp corners 
Key features:
- Configurable number of segments for curved parts (quadsegs) 
- Support for different end cap styles 
- Customizable join styles for corners 
- Adjustable mitre limit for sharp angles 
- Preserves CRS information 
- Works with any GeoInterface-compatible geometry 
The function handles the conversion between GeometryOps and GEOS geometries automatically, and wraps the result back in a GeoInterface-compatible format.
const _GEOS_CAPSTYLE_LOOKUP = Dict{Symbol, LG.GEOSBufCapStyles}(
    :round => LG.GEOSBUF_CAP_ROUND,
    :flat => LG.GEOSBUF_CAP_FLAT,
    :square => LG.GEOSBUF_CAP_SQUARE,
)
const _GEOS_JOINSTYLE_LOOKUP = Dict{Symbol, LG.GEOSBufJoinStyles}(
    :round => LG.GEOSBUF_JOIN_ROUND,
    :mitre => LG.GEOSBUF_JOIN_MITRE,
    :bevel => LG.GEOSBUF_JOIN_BEVEL,
)
to_cap_style(style::Symbol) = _GEOS_CAPSTYLE_LOOKUP[style]
to_cap_style(style::LG.GEOSBufCapStyles) = style
to_cap_style(num::Integer) = num
to_join_style(style::Symbol) = _GEOS_JOINSTYLE_LOOKUP[style]
to_join_style(style::LG.GEOSBufJoinStyles) = style
to_join_style(num::Integer) = num
function GO.buffer(alg::GEOS, geometry, distance; calc_extent = true, kwargs...)The reason we use apply here is so that this also works with featurecollections, tables, vectors of geometries, etc!
    return apply(TraitTarget{GI.AbstractGeometryTrait}(), geometry; kwargs...) do geom
        newgeom = LG.bufferWithStyle(
            GI.convert(LG, geom), distance;
            quadsegs = get(alg, :quadsegs, 8),
            endCapStyle = to_cap_style(get(alg, :endCapStyle, :round)),
            joinStyle = to_join_style(get(alg, :joinStyle, :round)),
            mitreLimit = get(alg, :mitreLimit, 5.0),
        )
        return _wrap(newgeom; crs = GI.crs(geom), calc_extent)
    end
endThis page was generated using Literate.jl.
