1

I want to generate a number of random points over a given area, e.g. all land masses of the world. For this I have coded

var fcLandMasses = ee.FeatureCollection('ft:1l9VK5FJ4_hiH2gHjr0MtxwB-CrNEqOE5EBlW6Q');
var fcRandomPoints = ee.FeatureCollection.randomPoints(fcLandMasses,numberOfPoints,seed);

where you need to set numberOfPoints to the number of points you want to generate and seed to an arbitrary non-negative integer to ensure repeatability.

How can I clean up the FeatureCollection fcRandomPoints such that points located too close to each other (i.e. within a certain buffer) are removed?

I think there are two general choices:

  1. Keeping one (e.g. the first-appearing) point of points within that buffer.
  2. Keeping the average of all points within that buffer.

I'd like to follow option 2, which will probably include a mapping over fcRandomPoints.

What is the most efficient way to implement this?

1

Option 1 (You can also find it here: https://github.com/gee-community/gee_tools):

var filterDistance = function(points, distance) {
  var filt2 = ee.List([])
  var filt = points.iterate(function(el, ini){
                         var ini = ee.List(ini)
                         var fcini = ee.FeatureCollection(ini)
                         var buf = ee.Feature(el).geometry().buffer(distance)
                         var s = fcini.filterBounds(buf).size()
                         var cond = s.lte(0)
                         return ee.Algorithms.If(cond, ini.add(el), ini)
                       }, filt2)
  var filtered = ee.FeatureCollection(ee.List(filt))
  return filtered
}

Option 2:

var filterDistance = function(points, distance) {      
  var sum = points.iterate(function(el,fir){
    var buf = ee.Feature(el).geometry().buffer(distance)
    var s = points.filterBounds(buf).size()
    return ee.Number(fir).add(s)
  },ee.Number(0))
  var mean = ee.Number(sum).divide(points.size()).ceil()

  var filt2 = ee.List([])
  var filt = points.iterate(function(el, ini){
                         var ini = ee.List(ini)
                         var fcini = ee.FeatureCollection(ini)
                         var buf = ee.Feature(el).geometry().buffer(distance)
                         var s = fcini.filterBounds(buf).size()
                         var cond = s.lte(mean)
                         return ee.Algorithms.If(cond, ini.add(el), ini)
                       }, filt2)
  var filtered = ee.FeatureCollection(ee.List(filt))
  return filtered
}

Test

// TEST
var r1 = filterDistance(fcRandomPoints, 50000)
Map.addLayer(r1)
Map.addLayer(fcRandomPoints)
print(r1.size())

I think option 1 works better (cleaner), but of course depends on your needs.

  • Thanks a lot! Option 1 solved my problem, while Option 2 did not produce correct results on the very same dataset. Great work! Now I need to understand how you did it. ;) – Michael Oct 20 '17 at 9:41
  • Yes, option 1 works better, but in option 2 I made what you asked Keeping the average of all points within that buffer. I am available as a freelancer ;) – Rodrigo E. Principe Oct 20 '17 at 10:25
  • No, option 2 did not work at all: After running the code, I found many clusters of very close points (definitely within the buffer) were still represented in the reduced dataset. In other words: Option 1 reduced 1000 random points to about 920, which I can confirm to be correct from visual inspection. Option 2 applied on the same dataset reduced the same 1000 random points to 999 reduced points, i.e. basically all points were kept. – Michael Oct 20 '17 at 12:38
  • Yes, in option 2 there will be as many close points as the mean in the buffer. You can print the mean (inside the function) and see how many points are 'allowed' within the buffer. When the iteration reaches a point that within its buffer has more than the average (mean), drops that point. – Rodrigo E. Principe Oct 20 '17 at 13:03
  • Ah, I think there was a misunderstanding then. With Option 2 I meant the SPATIAL mean (i.e. the mean location) of the points within the buffer should be kept, all original points within the buffer should be deleted. The number of points in the reduced dataset would then be exactly the same as if Option 1 were applied. Only difference: Location of the reduced points. – Michael Oct 20 '17 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.