GEE Polygon Tool – Using GEE Apps to Pass Polygon Drawing Tool onto Raster and GetDownloadURL

dashboardgoogle-earth-enginegoogle-earth-engine-javascript-api

I'm trying to connect a polygon drawing tool that I have code for to an app that allows the user to generate a download link for the raster layer displayed. The idea is that the user draws a polygon and any raster points that fall within their polygon are included in the downloaded image. Currently the download button (in second link) just downloads the entire viewport.

Here is the drawing tool code from the GEE website (I don't understand it fully tbh): https://code.earthengine.google.com/e0b5eff2f2b44349187d215d42ce7eff

Here is my current simple app:

var m = {};

m.col = ee.ImageCollection(
  'users/harleyzhang/CurrentSagebrushBmass')
  
m.imgInfo = {
  bands: {
    'Current Sagebrush Biomass': {
      bname: 'b1',
      //color: 'd4e7b0',
      vis: {
        min: 284.9775085449219,
        max: 998.4847412109375,
        palette: ['feedde', 'fdbe85', 'fd8d3c', 'e6550d', 'a63603']
      }
    }
  }
}

var c = {};

c.controlPanel = ui.Panel();
c.map = ui.Map();

c.info = {};
c.info.titleLabel = ui.Label('Current Sagebrush Biomass Test App');
c.info.aboutLabel = ui.Label('Test app for Stepwat2 interpolated data for current sagebrush biomass.');

c.info.panel = ui.Panel([
  c.info.titleLabel, c.info.aboutLabel
  ]);

c.selectLayer = {};
c.selectLayer.label = ui.Label('Select a layer to display');
c.selectLayer.selector = ui.Select(Object.keys(m.imgInfo.bands), null, 'Current Sagebrush Biomass'); // GET RASTERS
c.selectLayer.panel = ui.Panel([c.selectLayer.label, c.selectLayer.selector]);

c.dividers = {}
c.dividers.divider1 = ui.Panel()

ui.root.clear();
ui.root.add(c.controlPanel);
ui.root.add(c.map);

c.controlPanel.add(c.info.panel);
c.controlPanel.add(c.dividers.divider1)
c.controlPanel.add(c.selectLayer.panel);

var s = {};

c.controlPanel.style().set({
  width: '350px'
});

s.aboutText = {
  fontSize: '13px',
  color: '505050'
};
s.widgetTitle = {
  fontSize: '15px',
  fontWeight: 'bold',
  margin: '8px 8px 0px 8px',
  color: '383838'
};
s.stretchHorizontal = {
  stretch: 'horizontal'
};

s.divider = {
  backgroundColor: 'F0F0F0',
  height: '4px',
  margin: '20px 0px'
};

c.info.titleLabel.style().set({
  fontSize: '20px',
  fontWeight: 'bold'
});

c.info.aboutLabel.style().set(s.aboutText);

c.selectLayer.selector.style().set(s.stretchHorizontal);
c.selectLayer.label.style().set(s.widgetTitle);
c.dividers.divider1.style().set(s.divider);

var imgCol;
function updateMap() {
  var band = c.selectLayer.selector.getValue();
  
  imgCol = m.col.select(m.imgInfo.bands[band].bname);

  var layer = ui.Map.Layer({
    eeObject: imgCol,
    visParams: m.imgInfo.bands[band].vis, 
    name: band
  });
  c.map.layers().set(0, layer);
}

c.selectLayer.selector.onChange(updateMap)

updateMap()

// function to generate a download URL of the image for the viewport region. 
function downloadImg() {
  var viewBounds = ee.Geometry.Rectangle(Map.getBounds()); // entire viewport is selected
  var downloadArgs = {
    name: 'sample_image',
    crs: 'EPSG:4326',
    region: viewBounds.toGeoJSONString()
 };
 var size = imgCol.size();
 var img = imgCol.first(); 

 var url =img.getDownloadURL(downloadArgs);
 urlLabel.setUrl(url);
 urlLabel.style().set({shown: true});
}

var downloadButton = ui.Button('Get download link', downloadImg);
var urlLabel = ui.Label('Download', {shown: false});
var buttons = ui.Panel([downloadButton, urlLabel]);
c.controlPanel.add(buttons);

My question is, how can I pass the geometry of a drawn polygon to first to the raster dataset (to select only the points inside their shape) and then pass the raster points to the getDownloadURL()?

Best Answer

In the most basic way, you want to initialize drawing tools for your map. Then you can access geometries drawn with those drawing tools using layers().

From there you can convert them to geometries and pass them to the region parameter.

// This sets the available draw modes. point and line would also be available
c.map.drawingTools().setDrawModes(["polygon", "rectangle"])
// This sets the shape selected by default
c.map.drawingTools().setShape("rectangle")


// function to generate a download URL of the image for the viewport region. 
function downloadImg() {
  var viewBounds = ee.Geometry.Rectangle(Map.getBounds()); // entire viewport is selected
  var downloadArgs = {
    name: 'sample_image',
    crs: 'EPSG:4326',
    // This gets the first layer of the drawn geometries and unions all of them into one
    region: c.map.drawingTools().layers().get(0).toGeometry()
 };
 var size = imgCol.size();
 var img = imgCol.first(); 

 var url =img.getDownloadURL(downloadArgs);
 urlLabel.setUrl(url);
 urlLabel.style().set({shown: true});
}