Skill Tracer
Skills › Scientific Agent Skills › geomaster › programming-languages.md

programming-languages.md

424 lines · skills/geomaster/references/programming-languages.md at 5f2bc03

Open on GitHub
1# Multi-Language Geospatial Programming
2
3Geospatial programming across R, Julia, JavaScript, C++, Java, Go, Rust and Python.
4Reviewed 2026-10-01 against upstream sources listed below. These are illustrative
5language-specific fragments, not compiled/executed cross-language coverage. Python
6runtime coverage is recorded separately in [review.md](review.md).
7

Multi-Language Geospatial Programming

Geospatial programming across R, Julia, JavaScript, C++, Java, Go, Rust and Python. Reviewed 2026-10-01 against upstream sources listed below. These are illustrative language-specific fragments, not compiled/executed cross-language coverage. Python runtime coverage is recorded separately in review.md.

Raw lines 1 to 7
8## R Geospatial
9

R Geospatial

Raw lines 8 to 9
10### sf (Simple Features)
12```r
13library(sf)
14library(dplyr)
15library(ggplot2)
17# Read spatial data
18roads <- st_read("roads.shp")
19zones <- st_read("zones.geojson")
21# Basic operations
22st_crs(roads) # Check CRS
23roads_utm <- st_transform(roads, 32610) # Reproject
25# Geometric operations
26roads_buffer <- st_buffer(roads_utm, dist = 100) # Buffer
27roads_simplify <- st_simplify(roads_utm, dTolerance = 1) # Simplify
28roads_centroid <- st_centroid(roads) # Centroid
30# Spatial joins
31joined <- st_join(roads, zones, join = st_intersects)
33# Overlay
34intersection <- st_intersection(roads, zones)
36# Plot
37ggplot() +
38 geom_sf(data = zones, fill = NA) +
39 geom_sf(data = roads, color = "blue") +
40 theme_minimal()
42# Calculate area
43zones$area <- st_area(zones) # sf returns units; geographic data can use geodesic/S2 area
44zones$area_km2 <- units::set_units(st_area(zones), km^2) # Convert to km2
45```

sf (Simple Features)

library(sf)
library(dplyr)
library(ggplot2)

# Read spatial data
roads <- st_read("roads.shp")
zones <- st_read("zones.geojson")

# Basic operations
st_crs(roads)  # Check CRS
roads_utm <- st_transform(roads, 32610)  # Reproject

# Geometric operations
roads_buffer <- st_buffer(roads_utm, dist = 100)  # Buffer
roads_simplify <- st_simplify(roads_utm, dTolerance = 1)  # Simplify
roads_centroid <- st_centroid(roads)  # Centroid

# Spatial joins
joined <- st_join(roads, zones, join = st_intersects)

# Overlay
intersection <- st_intersection(roads, zones)

# Plot
ggplot() +
  geom_sf(data = zones, fill = NA) +
  geom_sf(data = roads, color = "blue") +
  theme_minimal()

# Calculate area
zones$area <- st_area(zones)  # sf returns units; geographic data can use geodesic/S2 area
zones$area_km2 <- units::set_units(st_area(zones), km^2)  # Convert to km2
Raw lines 10 to 46
47### terra (Raster Processing)
49```r
50library(terra)
52# Load raster
53r <- rast("elevation.tif")
55# Basic info
57ext(r) # Extent
58crs(r) # CRS
59res(r) # Resolution
61# Raster calculations
62slope <- terrain(r, v = "slope")
63aspect <- terrain(r, v = "aspect")
65# Multi-raster operations
66ndvi <- (nir - red) / (nir + red) # named, aligned, masked reflectance SpatRasters
68# Focal operations
69focal_mean <- focal(r, w = matrix(1, 3, 3), fun = mean)
70focal_sd <- focal(r, w = matrix(1, 5, 5), fun = sd)
72# Zonal statistics
73zones <- vect("zones.shp")
74zonal_mean <- extract(r, zones, fun = mean, na.rm = TRUE)
76# Extract values at points
77points <- vect("points.shp")
78values <- extract(r, points)
80# Write output
81writeRaster(slope, "slope.tif", overwrite = TRUE)
82```

terra (Raster Processing)

library(terra)

# Load raster
r <- rast("elevation.tif")

# Basic info
r
ext(r)  # Extent
crs(r)  # CRS
res(r)  # Resolution

# Raster calculations
slope <- terrain(r, v = "slope")
aspect <- terrain(r, v = "aspect")

# Multi-raster operations
ndvi <- (nir - red) / (nir + red)  # named, aligned, masked reflectance SpatRasters

# Focal operations
focal_mean <- focal(r, w = matrix(1, 3, 3), fun = mean)
focal_sd <- focal(r, w = matrix(1, 5, 5), fun = sd)

# Zonal statistics
zones <- vect("zones.shp")
zonal_mean <- extract(r, zones, fun = mean, na.rm = TRUE)

# Extract values at points
points <- vect("points.shp")
values <- extract(r, points)

# Write output
writeRaster(slope, "slope.tif", overwrite = TRUE)
Raw lines 47 to 83
84### R Workflows
86```r
87# Complete land cover classification
88library(sf)
89library(terra)
90library(randomForest)
91library(caret)
93# 1. Load data
94training <- st_read("training.shp")
95s2 <- rast("sentinel2.tif")
97# 2. Extract training data
98training_points <- st_centroid(training)
99training_points <- st_transform(training_points, crs(s2))
100values <- extract(s2, vect(training_points), ID = FALSE)
102# 3. Combine with labels
103df <- data.frame(values)
104df$class <- as.factor(training$class_id)
106# 4. Train model
107set.seed(42)
108# Use independently assigned spatial folds from the training table.
109train_index <- which(training$fold != "holdout")
110train_data <- df[train_index, ]
111test_data <- df[-train_index, ]
113rf_model <- randomForest(class ~ ., data = train_data, ntree = 100)
115# 5. Predict
116predicted <- predict(s2, model = rf_model)
118# 6. Accuracy
119conf_matrix <- confusionMatrix(predict(rf_model, test_data), test_data$class)
120print(conf_matrix)
122# 7. Export
123writeRaster(predicted, "classified.tif", overwrite = TRUE)
124```

R Workflows

# Complete land cover classification
library(sf)
library(terra)
library(randomForest)
library(caret)

# 1. Load data
training <- st_read("training.shp")
s2 <- rast("sentinel2.tif")

# 2. Extract training data
training_points <- st_centroid(training)
training_points <- st_transform(training_points, crs(s2))
values <- extract(s2, vect(training_points), ID = FALSE)

# 3. Combine with labels
df <- data.frame(values)
df$class <- as.factor(training$class_id)

# 4. Train model
set.seed(42)
# Use independently assigned spatial folds from the training table.
train_index <- which(training$fold != "holdout")
train_data <- df[train_index, ]
test_data <- df[-train_index, ]

rf_model <- randomForest(class ~ ., data = train_data, ntree = 100)

# 5. Predict
predicted <- predict(s2, model = rf_model)

# 6. Accuracy
conf_matrix <- confusionMatrix(predict(rf_model, test_data), test_data$class)
print(conf_matrix)

# 7. Export
writeRaster(predicted, "classified.tif", overwrite = TRUE)
Raw lines 84 to 125
126## Julia Geospatial

Julia Geospatial

Raw lines 126 to 127
128### ArchGDAL.jl
130```julia
131using ArchGDAL
133# Work inside the dataset lifetime; do not return borrowed feature geometries.
134ArchGDAL.read("countries.shp") do dataset
135 layer = ArchGDAL.getlayer(dataset, 0)
136 for feature in layer
137 geometry = ArchGDAL.getgeom(feature)
138 println(ArchGDAL.toWKT(geometry))
139 end
140end
142# Synthetic planar coordinates in chosen map units:
143point = ArchGDAL.createpoint(0.0, 0.0)
144buffered = ArchGDAL.buffer(point, 100.0)
145```
147GeoInterface defines interfaces; it is not a general constructor/geometry-operation
148namespace. Use an actual geometry backend. Clone borrowed geometries if they must
149outlive their owning dataset/feature.

ArchGDAL.jl

using ArchGDAL

# Work inside the dataset lifetime; do not return borrowed feature geometries.
ArchGDAL.read("countries.shp") do dataset
    layer = ArchGDAL.getlayer(dataset, 0)
    for feature in layer
        geometry = ArchGDAL.getgeom(feature)
        println(ArchGDAL.toWKT(geometry))
    end
end

# Synthetic planar coordinates in chosen map units:
point = ArchGDAL.createpoint(0.0, 0.0)
buffered = ArchGDAL.buffer(point, 100.0)

GeoInterface defines interfaces; it is not a general constructor/geometry-operation namespace. Use an actual geometry backend. Clone borrowed geometries if they must outlive their owning dataset/feature.

Raw lines 128 to 150
151### GeoStats.jl
153```julia
154using GeoStats
155samples = georef((; value=[1., 2., 1.5]), [(0., 0.), (10., 0.), (5., 10.)])
156grid = CartesianGrid(10, 10)
157result = samples |> Interpolate(grid, model=Kriging(GaussianVariogram(range=10.)))
158```
160Current GeoStats uses interpolation transforms, not the former `SimulationProblem`
161and `solve(OrdinaryKriging(...))` sketches. This uses synthetic Cartesian coordinates
162and a chosen variogram, not a fitted geostatistical model. Fit/check an empirical
163variogram, validate spatially and define units/support before a scientific result.

GeoStats.jl

using GeoStats
samples = georef((; value=[1., 2., 1.5]), [(0., 0.), (10., 0.), (5., 10.)])
grid = CartesianGrid(10, 10)
result = samples |> Interpolate(grid, model=Kriging(GaussianVariogram(range=10.)))

Current GeoStats uses interpolation transforms, not the former SimulationProblem and solve(OrdinaryKriging(...)) sketches. This uses synthetic Cartesian coordinates and a chosen variogram, not a fitted geostatistical model. Fit/check an empirical variogram, validate spatially and define units/support before a scientific result.

Raw lines 151 to 164
165## JavaScript (Node.js & Browser)

JavaScript (Node.js & Browser)

Raw lines 165 to 166
167### Turf.js (Browser/Node)
169```javascript
170// npm install @turf/turf
171const turf = require('@turf/turf');
173// Create features
174const pt1 = turf.point([-122.4, 37.7]);
175const pt2 = turf.point([-122.3, 37.8]);
177// Distance (in kilometers)
178const distance = turf.distance(pt1, pt2, { units: 'kilometers' });
180// Buffer
181const buffered = turf.buffer(pt1, 5, { units: 'kilometers' });
183// Bounding box
184const bbox = turf.bbox(buffered);
186// Along a line
187const line = turf.lineString([[-122.4, 37.7], [-122.3, 37.8]]);
188const along = turf.along(line, 2, { units: 'kilometers' });
190// Within
191const points = turf.points([
192 [-122.4, 37.7],
193 [-122.35, 37.75],
194 [-122.3, 37.8]
195]);
196const polygon = turf.polygon([[[-122.4, 37.7], [-122.3, 37.7], [-122.3, 37.8], [-122.4, 37.8], [-122.4, 37.7]]]);
197const ptsWithin = turf.pointsWithinPolygon(points, polygon);
199// Nearest point
200const nearest = turf.nearestPoint(pt1, points);
202// Area
203const area = turf.area(polygon); // square meters
205```

Turf.js (Browser/Node)

// npm install @turf/turf
const turf = require('@turf/turf');

// Create features
const pt1 = turf.point([-122.4, 37.7]);
const pt2 = turf.point([-122.3, 37.8]);

// Distance (in kilometers)
const distance = turf.distance(pt1, pt2, { units: 'kilometers' });

// Buffer
const buffered = turf.buffer(pt1, 5, { units: 'kilometers' });

// Bounding box
const bbox = turf.bbox(buffered);

// Along a line
const line = turf.lineString([[-122.4, 37.7], [-122.3, 37.8]]);
const along = turf.along(line, 2, { units: 'kilometers' });

// Within
const points = turf.points([
  [-122.4, 37.7],
  [-122.35, 37.75],
  [-122.3, 37.8]
]);
const polygon = turf.polygon([[[-122.4, 37.7], [-122.3, 37.7], [-122.3, 37.8], [-122.4, 37.8], [-122.4, 37.7]]]);
const ptsWithin = turf.pointsWithinPolygon(points, polygon);

// Nearest point
const nearest = turf.nearestPoint(pt1, points);

// Area
const area = turf.area(polygon); // square meters
Raw lines 167 to 206
207### Leaflet (Web Mapping)
209```javascript
210// Initialize map
211const map = L.map('map').setView([37.7, -122.4], 13);
213// Add tile layer
214L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
215 attribution: '© OpenStreetMap contributors'
216}).addTo(map);
218// Add GeoJSON layer
219fetch('data.geojson')
220 .then(response => response.json())
221 .then(data => {
222 L.geoJSON(data, {
223 style: function(feature) {
224 return { color: feature.properties.color };
225 },
226 onEachFeature: function(feature, layer) {
227 const label = document.createElement('span');
228 label.textContent = String(feature.properties.name ?? '');
229 layer.bindPopup(label);
230 }
231 }).addTo(map);
232 });
234// Add markers
235const marker = L.marker([37.7, -122.4]).addTo(map);
236marker.bindPopup("Hello!").openPopup();
238// Draw circles
239const circle = L.circle([37.7, -122.4], {
240 color: 'red',
241 fillColor: '#f03',
242 fillOpacity: 0.5,
243 radius: 500
244}).addTo(map);
245```

Leaflet (Web Mapping)

// Initialize map
const map = L.map('map').setView([37.7, -122.4], 13);

// Add tile layer
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap contributors'
}).addTo(map);

// Add GeoJSON layer
fetch('data.geojson')
  .then(response => response.json())
  .then(data => {
    L.geoJSON(data, {
      style: function(feature) {
        return { color: feature.properties.color };
      },
      onEachFeature: function(feature, layer) {
        const label = document.createElement('span');
        label.textContent = String(feature.properties.name ?? '');
        layer.bindPopup(label);
      }
    }).addTo(map);
  });

// Add markers
const marker = L.marker([37.7, -122.4]).addTo(map);
marker.bindPopup("Hello!").openPopup();

// Draw circles
const circle = L.circle([37.7, -122.4], {
  color: 'red',
  fillColor: '#f03',
  fillOpacity: 0.5,
  radius: 500
}).addTo(map);
Raw lines 207 to 246
247## C++ Geospatial

C++ Geospatial

Raw lines 247 to 248
249### GDAL C++ API
251```cpp
252#include "gdal_priv.h"
253#include "ogr_api.h"
254#include "ogr_spatialref.h"
255#include "ogrsf_frmts.h"
256#include <stdexcept>
258// Inside an application entry point, after GDALAllRegister():
259// Open raster
260GDALDataset *poDataset = (GDALDataset *) GDALOpen("input.tif", GA_ReadOnly);
262if (poDataset == nullptr) throw std::runtime_error("Raster open failed");
263// Get band
264GDALRasterBand *poBand = poDataset->GetRasterBand(1);
266// Read data
267int nXSize = poBand->GetXSize();
268int nYSize = poBand->GetYSize();
269float *pafScanline = (float *) CPLMalloc(sizeof(float) * nXSize);
270CPLErr read_status = poBand->RasterIO(GF_Read, 0, 0, nXSize, 1,
271 pafScanline, nXSize, 1, GDT_Float32, 0, 0);
272// Check read_status != CE_None and handle I/O errors before using values.
274CPLFree(pafScanline);
275GDALClose(poDataset);
277// Vector data
278GDALDataset *poDS = (GDALDataset *) GDALOpenEx("roads.shp",
279 GDAL_OF_VECTOR, NULL, NULL, NULL);
280if (poDS == nullptr) throw std::runtime_error("Vector open failed");
281OGRLayer *poLayer = poDS->GetLayer(0);
283OGRFeature *poFeature;
284poLayer->ResetReading();
285while ((poFeature = poLayer->GetNextFeature()) != NULL) {
286 OGRGeometry *poGeometry = poFeature->GetGeometryRef();
287 // Process geometry
288 OGRFeature::DestroyFeature(poFeature);
291GDALClose(poDS);
292```

GDAL C++ API

#include "gdal_priv.h"
#include "ogr_api.h"
#include "ogr_spatialref.h"
#include "ogrsf_frmts.h"
#include <stdexcept>

// Inside an application entry point, after GDALAllRegister():
// Open raster
GDALDataset *poDataset = (GDALDataset *) GDALOpen("input.tif", GA_ReadOnly);

if (poDataset == nullptr) throw std::runtime_error("Raster open failed");
// Get band
GDALRasterBand *poBand = poDataset->GetRasterBand(1);

// Read data
int nXSize = poBand->GetXSize();
int nYSize = poBand->GetYSize();
float *pafScanline = (float *) CPLMalloc(sizeof(float) * nXSize);
CPLErr read_status = poBand->RasterIO(GF_Read, 0, 0, nXSize, 1,
                 pafScanline, nXSize, 1, GDT_Float32, 0, 0);
// Check read_status != CE_None and handle I/O errors before using values.

CPLFree(pafScanline);
GDALClose(poDataset);

// Vector data
GDALDataset *poDS = (GDALDataset *) GDALOpenEx("roads.shp",
    GDAL_OF_VECTOR, NULL, NULL, NULL);
if (poDS == nullptr) throw std::runtime_error("Vector open failed");
OGRLayer *poLayer = poDS->GetLayer(0);

OGRFeature *poFeature;
poLayer->ResetReading();
while ((poFeature = poLayer->GetNextFeature()) != NULL) {
    OGRGeometry *poGeometry = poFeature->GetGeometryRef();
    // Process geometry
    OGRFeature::DestroyFeature(poFeature);
}

GDALClose(poDS);
Raw lines 249 to 293
294## Java Geospatial

Java Geospatial

Raw lines 294 to 295
296### GeoTools
298```java
299import org.geotools.api.data.FileDataStore;
300import org.geotools.api.data.FileDataStoreFinder;
301import org.geotools.data.simple.SimpleFeatureCollection;
302import org.geotools.data.simple.SimpleFeatureIterator;
303import org.geotools.api.data.SimpleFeatureSource;
304import org.geotools.geometry.jts.JTS;
305import org.geotools.referencing.CRS;
306import org.geotools.api.feature.simple.SimpleFeature;
307import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
309import java.io.File;
310import org.geotools.api.referencing.operation.MathTransform;
311import org.locationtech.jts.geom.Geometry;
312import org.locationtech.jts.geom.Coordinate;
313import org.locationtech.jts.geom.GeometryFactory;
314import org.locationtech.jts.geom.Point;
316// Load shapefile
317File file = new File("roads.shp");
318FileDataStore store = FileDataStoreFinder.getDataStore(file);
319SimpleFeatureSource featureSource = store.getFeatureSource();
321// Read features
322SimpleFeatureCollection collection = featureSource.getFeatures();
323try (SimpleFeatureIterator iterator = collection.features()) {
324 while (iterator.hasNext()) {
325 SimpleFeature feature = iterator.next();
326 Geometry geom = (Geometry) feature.getDefaultGeometryProperty().getValue();
327 // Process geometry
328 }
331// Create point
332GeometryFactory gf = new GeometryFactory();
333Point point = gf.createPoint(new Coordinate(-122.4, 37.7));
335// Reproject
336CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326", true);
337CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:32610", true);
338MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS);
339Geometry reprojected = JTS.transform(point, transform);
340store.dispose(); // In production use finally to release the datastore even on error.
341```

GeoTools

import org.geotools.api.data.FileDataStore;
import org.geotools.api.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.api.data.SimpleFeatureSource;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.geotools.api.feature.simple.SimpleFeature;
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;

import java.io.File;
import org.geotools.api.referencing.operation.MathTransform;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;

// Load shapefile
File file = new File("roads.shp");
FileDataStore store = FileDataStoreFinder.getDataStore(file);
SimpleFeatureSource featureSource = store.getFeatureSource();

// Read features
SimpleFeatureCollection collection = featureSource.getFeatures();
try (SimpleFeatureIterator iterator = collection.features()) {
    while (iterator.hasNext()) {
        SimpleFeature feature = iterator.next();
        Geometry geom = (Geometry) feature.getDefaultGeometryProperty().getValue();
        // Process geometry
    }
}

// Create point
GeometryFactory gf = new GeometryFactory();
Point point = gf.createPoint(new Coordinate(-122.4, 37.7));

// Reproject
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326", true);
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:32610", true);
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS);
Geometry reprojected = JTS.transform(point, transform);
store.dispose(); // In production use finally to release the datastore even on error.
Raw lines 296 to 342
343## Go Geospatial
345### Orb geometry and spherical metrics
347```go
348package main
350import (
351 "fmt"
352 "github.com/paulmach/orb"
353 "github.com/paulmach/orb/geojson"
354 "github.com/paulmach/orb/geo"
357func main() {
358 // Create point
359 point := orb.Point{-122.4, 37.7}
361 // Create linestring
362 line := orb.LineString{
363 {-122.4, 37.7},
364 {-122.3, 37.8},
365 }
367 // Create polygon
368 polygon := orb.Polygon{
369 {{-122.4, 37.7}, {-122.3, 37.7}, {-122.3, 37.8}, {-122.4, 37.8}, {-122.4, 37.7}},
370 }
372 // GeoJSON feature
373 feature := geojson.NewFeature(polygon)
374 feature.Properties["name"] = "Zone 1"
376 _ = line
377 _ = feature
378 // Spherical geographic metrics (not planar degrees)
379 distance := geo.Distance(point, orb.Point{-122.3, 37.8})
381 // Area
382 area := geo.Area(polygon)
384 fmt.Printf("Distance: %.2f meters\n", distance)
385 fmt.Printf("Area: %.2f square meters\n", area)
387```
389For more code examples across all languages, see [code-examples.md](code-examples.md).

Orb geometry and spherical metrics

package main

import (
    "fmt"
    "github.com/paulmach/orb"
    "github.com/paulmach/orb/geojson"
    "github.com/paulmach/orb/geo"
)

func main() {
    // Create point
    point := orb.Point{-122.4, 37.7}

    // Create linestring
    line := orb.LineString{
        {-122.4, 37.7},
        {-122.3, 37.8},
    }

    // Create polygon
    polygon := orb.Polygon{
        {{-122.4, 37.7}, {-122.3, 37.7}, {-122.3, 37.8}, {-122.4, 37.8}, {-122.4, 37.7}},
    }

    // GeoJSON feature
    feature := geojson.NewFeature(polygon)
    feature.Properties["name"] = "Zone 1"

    _ = line
    _ = feature
    // Spherical geographic metrics (not planar degrees)
    distance := geo.Distance(point, orb.Point{-122.3, 37.8})

    // Area
    area := geo.Area(polygon)

    fmt.Printf("Distance: %.2f meters\n", distance)
    fmt.Printf("Area: %.2f square meters\n", area)
}

For more code examples across all languages, see code-examples.md.

Raw lines 345 to 390
391## Rust geospatial
393This fragment targets the reviewed `geo` 0.33.1 API. Geometry methods are planar and
394unitless; use a projected metre grid for the buffer/simplification shown.
396```rust
397// Cargo.toml: geo = "0.33.1"
398use geo::{Point, LineString, Polygon, Buffer, Centroid, Contains, Simplify};
399fn main() {
400 let polygon = Polygon::new(LineString::from(vec![
401 (0., 0.), (100., 0.), (100., 100.), (0., 100.), (0., 0.)
402 ]), vec![]);
403 let point = Point::new(50., 50.);
404 let buffered = polygon.buffer(10.);
405 let simplified = polygon.simplify(1.);
406 println!("{} {:?}", polygon.contains(&point), buffered.centroid());
407 let _ = simplified;
409```
411For CRS conversion, use a compatible `proj` crate/native PROJ version and
412`Proj::new_known_crs(source, target, None)` with a verified axis-order contract.
413Do not buffer longitude/latitude by 1000 and label it metres. `simplify` can change
414topology; validate the result. Pin language dependencies in the actual project.
416Sources: [sf unary](https://r-spatial.github.io/sf/reference/geos_unary.html),
417[terra extract](https://rspatial.github.io/terra/reference/extract.html),
418[ArchGDAL geometry](https://yeesian.com/ArchGDAL.jl/latest/geometries/),
419[GeoStats interpolation](https://juliaearth.github.io/GeoStatsDocs/stable/interpolation/),
420[GeoTools35 quickstart](https://docs.geotools.org/stable/userguide/tutorial/quickstart/maven.html),
421[orb geo](https://pkg.go.dev/github.com/paulmach/orb/geo),
422[GeoRust](https://docs.rs/geo/latest/geo/),
423[Turf](https://turfjs.org/docs/api/interpolate),
424[OSM tile policy](https://operations.osmfoundation.org/policies/tiles/).

Rust geospatial

This fragment targets the reviewed geo 0.33.1 API. Geometry methods are planar and unitless; use a projected metre grid for the buffer/simplification shown.

// Cargo.toml: geo = "0.33.1"
use geo::{Point, LineString, Polygon, Buffer, Centroid, Contains, Simplify};
fn main() {
    let polygon = Polygon::new(LineString::from(vec![
        (0., 0.), (100., 0.), (100., 100.), (0., 100.), (0., 0.)
    ]), vec![]);
    let point = Point::new(50., 50.);
    let buffered = polygon.buffer(10.);
    let simplified = polygon.simplify(1.);
    println!("{} {:?}", polygon.contains(&point), buffered.centroid());
    let _ = simplified;
}

For CRS conversion, use a compatible proj crate/native PROJ version and Proj::new_known_crs(source, target, None) with a verified axis-order contract. Do not buffer longitude/latitude by 1000 and label it metres. simplify can change topology; validate the result. Pin language dependencies in the actual project.

Sources: sf unary, terra extract, ArchGDAL geometry, GeoStats interpolation, GeoTools35 quickstart, orb geo, GeoRust, Turf, OSM tile policy.

Raw lines 391 to 424