# Earth Engine calculation of distance between points to nearest water

I have a list of points and I want to calculate the distance between each of them to the nearest body of water larger than n=10 pixels. In other words, for each point, I want to return a number showing how far the nearest water is, but the body of water needs to be bigger than a minimum size. I think I can use the annual Global Surface Water dataset https://developers.google.com/earth-engine/datasets/catalog/JRC_GSW1_3_YearlyHistory#description as the source for bodies of water, where a pixel code greater than 2 means permanent water. Is this possible within Google Earth Engine and if so, any ideas on how to go about this?

As an example, I define the existence of water as a minimum pixel value >2 over a past 5-year period before a desired date:

``````# A sample point
point = ee.Geometry.Point([-121.771399, 40.330908],'EPSG:4269')

# Extract image collection in desired time period
collection = ee.ImageCollection('JRC/GSW1_3/YearlyHistory')\
.filterDate(ee.Date('2019-08-27').advance(-5, 'year'), '2019-08-27') # To see if a pixel had water over the past 5 years

# Pixels that had permanent water (water_class>2) over past 5 years (by taking min of pixel values over 5-year collection)
water = collection.min().gt(2)
``````

You can filter out smaller water bodies my masking based on `connectedPixelCount()`. Then you can create an image with distances to water using `fastDistanceTransform()`, and finally get the distance of a point by `reduceRegion()` on that distance image for that point. Something like this:

``````var point = ee.Geometry.Point([-121.771399, 40.330908], 'EPSG:4269')
var collection = ee.ImageCollection('JRC/GSW1_3/YearlyHistory')

var water = collection.min().gt(2)
.selfMask() // Mask all pixels but the actual water pixels

var nominalScale = 30 // Scale of JRC/GSW1_3/YearlyHistory
var minPixels = 10 // What you specified in the question
var minArea = Math.pow(nominalScale, 2) * minPixels

var pixelCount = water.connectedPixelCount({maxSize: 100})
var area = pixelCount.multiply(ee.Image.pixelArea())
var largeWaterBodies = water.updateMask(area.gte(minArea))

var distance = largeWaterBodies
.fastDistanceTransform({
neighborhood: 1024
})
.multiply(ee.Image.pixelArea())
.sqrt()
.rename('waterDistance')

var distanceFromPoint = distance
.reduceRegion({
reducer: ee.Reducer.first(),
geometry: point,
scale: nominalScale
})
.getNumber('waterDistance')
``````

• This solution works great. What does maxSize:100 do in `connectedPixelCount`? Also, am I right in thinking that neighborhood:1024 in the `fastDistanceTransform` sets the limits of where the search for water bodies will be carried out and therefore the maximum distance possible? What will be returned if no water exists within that neighborhood? Commented Jul 23, 2021 at 15:48
• `maxSize` inside `connectedPixelCount()` is the maximum number of pixels to try to count. The function will report that number even if there are more pixels. I added a pixelCount layer - inspect some pixels inside large water bodies - they'll report `100`. Commented Jul 23, 2021 at 16:05
• I'm not completely clear about the semantics of `fastDistanceTransform()` outside the neighborhood. Here's a script you can experiment with: code.earthengine.google.com/c0a1b4897973530e90af672cb81b8d65 Commented Jul 23, 2021 at 16:20