Skip to content

Instantly share code, notes, and snippets.

@dirceu-jr
Created February 6, 2026 17:30
Show Gist options
  • Select an option

  • Save dirceu-jr/509316f22c285a80f35ceeba11846f94 to your computer and use it in GitHub Desktop.

Select an option

Save dirceu-jr/509316f22c285a80f35ceeba11846f94 to your computer and use it in GitHub Desktop.
GEE Optim by Opus 4.5

ENN (Euclidean Nearest Neighbor) Performance Optimization

Current Approach Bottlenecks

The current implementation in gee.js uses:

  1. reduceToVectors to vectorize forest fragments
  2. ee.Join.saveBest with withinDistance for spatial join to find nearest neighbors

This is computationally expensive because:

Issue Impact
Vectorization overhead reduceToVectors on large areas creates massive feature collections
Spatial join complexity ee.Join.saveBest with withinDistance is O(n²) worst case
Per-tile processing Even with grid subdivision, each tile requires expensive vectorization

Alternative Approaches

1. Distance-Based Raster Approach (Most Promising)

Instead of vectorizing and computing pairwise vector distances, use raster distance operations:

// For each patch, compute distance to nearest "edge" of any OTHER patch
// This avoids vectorization entirely

var forestMask = native_i.gt(0);  // Binary: is forest

// Compute Euclidean distance to nearest forest pixel
var distToForest = forestMask.not().cumulativeCost({
  source: forestMask,
  maxDistance: searchRadius
});

// OR simpler approach using fastDistanceTransform
var distToForest = forestMask.fastDistanceTransform().sqrt().multiply(30); // in meters

The challenge is distinguishing distance to same patch vs other patches. One workaround:

// Dilate each patch and find where they "touch"
// Edge pixels of each fragment
var edges = forestMask.focal_min(1).subtract(forestMask).eq(-1);
// Distance from edge to nearest edge
var ennRaster = forestMask.cumulativeCost({source: edges, maxDistance: searchRadius});

2. Morphological Edge Detection + Distance Transform

// Extract fragment boundaries
var fragmentBoundaries = native_i.reduceNeighborhood({
  reducer: ee.Reducer.countDistinct(),
  kernel: ee.Kernel.square(1)
}).gt(1).selfMask();

// Distance from each fragment to nearest boundary of different fragment
var enn = fragmentBoundaries.cumulativeCost({
  source: fragmentBoundaries,
  maxDistance: searchRadius
}).clip(grid_i);

3. Subsample + Interpolate

If exact per-pixel ENN isn't required:

  • Compute ENN at coarser resolution (e.g., 250m)
  • Interpolate results back to 30m

Key Questions to Define Optimal Approach

  1. Is per-pixel ENN required, or would per-fragment (single distance value per fragment) suffice?
  2. What's the typical fragment size and count per tile?
  3. Are you computing edge-to-edge distance or centroid-to-centroid?
  4. What's the acceptable error margin for distance?

Recommendation

The distance transform approach could potentially eliminate vectorization entirely and run much faster on GEE's parallel raster infrastructure. Prototype this first before exploring hybrid approaches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment