├── LICENSE ├── README.md ├── applications ├── bathymetry.js ├── precipitation_indices.js ├── remove.cmd └── waterbody_area.js ├── examples ├── animation-test-false ├── animation-test-false-all ├── animation-test-false-idw ├── animation-test-false-indices ├── animation-test-false-intervals ├── animation-test-false-intervals-S3 ├── animation-test-grace ├── animation-test-hand ├── animation-test-jrc ├── animation-test-last-mr.js ├── animation-test-lights ├── animation-test-no2 ├── animation-test-no2-style2 ├── animation-test-optical-stretched ├── animation-test-options ├── animation-test-proba ├── animation-test-s1 ├── animation-test-s1-SM ├── animation-test-s1-daily ├── animation-test-s1-ice ├── animation-test-s1-ice-river ├── animation-test-s1-s3-by-day ├── animation-test-sprite ├── animation-test-temperature ├── animation-v2-controls ├── assets-test-DOS ├── assets-test-burn-bad-pixels ├── assets-test-cloudfree.js ├── assets-test-cloudless ├── assets-test-cloudmask ├── assets-test-cloudmask-custom ├── assets-test-cloudmask-s2 ├── assets-test-composebydate ├── assets-test-filterclouds ├── assets-test-get-by-name ├── assets-test-getinfo ├── assets-test-imagesfrominfo ├── assets-test-maskedFraction.js ├── assets-test-tier2.js ├── charting-test-colorrangeplot ├── charting-test-colorrangeplot-India-drought ├── charting-test-colorrangeplot-India-drought-s1 ├── charting-test-colorrangeplot-proba ├── charting-test-radiance-reflectance ├── charting-test-rug-monthly-map-animate.js ├── charting-test-rug-monthly-map.js ├── charting-test-rug-monthly.js ├── charting-test-rug-simple.js ├── charting-test-rug-with-chart ├── charting-test-rug-with-clickable-chart ├── charting-test-simple ├── cloud-utils-test ├── earth-test ├── earth-test-as-animation ├── earth-test-as-layer ├── earth-test-as-layer-multiple ├── earth-test-s2-scenes-animation ├── gallery-test ├── gallery-test-images-date ├── gallery-test-monthly ├── gallery-test-multisensor ├── gallery-test-text-frame ├── geometry-test-cutLines ├── geometry-test-geojson ├── geometry-test-geojson-client ├── geometry-test-stdellipse ├── geometry-test-transects ├── geometry-test-vector ├── gl-test-dem ├── gl-test-empty ├── gl-test-gradient ├── gl-test-mesh ├── gl-test-rotate-image ├── gl-test-sphere ├── gl-test-sphere-phong ├── gl-test-sphere-shadow ├── gl-test-spheres ├── gl-test-trouchet ├── gl-test-trouchet-textured ├── grid-test ├── grid-test-NxM ├── grid-test-vector-geometry ├── hydro-test-catchments-rivers ├── hydro-test-hand ├── image-view-test ├── palettes-test ├── palettes-test-crameri-dem ├── palettes-test-crameri-dem-alos ├── palettes-test-crameri-dem-changes ├── palettes-test-multiple ├── palettes-test-thumb ├── palettes-test-thumb-crameri ├── promise-test ├── slic-examples ├── style-test-frame-scalebar ├── style-test-gradientbar ├── style-test-gradientbar-scalebar ├── style-test-northarrow ├── style-test-symbology ├── style-test-symbology-points ├── text-dev-font.js ├── text-test-align.js ├── text-test-all-fonts.js ├── text-test-annotate.js ├── text-test-debug ├── text-test-landsat.js ├── text-test-simple.js ├── text-test-stress.js ├── thresholding-test ├── thresholding-test-ndwi ├── tiler-test ├── ui-test-transect ├── utils-test-fillGaps ├── utils-test-hexgrid ├── utils-test-hillshade ├── utils-test-hillshade-multi ├── utils-test-hillshade-multi-alos ├── utils-test-hillshade-multi-water ├── utils-test-hillshade-multi-water-app ├── utils-test-isolines ├── utils-test-isolines-dynamic ├── utils-test-peronamalik ├── utils-test-profile ├── utils-test-stretchImage ├── utils-test-video-export-parameters ├── water-test └── water-test-China └── src ├── animation ├── assets ├── charting ├── cloud-utils ├── earth ├── gallery ├── geometry ├── gl ├── grid ├── hydro ├── image-view ├── palettes ├── promise ├── slic ├── stat ├── style ├── text ├── thresholding ├── tiler ├── ui └── utils /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Google Earth Engine Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A set of userful utilities for Google Earth Engine (JavaScript version) 2 | 3 | For Python version of some utilities see: https://github.com/gee-community/ee-packages-py 4 | 5 | Access scripts in Google Earth Engine Code Editor: 6 | 7 | https://code.earthengine.google.com/?accept_repo=users/gena/packages 8 | 9 | See some examples of how to use these scripts in the following [slides](https://docs.google.com/presentation/d/103gfl3gS8rokkrcMJV9qMBnkV7oLLbDf8ygDu6QaIZQ). 10 | 11 | The library includes the following main scripts: 12 | 13 | * animation - animate image collection in Code Editor by adding multiple images as map layers and toggle their opacity 14 | * assets - harmonize access to medium-resolution optical satellite image collections (Landsat 4,5,7,8,9 and Sentinel-2) 15 | * charting - scatter chart, rug plot, colorbar chart as a map layer in code editor 16 | * earth - inset Earth in Code Editor 17 | * gallery - project image colleciton as a filmstrip map layer 18 | * geometry - transect, vector, center point, concave hull 19 | * gl - emulate a subset of fragment shader in Earth Engine (proof-of-concept, 1000x slower than in GPU) 20 | * grid - generate regular grid (vector or raster) 21 | * hydro - access to some of hydologicla layers 22 | * palettes - palettes, see docs here: https://github.com/gee-community/ee-palettes 23 | * promise - (incomplete) emulate JavaScript async Promise 24 | * stat - dnorm, qnorm 25 | * style - north arrow, gradient bar, scale bar, frame with coordinates, map styles (use https://github.com/aazuspan/snazzy instead) 26 | * text - draw text annotations in map layers 27 | * thresholding - Otsu thresholding, threaholding based on Otsu and Canny Edge Detector methods (see my [PhD thesis](https://repository.tudelft.nl/islandora/object/uuid%3A510bd39f-407d-4bb6-958e-dea363c5e2a8) for examples) 28 | * tiler - generate SlippyMap tiles for a given zoom level and bounds 29 | * ui - (prototype, slow) draw area tool, draw transect tool 30 | * utils - stretch image bandwise, isolines, fast focal max/min/weight, hillshadeRGB, Perona-Malik speckle filter, multitemporal speckle filter, skeletonization (image morphology), PCA 31 | -------------------------------------------------------------------------------- /applications/precipitation_indices.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021 Deltares. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | 7 | Author: Gennadii Donchyts (gennadiy.donchyts@gmail.com) 8 | */ 9 | 10 | function qnorm(x) { 11 | return x.multiply(2).subtract(1).erfInv().multiply(Math.sqrt(2)) 12 | } 13 | 14 | function aggregateSum(images, aggregationDelta, aggregationUnit) { 15 | var times = images.reduceColumns(ee.Reducer.minMax(), ['system:time_start']) 16 | 17 | var timeStart = ee.Date(times.get('min')).advance(aggregationDelta, aggregationUnit) 18 | var timeStop = ee.Date(times.get('max')) 19 | 20 | return images.map(function(i) { 21 | var t = i.date() 22 | 23 | var total = images.filterDate(t.advance(-aggregationDelta, aggregationUnit), t).sum() 24 | 25 | return total 26 | .copyProperties(i, ['system:time_start']) 27 | .set({ count: total.bandNames().size() }) 28 | }).filterDate(timeStart, timeStop) 29 | } 30 | 31 | function computeCDF(images) { 32 | var percentiles = ee.List.sequence(0, 100) 33 | var cdf = images.reduce(ee.Reducer.percentile(percentiles)).toArray() 34 | 35 | return cdf 36 | } 37 | 38 | /*** 39 | * Computes different drought indices such as SPI, SPEI 40 | * 41 | * @param {ee.ImageCollection} precipitation An image collection containint precipitation data (a single band) 42 | * @param {number} aggregation A number of aggregation steps in aggregationUnits to apply before computing drought indices 43 | * @param {string} aggregationUnit A time unit for aggregation, currently supported units are: "day", "month" 44 | */ 45 | function computeSPI(precipitation, aggregation, aggregationUnit, precipitationAll, cdfCache) { 46 | var precipitationAggregated = aggregateSum(precipitation, aggregation, aggregationUnit) 47 | 48 | var cdf = computeCDF(precipitationAggregated) 49 | 50 | if(precipitationAll) { 51 | cdf = computeCDF(aggregateSum(precipitationAll, aggregation, aggregationUnit)) 52 | } 53 | 54 | if(cdfCache) { 55 | cdf = cdfCache 56 | } 57 | 58 | // fix for max value 59 | cdf = cdf.arrayCat(ee.Image.constant(10000).toArray(), 0) 60 | 61 | return precipitationAggregated.map(function(i) { 62 | var p = cdf.gte(i).arrayArgmax().arrayFlatten([['SPI']]).int() 63 | 64 | return qnorm(p.divide(100).clamp(0.00001, 0.99999)) 65 | .copyProperties(i, ['system:time_start']) 66 | }) 67 | } 68 | 69 | exports.aggregateSum = aggregateSum 70 | 71 | exports.computeCDF = computeCDF 72 | 73 | exports.computeSPI = computeSPI 74 | -------------------------------------------------------------------------------- /examples/animation-test-false-intervals: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var animation = require('users/gena/packages:animation') 9 | var assets = require('users/gena/packages:assets') 10 | var palettes = require('users/gena/packages:colorbrewer').Palettes 11 | 12 | var bounds = ee.Geometry(Map.getBounds(true)) 13 | //.centroid(1) 14 | 15 | var start = { year: 2010, month: 1 } 16 | var stop = { year: 2017, month: 1 } 17 | 18 | start.date = ee.Date.fromYMD(start.year, start.month, 1) 19 | stop.date = ee.Date.fromYMD(stop.year, stop.month, 1) 20 | 21 | // get images from one or multiple missions 22 | var images = assets.getImages(bounds, { 23 | fast: true, 24 | filter: ee.Filter.date(start.date, stop.date), 25 | //filterMasked: true, 26 | missions: [ 27 | 'S2', 28 | 'L8', 29 | 'L7', 30 | //'L5' 31 | ] 32 | }) 33 | 34 | // images = images.sort('system:time_start').map(function(i) { 35 | // return i.visualize({bands:['swir','nir','red'], gamma: 2, min: 0.07}) 36 | // .set({ label: i.date().format('YYYY-MM-dd') }) 37 | // }) 38 | //animation.animate(images, {label: 'label', maxFrames: 300}) 39 | 40 | // filter out noisy images 41 | /*images = assets.getMostlyCleanImages(images, bounds, { 42 | scale: Map.getScale() * 20, 43 | 44 | // how much should we deviate from cloud frequency when filtering images, use negative value to allow more (cloudy) images 45 | cloudFrequencyThresholdDelta: 0.15, 46 | 47 | // percentile and band used for cloudness, usually enough to choose one like green 48 | scorePercentile: 85, 49 | qualityBand: 'green', 50 | }) 51 | */ // .sort('system:time_start') 52 | //.sort('quality') 53 | 54 | print('Count: ', images.size()) 55 | 56 | // raw 57 | /*images = images 58 | .map(function(i) { 59 | var image = i 60 | //var image = images.filterDate(i.date(), i.date().advance(-1, 'month')).mosaic() 61 | 62 | //return image.visualize({bands:['red','green','blue'], gamma: 1.4, min:0.05, max:[0.5, 0.5, 0.55]}) 63 | //return image.normalizedDifference(['nir','red']).visualize({palette:palettes.YlGn[9], min: -0.1, max: 1}) 64 | return image.visualize({bands:['swir','nir','red'], gamma: 2, min: 0.05, max: 0.6}) 65 | .set({ label: i.date().format('YYYY-MM-dd') }) 66 | }) 67 | */ 68 | 69 | // per interval 70 | var monthStep = 1 71 | var averagingStep = 24 72 | var images = ee.List.sequence(start.year, stop.year, 1).map(function(year) { 73 | return ee.List.sequence(1, 12, monthStep).map(function(month) { 74 | var start = ee.Date.fromYMD(year, month, 1) 75 | var stop = start.advance(averagingStep, 'month') 76 | 77 | var image = images 78 | .filterDate(start, stop) 79 | .select(['swir','nir','red']) 80 | //.select(['red', 'green', 'blue']) 81 | .reduce(ee.Reducer.percentile([20])) 82 | //.reduce(ee.Reducer.median()) 83 | 84 | image = image.visualize({gamma: 1.5, min: 0.05, max:[0.5, 0.5, 0.5]}) 85 | 86 | return image 87 | .set({label: start.format('YYYY-MM-dd').cat(' - ').cat(stop.format('YYYY-MM-dd'))}) 88 | }) 89 | }).flatten() 90 | 91 | images = ee.ImageCollection(images) 92 | 93 | // animate 94 | animation.animate(images, {label: 'label', maxFrames: 200}) 95 | 96 | // export video 97 | var utils = require('users/gena/packages:utils') 98 | utils.exportVideo(images, {bounds: bounds, label: 'label', maxFrames: 600, name: 'animation', label: 'label' }) 99 | 100 | 101 | -------------------------------------------------------------------------------- /examples/animation-test-grace: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var grace_land = ee.ImageCollection("NASA/GRACE/MASS_GRIDS/LAND"), 3 | grace_ocean = ee.ImageCollection("NASA/GRACE/MASS_GRIDS/OCEAN"), 4 | swbd = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24"); 5 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 6 | /* 7 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 8 | 9 | This work is licensed under the terms of the MIT license. 10 | For a copy, see . 11 | */ 12 | 13 | var animation = require('users/gena/packages:animation') 14 | var utils = require('users/gena/packages:utils') 15 | var palettes = require('users/gena/packages:colorbrewer').Palettes 16 | 17 | grace_land = grace_land.select('lwe_thickness_jpl').filterDate('2012-01-01', '2018-01-01') 18 | 19 | var images = grace_land.map(function(i) { 20 | i = i.resample('bilinear') 21 | 22 | var rgb = i.visualize({ min: -10, max: 10, palette: palettes.RdYlBu[9] }) 23 | 24 | var weight = 1.5, height_multiplier = 50000, azimuth = 0, zenith = 30 25 | var result = utils.hillshadeit(rgb, i, weight, height_multiplier, azimuth, zenith) 26 | 27 | return result 28 | .updateMask(swbd.select('water_mask').eq(0)) 29 | //.updateMask(i.abs().divide(5)) 30 | .set({ label: i.date().format('YYYY-MM') }) 31 | }) 32 | 33 | Map.addLayer(ee.Image(1), {palette:['black']}, 'black', true, 0.9) 34 | animation.animate(images, {label: 'label', maxFrames: 50, opacity: 0.7, preload: false}) 35 | 36 | -------------------------------------------------------------------------------- /examples/animation-test-hand: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var s2 = ee.ImageCollection("COPERNICUS/S2"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | Map.addLayer(s2.select(['B12','B8','B2']).reduce(ee.Reducer.percentile([20])), {min:1000, max: 3500}, 'S2 20%', false) 12 | Map.addLayer(s2.select(['B12','B8','B2']).reduce(ee.Reducer.percentile([40])), {min:1000, max: 3500}, 'S2 40%', false) 13 | Map.addLayer(s2.select(['B12','B8','B2']).reduce(ee.Reducer.percentile([50])), {min:1000, max: 3500}, 'S2 60%', false) 14 | 15 | var hand30_1000 = ee.Image("users/gena/GlobalHAND/30m/hand-1000") 16 | 17 | var images = ee.List.sequence(0, 60, 1).map(function(th) { 18 | return ee.Image(1).updateMask(hand30_1000.gt(ee.Image.constant(th)).multiply(0.7)) 19 | .set({ label: ee.Number(th).format('%d') }) 20 | }) 21 | 22 | images = ee.ImageCollection(images) 23 | 24 | var animation = require('users/gena/packages:animation') 25 | animation.animate(images, {label: 'label', maxFrames: 60}) 26 | 27 | Map.setOptions('SATELLITE') -------------------------------------------------------------------------------- /examples/animation-test-last-mr.js: -------------------------------------------------------------------------------- 1 | var assets = require('users/gena/packages:assets') 2 | var animation = require('users/gena/packages:animation') 3 | 4 | var images = assets.getImages(Map.getCenter(), { 5 | missions: ['S2', 'L7', 'L8'], 6 | filter: ee.Filter.date('2020-04-29', '2020-06-01') 7 | }) 8 | 9 | images = images.sort('system:time_start') 10 | .map(function(i) { 11 | return i.set({ label: i.date().format() }) 12 | }) 13 | 14 | animation.animate(images, { vis: { min: 0.05, max: 0.4 }, label: 'label' }) -------------------------------------------------------------------------------- /examples/animation-test-lights: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var animation = require('users/gena/packages:animation') 9 | var palettes = require('users/gena/packages:colorbrewer').Palettes 10 | 11 | var collection = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG').select('avg_rad') 12 | // .map(function(i) { return i.resample('bicubic')}) 13 | 14 | 15 | var images = ee.List.sequence(2013, 2016).map(function(year) { 16 | return ee.List.sequence(1, 12).map(function(month) { 17 | var begin = ee.Date.fromYMD(year, month, 1) 18 | var end = begin.advance(6, 'month') 19 | var image = collection.filterDate(begin, end).median() 20 | 21 | image = image 22 | .where(image.lte(0), 0) 23 | 24 | image = image 25 | .mask(image.multiply(0.25)) 26 | 27 | return image.visualize({ 28 | min: 0, 29 | max: 35, 30 | palette: palettes.YlOrRd[9].reverse() 31 | }).set({ label: begin.format('YYYY-MM') }) 32 | }) 33 | }).flatten() 34 | 35 | images = ee.ImageCollection(images) 36 | 37 | // print(images.aggregate_array('label')) 38 | Map.addLayer(ee.Image(1), {palette:['black']}, 'black', true, 0.9) 39 | animation.animate(images, {label: 'label', maxFrames: 50, opacity: 0.7}) 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/animation-test-no2: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var no2 = ee.ImageCollection("COPERNICUS/S5P/NRTI/L3_NO2"), 3 | ne = ee.Image("users/gena/NE1_HR_LC_SR_W"), 4 | land = ee.Image("users/gena/land_polygons_image"); 5 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 6 | var gl = require('users/gena/packages:gl') 7 | var palettes = require('users/gena/packages:palettes') 8 | var style = require('users/gena/packages:style') 9 | var animation = require('users/gena/packages:animation') 10 | var utils = require('users/gena/packages:utils') 11 | 12 | var dem = ee.Image("JAXA/ALOS/AW3D30/V2_2").select('AVE_DSM') 13 | // var dem = ee.Image("USGS/NED") 14 | 15 | 16 | // var weight = 1.0 17 | // var extrusion = 30 18 | // var sunAzimuth = 315 19 | // var sunElevation = 15 20 | // var contrast = 0 21 | // var brightness = 0 22 | // var saturation = 0.25 23 | // var shadows = true 24 | 25 | // var styled = ne.visualize({ gamma: 0.3, min: 0, max: 255 }) 26 | // dem = dem.unmask(0, false).multiply(land.mask()) 27 | 28 | var weight = 0.6 29 | var extrusion = 5 30 | var sunAzimuth = 315 + 90 31 | var sunElevation = 5 32 | var contrast = 0 33 | var brightness = 0 34 | var saturation = 0.5 35 | var shadows = true 36 | 37 | var styled = ne.visualize({ min: 0, max: 255 }) 38 | dem = dem.updateMask(land.mask()).blend(ee.Image(0).float().updateMask(land.mask().not())) 39 | 40 | 41 | var demHillshaded = utils.hillshadeRGB(styled, dem, weight, extrusion, sunAzimuth, sunElevation, contrast, brightness, saturation, shadows) 42 | 43 | // Map.addLayer(demHillshaded, {}, 'dem (hillshade)') 44 | 45 | 46 | Map.setOptions('HYBRID') 47 | // Map.setOptions('TERRAIN') 48 | // style.SetMapStyleDark() 49 | 50 | var no2Var = 'tropospheric_NO2_column_number_density' 51 | // var no2Var = 'NO2_column_number_density' 52 | 53 | // var palette = palettes.matplotlib.magma[7] 54 | // var palette = ["#000004","#2C105C","#711F81","#B63679","#EE605E","#FDAE78","#FCFDBF"] 55 | 56 | var palette = palettes.crameri.roma[50].slice(0).reverse().slice(20) 57 | 58 | var vis = { 59 | min: 0.00009, max: 0.00016, 60 | palette: palette 61 | } 62 | 63 | // var vis = { 64 | // min: 0.00001, max: 0.0004, 65 | // palette: palette 66 | // }; 67 | 68 | 69 | no2 = no2.select([no2Var, 'cloud_fraction']) 70 | 71 | function resample(images) { 72 | return images.map(function(i) { return i.resample('bicubic') }) 73 | } 74 | 75 | var start = ee.Date('2019-09-01') 76 | 77 | var timeStep = 1 // days 78 | // var timeMax = 7 * 40 79 | var timeMax = 7 * 4 80 | var timeWindow = -30 // duration to look back in days 81 | 82 | var dates = ee.List.sequence(0, timeMax, timeStep).map(function(offset) { 83 | return start.advance(offset, 'day') 84 | }) 85 | 86 | function maskClouds(i) { 87 | var mask = gl.smoothstep(0, 0.15, i.select('cloud_fraction')) 88 | return i.updateMask(mask) 89 | } 90 | 91 | function smoothen(i) { 92 | return i.convolve(ee.Kernel.gaussian(10000, 5000, 'meters')) 93 | .copyProperties(i, ['system:time_start']) 94 | } 95 | 96 | no2 = no2.filterDate(start.advance(timeWindow, 'day'), start.advance(timeMax, 'day')) 97 | .map(maskClouds) 98 | .map(smoothen) 99 | .select(no2Var) 100 | 101 | print(no2.first()) 102 | 103 | var images = dates.map(function(t) { 104 | t = ee.Date(t) 105 | var imagesSample = no2.filterDate(t.advance(timeWindow, 'day'), t) 106 | var i = imagesSample 107 | // .median() 108 | // .reduce(ee.Reducer.percentile([25])) 109 | .mean() 110 | // .unmask(0, false) 111 | return i.set({ 112 | count: imagesSample.size(), 113 | 'system:time_start': t.millis() 114 | }) 115 | }) 116 | 117 | images = ee.ImageCollection(images).filter(ee.Filter.gt('count', 0)) 118 | 119 | // Map.addLayer(images.first()) 120 | 121 | var images = images.map(function(i) { 122 | var t = i.date() 123 | 124 | var mask = gl.smoothstep(0, vis.min, i).multiply(0.95) 125 | // var mask = i.unitScale(vis.min - (vis.max-vis.min) * 0.5, vis.max).add(0.1).multiply(0.9) 126 | 127 | return ee.ImageCollection([ 128 | demHillshaded.visualize({ forceRgbOutput: true }), 129 | ee.Image(1).byte().mask(0.15).visualize({ palette: ['000000'], forceRgbOutput: true }), 130 | i.updateMask(mask).visualize(vis) 131 | ]).mosaic().set({ label: t.format('YYYY-MM-dd') }) 132 | }) 133 | 134 | // Map.addLayer(images.first()) 135 | // throw(0) 136 | 137 | animation.animate(images, { label: 'label', maxFrames: 150 }) 138 | -------------------------------------------------------------------------------- /examples/animation-test-optical-stretched: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = 3 | /* color: #b6d6b5 */ 4 | /* shown: false */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[32.515911797989816, 30.274156950351514], 12 | [32.515911797989816, 29.948059612923323], 13 | [32.65907738636872, 29.948059612923323], 14 | [32.65907738636872, 30.274156950351514]]], null, false); 15 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 16 | /* 17 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 18 | 19 | This work is licensed under the terms of the MIT license. 20 | For a copy, see . 21 | */ 22 | 23 | exports.doc = "Animates images stretched (DOS-corrected) over a given polygon" 24 | 25 | var utils = require('users/gena/packages:utils') 26 | var assets = require('users/gena/packages:assets') 27 | var animation = require('users/gena/packages:animation') 28 | 29 | Map.setOptions('HYBRID') 30 | 31 | var images = assets.getImages(Map.getCenter(), { 32 | missions: ['S2', 'L8', 'L9', 'L7'], 33 | resample: 'bicubic', 34 | filter: ee.Filter.date('2022-06-10', '2023-01-01') 35 | }) 36 | 37 | // images = assets.getMostlyCleanImages(images, Map.getBounds(true)) 38 | 39 | images = images.sort('system:time_start') 40 | 41 | function stretch(image) { 42 | // var bands = ['swir', 'nir', 'green'] 43 | var bands = ['red', 'green', 'blue'] 44 | var image2 = utils.stretchImage(image.select(bands), { 45 | percentiles: [0, 99], 46 | max: 0.35, 47 | bounds: Map.getBounds(true), 48 | scale: Map.getScale() * 5 49 | }) 50 | 51 | var bands = ['swir', 'nir', 'green'] 52 | var image3 = utils.stretchImage(image.select(bands), { 53 | percentiles: [0, 99], 54 | bounds: Map.getBounds(true), 55 | max: 0.35, 56 | scale: Map.getScale() * 5 57 | }) 58 | 59 | image2 = image2.add(image3.multiply(ee.Image.constant([0.2, 0.1, 0.1]))) 60 | 61 | image2 = image2.set({ label: image.date().format('YYYY-MM-dd hh:mm') }) 62 | 63 | return image2 64 | } 65 | 66 | print(images.size()) 67 | 68 | images = images.map(stretch) 69 | 70 | animation.animate(images, { 71 | vis: { min: 0, max: 1.5 }, 72 | label: 'label', 73 | maxFrames: 100 74 | }) 75 | 76 | -------------------------------------------------------------------------------- /examples/animation-test-options: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("NOAA/GOES/16/MCMIPF"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | // generate some nice image collection 5 | 6 | images = images 7 | .filterDate('2020-08-01T09:00', '2020-08-02T09:00') 8 | .map(function(i) { 9 | var c = function(n) { return ee.Number(i.get(n)) } 10 | 11 | var b = i.select('CMI_C01').resample('bicubic').multiply(c('CMI_C01_scale')).add(c('CMI_C01_offset')).unitScale(0, 1.3) 12 | var r = i.select('CMI_C02').resample('bicubic').multiply(c('CMI_C02_scale')).add(c('CMI_C02_offset')).unitScale(0, 1.3) 13 | var n = i.select('CMI_C03').resample('bicubic').multiply(c('CMI_C03_scale')).add(c('CMI_C03_offset')).unitScale(0, 1.3) 14 | 15 | return ee.Image([r.divide(b), n, b]) 16 | .set({ t: i.date().format('YYYY-MM-dd HH:mm:ss') }) 17 | }) 18 | 19 | print(images.size()) 20 | 21 | // animate 22 | 23 | var animation = require('users/gena/packages:animation') 24 | 25 | var a = animation.animate(images, { 26 | vis: { 27 | min: [0.7, 0.05, 0.05], 28 | max: [1.5, 0.4, 0.2], 29 | gamma: 1.3 30 | }, 31 | width: '20%', 32 | position: 'bottom-center', // works as the rest of the widgets 33 | label: 't', // label to show next to the slider 34 | timeStep: 50, // ms between frames when playing 35 | preload: true, // set to false to avoid preloading all frames 36 | preloadCount: 5, // number of frames to preload when preload is false 37 | compact: true, // set to true to hide some controls, might be useful for apps 38 | hidePlay: true, 39 | maxFrames: images.size() 40 | }) 41 | 42 | 43 | // post-process, customize styling of some controls 44 | 45 | print('Executed *before* animation map layers are added') 46 | 47 | a.then(function() { 48 | print('Executed after animated layers are added') 49 | 50 | a.panel.style().set({ 'background-color': '#00000055' }) 51 | a.panel.widgets().get(0).style().set({ 'background-color': '#00000000' }) 52 | a.panel.widgets().get(1).style().set({ 'background-color': '#00000000' }) 53 | a.panel.widgets().get(2).style().set({ 'background-color': '#00000000' }) 54 | a.panel.widgets().get(0).style().set({ 'color': '#ffffff' }) 55 | a.panel.widgets().get(1).style().set({ 'color': '#ffffff' }) 56 | a.panel.widgets().get(1).style().set({ fontSize: 0 }) 57 | a.panel.widgets().get(2).style().set({ 'color': '#ffffff' }) 58 | 59 | 60 | // change properties of the main panel of animation controls 61 | print(a.panel) 62 | a.panel.widgets().reset([]) 63 | }) 64 | 65 | -------------------------------------------------------------------------------- /examples/animation-test-proba: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var proba100 = ee.ImageCollection("VITO/PROBAV/C1/S1_TOC_100M"), 3 | proba333 = ee.ImageCollection("VITO/PROBAV/C1/S1_TOC_333M"); 4 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 5 | var animation = require('users/gena/packages:animation') 6 | var assets = require('users/gena/packages:assets') 7 | 8 | var bounds = Map.getBounds(true) 9 | var scale = Map.getScale() 10 | var start = '2015-01-01' 11 | var stop = '2016-01-01' 12 | 13 | var images = proba100.merge(proba333) 14 | .filterBounds(bounds) 15 | .filterDate(start, stop) 16 | 17 | print(images.size()) 18 | 19 | images = images.map(function(i) { 20 | var isNonEmpty = i.select(0).reduceRegion({ reducer: ee.Reducer.anyNonZero(), geometry: bounds, scale: scale * 10 }).values().get(0) 21 | 22 | return i.set({ isNonEmpty: isNonEmpty }) 23 | }) 24 | 25 | images = images.filter(ee.Filter.eq('isNonEmpty', 1)) 26 | 27 | print(images.size()) 28 | 29 | images = assets.getMostlyCleanImages(images, bounds, { 30 | qualityBand: 'RED' 31 | }) 32 | 33 | print(images.size()) 34 | 35 | var image = images 36 | .map(function(i) { return i.resample('bicubic') }) 37 | .select(['RED']) 38 | .reduce(ee.Reducer.percentile([3])) 39 | .divide(2000) 40 | .log() 41 | 42 | Map.addLayer(image, { min: -5, max: -2.5 }, 'percentile') 43 | 44 | throw(0) 45 | 46 | images = images.map(function(i) { 47 | i = i.resample('bicubic').divide(2000) 48 | 49 | return i.addBands(i.select('BLUE').add(i.select('RED')).multiply(0.5).rename('GREEN')).log() 50 | }) 51 | 52 | animation.animate(images, { vis: { bands: ['RED', 'GREEN', 'BLUE'], min: -5, max: -2.5 } }) 53 | -------------------------------------------------------------------------------- /examples/animation-test-s1-SM: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var s1 = ee.ImageCollection("COPERNICUS/S1_GRD"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | function toNatural(i) { 5 | return ee.Image(ee.Image.constant(10.0).pow(i.divide(10.0)).copyProperties(i, ['system:time_start'])); 6 | } 7 | 8 | // var mode = 'IW' 9 | var mode = 'SM' 10 | 11 | s1 = s1 12 | .filterBounds(Map.getBounds(true)) 13 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VH')) 14 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV')) 15 | .filter(ee.Filter.eq('instrumentMode', mode)) 16 | 17 | Map.addLayer(s1.count().mask(s1.count()), {min:0, max: 10}, 'count', false) 18 | print(s1.size()) 19 | 20 | function show(image) { 21 | var vh = image.select('VH') 22 | var vv = image.select('VV') 23 | 24 | image = toNatural(image) 25 | 26 | image = image.addBands(image.normalizedDifference(['VH', 'VV']).rename('VH/VV')) 27 | 28 | //image = image.visualize({min: [0.03, 0.01, -0.6], max: [0.15, 1, 0.1], gamma: 2.5, bands: ['VH', 'VV', 'VH/VV']}) 29 | image = ee.Image([vh, vv, image.select('VH/VV')]).visualize({min: [-20, -20, -0.6], max: [-5, -5, 0.1], gamma: 1.5, bands: ['VH', 'VV', 'VH/VV']}) 30 | 31 | return image 32 | } 33 | 34 | var animation = require('users/gena/packages:animation') 35 | 36 | s1 = s1 37 | .sort('system:time_start') 38 | .sort('orbitProperties_pass') 39 | 40 | var images = s1.map(show) 41 | 42 | animation.animate(images) 43 | 44 | -------------------------------------------------------------------------------- /examples/animation-test-s1-ice: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([-106.08432372870175, -75.01841918726436]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var animation = require("users/gena/packages:animation") 12 | 13 | Map.centerObject(geometry, 9) 14 | 15 | var mode = 'IW' 16 | var bands = 'HH' 17 | 18 | var start = '2017-10-10' 19 | var end = '2018-12-31' 20 | 21 | var vmin = -20.0; 22 | var vmax = -10.0; 23 | 24 | var palette = [ 25 | '#030512', 26 | '#0e1023', 27 | '#1b1a36', 28 | '#26244a', 29 | '#302e5f', 30 | '#383874', 31 | '#3c4288', 32 | '#3e4f9b', 33 | '#3e5da8', 34 | '#3e6cb1', 35 | '#427ab7', 36 | '#4887bc', 37 | '#5295c0', 38 | '#5da3c5', 39 | '#6ab1cb', 40 | '#7abed0', 41 | '#8ccbd5', 42 | '#a3d7dc', 43 | '#bce3e6', 44 | '#d4f0f2' 45 | ] 46 | 47 | var images = ee.ImageCollection('COPERNICUS/S1_GRD') 48 | .filterBounds(geometry) 49 | .filterMetadata('instrumentMode', 'equals', mode) 50 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', bands)) 51 | .filterDate(start, end) 52 | .filterBounds(geometry) 53 | 54 | var duration = 6 55 | var imagesComposite = ee.List.sequence(0, 120, duration).map(function(t) { 56 | var t0 = ee.Date(start).advance(t, 'day') 57 | var t1 = ee.Date(start).advance(t, 'day').advance(duration, 'day') 58 | var results = images.filterDate(t0, t1) 59 | 60 | return results.max().set({ count: results.size(), 'system:time_start': t0.millis() }) 61 | }).filter(ee.Filter.gt('count', 0)) 62 | 63 | imagesComposite = ee.ImageCollection(imagesComposite) 64 | 65 | function visualize(image) { 66 | var rgb = ee.Image(10.0).pow(image.divide(10.0)) 67 | .visualize({ bands: bands, min: 0, max: 1, palette: palette }) 68 | 69 | return rgb.set({label: ee.Date(image.get('system:time_start')).format("YYYY-MM-dd")}) 70 | }; 71 | 72 | var video = imagesComposite.map(visualize) 73 | print(video.first()) 74 | 75 | animation.animate(video, { maxFrames: 50, label: 'label' }) 76 | -------------------------------------------------------------------------------- /examples/animation-test-s1-ice-river: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([-118.19064684851986, 55.92195209221348]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var animation = require("users/gena/packages:animation") 12 | 13 | // Map.centerObject(geometry, 9) 14 | 15 | var mode = 'IW' 16 | var bands = 'VV' 17 | 18 | var start = '2019-01-01' 19 | var end = '2020-01-01' 20 | 21 | var vmin = -23.0; 22 | var vmax = 3.0; 23 | 24 | var palette = [ 25 | '#030512', 26 | '#0e1023', 27 | '#1b1a36', 28 | '#26244a', 29 | '#302e5f', 30 | '#383874', 31 | '#3c4288', 32 | '#3e4f9b', 33 | '#3e5da8', 34 | '#3e6cb1', 35 | '#427ab7', 36 | '#4887bc', 37 | '#5295c0', 38 | '#5da3c5', 39 | '#6ab1cb', 40 | '#7abed0', 41 | '#8ccbd5', 42 | '#a3d7dc', 43 | '#bce3e6', 44 | '#d4f0f2' 45 | ] 46 | 47 | var images = ee.ImageCollection('COPERNICUS/S1_GRD') 48 | .filterBounds(geometry) 49 | 50 | print(images.aggregate_array('instrumentMode')) 51 | print(images.aggregate_array('transmitterReceiverPolarisation')) 52 | 53 | images = images 54 | .filterMetadata('instrumentMode', 'equals', mode) 55 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', bands)) 56 | .filterDate(start, end) 57 | .filterBounds(geometry) 58 | 59 | var images_asc = images.filter(ee.Filter.eq('orbitProperties_pass', 'ASCENDING')) 60 | var images_desc = images.filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING')) 61 | 62 | images = images_asc 63 | //images = images_desc 64 | 65 | 66 | var duration = 6 67 | var imagesComposite = ee.List.sequence(0, 120, duration).map(function(t) { 68 | var t0 = ee.Date(start).advance(t, 'day') 69 | var t1 = ee.Date(start).advance(t, 'day').advance(duration, 'day') 70 | var results = images.filterDate(t0, t1) 71 | 72 | return results.max().set({ count: results.size(), 'system:time_start': t0.millis() }) 73 | }).filter(ee.Filter.gt('count', 0)) 74 | 75 | imagesComposite = ee.ImageCollection(imagesComposite) 76 | 77 | function visualize(image) { 78 | // var rgb = ee.Image(10.0).pow(image.divide(10.0)) 79 | // .visualize({ bands: bands, min: 0, max: 1, palette: palette }) 80 | 81 | var rgb = image 82 | .visualize({ bands: bands, min: vmin, max: vmax, palette: palette }) 83 | 84 | return rgb.set({label: ee.Date(image.get('system:time_start')).format("YYYY-MM-dd")}) 85 | }; 86 | 87 | var video = imagesComposite.map(visualize) 88 | print(video.first()) 89 | 90 | animation.animate(video, { maxFrames: 50, label: 'label' }) 91 | -------------------------------------------------------------------------------- /examples/animation-test-sprite: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var animation = require('users/gena/packages:animation') 9 | 10 | var scale = Map.getScale() 11 | var bounds = Map.getBounds(true) 12 | var maxFrames = 30 13 | var getGlyph = animation.getGlyph({ scale: scale, bounds: bounds, frameCount: maxFrames }) 14 | 15 | var images = ee.List.sequence(0, maxFrames).map(getGlyph) 16 | 17 | animation.animate(images, { maxFrames: maxFrames, position: 'bottom-center', timeStep: 50 }) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/animation-test-temperature: -------------------------------------------------------------------------------- 1 | var assets = require('users/gena/packages:assets') 2 | var animation = require('users/gena/packages:animation') 3 | var palettes = require('users/gena/packages:palettes') 4 | 5 | var bounds = ee.Geometry(Map.getBounds(true)) 6 | var scale = Map.getScale() * 5 7 | var palette = palettes.cmocean.Thermal[7] 8 | 9 | var images = assets.getImages(bounds/*.centroid(1)*/, { 10 | includeTemperature: true, 11 | missions: ['L8'], // 'L7'], 12 | resample: true, 13 | // filter: ee.Filter.date('2010-01-01', '2020-01-01'), 14 | clipBufferSize: 12000 15 | }) 16 | 17 | images = assets.getMostlyCleanImages(images, bounds, { 18 | cloudFrequencyThresholdDelta: 0 19 | }) 20 | 21 | images = images.map(function(i) { 22 | return i.subtract(273.15).copyProperties(i, ['system:time_start']) 23 | }) 24 | 25 | // images = images.filter(ee.Filter.or( 26 | // ee.Filter.dayOfYear(335, 365), 27 | // ee.Filter.dayOfYear(0, 60) 28 | // )) 29 | 30 | Map.addLayer(images.select('temp').reduce(ee.Reducer.stdDev()), {min: 10, max: 15, palette: palette}, 'stdDev') 31 | // Map.addLayer(images.select('temp').reduce(ee.Reducer.median()), {min: 14, max: 25, palette: palette}, 'median') 32 | Map.addLayer(images.select('temp').reduce(ee.Reducer.mean()), {min: 14, max: 25, palette: palette}, 'mean') 33 | 34 | print('Image count: ', images.size()) 35 | 36 | images = images.sort('system:time_start') 37 | 38 | Map.addLayer(images.select('temp'), {}, 'temp (raw)', false) 39 | function visualize(i) { 40 | // var minMax = i.select('temp').reduceRegion({ 41 | // reducer: ee.Reducer.percentile([2, 98]), 42 | // geometry: bounds, 43 | // scale: scale, 44 | // tileScale: 4 45 | // }).values() 46 | // var min = minMax.get(0) 47 | // var max = minMax.get(1) 48 | 49 | i = i.subtract(273.15) 50 | 51 | var min = 15 52 | var max = 25 53 | 54 | return i.visualize({bands: 'temp', min: min, max: max, palette: palette, forceRgbOutput: true}) 55 | .set({label: i.date().format('YYYY-MM-dd')}) 56 | } 57 | 58 | var yearStart = 2014 59 | var yearStop = 2017 60 | var yearWindow = 1 / 2 61 | var yearsDelta = 1 / 4 62 | 63 | var yearOffsets = ee.List.sequence(0, (yearStop - yearStart) / yearsDelta, yearsDelta) 64 | 65 | print(yearOffsets) 66 | 67 | // group by years 68 | images = yearOffsets.map(function(yearOffset) { 69 | var start = ee.Date.fromYMD(yearStart, 1, 1).advance(yearOffset, 'year') 70 | var stop = start.advance(yearWindow, 'year') 71 | 72 | return images.filterDate(start, stop).median() 73 | .set('system:time_start', start.millis()) 74 | }) 75 | 76 | images = ee.ImageCollection(images) 77 | 78 | images = images.map(visualize) 79 | 80 | print(images.first()) 81 | 82 | // animation.animate(images, {label: 'label', maxFrames: 110}) 83 | 84 | Export.video.toDrive({ 85 | collection: images, 86 | description: 'Aleppo-temperature', 87 | fileNamePrefix:'Aleppo-temperature', 88 | framesPerSecond: 15, 89 | dimensions: '1920', 90 | region: bounds, 91 | maxFrames: 120 92 | }) -------------------------------------------------------------------------------- /examples/animation-v2-controls: -------------------------------------------------------------------------------- 1 | var layers = [ui.Map.Layer(), ui.Map.Layer()] 2 | var currentIndex = 0 3 | var onPlayPause = function() {} 4 | var onHideLayers = function() {} 5 | var onTransparentLayers = function() {} 6 | var onSlide = function() {} 7 | var onOptions = function() {} 8 | 9 | var position = 'top-center' 10 | var width = '600px' 11 | var opacity = 1 12 | var compact = false 13 | 14 | 15 | var textPlay = '▶' 16 | var textPause = '⏸' 17 | var textOptions = '🎦' 18 | 19 | var buttonPlayPause = ui.Button(textPlay, onPlayPause) 20 | var buttonOptions = ui.Button(textOptions, onOptions) 21 | var buttonHideLayers = ui.Button('Hide', onHideLayers) 22 | 23 | var slider = ui.Slider({ 24 | min: 0, 25 | max: layers.length - 1, 26 | step: 1, 27 | style: {stretch: 'horizontal'} 28 | }); 29 | 30 | slider.onSlide(onSlide) 31 | 32 | var sliderOpacity = ui.Slider({ 33 | min:0, max: 1, step: 0.1 34 | }) 35 | 36 | sliderOpacity.onSlide(function(o) { 37 | layers[currentIndex].setOpacity(o) 38 | opacity = o 39 | }) 40 | 41 | sliderOpacity.setValue(opacity) 42 | 43 | var label = ui.Label(''); 44 | 45 | var widgets = [slider, label, buttonPlayPause, buttonOptions] 46 | 47 | // buttonHideLayers, , sliderOpacity 48 | 49 | if(compact) { 50 | widgets = [buttonPlayPause, slider, label] 51 | } 52 | 53 | // Create a panel that contains both the slider and the label. 54 | var panel = ui.Panel({ 55 | widgets: widgets, 56 | layout: ui.Panel.Layout.flow('horizontal'), 57 | style: { 58 | position: position, 59 | padding: '7px', 60 | width: width 61 | } 62 | }); 63 | 64 | Map.add(panel) 65 | -------------------------------------------------------------------------------- /examples/assets-test-DOS: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([-116.71001623094513, 32.38087076052869]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var assets = require('users/gena/packages:assets') 12 | var animation = require('users/gena/packages:animation') 13 | 14 | // Map.centerObject(geometry, 13) 15 | 16 | var bounds = ee.Geometry(Map.getBounds(true)) 17 | 18 | var images = assets.getImages(bounds.centroid(1), { 19 | missions: [ 'S2', 'L8', 'L7' ], 20 | filter: ee.Filter.date('2020-01-01', '2021-01-01'), 21 | // resample: 'bicubic', // BUG: fails when bicubic is used, DOS returns negative values 22 | }) 23 | 24 | // remove totally clouded images for current area 25 | // images = assets.getMostlyCleanImages(images, bounds, { cloudFrequencyThresholdDelta: 0.15 }) 26 | images = assets.getMostlyCleanImages(images, bounds) 27 | 28 | images = images.sort('system:time_start', false) 29 | // .limit(30) // use only first 30 30 | .map(function(i) { return i.set({ label: i.date().format('YYYY-MM-dd') }) }) 31 | 32 | 33 | var maxDarkValue = 0.2 34 | images = assets.correctDOS(images, bounds, Map.getScale(), maxDarkValue) 35 | 36 | print(images.aggregate_array('dark')) 37 | 38 | animation.animate(images, { 39 | vis: { bands: ['red', 'green', 'blue'], min: 0.015, max: 0.05 }, 40 | label: 'label' 41 | }) 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/assets-test-burn-bad-pixels: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var assets = require('users/gena/packages:assets') 9 | var animation = require('users/gena/packages:animation') 10 | 11 | var bounds = ee.Geometry(Map.getBounds(true)) 12 | 13 | var images = assets.getImages(bounds.centroid(1), { 14 | resample: true, 15 | filter: ee.Filter.date('2015-01-01', '2020-01-01') 16 | }) 17 | 18 | print('image count: ', images.size()) 19 | 20 | // add raw images to map 21 | Map.addLayer(images, {}, 'images (raw)', false) 22 | 23 | images = assets.getMostlyCleanImages(images, bounds) 24 | 25 | images = images 26 | .sort('system:time_start') 27 | 28 | print('image count (clean): ', images.size()) 29 | 30 | // add raw images to map 31 | Map.addLayer(images, {}, 'images (raw, clean)', false) 32 | 33 | // compute per-pixel quality score 34 | /*var includeNeighborhood = false*/ 35 | 36 | var thMin = 75 // CDF thredholds 37 | var thMax = 95 38 | images = assets.addCdfQualityScore(images, thMin, thMax /*, includeNeighborhood*/) 39 | 40 | // visualize 41 | 42 | // raw images 43 | var imagesRGB = images.map(function(i) { 44 | var image = i.visualize({min: 0.05, max: 0.5}) 45 | 46 | return image 47 | }) 48 | 49 | animation.animate(imagesRGB, { preload: false }) 50 | 51 | // weights 52 | var weight = images.map(function(i) { 53 | var weight = i.select('weight') 54 | weight = weight.mask(ee.Image.constant(1).subtract(weight)) 55 | 56 | weight = weight.visualize({palette: ['ffff00'], min: 0, max: 1}) 57 | 58 | var image = i.visualize({min: 0.05, max: 0.5}) 59 | 60 | var composite = ee.ImageCollection.fromImages([ 61 | image, 62 | weight 63 | ]) 64 | 65 | return composite.mosaic() 66 | }) 67 | 68 | animation.animate(weight, {position: 'bottom-center'}) 69 | 70 | 71 | 72 | 73 | 74 | /* 75 | images = images.map(function(i) { 76 | var weight = i.select('weight') 77 | weight = weight.mask(weight.not()) 78 | weight = weight.visualize({palette: ['000000', 'ffff00'], min: 0, max: 1}) 79 | 80 | var image = i.visualize({min: 0.05, max: 0.35}) 81 | 82 | var composite = ee.ImageCollection.fromImages([ 83 | image, 84 | weight 85 | ]) 86 | 87 | return composite.mosaic() 88 | .set({label: i.date().format()}) 89 | }) 90 | */ -------------------------------------------------------------------------------- /examples/assets-test-cloudfree.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var assets = require('users/gena/packages:assets') 9 | var animation = require('users/gena/packages:animation') 10 | 11 | var images = assets.getImages(Map.getCenter(), { 12 | missions: [ 13 | 'S2', 14 | 'L8', 15 | //'L7' 16 | ], 17 | 18 | filter: ee.Filter.date('2020-01-01', '2021-01-01') 19 | }) 20 | 21 | var bounds = Map.getCenter().buffer(Map.getScale()*200) 22 | 23 | images = assets.getMostlyCleanImages(images, bounds, { 24 | //cloudFrequencyThresholdDelta: 0.15, 25 | percentile: 98, 26 | qualityBand: 'green', 27 | scale: Map.getScale() 28 | }) 29 | 30 | 31 | images = images.sort('system:time_start') 32 | //images = images.sort('quality_score') 33 | 34 | images = images.map(function(i) { 35 | return i.visualize({bands: ['red', 'green', 'blue'], min: 0.05, max: 0.4}) 36 | .set({label: i.date().format().cat(' ').cat(ee.Number(i.get('quality_score')).format('%.3f'))}) 37 | }) 38 | 39 | animation.animate(images, {maxFrames: 80}) 40 | .then(function() { 41 | Map.addLayer(ee.Image().paint(bounds, 1, 3), {palette: ['ffff00']}, 'aoi') 42 | }) 43 | 44 | -------------------------------------------------------------------------------- /examples/assets-test-cloudless: -------------------------------------------------------------------------------- 1 | var animation = require('users/gena/packages:animation') 2 | var assets = require('users/gena/packages:assets') 3 | 4 | var geometry = Map.getCenter() 5 | 6 | // var images = ee.ImageCollection('COPERNICUS/S2').filterBounds(geometry) 7 | // var vis = { min: 300, max: 4000, bands: ['B12', 'B8', 'B3'] } 8 | 9 | var images = assets.getImages(geometry, { missions: ['S2'] }) 10 | var vis = { min: 0.03, max: 0.4, bands: ['swir', 'nir', 'green'] } 11 | 12 | print('Image count: ', images.size()) 13 | 14 | images = assets.getMostlyCleanImages(images, Map.getBounds(true)).sort('system:time_start') 15 | print('Image count (cleaner): ', images.size()) 16 | 17 | animation.animate(images, { 18 | vis: vis, 19 | position: 'bottom-right', 20 | maxFrames: 50, 21 | width: '500px', 22 | timeStep: 50 23 | }) -------------------------------------------------------------------------------- /examples/assets-test-cloudmask: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([-118.92365767542618, 35.86338577732068]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var assets = require('users/gena/packages:assets') 5 | 6 | var images = assets.getImages(geometry, { 7 | missions: ['S2', 'L8'], 8 | cloudMask: true 9 | }) 10 | 11 | var image = images.first() 12 | print(image.bandNames()) // "cloud" band is added 13 | 14 | Map.addLayer(image.updateMask(image.select('cloud'))) 15 | 16 | Map.centerObject(image) 17 | 18 | -------------------------------------------------------------------------------- /examples/assets-test-cloudmask-custom: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([-118.92365767542618, 35.86338577732068]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var assets = require('users/gena/packages:assets') 5 | 6 | /*** 7 | * Use custom strategy for cloud masking per sensor 8 | */ 9 | var cloudMaskAlgorithms = { 10 | L8: function(image) { 11 | var qa = image.select('BQA'); 12 | /// Check that the cloud bit is off. 13 | // See https://www.usgs.gov/land-resources/nli/landsat/landsat-collection-1-level-1-quality-assessment-band 14 | var mask = qa.bitwiseAnd(1 << 4).eq(0); 15 | 16 | return image.addBands(mask.rename('cloud')); 17 | }, 18 | 19 | S2: function(image) { 20 | var qa = image.select('QA60'); 21 | // Bits 10 and 11 are clouds and cirrus, respectively. 22 | var cloudBitMask = 1 << 10; 23 | var cirrusBitMask = 1 << 11; 24 | // Both flags should be set to zero, indicating clear conditions. 25 | var mask = qa.bitwiseAnd(cloudBitMask).eq(0) 26 | .and(qa.bitwiseAnd(cirrusBitMask).eq(0)); 27 | 28 | 29 | mask = mask.rename('cloud') 30 | 31 | return image.addBands(mask) 32 | }, 33 | L7: function(image) { 34 | var cloudMask = ee.Image.constant(0).rename('cloud') 35 | 36 | // TODO: implement cloud masking for L7 37 | 38 | return image.addBands(cloudMask) 39 | }, 40 | L5: function(image) { 41 | var cloudMask = ee.Image.constant(0).rename('cloud') 42 | 43 | // TODO: implement cloud masking for L7 44 | 45 | return image.addBands(cloudMask) 46 | }, 47 | L4: function(image) { 48 | var cloudMask = ee.Image.constant(0).rename('cloud') 49 | 50 | // TODO: implement cloud masking for L7 51 | 52 | return image.addBands(cloudMask) 53 | } 54 | } 55 | 56 | var images = assets.getImages(geometry, { 57 | missions: ['S2', 'L8'], 58 | cloudMask: true, 59 | cloudMaskAlgorithms: cloudMaskAlgorithms 60 | }) 61 | 62 | var image = images.first() 63 | print(image) 64 | 65 | Map.addLayer(image.updateMask(image.select('cloud'))) 66 | 67 | Map.centerObject(image) 68 | 69 | -------------------------------------------------------------------------------- /examples/assets-test-cloudmask-s2: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var bounds = 3 | /* color: #d63000 */ 4 | /* shown: false */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[-39.655934217371815, -5.031373071272657], 12 | [-39.655934217371815, -5.215342678066852], 13 | [-39.351063611903065, -5.215342678066852], 14 | [-39.351063611903065, -5.031373071272657]]], null, false); 15 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 16 | var assets = require('users/gena/packages:assets') 17 | 18 | var images = assets.getImages(bounds, { 19 | missions: ['S2'], 20 | cloudMask: true, 21 | filter: ee.Filter.date('2020-05-01', '2022-01-01') 22 | }).sort('system:time_start') 23 | 24 | var image = images.first() 25 | 26 | Map.addLayer(image) 27 | Map.addLayer(image.select('cloud').selfMask(), { palette: ['ffff00'] }) -------------------------------------------------------------------------------- /examples/assets-test-composebydate: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("COPERNICUS/S2"), 3 | geometry = 4 | /* color: #7c89d6 */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[-85.173178950396, 38.90067265484757], 12 | [-85.173178950396, 38.25222180232338], 13 | [-84.1459572707085, 38.25222180232338], 14 | [-84.1459572707085, 38.90067265484757]]], null, false); 15 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 16 | images = images 17 | .filterBounds(geometry) 18 | .filterDate('2019-01-01', '2020-01-01') 19 | 20 | print(images.size()) 21 | 22 | Map.addLayer(images.select('B1').count(), { min: 71, max: 583, palette: ['black', 'red']}, 'count') 23 | 24 | print(ui.Chart.feature.histogram(images.map(function(i) { return i.set({doy: i.date().getRelative('day', 'year') }) }), 'doy', 150)) 25 | 26 | // merge by date 27 | var assets = require('users/gena/packages:assets') 28 | 29 | images = assets.composeByDate(images) 30 | 31 | print(images.size()) 32 | 33 | Map.addLayer(images.select('B1').count(), { min: 71, max: 583, palette: ['black', 'red']}, 'count (after mosaic)') 34 | 35 | print(ui.Chart.feature.histogram(images.map(function(i) { return i.set({doy: i.date().getRelative('day', 'year') }) }), 'doy', 150)) -------------------------------------------------------------------------------- /examples/assets-test-filterclouds: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | // https://code.earthengine.google.com/?accept_repo=users/gena/packages 9 | 10 | var assets = require('users/gena/packages:assets') 11 | var animation = require('users/gena/packages:animation') 12 | var gallery = require('users/gena/packages:gallery') 13 | 14 | var region = Map.getCenter().buffer(Map.getScale() * 50).bounds() 15 | Map.addLayer(region, {}, 'area of intereset') 16 | 17 | // get all images over region 18 | var images = assets.getImages(region, { 19 | filterMasked: true, 20 | missions: ['S2', 'L8'] 21 | }) 22 | .filterDate('2016-01-01', '2017-01-01') 23 | 24 | print('image count: ', images.size()) 25 | 26 | // add cuatom quality band used to determine cloudiness over the region 27 | images = images.map(function(i) { 28 | var q = i.select('green').add(i.select('swir')).rename('q') 29 | return i.addBands(q) 30 | }) 31 | 32 | // add a very simple quality score (uses regional percentile of a green band by default) 33 | var cloudOptions = {scale: Map.getScale() * 5, percentile: 85, cloudFrequencyThresholdDelta: 0.05, qualityBand: 'q'} 34 | images = assets.addQualityScore(images, region, cloudOptions) 35 | 36 | function visualize(i) { 37 | return i.visualize({ min: 0.03, max: 0.4 }) 38 | } 39 | 40 | var rgbAll = images 41 | .sort('quality_score') 42 | .map(visualize) 43 | 44 | // show 45 | var imagesAll = gallery.draw(rgbAll, region, 10, 10) 46 | Map.addLayer(imagesAll, {}, 'images (all)') 47 | 48 | // now remove cloudy ones (currently works fine only for annual collections 49 | // uses cloud frequency from http://www.earthenv.org/cloud 50 | var images = assets.getMostlyCleanImages(images, region, cloudOptions) 51 | 52 | print('image count (clean): ', images.size()) 53 | 54 | var rgbLessClouds = images 55 | .sort('quality_score') 56 | .map(visualize) 57 | 58 | // show 59 | var imagesClean = gallery.draw(rgbLessClouds, region, 10, 10) 60 | Map.addLayer(imagesClean, {}, 'images (clean)') 61 | 62 | 63 | -------------------------------------------------------------------------------- /examples/assets-test-get-by-name: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var assets = require('users/gena/packages:assets') 9 | 10 | var city = assets.getCity('Paris') 11 | 12 | var country = assets.getCountry('Belgium') 13 | 14 | var river = assets.getRiver('Rhine') 15 | 16 | Map.addLayer(river, {color: 'blue'}, river) 17 | Map.addLayer(city, {color: 'blue'}, city) 18 | Map.addLayer(country, {color: 'blue'}, country) 19 | 20 | Map.centerObject(river, 6) -------------------------------------------------------------------------------- /examples/assets-test-getinfo: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | 9 | var assets = require('users/gena/packages:assets') 10 | 11 | var images = assets.getImages(Map.getCenter()).limit(10) 12 | 13 | var info = assets.getImageInfo(images) 14 | 15 | print(info) 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/assets-test-maskedFraction.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var bounds = 3 | /* color: #d63000 */ 4 | /* displayProperties: [ 5 | { 6 | "type": "rectangle" 7 | } 8 | ] */ 9 | ee.Geometry.Polygon( 10 | [[[3.5209835666738627, 51.82801113688724], 11 | [3.5209835666738627, 51.13873267953637], 12 | [4.918993820580113, 51.13873267953637], 13 | [4.918993820580113, 51.82801113688724]]], null, false); 14 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 15 | var assets = require('users/gena/packages:assets') 16 | 17 | var images = assets.getImages(bounds, { 18 | filter: ee.Filter.date('2017-01-01', '2018-01-01'), 19 | filterMasked: true, 20 | filterMaskedFraction: 0.85, 21 | scale: Map.getScale() * 10 22 | }) 23 | 24 | 25 | print(images.size()) -------------------------------------------------------------------------------- /examples/assets-test-tier2.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([4.904669562931645, 51.81809355570926]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | // By default, assets.getImages() returns Landsat T1 images. 12 | // Use includeTier2: true option to include T2 as well 13 | 14 | // WARNING: use T2 at your own risk, many of T2 images look quite fine, but some could be bad 15 | // Example of badly registered images: https://code.earthengine.google.com/531e3341b65e427df53e0e3f82e1f1f2 16 | 17 | var assets = require('users/gena/packages:assets') 18 | var charting = require('users/gena/packages:charting') 19 | 20 | var start = ee.Date('2017-01-01') 21 | var stop = ee.Date('2018-01-01') 22 | 23 | Map.centerObject(geometry, 8) 24 | 25 | var imagesT1 = assets.getImages(geometry, { 26 | missions: [ 'L8' ], 27 | filter: ee.Filter.date(start, stop) 28 | }) 29 | 30 | var imagesT1T2 = assets.getImages(geometry, { 31 | missions: [ 'L8' ], 32 | filter: ee.Filter.date(start, stop), 33 | includeTier2: true 34 | }) 35 | 36 | // rug plots 37 | charting.showTimesRugPlot(imagesT1, { tmin: start.millis(), tmax: stop.millis() }) 38 | charting.showTimesRugPlot(imagesT1T2, { tmin: start.millis(), tmax: stop.millis() }) 39 | 40 | // show 41 | Map.addLayer(ee.Image(imagesT1.toList(1, 5).get(0)) , { min: 0, max: 0.4 }, 'T1') 42 | Map.addLayer(ee.Image(imagesT1T2.toList(1, 6).get(0)) , { min: 0, max: 0.4 }, 'T2') 43 | -------------------------------------------------------------------------------- /examples/charting-test-colorrangeplot: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometrySampling = /* color: #0b4a8b */ee.Geometry.Polygon( 3 | [[[-3.1817273987824137, 16.69313705684485], 4 | [-3.1817273987824137, 16.485188656693424], 5 | [-2.9784803284699137, 16.485188656693424], 6 | [-2.9784803284699137, 16.69313705684485]]], null, false), 7 | geometryPlot = /* color: #96ff7c */ee.Geometry.Polygon( 8 | [[[-2.9283552063996012, 16.69050620616005], 9 | [-2.9283552063996012, 16.481896530430337], 10 | [-2.2334699524933512, 16.481896530430337], 11 | [-2.2334699524933512, 16.69050620616005]]], null, false); 12 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 13 | var assets = require('users/gena/packages:assets') 14 | var charting = require('users/gena/packages:charting') 15 | var animation = require('users/gena/packages:animation') 16 | 17 | Map.centerObject(ee.FeatureCollection([geometrySampling, geometryPlot])) 18 | 19 | var start = ee.Date('2015-01-01') 20 | var stop = ee.Date('2019-01-01') 21 | 22 | var images = assets.getImages(geometrySampling, { 23 | missions: ['S2', 'L8'], 24 | filter: ee.Filter.date(start, stop) 25 | }) 26 | 27 | images = assets.excludeMasked(images, geometrySampling, 30) 28 | 29 | var imagesS2 = images.filter(ee.Filter.eq('MISSION', 'S2')) 30 | var imagesL8 = images.filter(ee.Filter.eq('MISSION', 'L8')) 31 | 32 | var plot = new charting.Plot(geometryPlot) 33 | 34 | plot.setName('Plot 1') 35 | 36 | // set plot x range usign times 37 | var timesS2 = ee.List(imagesS2.aggregate_array('system:time_start')) 38 | var timesL8 = ee.List(imagesL8.aggregate_array('system:time_start')) 39 | 40 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 41 | 42 | // add rug plots 43 | plot.addRugSeries('rug S2', timesS2, { width: 1.5, color: '000000' }) 44 | plot.addRugSeries('rug L8', timesL8, { width: 1.5, color: 'ff0000' }) 45 | 46 | // add colorbar CDF plot 47 | var vis = { min: 0.05, max: 0.5, gamma: 1.5, bands: ['swir', 'nir', 'green'] } 48 | 49 | plot.addColorbarSeries('colorbar S2', imagesS2, geometrySampling, vis, 10) 50 | plot.addColorbarSeries('colorbar L8', imagesL8, geometrySampling, vis, 30) 51 | 52 | var imagesClean = assets.getMostlyCleanImages(images, geometrySampling, 30) 53 | var imagesCleanS2 = imagesClean.filter(ee.Filter.eq('MISSION', 'S2')) 54 | var imagesCleanL8 = imagesClean.filter(ee.Filter.eq('MISSION', 'L8')) 55 | plot.addColorbarSeries('colorbar S2', imagesCleanS2, geometrySampling, vis, 10) 56 | plot.addColorbarSeries('colorbar L8', imagesCleanL8, geometrySampling, vis, 30) 57 | 58 | plot.show() 59 | 60 | // show S2 61 | animation.animate(imagesS2, { 62 | clipArea: geometrySampling, 63 | vis: { min: 0.05, max: 0.5, gamma: 1.4 } 64 | }) 65 | 66 | -------------------------------------------------------------------------------- /examples/charting-test-colorrangeplot-India-drought: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometrySampling = 3 | /* color: #0b4a8b */ 4 | /* displayProperties: [ 5 | { 6 | "type": "rectangle" 7 | } 8 | ] */ 9 | ee.Geometry.Polygon( 10 | [[[80.12346156964873, 13.19996721453835], 11 | [80.12346156964873, 13.126086409475468], 12 | [80.20860561261748, 13.126086409475468], 13 | [80.20860561261748, 13.19996721453835]]], null, false), 14 | geometryPlot = 15 | /* color: #96ff7c */ 16 | /* displayProperties: [ 17 | { 18 | "type": "rectangle" 19 | } 20 | ] */ 21 | ee.Geometry.Polygon( 22 | [[[80.21358379254912, 13.19996721453835], 23 | [80.21358379254912, 13.126420761896163], 24 | [80.44378169904326, 13.126420761896163], 25 | [80.44378169904326, 13.19996721453835]]], null, false); 26 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 27 | var assets = require('users/gena/packages:assets') 28 | var charting = require('users/gena/packages:charting') 29 | var animation = require('users/gena/packages:animation') 30 | 31 | Map.centerObject(ee.FeatureCollection([geometrySampling, geometryPlot]), 13) 32 | 33 | var start = ee.Date('2017-01-01') 34 | var stop = ee.Date('2020-01-01') 35 | 36 | var scale = Map.getScale() 37 | 38 | var images = assets.getImages(geometrySampling, { 39 | missions: ['S2', 'L8'], 40 | filter: ee.Filter.date(start, stop) 41 | }) 42 | 43 | images = assets.excludeMasked(images, geometrySampling, 30) 44 | 45 | var imagesS2 = images.filter(ee.Filter.eq('MISSION', 'S2')) 46 | var imagesL8 = images.filter(ee.Filter.eq('MISSION', 'L8')) 47 | 48 | var plot = new charting.Plot(geometryPlot) 49 | 50 | plot.setName('Plot 1') 51 | 52 | // set plot x range usign times 53 | var timesS2 = ee.List(imagesS2.aggregate_array('system:time_start')) 54 | var timesL8 = ee.List(imagesL8.aggregate_array('system:time_start')) 55 | 56 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 57 | 58 | // add rug plots 59 | plot.addRugSeries('rug S2', timesS2, { width: 1.5, color: '000000' }) 60 | plot.addRugSeries('rug L8', timesL8, { width: 1.5, color: 'ff0000' }) 61 | 62 | // add colorbar CDF plot 63 | var vis = { min: 0.05, max: 0.5, gamma: 1.5, bands: ['swir', 'nir', 'green'] } 64 | 65 | // plot.addColorbarSeries('colorbar S2', imagesS2, geometrySampling, vis, 10) 66 | // plot.addColorbarSeries('colorbar L8', imagesL8, geometrySampling, vis, 30) 67 | 68 | var imagesClean = assets.getMostlyCleanImages(images, geometrySampling, { 69 | cloudFrequencyThresholdDelta: -0.1 70 | }) 71 | 72 | // imagesClean = imagesClean.map(function(i) { 73 | // return i.updateMask(i.select('green').lt(0.2)) 74 | // }) 75 | 76 | imagesClean = imagesClean.sort('system:time_start') 77 | 78 | imagesClean = imagesClean.map(function(i) { 79 | var cloud = i.select('green').gt(0.3) 80 | 81 | var cloudArea = ee.Image.pixelArea().mask(cloud).reduceRegion({ 82 | reducer: ee.Reducer.sum(), 83 | geometry: geometrySampling, 84 | scale: scale * 5 85 | }).get('area') 86 | 87 | return i.updateMask(cloud.not()) 88 | .set({ cloudArea: cloudArea }) 89 | }) 90 | 91 | print(ui.Chart.feature.histogram(imagesClean, 'cloudArea', 50)) 92 | 93 | imagesClean = imagesClean.filter(ee.Filter.lt('cloudArea', 5000000)) 94 | 95 | var imagesCleanS2 = imagesClean.filter(ee.Filter.eq('MISSION', 'S2')) 96 | var imagesCleanL8 = imagesClean.filter(ee.Filter.eq('MISSION', 'L8')) 97 | var N = 1500 98 | plot.addColorbarSeries('colorbar S2 (clean)', imagesCleanS2, geometrySampling, vis, 10, N) 99 | plot.addColorbarSeries('colorbar L8 (clean)', imagesCleanL8, geometrySampling, vis, 30, N) 100 | 101 | plot.show() 102 | 103 | var styleSelection = { width: 2, color: '00ffff', fillColor: '00ffff33' } 104 | 105 | var frames = imagesClean.map(function(i) { 106 | var t = ee.Number(i.get('system:time_start')) 107 | var position = ee.Geometry(plot.getVLine(t).buffer(scale * 5).bounds()) 108 | 109 | return ee.FeatureCollection(position).style(styleSelection) 110 | .blend(i.visualize({ min: 0.05, max: 0.5, gamma: 1.4 }).clip(geometrySampling)) 111 | .set({ 112 | label: i.date().format('YYYY-MM-dd').cat(', ').cat(i.get('MISSION')), 113 | }) 114 | }) 115 | 116 | // show S2 117 | animation.animate(frames, { 118 | //clipArea: geometrySampling, 119 | //vis: { min: 0.05, max: 0.5, gamma: 1.4 }, 120 | maxFrames: 150, 121 | label: 'label', 122 | compact: true 123 | }) 124 | 125 | -------------------------------------------------------------------------------- /examples/charting-test-colorrangeplot-India-drought-s1: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometryPlot = /* color: #000000 */ee.Geometry.LinearRing( 3 | [[80.12912450628426, 13.20159462348145], 4 | [80.12912450628426, 13.195410927470213], 5 | [80.20225225286629, 13.195410927470213], 6 | [80.20225225286629, 13.20159462348145], 7 | [80.12912450628426, 13.20159462348145]]), 8 | geometry = /* color: #000000 */ee.Geometry.LinearRing( 9 | [[80.12689290838387, 13.203349427619615], 10 | [80.12689290838387, 13.133147443736638], 11 | [80.20431218938973, 13.133147443736638], 12 | [80.20431218938973, 13.203349427619615], 13 | [80.12689290838387, 13.203349427619615]]); 14 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 15 | /* 16 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 17 | 18 | This work is licensed under the terms of the MIT license. 19 | For a copy, see . 20 | */ 21 | 22 | var animation = require('users/gena/packages:animation') 23 | var text = require('users/gena/packages:text') 24 | var charting = require('users/gena/packages:charting') 25 | 26 | var start = ee.Date('2017-01-01') 27 | var stop = ee.Date('2020-01-01') 28 | 29 | geometry = geometry.bounds() 30 | geometryPlot = geometryPlot.bounds() 31 | 32 | Map.centerObject(geometry, 13) 33 | 34 | var bounds = ee.Geometry(Map.getBounds(true)) 35 | var scale = Map.getScale() 36 | 37 | var images = ee.ImageCollection("COPERNICUS/S1_GRD") 38 | .filterDate(start, stop) 39 | .filterBounds(geometry.centroid(1)) 40 | .map(function(i) { return i.select([0, 1]).rename(['b1','b2']) }) 41 | .sort('system:time_start') 42 | 43 | // generate rug plot (show acquisition times) 44 | var plot = new charting.Plot(geometryPlot) 45 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 46 | var times = ee.List(images.aggregate_array('system:time_start')) 47 | plot.addRugSeries('rug S1', times, { width: 1.5, color: '000000' }, 1) 48 | 49 | // get plot image 50 | var plotImage = plot.getImage() 51 | 52 | images = images.map(function(i) { 53 | // brush 54 | var position = ee.Geometry(plot.getVLine(i.get('system:time_start')).buffer(scale * 3).bounds()) 55 | var brush = ee.FeatureCollection(position) 56 | .style({ width: 2, color: 'ffff00', fillColor: 'ffff0055' }) 57 | 58 | // image 59 | var image = i 60 | .visualize({bands: ['b2', 'b1', 'b1'], min: -22, max: -2}) 61 | .clip(geometry) 62 | 63 | // time label 64 | var pt = text.getLocation(geometry, 'left', '15%', '3%') 65 | var time = i.date().format('YYYY-MM-dd') 66 | var label = text.draw(time, pt, scale, { 67 | fontSize: 24, textColor: '000000', fontType: 'Consolas', 68 | outlineColor: 'ffffff', outlineWidth: 2.5, outlineOpacity: 0.8 69 | }) 70 | 71 | // blend 72 | return image 73 | .blend(plotImage) 74 | .blend(brush) 75 | .blend(label) 76 | .set({ label: time }) 77 | }) 78 | 79 | Export.video.toDrive({ 80 | collection: images, 81 | description: 'India_reservoir', 82 | fileNamePrefix: 'India_reservoir', 83 | framesPerSecond: 5, 84 | region: geometry, 85 | scale: scale, 86 | crs: 'EPSG:3857' 87 | }) 88 | 89 | animation.animate(images, {label: 'label', maxFrames: 100}) 90 | -------------------------------------------------------------------------------- /examples/charting-test-colorrangeplot-proba: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometrySampling = /* color: #0b4a8b */ee.Geometry.Polygon( 3 | [[[-3.1817273987824137, 16.69313705684485], 4 | [-3.1817273987824137, 16.485188656693424], 5 | [-2.9784803284699137, 16.485188656693424], 6 | [-2.9784803284699137, 16.69313705684485]]], null, false), 7 | geometryPlot = /* color: #96ff7c */ee.Geometry.Polygon( 8 | [[[-2.9283552063996012, 16.69050620616005], 9 | [-2.9283552063996012, 16.481896530430337], 10 | [-2.2334699524933512, 16.481896530430337], 11 | [-2.2334699524933512, 16.69050620616005]]], null, false); 12 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 13 | var assets = require('users/gena/packages:assets') 14 | var charting = require('users/gena/packages:charting') 15 | var animation = require('users/gena/packages:animation') 16 | 17 | Map.centerObject(ee.FeatureCollection([geometrySampling, geometryPlot])) 18 | 19 | var start = ee.Date('2015-01-01') 20 | var stop = ee.Date('2019-01-01') 21 | 22 | var images = assets.getImages(geometrySampling, { 23 | missions: ['S2', 'L8'], 24 | filter: ee.Filter.date(start, stop) 25 | }) 26 | 27 | images = assets.excludeMasked(images, geometrySampling, 30) 28 | 29 | var imagesS2 = images.filter(ee.Filter.eq('MISSION', 'S2')) 30 | var imagesL8 = images.filter(ee.Filter.eq('MISSION', 'L8')) 31 | 32 | var imagesPROBA = ee.ImageCollection('VITO/PROBAV/C1/S1_TOC_100M') 33 | .filterDate(start, stop) 34 | .select(['SWIR', 'NIR', 'RED'], ['swir', 'nir', 'red']) 35 | 36 | imagesPROBA = assets.excludeMasked(imagesPROBA, geometrySampling, Map.getScale() * 10) 37 | 38 | imagesPROBA = imagesPROBA.map(function(i) { 39 | return i.multiply(5).divide(10000) 40 | .copyProperties(i, ['system:time_start']) 41 | }) 42 | 43 | // show PROBA 44 | // animation.animate(imagesPROBA, { 45 | // clipArea: geometrySampling, 46 | // vis: { min: 0.05, max: 0.5, gamma: 1.4 } 47 | // }) 48 | 49 | // show S2 50 | // animation.animate(imagesS2, { 51 | // clipArea: geometrySampling, 52 | // vis: { min: 0.05, max: 0.5, gamma: 1.4 } 53 | // }) 54 | 55 | 56 | var plot = new charting.Plot(geometryPlot) 57 | 58 | plot.setName('Plot 1') 59 | 60 | // set plot x range usign times 61 | var timesS2 = ee.List(imagesS2.aggregate_array('system:time_start')) 62 | var timesL8 = ee.List(imagesL8.aggregate_array('system:time_start')) 63 | var timesPROBA = ee.List(imagesPROBA.aggregate_array('system:time_start')) 64 | 65 | var minMaxS2 = ee.Dictionary(timesS2.reduce(ee.Reducer.minMax())) 66 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 67 | 68 | // add rug plots 69 | plot.addRugSeries('rug S2', timesS2, { width: 1.5, color: '000000' }) 70 | plot.addRugSeries('rug L8', timesL8, { width: 1.5, color: 'ff0000' }) 71 | plot.addRugSeries('rug PROBA', timesPROBA, { width: 1.5, color: 'ff00ff' }) 72 | 73 | // add colorbar CDF plot 74 | var vis = { min: 0.05, max: 0.5, gamma: 1.5, bands: ['swir', 'nir', 'red'] } 75 | var N = 250 76 | plot.addColorbarSeries('colorbar S2', imagesS2, geometrySampling, vis, 10, N) 77 | plot.addColorbarSeries('colorbar L8', imagesL8, geometrySampling, vis, 30, N) 78 | plot.addColorbarSeries('colorbar PROBA', imagesPROBA, geometrySampling, vis, 100, N) 79 | 80 | // var imagesClean = assets.getMostlyCleanImages(images, geometrySampling, 30) 81 | // var imagesCleanS2 = imagesClean.filter(ee.Filter.eq('MISSION', 'S2')) 82 | // var imagesCleanL8 = imagesClean.filter(ee.Filter.eq('MISSION', 'L8')) 83 | // plot.addColorbarSeries('colorbar S2', imagesCleanS2, geometrySampling, vis, 10) 84 | // plot.addColorbarSeries('colorbar L8', imagesCleanL8, geometrySampling, vis, 30) 85 | 86 | plot.show() 87 | 88 | -------------------------------------------------------------------------------- /examples/charting-test-radiance-reflectance: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var point = /* color: #98ff00 */ee.Geometry.Point([-120.14626979827881, 39.382543889164005]), 3 | box = /* color: #5cb451 */ee.Geometry.LineString( 4 | [[-120.12531653117071, 39.360917651511265], 5 | [-120.06206799560834, 39.40429581166964]]); 6 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 7 | /* 8 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 9 | 10 | This work is licensed under the terms of the MIT license. 11 | For a copy, see . 12 | */ 13 | 14 | // Repository: https://code.earthengine.google.com/?accept_repo=users/gena/packages 15 | // File: charting-test-radiance-reflectance 16 | 17 | Map.centerObject(box) 18 | 19 | var charting = require('users/gena/packages:charting') 20 | 21 | var bands = ['red', 'green', 'blue', 'nir', 'swir1'] 22 | 23 | var assetsReflectance = [ 24 | { id: 'LANDSAT/LC8_L1T_TOA', bands: ['B2', 'B3', 'B4', 'B5', 'B6'], multiplier: 1 }, 25 | { id: 'LANDSAT/LE7_L1T_TOA', bands: ['B1', 'B2', 'B3', 'B4', 'B5'], multiplier: 1 }, 26 | { id: 'LANDSAT/LT5_L1T_TOA', bands: ['B1', 'B2', 'B3', 'B4', 'B5'], multiplier: 1 }, 27 | { id: 'LANDSAT/LT4_L1T_TOA', bands: ['B1', 'B2', 'B3', 'B4', 'B5'], multiplier: 1 } 28 | ] 29 | 30 | var assetsRadiance = [ 31 | { id: 'LANDSAT/LC8_L1T', bands: ['B2', 'B3', 'B4', 'B5', 'B6'], multiplier: 1/65535 }, 32 | { id: 'LANDSAT/LE7_L1T', bands: ['B1', 'B2', 'B3', 'B4', 'B5'], multiplier: 1/255 }, 33 | { id: 'LANDSAT/LT5_L1T', bands: ['B1', 'B2', 'B3', 'B4', 'B5'], multiplier: 1/255 }, 34 | { id: 'LANDSAT/LT4_L1T', bands: ['B1', 'B2', 'B3', 'B4', 'B5'], multiplier: 1/255 } 35 | ] 36 | 37 | function plotAssets(assets, name, bounds) { 38 | // initialize collections 39 | var collections = assets.map(function(asset, ic) { 40 | return ee.ImageCollection.load(asset.id).select(asset.bands, bands).map(function(i) { return i.multiply(asset.multiplier) }) 41 | }) 42 | 43 | // merge collections 44 | var collection = ee.List(collections).iterate(function(c, p) { 45 | return ee.ImageCollection(p).merge(c) 46 | }, ee.ImageCollection([])) 47 | collection = ee.ImageCollection(collection) 48 | 49 | // get images 50 | collection = collection 51 | .filterBounds(point) 52 | //.filterDate('2000-01-01', '2018-01-01') 53 | 54 | // add first image 55 | var image = ee.Image(collection.toList(1,2).get(0)) 56 | 57 | Map.addLayer(image, {bands: ['swir1', 'nir', 'green'], min:0, max:0.5}, 'first image', false) 58 | 59 | // sample locations around given point 60 | var radius = 120 61 | var samplingArea = point.buffer(radius) 62 | Map.addLayer(samplingArea, {color:'grey'}, 'sampling area') 63 | 64 | // add scatter chart 65 | var chart = new charting.ScatterChart(bounds); 66 | 67 | chart.targetScale = Map.getScale() 68 | var axesBands = ['green', 'swir1'] 69 | var renderBands = ['swir1', 'nir', 'green'] 70 | var chartImage = chart.render(collection, samplingArea, axesBands, renderBands, {bands: renderBands, min:0, max:0.5}) 71 | Map.addLayer(chartImage, {}, 'green vs swir1 ' + name, false) 72 | 73 | var axesBands = ['green', 'nir'] 74 | var renderBands = ['red', 'green', 'nir'] 75 | var chartImage = chart.render(collection, samplingArea, axesBands, renderBands, {bands: renderBands, min:0, max:0.5}) 76 | Map.addLayer(chartImage, {}, 'green vs nir ' + name) 77 | } 78 | 79 | var box2 = ee.Geometry.LineString(box.bounds().transform(box.projection().translate(-0.065,0), 1).coordinates().get(0)) 80 | 81 | plotAssets(assetsRadiance, 'radiance', box.bounds()) 82 | 83 | plotAssets(assetsReflectance, 'reflectance', box2.bounds()) -------------------------------------------------------------------------------- /examples/charting-test-rug-monthly-map.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var amsterdam = /* color: #d63000 */ee.Geometry.Point([4.893507460392708, 52.369480378428484]), 3 | geometry = 4 | /* color: #98ff00 */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[4.680990675724739, 52.32543570628328], 12 | [4.680990675724739, 52.30948571154238], 13 | [5.114950636662239, 52.30948571154238], 14 | [5.114950636662239, 52.32543570628328]]], null, false), 15 | geometry2 = 16 | /* color: #0b4a8b */ 17 | /* shown: false */ 18 | /* displayProperties: [ 19 | { 20 | "type": "rectangle" 21 | } 22 | ] */ 23 | ee.Geometry.Polygon( 24 | [[[4.681977526100756, 52.423219683741884], 25 | [4.681977526100756, 52.32848444455118], 26 | [5.113534227760912, 52.32848444455118], 27 | [5.113534227760912, 52.423219683741884]]], null, false); 28 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 29 | var charting = require('users/gena/packages:charting') 30 | var animation = require('users/gena/packages:animation') 31 | 32 | // get S2 and L8 image times for Amsterdam 33 | var start = ee.Date('2016-01-01') 34 | var stop = ee.Date('2017-01-01') 35 | 36 | var imagesS2 = ee.ImageCollection('COPERNICUS/S2') 37 | .filterDate(start, stop) 38 | .filterBounds(amsterdam) 39 | 40 | var timesS2 = imagesS2.aggregate_array('system:time_start') 41 | 42 | var imagesL8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 43 | .filterDate(start, stop) 44 | .filterBounds(amsterdam) 45 | 46 | var timesL8 = imagesL8.aggregate_array('system:time_start') 47 | 48 | var timesMonthly = ee.List.sequence(1, 12).map(function(m) { 49 | return ee.Date.fromYMD(2016, 1, 1).advance(m, 'month').millis() 50 | }) 51 | 52 | var timesWeekly = ee.List.sequence(1, 365, 7).map(function(d) { 53 | return ee.Date.fromYMD(2016, 1, 1).advance(d, 'day').millis() 54 | }) 55 | 56 | // define plot target rectangle 57 | var rect = geometry 58 | 59 | // instantiate a rug plot 60 | var plot = new charting.Plot(rect.bounds(), { 61 | area: { width: 2, color: '000000', fillColor: 'ffffff' } 62 | }) 63 | 64 | // set domain 65 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 66 | 67 | // add month bars 68 | plot.addRugSeries('weeks', timesWeekly, { width: 1, color: '00000055' }) 69 | plot.addRugSeries('months', timesMonthly, { width: 2, color: '000000' }) 70 | 71 | // add S2 times (red) 72 | plot.addRugSeries('S2 times', timesS2, { width: 3, color: 'red' }, 0, 0.3) 73 | 74 | // add L8 times (green) 75 | plot.addRugSeries('L8 times', timesL8, { width: 3, color: 'green' }, 0.7, 1) 76 | 77 | // add plot to the map 78 | // Map.addLayer(plot.getImage()) 79 | 80 | // shows plot elements as map layers 81 | plot.show() 82 | 83 | // animate images 84 | var styleSelection = { width: 2, color: '00ffff', fillColor: '00ffff33' } 85 | 86 | imagesS2 = imagesS2.map(function(i) { 87 | var position = plot.getVLine(i.date().millis()).buffer(Map.getScale() * 5).bounds() 88 | 89 | return ee.ImageCollection([ 90 | i.visualize({ bands: ['B12', 'B8', 'B3'], min: 400, max: 4000 }), 91 | ee.FeatureCollection(position).style(styleSelection), 92 | ee.Image().paint(geometry2, 1).visualize({ palette: ['000000']}) 93 | ]).mosaic().clip(geometry2) 94 | .set({ 95 | date: i.date().format('YYYY-MMM') 96 | }) 97 | }) 98 | 99 | animation.animate(imagesS2, { maxFrames: imagesS2.size(), label: 'label' }) 100 | -------------------------------------------------------------------------------- /examples/charting-test-rug-monthly.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var amsterdam = /* color: #d63000 */ee.Geometry.Point([4.903566536318964, 52.37605514091119]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var charting = require('users/gena/packages:charting') 5 | 6 | print('A rug plot showing overpass time of Sentinel-2 (red) and Landsat 8 (green) ' + 7 | 'for Amsterdam in 2016') 8 | 9 | // get S2 and L8 image times for Amsterdam 10 | var start = ee.Date('2016-01-01') 11 | var stop = ee.Date('2017-01-01') 12 | 13 | var imagesS2 = ee.ImageCollection('COPERNICUS/S2') 14 | .filterDate(start, stop) 15 | .filterBounds(amsterdam) 16 | 17 | var timesS2 = imagesS2.aggregate_array('system:time_start') 18 | 19 | var imagesL8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 20 | .filterDate(start, stop) 21 | .filterBounds(amsterdam) 22 | 23 | var timesL8 = imagesL8.aggregate_array('system:time_start') 24 | 25 | var timesMonthly = ee.List.sequence(1, 12).map(function(m) { 26 | return ee.Date.fromYMD(2016, 1, 1).advance(m, 'month').millis() 27 | }) 28 | 29 | var timesWeekly = ee.List.sequence(1, 365, 7).map(function(d) { 30 | return ee.Date.fromYMD(2016, 1, 1).advance(d, 'day').millis() 31 | }) 32 | 33 | // define plot (virtual) rectangle 34 | var rect = ee.Geometry.Rectangle({ coords: [[0, 0], [100, 4]], geodesic: false }) 35 | 36 | // instantiate a rug plot 37 | var plot = new charting.Plot(rect.bounds(), { 38 | area: { width: 2, color: '000000', fillColor: '00000011' } 39 | }) 40 | 41 | // set domain 42 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 43 | 44 | // add days bars 45 | plot.addRugSeries('weeks', timesWeekly, { width: 1, color: '00000044' }) 46 | 47 | // add month bars 48 | plot.addRugSeries('months', timesMonthly, { width: 2, color: '000000' }) 49 | 50 | // add S2 times (red) 51 | plot.addRugSeries('S2 times', timesS2, { width: 2, color: 'red' }, 0, 0.3) // 0 and 0.3 hare are start and end of the line, in % of the plot height 52 | 53 | // add L8 times (green) 54 | plot.addRugSeries('L8 times', timesL8, { width: 2, color: 'green' }, 0.7, 1) 55 | 56 | // show plot 57 | print(plot.getThumbnail({ dimensions: '1200x48'})) 58 | -------------------------------------------------------------------------------- /examples/charting-test-rug-simple.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var amsterdam = /* color: #d63000 */ee.Geometry.Point([4.893507460392708, 52.369480378428484]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var charting = require('users/gena/packages:charting') 5 | 6 | // get S2 and L8 image times for Amsterdam 7 | var start = ee.Date('2016-01-01') 8 | var stop = ee.Date('2017-01-01') 9 | 10 | var images = ee.ImageCollection('COPERNICUS/S2') 11 | .filterDate(start, stop) 12 | .filterBounds(amsterdam) 13 | 14 | var times = images.aggregate_array('system:time_start') 15 | 16 | // define plot (virtual) rectangle 17 | var rect = ee.Geometry.Rectangle({ coords: [[0, 0], [100, 6]], geodesic: false }) 18 | 19 | // instantiate a rug plot 20 | var plot = new charting.Plot(rect.bounds(), { 21 | area: { width: 1, color: '000000', fillColor: '00000011' } 22 | }) 23 | 24 | // set domain 25 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 26 | 27 | // add S2 times (red) 28 | plot.addRugSeries('S2 times', times, { width: 1, color: 'red' }) 29 | 30 | // show plot 31 | print(plot.getThumbnail({ dimensions: '600x24'})) 32 | -------------------------------------------------------------------------------- /examples/charting-test-rug-with-chart: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var pt = /* color: #d63000 */ee.Geometry.Point([72.94506757267176, 19.010026096782486]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var charting = require('users/gena/packages:charting') 5 | 6 | var collections = [ 7 | { id: 'LANDSAT/LC08/C01/T1_RT_TOA', color: 'blue', vis: { min: 0.02, max: 0.4, bands: ['B5', 'B4', 'B2'] } }, 8 | { id: 'LANDSAT/LC08/C01/T2_TOA', color: 'blue', vis: { min: 0.02, max: 0.4, bands: ['B5', 'B4', 'B2'] } }, 9 | { id: 'COPERNICUS/S2', color: 'black', vis: { min: 200, max: 4000, bands: ['B12', 'B8', 'B2'] } }, 10 | { id: 'COPERNICUS/S1_GRD', color: 'green', vis: { min: -30, max: -5 } } 11 | ] 12 | 13 | collections.map(function(c) { 14 | c.collection = ee.ImageCollection(c.id).filterBounds(pt) 15 | }) 16 | 17 | var layer = ui.Map.Layer(ee.Image(), {}, 'image') 18 | Map.layers().add(layer) 19 | 20 | 21 | function showThumb(year) { 22 | print(year) 23 | 24 | var start = ee.Date.fromYMD(year, 1, 1) 25 | var stop = start.advance(1, 'year') 26 | 27 | print(start, stop) 28 | 29 | // plot 30 | var rect = ee.Geometry.Rectangle({ coords: [[0, 0], [100, 6]], geodesic: false }) 31 | 32 | // add rug plots 33 | collections.map(function(c) { 34 | var plot = new charting.Plot(rect.bounds(), { 35 | area: { width: 1, color: '000000', fillColor: '00000011' } 36 | }) 37 | 38 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 39 | 40 | var images = c.collection.filterDate(start, stop) 41 | var times = ee.List(images.aggregate_array('system:time_start')) 42 | 43 | plot.addRugSeries(c.id, times, { width: 1, color: c.color }) 44 | 45 | print(plot.getThumbnail({ dimensions: '600x24'})) 46 | 47 | var chart = ui.Chart.array.values(ee.List.repeat(1, times.size()), 0, times).setOptions({ title: c.id, pointSize: 2 }) 48 | // print('Click on the series points to add images') 49 | // print(chart) 50 | 51 | chart.onClick(function(v) { 52 | layer.setEeObject(c.collection.filterDate(v).first().visualize(c.vis)) 53 | }) 54 | }) 55 | } 56 | 57 | var years = ee.List.sequence(2019, 2021) 58 | years.evaluate(function(years) { years.map(showThumb) }) 59 | -------------------------------------------------------------------------------- /examples/charting-test-rug-with-clickable-chart: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var pt = /* color: #196aff */ee.Geometry.Point([-4.666254986673039, 58.106753844642206]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var charting = require('users/gena/packages:charting') 5 | 6 | var collections = [ 7 | { id: 'LANDSAT/LE07/C01/T1_RT', color: 'red' }, 8 | { id: 'LANDSAT/LE07/C01/T2', color: 'red' }, 9 | { id: 'LANDSAT/LC08/C01/T1_RT', color: 'blue' }, 10 | { id: 'LANDSAT/LC08/C01/T2', color: 'blue' }, 11 | { id: 'COPERNICUS/S2', color: 'black' }, 12 | { id: 'COPERNICUS/S1_GRD', color: 'green' } 13 | ] 14 | 15 | collections.map(function(c) { 16 | c.collection = ee.ImageCollection(c.id).filterBounds(pt) 17 | }) 18 | 19 | var layer = ui.Map.Layer(ee.Image(), {}, 'image') 20 | Map.layers().add(layer) 21 | 22 | function showThumb(year) { 23 | print(year) 24 | 25 | var start = ee.Date.fromYMD(year, 1, 1) 26 | var stop = start.advance(1, 'year') 27 | 28 | // plot 29 | var rect = ee.Geometry.Rectangle({ coords: [[0, 0], [100, 4]], geodesic: false }) 30 | 31 | // add rug plots 32 | collections.map(function(c) { 33 | var plot = new charting.Plot(rect.bounds(), { 34 | area: { width: 1, color: '000000', fillColor: '00000011' } 35 | }) 36 | 37 | plot.setMinMax(start.millis(), stop.millis(), 0, 1) 38 | 39 | var images = c.collection.filterDate(start, stop) 40 | var times = ee.List(images.aggregate_array('system:time_start')) 41 | plot.addRugSeries(c.id, times, { width: 1, color: c.color }) 42 | 43 | var chart = ui.Chart.array.values(ee.List.repeat(1, times.size()), 0, times).setOptions({ title: c.id, pointSize: 2 }) 44 | 45 | // print(chart) 46 | 47 | chart.onClick(function(v) { 48 | layer.setEeObject(c.collection.filterDate(v).first()) 49 | }) 50 | 51 | 52 | print(plot.getThumbnail({ dimensions: '600x24'})) 53 | }) 54 | } 55 | 56 | var years = ee.List.sequence(2019, 2020) 57 | years.evaluate(function(years) { years.map(showThumb) }) 58 | 59 | -------------------------------------------------------------------------------- /examples/charting-test-simple: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA"), 3 | geometry = /* color: #98ff00 */ee.Geometry.LineString( 4 | [[77.32950479045007, 30.822360787673027], 5 | [77.39644824196205, 30.884546299852897]]); 6 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 7 | /* 8 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 9 | 10 | This work is licensed under the terms of the MIT license. 11 | For a copy, see . 12 | */ 13 | 14 | // Source: charting file in https://code.earthengine.google.com/?accept_repo=users/gena/packages 15 | 16 | var region = /* color: #d63000 */ee.Geometry.Polygon( 17 | [[[77.4, 30.9], 18 | [77.4, 30.8], 19 | [77.515, 30.8], 20 | [77.515, 30.9]]]) 21 | 22 | Map.centerObject(geometry) 23 | 24 | region = region.buffer(-1700).bounds() // ee.ImageCollection.getRegion() crashes after ~75k points 25 | 26 | var bands = ['B5', 'B6'] 27 | var min = 0.05 28 | var max = 0.45 29 | var vis = {min: min, max: max, bands: ['B6', 'B5', 'B6']} 30 | 31 | images = images 32 | .filterBounds(region) 33 | .filter(ee.Filter.lt('CLOUD_COVER', 50)) 34 | .sort('system:time_start') 35 | .select(bands) 36 | 37 | // draw scatter chart as a map layer 38 | var charting = require('users/gena/packages:charting') 39 | 40 | var chart = new charting.ScatterChart(geometry.bounds()) 41 | chart.samplingScale = 90 // scale used to sample images 42 | chart.targetScale = Map.getScale() // scale used to draw points 43 | 44 | var axesBands = bands 45 | var renderBands = vis.bands 46 | 47 | // single chart 48 | function testSingleChart() { 49 | Map.addLayer(region, {}, 'region') 50 | 51 | var images2 = images.limit(2) // just two images 52 | 53 | var chartImage = chart.render(images2, region, axesBands, renderBands, vis) 54 | Map.addLayer(chartImage, {}, 'chart') 55 | 56 | Map.addLayer(images2.median().clip(region), vis, 'image') 57 | } 58 | 59 | // multiple charts 60 | function testMultipleCharts() { 61 | var frames = images.map(function(i) { 62 | var imageChart = chart.render(ee.ImageCollection.fromImages([i]), region, axesBands, renderBands, vis) 63 | var imageRgb = i.visualize(vis) 64 | 65 | return ee.ImageCollection.fromImages([ 66 | imageRgb.clip(region), 67 | imageChart 68 | ]).mosaic() 69 | }) 70 | 71 | var animation = require('users/gena/packages:animation') 72 | animation.animate(frames, {maxFrames: 30}) 73 | } 74 | 75 | testSingleChart() 76 | //testMultipleCharts() -------------------------------------------------------------------------------- /examples/cloud-utils-test: -------------------------------------------------------------------------------- 1 | var cloudUtils = require('users/gena/packages:cloud-utils') 2 | 3 | var testimage = ee.Image('LANDSAT/LC8_L1T_TOA/LC81680742014018LGN00'); 4 | Map.addLayer(testimage, {bands: ['B5', 'B4', 'B3'], max: 1}, 'TOA'); 5 | 6 | var cloudScore = ee.Algorithms.Landsat.simpleCloudScore(testimage).select('cloud'); 7 | var cloudMask = cloudScore.gt(40).reproject(ee.Projection('EPSG:3857').atScale(30)); 8 | 9 | Map.addLayer(cloudMask.mask(cloudMask),{palette:['fb8072']},'Cloud'); 10 | 11 | var sunElevation = testimage.get('SUN_ELEVATION'); 12 | print(sunElevation); 13 | var sunAzimuth = ee.Number(testimage.get('SUN_AZIMUTH')); 14 | print(sunAzimuth); 15 | var cloudshadows = cloudUtils.computeCloudShadowMask(sunElevation,sunAzimuth,cloudMask); 16 | 17 | // remove dark pixels 18 | var irSumThresh = 0.35;//Sum of IR bands to include as shadows within TDOM and the shadow shift method (lower number masks out less) 19 | var darkPixels = testimage.select(['B5','B6','B7']).reduce(ee.Reducer.sum()).lt(irSumThresh) 20 | // .focal_min(contractPixels).focal_max(dilatePixels) 21 | 22 | Map.addLayer(cloudshadows.mask(cloudshadows.and(darkPixels)), {palette:['ffffb3']}, 'Cloudshadows'); 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/earth-test: -------------------------------------------------------------------------------- 1 | var Earth = require('users/gena/packages:earth').Earth 2 | 3 | var earth = new Earth(-90, 0, { showCenter: true }) 4 | 5 | Map.add(earth) 6 | 7 | var earth2 = new Earth(90, 0) 8 | 9 | earth2.style().set({ position: 'bottom-left' }) 10 | 11 | Map.add(earth2) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/earth-test-as-animation: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var pt = /* color: #d63000 */ee.Geometry.Point([-68.83521740840641, 34.08885648046128]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var Earth = require('users/gena/packages:earth').Earth 5 | 6 | var earth = new Earth(10, 10/*, { scale: 10000 }*/) 7 | 8 | var a = require('users/gena/packages:animation') 9 | 10 | // Map.addLayer(earth.getImageAt(pt)) 11 | 12 | 13 | // var images = ee.List.sequence(0.0, Math.PI, Math.PI / 20).map(function(i) { return earth.getImageAt(pt, { zoom: ee.Number(i).sin().multiply(0.1).add(0.5) })}) 14 | // a.animate(images) 15 | 16 | 17 | // https://www.desmos.com/calculator/19ua52oivv 18 | var heartbeat = ee.List.sequence(-2, 2, 0.1).map(function(x) { 19 | x = ee.Number(x) 20 | 21 | var a = 0.2 22 | var d = 1.4 23 | var h = 3 24 | var s = 0.04 25 | var w = 0.02 26 | 27 | return x.add(d).pow(2).multiply(-1).divide(2*w).exp() 28 | .add(x.subtract(d).pow(2).multiply(-1).divide(2*w).exp()) 29 | .add(x.divide(s).multiply(-1).add(h).subtract(x).multiply(x.multiply(7).pow(2).divide(-2).exp())).multiply(a) 30 | }) 31 | 32 | var images = heartbeat.map(function(v) { 33 | return earth.getImageAt(pt, { zoom: ee.Number(v).sin().multiply(0.1).add(0.5) }) 34 | }) 35 | 36 | a.animate(images, { maxFrames: images.size() }) 37 | 38 | 39 | // thumbnail is a little bit more complicated 40 | // var images = heartbeat.map(function(v) { 41 | // var i = earth.getImageAt(pt, { zoom: ee.Number(v).sin().multiply(0.1).add(0.5) }) 42 | // return i.mask().select(0).not().visualize({ palette: ['white']}).blend(i.visualize()) 43 | // }) 44 | 45 | 46 | // // Define arguments for animation function parameters. 47 | // var videoArgs = { 48 | // dimensions: 500, 49 | // framesPerSecond: 10, 50 | // min: 0, max: 255 51 | // }; 52 | 53 | // print(ui.Thumbnail(ee.ImageCollection(images), videoArgs)) 54 | -------------------------------------------------------------------------------- /examples/earth-test-as-layer: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var pt = /* color: #d63000 */ee.Geometry.Point([-68.83521740840641, 34.08885648046128]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var Earth = require('users/gena/packages:earth').Earth 5 | 6 | var earth = new Earth(10, 10, { scale: 10000 }) 7 | 8 | Map.addLayer(earth.getImageAt(pt, { zoom: 0.2 })) 9 | -------------------------------------------------------------------------------- /examples/earth-test-as-layer-multiple: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var points = /* color: #20d61e */ee.FeatureCollection( 3 | [ee.Feature( 4 | ee.Geometry.Point([-96.1252564709064, 44.93352129458624]), 5 | { 6 | "system:index": "0" 7 | }), 8 | ee.Feature( 9 | ee.Geometry.Point([5.354837331344804, 51.27681689672661]), 10 | { 11 | "system:index": "1" 12 | }), 13 | ee.Feature( 14 | ee.Geometry.Point([77.4251498313448, 20.778384499843177]), 15 | { 16 | "system:index": "2" 17 | }), 18 | ee.Feature( 19 | ee.Geometry.Point([21.350931081344804, 1.385987621723786]), 20 | { 21 | "system:index": "3" 22 | }), 23 | ee.Feature( 24 | ee.Geometry.Point([-57.03678665478442, -7.468016025815568]), 25 | { 26 | "system:index": "4" 27 | })]); 28 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 29 | var Earth = require('users/gena/packages:earth').Earth 30 | 31 | // INCOMPLETE 32 | 33 | // var earths = points.getInfo().features.map(function(pt) { 34 | // var coords = pt.geometry.coordinates 35 | // var scale = 25000 36 | // var earth = new Earth(coords[0], coords[1], { scale: scale }) 37 | // var zoomMultiplier = 0.15 38 | 39 | // return earth.getImageAt(ee.Geometry(pt.geometry), zoomMultiplier) 40 | // }) 41 | 42 | // Map.addLayer(ee.Image(1), { palette: ['000000'] }, 'background', true, 0.5) 43 | 44 | // Map.addLayer(ee.ImageCollection(earths)) 45 | 46 | -------------------------------------------------------------------------------- /examples/earth-test-s2-scenes-animation: -------------------------------------------------------------------------------- 1 | var animation = require('users/gena/packages:animation') 2 | var palettes = require('users/gena/packages:palettes') 3 | var earth = require('users/gena/packages:earth'); 4 | 5 | Map.setCenter(4.83, -3.6, 3) 6 | Map.addLayer(ee.Image(1), { palette: ['black'] }, 'black', false) 7 | 8 | // parameters for orthographic projection 9 | var LON = -75.2; 10 | var LAT = 0; 11 | var SCALE = 0.5 * Map.getScale(); // this is the main parameter that controls scale of rendering, too small - EE will timout, too large - everything will look like a Minecraft (but faster, but SPI is still very slow) 12 | var ZOOM = 1; // earth zoom level 13 | 14 | var count = 10 15 | var frames = ee.List.sequence(1, count + 1) 16 | 17 | var images = ee.ImageCollection(frames.map(function(frame) { 18 | // generate an image with Sentinel-2 footprints with a decaying opacity 19 | var timeStart = ee.Date('2020-01-01') 20 | var timeStop = timeStart.advance(frame, 'day') 21 | var image = ee.ImageCollection('COPERNICUS/S2') 22 | // .filter(ee.Filter.eq('SPACECRAFT_NAME', 'Sentinel-2A')) 23 | .filterDate(timeStart, timeStop) 24 | .map(function(i) { 25 | // decaying opacity based on the image date and start date 26 | var opacity = ee.Number(count + 1).subtract(timeStop.difference(i.date(), 'day')).divide(count + 1).pow(5).multiply(255).int().format('%02x') 27 | var fillColor = ee.Algorithms.If(ee.String(i.get('SPACECRAFT_NAME')).match('Sentinel-2A'), 'ffff00', '00ffff') 28 | fillColor = ee.String(fillColor).cat(opacity) 29 | return i.set({ style: { width: 0, fillColor: fillColor } }) 30 | }) 31 | .style({ styleProperty: 'style' }) 32 | 33 | var ne = ee.Image("users/gena/NE1_HR_LC_SR_W").visualize({ gamma: 0.2 }) 34 | 35 | // compose footprints with Naturel Earth image 36 | image = ne.blend(image) 37 | 38 | // rotate Earth as well 39 | var LON = ee.Number(-75.2).add(ee.Number(frame).multiply(1)) 40 | var LAT = 0 41 | 42 | return earth.getEarthImage(image, LON, LAT, SCALE, ZOOM).set({ label: timeStart.format('YYYY-MM-dd') }) 43 | })) 44 | 45 | animation.animate(images, { 46 | position: 'bottom-center', 47 | compact: true 48 | }) 49 | -------------------------------------------------------------------------------- /examples/gallery-test: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([-7.522198423482791, 32.43942027481582]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var assets = require('users/gena/packages:assets') 12 | var imageGallery = require('users/gena/packages:gallery') 13 | 14 | var scale = Map.getScale() 15 | //var bounds = ee.Geometry(Map.getCenter()).buffer(50 * scale) 16 | var bounds = geometry.buffer(50 * scale) 17 | 18 | // get images from one or multiple missions 19 | var images = assets.getImages(bounds.centroid(1), { 20 | filter: ee.Filter.date("2018-01-01", "2020-01-01"), 21 | missions: [ 22 | 'S2', 23 | 'L8', 24 | //'L7', 25 | //'L5' 26 | ] 27 | }).sort('system:time_start') 28 | 29 | // add image gallery 30 | var options = {proj: 'EPSG:3857', flipX: false, flipY: true } 31 | var rows = 5, columns = 5 32 | var gallery = imageGallery.draw(images, bounds, rows, columns, scale, options) 33 | 34 | Map.addLayer(gallery, {bands: ['swir', 'nir', 'blue'], min: 0.05, max: 0.3}, 'gallery (false-color)', true); 35 | -------------------------------------------------------------------------------- /examples/gallery-test-images-date: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = 3 | /* color: #d63000 */ 4 | /* displayProperties: [ 5 | { 6 | "type": "rectangle" 7 | } 8 | ] */ 9 | ee.Geometry.Polygon( 10 | [[[38.99017811568136, 9.150180966271892], 11 | [38.99017811568136, 9.083909312983865], 12 | [39.0431356504714, 9.083909312983865], 13 | [39.0431356504714, 9.150180966271892]]], null, false); 14 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 15 | /* 16 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 17 | 18 | This work is licensed under the terms of the MIT license. 19 | For a copy, see . 20 | */ 21 | 22 | var assets = require('users/gena/packages:assets') 23 | var imageGallery = require('users/gena/packages:gallery') 24 | var text = require('users/gena/packages:text') 25 | var scale = Map.getScale() 26 | var bounds = geometry.bounds() 27 | 28 | // get images from one or multiple missions 29 | var images = assets.getImages(bounds, { 30 | filter: ee.Filter.date("2020-01-01", "2022-01-01"), 31 | missions: [ 32 | 'S2', 33 | 'L8', 34 | 'L7', 35 | //'L5' 36 | ], 37 | filterMasked: true, 38 | }) 39 | 40 | // images = assets.getMostlyCleanImages(images, bounds) 41 | 42 | images = images.filter(ee.Filter.calendarRange(8, 10, 'month')).sort('system:time_start') 43 | 44 | images = images.map(function(i) { 45 | var rgb = i.visualize({ bands: ['swir', 'nir', 'green'], min: 0.05, max: 0.5 }) 46 | 47 | var pt = text.getLocation(bounds, 'left', '2%', '2%') 48 | var label = text.draw(i.date().format('YYYY-MM-dd'), pt, scale, { textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2.5, outlineOpacity: 0.6, fontSize: 18 }) 49 | 50 | return rgb.blend(label) 51 | }) 52 | 53 | // add image gallery 54 | var options = {proj: 'EPSG:3857', flipX: false, flipY: true } 55 | var rows = 5, columns = 8 56 | var gallery = imageGallery.draw(images, bounds, rows, columns, scale, options) 57 | 58 | Map.addLayer(gallery, {}, 'gallery (false-color)', true); 59 | -------------------------------------------------------------------------------- /examples/gallery-test-monthly: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometryLabel = 3 | /* color: #d63000 */ 4 | /* shown: false */ 5 | ee.Geometry.Point([-104.81854696562625, 38.291704822204]), 6 | geometryGallery = 7 | /* color: #98ff00 */ 8 | /* shown: false */ 9 | /* displayProperties: [ 10 | { 11 | "type": "rectangle" 12 | } 13 | ] */ 14 | ee.Geometry.Polygon( 15 | [[[-104.82125520585478, 38.294351019931455], 16 | [-104.82125520585478, 38.23194594511732], 17 | [-104.71980333207549, 38.23194594511732], 18 | [-104.71980333207549, 38.294351019931455]]], null, false); 19 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 20 | var text = require('users/gena/packages:text') 21 | var gallery = require('users/gena/packages:gallery') 22 | 23 | Map.centerObject(geometryGallery, 12) 24 | 25 | var images = ee.ImageCollection('COPERNICUS/S2') 26 | .filterBounds(geometryLabel) 27 | 28 | var imagesMonthly = ee.List.sequence(0, 11).map(function(month) { 29 | month = ee.Number(month) 30 | return images.filter(ee.Filter.calendarRange(month, month.add(1), 'month')) 31 | .select(['B12', 'B8', 'B4']) 32 | .reduce(ee.Reducer.percentile([15])) 33 | .set({ label: ee.Date.fromYMD(2000, month.add(1), 1).format('MMM') }) 34 | }) 35 | 36 | imagesMonthly = ee.ImageCollection(imagesMonthly) 37 | 38 | // render monthly images + label 39 | var imagesRGB = imagesMonthly.map(function(i) { 40 | var label = text.draw(i.get('label'), geometryLabel, Map.getScale(), { 41 | fontSize:24, textColor: 'ffffff', outlineColor: '000000', outlineWidth: 3, outlineOpacity: 0.6}) 42 | 43 | return i.visualize({ min: 300, max: 3500 }).blend(label) 44 | }) 45 | 46 | // generate a single filmstrip image (rows x columns) 47 | var rows = 3 48 | var columns = 4 49 | var imageFilmstrip = gallery.draw(imagesRGB, geometryGallery.bounds(), rows, columns) 50 | 51 | Map.addLayer(imageFilmstrip) 52 | -------------------------------------------------------------------------------- /examples/geometry-test-cutLines: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.LineString( 3 | [[-104.71654486261713, 38.60407178910679], 4 | [-104.71549880110132, 38.6045035807679], 5 | [-104.71464049421655, 38.60484314325896], 6 | [-104.71366417013513, 38.604776069314006], 7 | [-104.71211385332452, 38.60442812221833], 8 | [-104.71122872434961, 38.605006635737176], 9 | [-104.71078884207117, 38.604507772907205]]); 10 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 11 | var g = require('users/gena/packages:geometry') 12 | 13 | var o = g.explodeLineString(geometry, { count: geometry.length().divide(15).floor() }) 14 | var segments = o.segments 15 | var points = o.points 16 | 17 | print(points.aggregate_array('offset')) 18 | 19 | Map.addLayer(ee.Image(0), {}, 'background', true, 0.5) 20 | Map.addLayer(o.segments.reduceToImage(['offset'], ee.Reducer.first()).focal_max(3).randomVisualizer()) 21 | Map.addLayer(o.points.style({ pointSize: 6 })) 22 | -------------------------------------------------------------------------------- /examples/geometry-test-geojson: -------------------------------------------------------------------------------- 1 | var geojson = { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "population": 200 8 | }, 9 | "geometry": { 10 | "type": "Point", 11 | "coordinates": [-112.0372, 46.608058] 12 | } 13 | } 14 | ] 15 | } 16 | 17 | exports.getFeatures = function() { return require('users/gena/packages:geometry').fromGeoJSON(geojson) } -------------------------------------------------------------------------------- /examples/geometry-test-geojson-client: -------------------------------------------------------------------------------- 1 | var features = require('users/gena/packages:geometry-test-geojson').getFeatures() 2 | 3 | Map.addLayer(features) 4 | Map.centerObject(features, 15) 5 | -------------------------------------------------------------------------------- /examples/geometry-test-stdellipse: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var points = 3 | /* color: #d63000 */ 4 | /* shown: false */ 5 | ee.FeatureCollection( 6 | [ee.Feature( 7 | ee.Geometry.Point([-149.19870133078322, 34.947115160827344]), 8 | { 9 | "system:index": "0" 10 | }), 11 | ee.Feature( 12 | ee.Geometry.Point([-148.51754898703322, 34.459390634049505]), 13 | { 14 | "system:index": "1" 15 | }), 16 | ee.Feature( 17 | ee.Geometry.Point([-147.90231461203322, 33.16322994946134]), 18 | { 19 | "system:index": "2" 20 | }), 21 | ee.Feature( 22 | ee.Geometry.Point([-148.64938492453322, 33.95057552851489]), 23 | { 24 | "system:index": "3" 25 | }), 26 | ee.Feature( 27 | ee.Geometry.Point([-148.69333023703322, 33.749845332622115]), 28 | { 29 | "system:index": "4" 30 | }), 31 | ee.Feature( 32 | ee.Geometry.Point([-148.57248062765822, 35.10006199788487]), 33 | { 34 | "system:index": "5" 35 | }), 36 | ee.Feature( 37 | ee.Geometry.Point([-148.36374039328322, 33.512011620307085]), 38 | { 39 | "system:index": "6" 40 | }), 41 | ee.Feature( 42 | ee.Geometry.Point([-147.11129898703322, 32.70218567549612]), 43 | { 44 | "system:index": "7" 45 | }), 46 | ee.Feature( 47 | ee.Geometry.Point([-145.99069351828322, 31.996818829698]), 48 | { 49 | "system:index": "8" 50 | }), 51 | ee.Feature( 52 | ee.Geometry.Point([-149.50631851828322, 36.215841038948135]), 53 | { 54 | "system:index": "9" 55 | }), 56 | ee.Feature( 57 | ee.Geometry.Point([-146.86959976828322, 33.38367564024694]), 58 | { 59 | "system:index": "10" 60 | })]); 61 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 62 | var g = require('users/gena/packages:geometry') 63 | 64 | var ellipse = g.standardDeviationEllipse(points) 65 | 66 | Map.centerObject(points) 67 | 68 | print(ellipse) 69 | 70 | Map.addLayer(points) 71 | Map.addLayer(ellipse, { color: 'green' }) -------------------------------------------------------------------------------- /examples/geometry-test-transects: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.LineString( 3 | [[-104.11332197432773, 30.116700307856185], 4 | [-103.47611494307773, 30.292353435692192], 5 | [-102.37748213057773, 30.102444432809047], 6 | [-101.77872724776523, 30.235419207764423], 7 | [-101.33378095870273, 30.368214352537645]]); 8 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 9 | var geomUtils = require('users/gena/packages:geometry') 10 | 11 | Map.centerObject(geometry) 12 | 13 | // number of segments to generate along the geometry 14 | var n = geometry.length().divide(10) 15 | 16 | // generate the list of offsets 17 | var distances = ee.List.sequence(0, geometry.length(), n) 18 | 19 | // split into n segments 20 | var segments = geometry.cutLines(distances).geometries() 21 | 22 | // generate transect for every segment by rotating it 23 | var transects = segments.map(function(g) { 24 | var length = 10000 25 | var transect = geomUtils.createTransectAtCentroid(g, length) 26 | 27 | return ee.Feature(transect) 28 | }) 29 | 30 | transects = ee.FeatureCollection(transects) 31 | 32 | Map.addLayer(transects) 33 | -------------------------------------------------------------------------------- /examples/geometry-test-vector: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var origin = /* color: #d63000 */ee.Geometry.Point([-126.01318359375, 40.9964840143779]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var geometryUtils = require('users/gena/packages:geometry') 12 | 13 | // show origin 14 | Map.addLayer(origin, {color: 'green'}, 'origin') 15 | 16 | Map.centerObject(origin, 8) 17 | 18 | // length in degrees 19 | var angle = 45 20 | var length = 1 // degrees 21 | var vector = geometryUtils.createVector(origin, angle, length) 22 | Map.addLayer(vector, {color: 'blue'}, 'vector') 23 | 24 | // length in meters 25 | var angle = 180 26 | var length = 50000 // meters 27 | var vector = geometryUtils.createVector(origin.transform('EPSG:3857'), angle, length) 28 | Map.addLayer(vector, {color: 'green'}, 'vector') 29 | 30 | // animate 31 | var animation = require('users/gena/packages:animation') 32 | var length = 1 // degrees 33 | var lines = ee.List.sequence(0, 360, 10).map(function(a) { 34 | var vector = geometryUtils.createVector(origin, a, length) 35 | 36 | return ee.Image().paint(vector, 1, 2).visualize({palette: ['ffff00']}) 37 | }) 38 | animation.animate(lines, {maxFrames: 37}) 39 | 40 | -------------------------------------------------------------------------------- /examples/gl-test-empty: -------------------------------------------------------------------------------- 1 | // Shadertoy ray marching tutorial: https://www.youtube.com/watch?v=yxNnRSefK94 2 | 3 | Map.setCenter(0, 0, 15) 4 | 5 | var gl = require('users/gena/packages:gl').init() 6 | 7 | function render(time) { 8 | var uv = gl.fragCoord.divide(gl.iResolution.xy) 9 | 10 | // make coordinates go from -1 to 1 11 | //uv = uv.multiply(2).subtract(1) 12 | 13 | return uv.addBands(0) 14 | 15 | return color 16 | } 17 | 18 | // ================================== 19 | Map.setLocked(true) 20 | 21 | var vis = { min: 0, max: 1 } 22 | 23 | // var vis = { min: -1, max: 1 } 24 | 25 | var image = render(0) 26 | Map.addLayer(image, vis, 'image') 27 | -------------------------------------------------------------------------------- /examples/gl-test-gradient: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("COPERNICUS/S2"), 3 | geometry = /* color: #de5a5a */ee.Geometry.LineString( 4 | [[55.18100532189851, 25.118768217524654], 5 | [55.16315224611867, 25.086590753213407]]); 6 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 7 | var gl = require('users/gena/packages:gl') 8 | 9 | Map.centerObject(geometry) 10 | 11 | var mask = gl.getGradientMask(geometry) 12 | 13 | var image = images 14 | .filterBounds(geometry.centroid()) 15 | .filterDate('2018-05-01', '2018-06-01') 16 | .first() 17 | .visualize({ bands: ['B11', 'B8', 'B2'], min: 500, max: 5000, gamma: 0.8 }) 18 | 19 | Map.addLayer(image.updateMask(mask)) 20 | 21 | -------------------------------------------------------------------------------- /examples/gl-test-mesh: -------------------------------------------------------------------------------- 1 | Map.setCenter(0, 0, 7) 2 | 3 | var mesh = { 4 | vertices: [ 5 | // front 6 | [-1.0, -1.0, 1.0], 7 | [ 1.0, -1.0, 1.0], 8 | [ 1.0, 1.0, 1.0], 9 | [-1.0, 1.0, 1.0], 10 | // back 11 | [-1.0, -1.0, -1.0], 12 | [ 1.0, -1.0, -1.0], 13 | [ 1.0, 1.0, -1.0], 14 | [-1.0, 1.0, -1.0], 15 | ], 16 | edges: [ 17 | [0, 1], [1, 2], [2, 3], [3, 0], 18 | [4, 5], [5, 6], [6, 7], [7, 4], 19 | [0, 4], [1, 5], [2, 6], [3, 7] 20 | ] 21 | } 22 | 23 | var rotationX = function(angle) { 24 | return ee.Array([ [1, 0, 0], [0, angle.cos(), angle.sin().multiply(-1)], [0, angle.sin(), angle.cos()] ]) 25 | } 26 | 27 | var rotationY = function(angle) { 28 | return ee.Array([ [angle.cos(), 0, angle.sin()], [0, 1, 0], [angle.sin().multiply(-1), 0, angle.cos()] ]) 29 | } 30 | 31 | var rotationZ = function(angle) { 32 | return ee.Array([ [angle.cos(), angle.sin().multiply(-1), 0], [angle.sin(), angle.cos(), 0], [0, 0, 1] ]) 33 | } 34 | 35 | function rotate(vertices, angle, rotation) { 36 | var angle = ee.Number(angle).multiply(Math.PI).divide(180) 37 | vertices = rotation(angle).matrixMultiply(ee.Array(vertices).transpose()).transpose() 38 | 39 | return vertices 40 | } 41 | 42 | var vertices = ee.Array(mesh.vertices) 43 | vertices = rotate(vertices, 10, rotationX) 44 | vertices = rotate(vertices, 10, rotationY) 45 | 46 | var angleCount = 60 47 | var angleMax = 360 48 | var angleStep = angleMax / angleCount 49 | var vertices = ee.List.sequence(0, angleMax, angleStep).iterate(function(angle, prev) { 50 | var list = ee.List(prev) 51 | 52 | var vertices = list.get(-1) 53 | 54 | vertices = rotate(vertices, angleStep, rotationY) 55 | 56 | return list.add(vertices) 57 | }, ee.List([vertices])) 58 | 59 | var images = ee.List(vertices).map(function(vertices) { 60 | vertices = ee.Array(vertices) 61 | 62 | var lines = mesh.edges.map(function(edge) { 63 | edge = ee.List(edge) 64 | 65 | return ee.Geometry.LineString([ 66 | vertices.slice(0, edge.get(0), ee.Number(edge.get(0)).add(1)).toList().flatten().slice(0, 2), 67 | vertices.slice(0, edge.get(1), ee.Number(edge.get(1)).add(1)).toList().flatten().slice(0, 2) 68 | ]) 69 | }) 70 | 71 | lines = ee.FeatureCollection(lines) 72 | 73 | return ee.Image().paint(lines, 1, 1) 74 | }) 75 | 76 | images = ee.ImageCollection(images) 77 | 78 | var animation = require('users/gena/packages:animation') 79 | animation.animate(images, { maxFrames: Math.floor(angleMax / angleStep) }) 80 | -------------------------------------------------------------------------------- /examples/gl-test-rotate-image: -------------------------------------------------------------------------------- 1 | var animation = require('users/gena/packages:animation') 2 | var gl = require('users/gena/packages:gl') 3 | 4 | var image = ee.Image(ee.ImageCollection('COPERNICUS/S2').filterBounds(Map.getCenter()).toList(1, 0).get(0))//.resample('bicubic') 5 | var vis = { min: 500, max: 5000, gamma: 1.4, bands: ['B12', 'B8', 'B4'] } 6 | 7 | Map.centerObject(image) 8 | 9 | // var image = ee.Image(ee.ImageCollection('LANDSAT/LC08/C01/T1_RT_TOA').filterBounds(Map.getCenter()).toList(1, 1).get(0))//.resample('bicubic') 10 | // var vis = { min: 0.0500, max: 0.5000, gamma: 1.4, bands: ['B6', 'B5', 'B4'] } 11 | 12 | var origin = Map.getCenter() 13 | var angles = ee.List.sequence(0, Math.PI * 2, Math.PI / 20) 14 | 15 | var images = angles.map(function(angle) { 16 | return gl.rotateImage(image, origin, angle) 17 | }) 18 | 19 | animation.animate(images, { vis: vis, maxFrames: 40 }) 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/gl-test-sphere: -------------------------------------------------------------------------------- 1 | // Shadertoy ray marching tutorial: https://www.youtube.com/watch?v=yxNnRSefK94 2 | 3 | var gl = require('users/gena/packages:gl').init() 4 | 5 | /*** 6 | * Signed distance function to show a sphere 7 | */ 8 | function sdfSphere(p) { 9 | return gl.length(p).subtract(1.0) 10 | } 11 | 12 | /*** 13 | * Raymarching 14 | * 15 | * o - origin 16 | * r - ray 17 | */ 18 | function trace(o, r) { 19 | var t = ee.Image.constant(0.0); 20 | 21 | var i = ee.List.sequence(0, 32, 1) 22 | 23 | t = i.iterate(function(i, prev) { 24 | prev = ee.Image(prev) 25 | var p = o.add(r.multiply(prev)) 26 | var d = sdfSphere(p) 27 | prev = prev.add(d.multiply(0.5)) 28 | return prev 29 | }, t) 30 | 31 | return ee.Image(t) 32 | } 33 | 34 | /*** 35 | * Main rendering function 36 | */ 37 | function render(time) { 38 | var uv = gl.fragCoord.divide(gl.iResolution.xy) 39 | 40 | // make coordinates go from -1 to 1 41 | uv = uv.multiply(2).subtract(1) 42 | 43 | uv = uv.multiply(ee.Image([gl.iResolution.x.divide(gl.iResolution.y), 1.0])) 44 | 45 | var z = -3 46 | 47 | var r = gl.normalize(uv.addBands(ee.Image.constant(1).rename('z'))) 48 | var o = ee.Image([0, 0, z]) 49 | var t = trace(o, r) 50 | var fog = ee.Image.constant(1).divide(ee.Image.constant(1.0).add(t.multiply(t).multiply(0.1))) 51 | 52 | var color = fog 53 | 54 | return color 55 | } 56 | 57 | // ================================== 58 | Map.setCenter(0, 0, 15) 59 | Map.setLocked(true) 60 | 61 | var vis = { min: 0, max: 1 } 62 | 63 | var image = render(0) 64 | Map.addLayer(image, vis, 'image') 65 | 66 | // var animation = require('users/gena/packages:animation') 67 | // var images = ee.List.sequence(0, 1.91, 0.1).map(function(t) { return render(t) }) 68 | // animation.animate(images, { vis: vis, timeStep: 50, maxFrames: 100 }) 69 | 70 | -------------------------------------------------------------------------------- /examples/gl-test-sphere-shadow: -------------------------------------------------------------------------------- 1 | // Shadertoy ray marching tutorial: https://www.youtube.com/watch?v=yxNnRSefK94 2 | 3 | var gl = require('users/gena/packages:gl').init() 4 | 5 | var z = -4 6 | var zlight = -3 7 | 8 | /*** 9 | * Signed distance function to show a sphere 10 | */ 11 | function sdfSphere(p) { 12 | return gl.length(p).subtract(1.0) 13 | } 14 | 15 | var EPSILON = 0.0001 16 | 17 | function sdfSphereNormal(p) { 18 | return gl.normalize( 19 | ee.Image([ 20 | sdfSphere(p.add(ee.Image.constant([EPSILON, 0, 0]))).subtract(sdfSphere(p.add(ee.Image.constant([-EPSILON, 0, 0])))), 21 | sdfSphere(p.add(ee.Image.constant([0, EPSILON, 0]))).subtract(sdfSphere(p.add(ee.Image.constant([0, -EPSILON, 0])))), 22 | sdfSphere(p.add(ee.Image.constant([0, 0, EPSILON]))).subtract(sdfSphere(p.add(ee.Image.constant([0, 0, -EPSILON])))) 23 | ]) 24 | ) 25 | } 26 | 27 | /*** 28 | * Raymarching 29 | * 30 | * o - origin 31 | * r - ray direction 32 | */ 33 | function trace(o, r) { 34 | var t = ee.Image.constant(0.0) 35 | var n = ee.Image.constant(0.0) 36 | 37 | for(var i=0; i<16; i++) { 38 | var p = o.add(r.multiply(t)) 39 | 40 | var sphere = sdfSphere(p) 41 | 42 | var Lp = ee.Image([1, 1.5, zlight]) 43 | var L = gl.normalize(Lp.subtract(o)) 44 | var N = sdfSphereNormal(p) 45 | var dotLN = L.toArray().arrayDotProduct(N.toArray()) 46 | 47 | var n = dotLN.multiply(ee.Image([1, 1, 0.3])) 48 | // var n = n.add(dotLN.multiply(ee.Image([1, 0.7, 0.1])) 49 | // //.multiply(sphere.abs().lt(0.5)) 50 | // .multiply(0.5) 51 | // ) 52 | 53 | 54 | // var n = n.add(sdfSphereNormal(p).multiply(sphere.lt(0.5))) 55 | 56 | t = t.add(sphere) 57 | } 58 | 59 | /* 60 | var i = ee.List.sequence(0, 32, 1) 61 | 62 | t = i.iterate(function(i, prev) { 63 | prev = ee.Image(prev) 64 | var p = o.add(r.multiply(prev)) 65 | 66 | var sphere = sdfSphere(p) 67 | 68 | prev = prev.add(sphere.multiply(0.5)) 69 | return prev 70 | }, t) 71 | */ 72 | 73 | t = ee.Image(t) 74 | 75 | /* 76 | var s = ee.Image.constant(0.0) 77 | var Lp = ee.Image([1, 1, 0]) 78 | var L = gl.normalize(Lp.subtract(o)) 79 | 80 | s = i.iterate(function(i, prev) { 81 | prev = ee.Image(prev) 82 | var p = o.add(r.multiply(prev)) 83 | 84 | var N = sdfSphereNormal(p) 85 | var dotLN = L.toArray().arrayDotProduct(N.toArray()) 86 | 87 | //var diff = dotLN.multiply(0.1) 88 | var diff = N 89 | 90 | prev = prev.add(diff) 91 | 92 | return prev 93 | }, s) 94 | */ 95 | var fog = ee.Image.constant(1).divide(ee.Image.constant(1.0).add(t.multiply(t).multiply(0.1))) 96 | 97 | fog = fog.add(n) 98 | 99 | return fog// .add(s) 100 | } 101 | 102 | /*** 103 | * Main rendering function 104 | */ 105 | function render(time) { 106 | var uv = gl.fragCoord.divide(gl.iResolution.xy) 107 | 108 | // make coordinates go from -1 to 1 109 | uv = uv.multiply(2).subtract(1) 110 | 111 | uv = uv.multiply(ee.Image([gl.iResolution.x.divide(gl.iResolution.y), 1.0])) 112 | 113 | var r = gl.normalize(uv.addBands(ee.Image.constant(1).rename('z'))) 114 | var o = ee.Image([0, 0, z]) 115 | var t = trace(o, r) 116 | 117 | var color = t 118 | 119 | return color 120 | } 121 | 122 | // ================================== 123 | // Map.setCenter(0, 0, 5) 124 | //Map.setLocked(true) 125 | 126 | var vis = { min: 0, max: 1 } 127 | 128 | var image = render(0) 129 | Map.addLayer(image.mask(ee.Image(1.2).subtract(image)), vis, 'image') 130 | 131 | // var animation = require('users/gena/packages:animation') 132 | // var images = ee.List.sequence(0, 1.91, 0.1).map(function(t) { return render(t) }) 133 | // animation.animate(images, { vis: vis, timeStep: 50, maxFrames: 100 }) 134 | 135 | -------------------------------------------------------------------------------- /examples/gl-test-spheres: -------------------------------------------------------------------------------- 1 | // Shadertoy ray marching tutorial: https://www.youtube.com/watch?v=yxNnRSefK94 2 | 3 | var gl = require('users/gena/packages:gl') 4 | 5 | /*** 6 | * Signed distance function for a 3D space filled with spheres 7 | */ 8 | function sdfSpace(p) { 9 | var q = gl.fract(p).multiply(2).subtract(1) 10 | 11 | return gl.length(q).subtract(0.25) 12 | } 13 | 14 | /*** 15 | * Raymarching 16 | * 17 | * o - origin 18 | * r - ray 19 | */ 20 | function trace(o, r) { 21 | var t = ee.Image.constant(0.0); 22 | 23 | var i = ee.List.sequence(0, 32, 1) 24 | 25 | t = i.iterate(function(i, prev) { 26 | prev = ee.Image(prev) 27 | var p = o.add(r.multiply(prev)) 28 | var d = sdfSpace(p) 29 | prev = prev.add(d.multiply(0.5)) 30 | return prev 31 | }, t) 32 | 33 | return ee.Image(t) 34 | } 35 | 36 | /*** 37 | * Main rendering function 38 | */ 39 | function render(time) { 40 | var info = gl.init(Map.getBounds(true)) 41 | 42 | var uv = info.fragCoord.divide(info.iResolution.xy) 43 | time = ee.Number(time) 44 | 45 | // make coordinates go from -1 to 1 46 | uv = uv.multiply(2).subtract(1) 47 | 48 | // set aspect ratio 49 | uv = uv.multiply(ee.Image([info.iResolution.x.divide(info.iResolution.y), 1.0])) 50 | 51 | // use time to move origin along z axis and to rotate 52 | var z = ee.Number(time).multiply(0.5) 53 | 54 | // normalize ray, FOV=90 55 | var r = gl.normalize(uv.addBands(ee.Image.constant(1).rename('z'))) 56 | 57 | // rotate r around y axis 58 | var angle = time.multiply(Math.PI / 4) 59 | r = gl.rotate(r, ['x', 'z'], angle) 60 | 61 | // origin 62 | var o = ee.Image([0, z, z]) 63 | 64 | // render 65 | var t = trace(o, r) 66 | 67 | // fog function 1/(1 + 0.1 * t^2) 68 | var fog = ee.Image.constant(1).divide(ee.Image.constant(1.0).add(t.multiply(t).multiply(0.1))) 69 | 70 | return fog 71 | } 72 | 73 | // ================================== 74 | Map.setCenter(0, 0, 15) 75 | Map.setLocked(true) 76 | 77 | var vis = { min: 0, max: 1 } 78 | 79 | // var image = render(0) 80 | // Map.addLayer(image, vis, 'image') 81 | 82 | var animation = require('users/gena/packages:animation') 83 | var images = ee.List.sequence(0, 2-0.0001, 0.05).map(function(t) { return render(t) }) 84 | animation.animate(images, { vis: vis, timeStep: 50, maxFrames: 100 }) 85 | 86 | -------------------------------------------------------------------------------- /examples/gl-test-trouchet: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var land = ee.Image("users/gena/land_polygons_image"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | // tutorial: https://youtu.be/2R7h76GoIJM 5 | 6 | Map.setCenter(78, 16, 6) 7 | // Map.setLocked(true) 8 | 9 | var gl = require('users/gena/packages:gl').init() 10 | 11 | function Hash21(p) { 12 | p = gl.fract(p.multiply(gl.vec2(234.34, 436.345))) 13 | p = p.add(gl.dot(p, p.add(34.23))) 14 | 15 | return gl.fract(p.select(0).multiply(p.select(1))).arrayFlatten([['x', 'y']]).select(0) 16 | } 17 | 18 | function render(time) { 19 | var uv = gl.fragCoord.subtract(gl.iResolution.xy.multiply(0.5)).divide(gl.iResolution.y) 20 | var UV = gl.fragCoord.divide(gl.iResolution.xy) 21 | 22 | var col = ee.Image([0, 0, 0]) 23 | 24 | uv = uv.add(ee.Image.constant(time)) 25 | 26 | uv = uv.multiply(30) 27 | 28 | var gv = gl.fract(uv).subtract(0.5) 29 | var id = uv.floor() 30 | var n = Hash21(id) 31 | var width = UV.select('y').multiply(0.2) 32 | // var width = ee.Image(0.2) 33 | gv = gv.where(n.lt(0.5), gv.multiply([-1, 1])) 34 | var gvs = gv.reduce(ee.Reducer.sum()) 35 | var d = gvs.abs().subtract(0.5).abs() 36 | var cUv = gv.subtract(gl.sign(gvs.add(.001)).multiply(0.5)) 37 | d = gl.length(cUv) 38 | var mask = gl.smoothstep(.01, -.01, d.subtract(0.5).abs().subtract(width)) 39 | var angle = cUv.select(0).atan2(cUv.select(1)) // -pi to pi 40 | var checker = id.reduce(ee.Reducer.sum()).mod(2.0).abs().multiply(2).subtract(1) 41 | 42 | var iTime = ee.Number(time) 43 | var flow = checker.multiply(angle).multiply(10).add(iTime).sin() 44 | 45 | var x = gl.fract(angle.divide(1.57)).subtract(iTime.multiply(0.3)) 46 | var y = d.add(width.subtract(0.5)).divide(width.multiply(2)) 47 | y = y.subtract(0.5).abs().multiply(2) 48 | var tUv = x.addBands(y) 49 | 50 | /* 51 | gl.texture() is not implemented yet 52 | 53 | vec2 tUv = vec2(x, y); 54 | col += texture(iChannel0, tUv).rgb*mask; 55 | */ 56 | 57 | // col = col.add(checker) 58 | // col = col.add(angle.multiply(checker).multiply(10).sin()) 59 | // col = col.add(x) 60 | col = col.add(ee.Image(1).subtract(y)) 61 | // col = col.add(tUv.addBands(0)) 62 | col = col.multiply(mask) 63 | 64 | // col = col.where(gv.select('x').gt(0.46).or(gv.select('y').gt(0.46)), ee.Image([1, 0, 0])) 65 | 66 | return col 67 | } 68 | 69 | // ================================== 70 | 71 | var image = render(0) 72 | 73 | var vis = { min: 0, max: 1 } 74 | 75 | Map.addLayer(image.updateMask(image.reduce(ee.Reducer.max())).updateMask(land.mask()), vis, 'image') 76 | Map.setOptions('SATELLITE') 77 | 78 | var dem = ee.Image("JAXA/ALOS/AW3D30/V2_2").select('AVE_DSM').multiply(10) 79 | Map.addLayer(ee.Terrain.hillshade(dem.add(dem.multiply(image.multiply(2))), 315, 25).updateMask(land.mask()), {}, 'dem', false) 80 | 81 | // not ready yet 82 | 83 | // var a = require('users/gena/packages:animation') 84 | // a.animate(ee.List.sequence(0, 10, 0.1).map(function(t) { 85 | // var i = render(t) 86 | // return i.updateMask(i.reduce(ee.Reducer.max())).updateMask(land.mask()) 87 | // }), { 88 | // vis: vis 89 | // }) 90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/grid-test: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | // source code for the grid package: https://code.earthengine.google.com/?accept_repo=users/gena/packages 9 | 10 | var g = require('users/gena/packages:grid') 11 | 12 | // vector grid 13 | var gridVector = g.generateGrid(-180, -50, 180, 50, 10, 10, 0, 0) 14 | Map.addLayer(gridVector, {}, 'grid vector') 15 | 16 | // raster grid 17 | var gridRaster = g.generateRasterGrid(ee.Geometry.Point(0, 0), 10, 10, ee.Projection('EPSG:4326')) 18 | Map.addLayer(gridRaster.select('id').randomVisualizer(), {}, 'grid raster') 19 | -------------------------------------------------------------------------------- /examples/grid-test-NxM: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Polygon( 3 | [[[-64.92167968749999, 34.655531078083555], 4 | [-66.67949218749999, 28.906915730294664], 5 | [-61.34013671874999, 30.982034292755003]]]); 6 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 7 | var grid = require('users/gena/packages:grid') 8 | 9 | var nx = 10 10 | var ny = 10 11 | var g = grid.generateGridForGeometryN(geometry, nx, ny) 12 | 13 | Map.addLayer(g.map(function(i) { return i.centroid() }), {}, 'grid 10x10') 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/grid-test-vector-geometry: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d6cf80 */ee.Geometry.Polygon( 3 | [[[-123.764453125, 46.22237311798524], 4 | [-113.393359375, 63.56613888086946], 5 | [-134.22343750000002, 59.37572044490845], 6 | [-135.71757812500002, 53.24940538373933], 7 | [-133.69609375000002, 47.6623893372254]]]), 8 | geometry2 = /* color: #c0d9ff */ee.Geometry.Polygon( 9 | [[[-82.93742004915627, 52.34900263629273], 10 | [-83.46476379915627, 61.3758611088044], 11 | [-93.48429504915626, 63.332588726606204], 12 | [-102.36124817415626, 62.124619525972726], 13 | [-100.77921692415626, 57.633849778352165], 14 | [-93.30851379915626, 46.1039805510087]]]); 15 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 16 | /* 17 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 18 | 19 | This work is licensed under the terms of the MIT license. 20 | For a copy, see . 21 | */ 22 | 23 | var g = require('users/gena/packages:grid') 24 | 25 | // generateGridForGeometry(g, dx, dy, opt_marginx, opt_marginy, opt_proj) 26 | 27 | // WEB 28 | var proj = 'EPSG:3857' 29 | var dx = 400000 30 | var dy = 400000 31 | var marginx = 0, marginy = 0 32 | var grid1 = g.generateGridForGeometry(geometry, dx, dy, marginx, marginy, proj) 33 | Map.addLayer(grid1, { color: 'brown' }, 'grid1') 34 | 35 | // GEO 36 | proj = 'EPSG:4326' 37 | dx = 2 38 | dy = 2 39 | var grid2 = g.generateGridForGeometry(geometry2, dx, dy, marginx, marginy, proj) 40 | Map.addLayer(grid2, { color: 'black' }, 'grid2') 41 | -------------------------------------------------------------------------------- /examples/hydro-test-catchments-rivers: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Point([104.15686444297819, 18.113424797553826]); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var hydro = require('users/gena/packages:hydro') 5 | 6 | // get catchments (all of level 6 and given an outlet) 7 | var catchments = hydro.getCatchments({level: 6}) 8 | var catchmentsSelected = hydro.getCatchments({outlet: geometry, level: 6}) 9 | 10 | Map.addLayer(catchments.style({color: 'ffffff55', width: 1, fillColor: '00000088'}), {}, 'catchments (all)') 11 | Map.addLayer(catchmentsSelected.style({color: 'ffff0055', width: 1, fillColor: 'ffff0088'}), {}, 'catchments (selected)') 12 | 13 | // add rivers (all) 14 | var rivers = hydro.getRivers() 15 | Map.addLayer(rivers.filter(ee.Filter.gt('UP_CELLS', 50000)).style({color: '00ffff', width: 1 }), {}, 'rivers (th > 50000)', true, 0.5) 16 | 17 | // add rivers(selected catchments only) 18 | var rivers = hydro.getRivers({catchments: catchmentsSelected}) 19 | 20 | Map.addLayer(rivers.filter(ee.Filter.gt('UP_CELLS', 10000)).style({color: '00ffff', width: 2 }), {}, 'rivers (selected, th > 10000)') 21 | Map.addLayer(rivers.filter(ee.Filter.gt('UP_CELLS', 1000)).style({color: '00ffff', width: 1 }), {}, 'rivers (selected, th > 1000)') 22 | 23 | var rivers = ee.FeatureCollection('users/gena/HydroEngine/riv_15s_lev06') 24 | 25 | print(rivers.first()) 26 | print(catchmentsSelected.first()) -------------------------------------------------------------------------------- /examples/hydro-test-hand: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var hydro = require('users/gena/packages:hydro') 9 | 10 | // var smoothing = true 11 | var smoothing = false 12 | 13 | hydro.Map.addHand({layer: {name: 'HAND 30m, SRTM, FA threhold = 1000', smoothing: smoothing}}) 14 | 15 | hydro.Map.addHand({layer: {name: 'HAND 90m, MERIT'}, type: 'MERIT', smoothing: smoothing}) -------------------------------------------------------------------------------- /examples/image-view-test: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var band = 'B8A' 9 | var image = ee.ImageCollection('COPERNICUS/S2').first().select(band) 10 | Map.centerObject(image.geometry().centroid(1), 19) 11 | 12 | image = image.divide(10000) 13 | 14 | Map.addLayer(image, {min: 0.05, max: 0.6 }, 'image') 15 | 16 | var imageView = require('users/gena/packages:image-view') 17 | var text = require('users/gena/packages:text') 18 | 19 | // show pixel centers 20 | var view = new imageView.ImageView(image.clip(ee.Geometry(Map.getBounds(true)))) 21 | 22 | var pixelCenters = view.getPixelCenters() 23 | 24 | Map.addLayer(pixelCenters.style({pointSize: 1, color: 'yellow'}), {}, 'pixel centers') 25 | 26 | // show pixel values 27 | var pixelValues = image.reduceRegions(pixelCenters, ee.Reducer.first().setOutputs([band]), Map.getScale()) 28 | 29 | print(pixelValues 30 | ) 31 | var labels = pixelValues.map(function(f) { 32 | var value = ee.Number(f.get(band)) 33 | var point = f.geometry() 34 | var scale = Map.getScale() 35 | var label = text.draw(value.format('%.2f'), point, scale, { fontSize: 16 }) 36 | 37 | return label 38 | }) 39 | 40 | var labels = ee.ImageCollection(labels).mosaic() 41 | 42 | Map.addLayer(labels, {}, 'label') 43 | -------------------------------------------------------------------------------- /examples/palettes-test: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("USGS/SRTMGL1_003"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var palettes = require('users/gena/packages:palettes') 12 | 13 | // colorbrewer 14 | Map.addLayer(dem, {min: 0, max: 3000, palette: palettes.colorbrewer.Blues[9]}, 'colorbrewer Blues[9]') 15 | 16 | // cmocean 17 | Map.addLayer(dem, {min: 0, max: 3000, palette: palettes.cmocean.Algae[7]}, 'cmocean Algae[7]') 18 | 19 | -------------------------------------------------------------------------------- /examples/palettes-test-crameri-dem: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("AHN/AHN2_05M_RUW"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var utils = require('users/gena/packages:utils') 5 | var palettes = require('users/gena/packages:palettes') 6 | 7 | Map.setOptions('HYBRID') 8 | Map.setCenter(4.408241, 52.177595, 18) 9 | dem = dem.resample('bicubic') 10 | .convolve(ee.Kernel.gaussian(0.5, 0.25, 'meters')) 11 | 12 | // var palette = palettes.crameri.lisbon[25] 13 | // palettes.showPalette('lisbon', palette) 14 | 15 | // var palette = palettes.cb.Greys[9].reverse() 16 | // palettes.showPalette('greys', palette) 17 | 18 | var palette = palettes.crameri.oleron[50] 19 | palettes.showPalette('oleron', palette) 20 | 21 | // var palette = palettes.crameri.roma[25].slice(0).reverse() 22 | // palettes.showPalette('roma', palette) 23 | 24 | var demRGB = dem.visualize({ min: -5, max: 5, palette: palette }) 25 | 26 | var weight = 0.4 // wegith of Hillshade vs RGB intensity (0 - flat, 1 - HS) 27 | var exaggeration = 5 // vertical exaggeration 28 | var azimuth = 315 // Sun azimuth 29 | var zenith = 20 // Sun elevation 30 | var brightness = -0.05 // 0 - default 31 | var contrast = 0.05 // 0 - default 32 | var saturation = 0.8 // 1 - default 33 | var castShadows = false 34 | 35 | // no shadows 36 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 37 | Map.addLayer(rgb, {}, 'DEM (no shadows)', false) 38 | 39 | // with shadows 40 | var castShadows = true 41 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 42 | Map.addLayer(rgb, {}, 'DEM') 43 | 44 | 45 | Map.addLayer(dem, {}, 'DEM (raw)', false) 46 | 47 | /* 48 | var frames = ee.List.sequence(5, 90, 1).map(function(zenith) { 49 | return utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 50 | }) 51 | 52 | 53 | var animation = require('users/gena/packages:animation') 54 | animation.animate(frames, { maxFrames: 90 }) 55 | */ -------------------------------------------------------------------------------- /examples/palettes-test-crameri-dem-changes: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("AHN/AHN2_05M_RUW"), 3 | dem2 = ee.Image("users/gena/AHN3_DSM"); 4 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 5 | var utils = require('users/gena/packages:utils') 6 | var palettes = require('users/gena/packages:palettes') 7 | var assets = require('users/gena/packages:assets') 8 | var animation = require('users/gena/packages:animation') 9 | 10 | Map.setOptions('HYBRID') 11 | // Map.setCenter(4.408241, 52.177595, 18) 12 | dem = dem.resample('bicubic') 13 | .convolve(ee.Kernel.gaussian(0.5, 0.25, 'meters')) 14 | 15 | // var palette = palettes.crameri.lisbon[25] 16 | // palettes.showPalette('lisbon', palette) 17 | 18 | var palette = palettes.crameri.oleron[50] 19 | // palettes.showPalette('oleron', palette) 20 | 21 | // var palette = palettes.crameri.roma[25].slice(0).reverse() 22 | // palettes.showPalette('roma', palette) 23 | 24 | var demRGB = dem.visualize({ min: -5, max: 5, palette: palette }) 25 | 26 | var weight = 0.5 // wegith of Hillshade vs RGB intensity (0 - flat, 1 - HS) 27 | var exaggeration = 25 // vertical exaggeration 28 | var azimuth = 315 // Sun azimuth 29 | var zenith = 15 // Sun elevation 30 | var brightness = -0.05 // 0 - default 31 | var contrast = 0.05 // 0 - default 32 | var saturation = 0.8 // 1 - default 33 | var castShadows = false 34 | 35 | // no shadows 36 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 37 | Map.addLayer(rgb, {}, 'DEM (no shadows)', false) 38 | 39 | // with shadows 40 | var castShadows = true 41 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 42 | Map.addLayer(rgb, {}, 'DEM') 43 | 44 | 45 | // with shadows (new) 46 | var demRGB2 = dem2.visualize({ min: -5, max: 5, palette: palette }) 47 | var rgb2 = utils.hillshadeRGB(demRGB2, dem2, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 48 | Map.addLayer(rgb2, {}, 'DEM2') 49 | 50 | // show changes 51 | var diff = dem2.subtract(dem) 52 | Map.addLayer(diff.mask(diff.abs().unitScale(0, 0.5)), { min: -0.5, max: 0.5, palette: palettes.cb.RdYlGn[5] }, 'changes', false) 53 | 54 | 55 | 56 | 57 | // animate 58 | 59 | // Map.addLayer(dem, {}, 'DEM (raw)', false) 60 | 61 | /* 62 | var frames = ee.List.sequence(5, 90, 1).map(function(zenith) { 63 | return utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 64 | }) 65 | 66 | 67 | var animation = require('users/gena/packages:animation') 68 | animation.animate(frames, { maxFrames: 90 }) 69 | */ 70 | 71 | 72 | // show s2 images 73 | var images = assets.getImages(Map.getCenter(), { missions: ['S2'], resample: 'bicubic' }) 74 | images = assets.getMostlyCleanImages(images, Map.getBounds(true), { cloudFrequencyThresholdDelta: 0.25}) 75 | images = images.map(function(i) { return i.set({ label: i.date().format('YYYY-MM-dd') })}) 76 | images = images.sort('system:time_start').distinct(['label']) 77 | print('Image count: ', images.size()) 78 | // animation.animate(images, { vis: { min: 0.05, max: 0.45 }}) 79 | 80 | 81 | // see https://www.ahn.nl/kwaliteitsbeschrijving for years 82 | 83 | // add water for AHN2 (2007) 84 | // var year1 = 2007 // Maasvlaakte 85 | var year1 = 2011 // Den Helder 86 | var images = assets.getImages(Map.getBounds(true), { missions: ['L7', 'L5'], filter: ee.Filter.date(year1 + '-01-01', (year1+2) + '-01-01'), resample: true }) 87 | var water = images.select(['green', 'nir']).reduce(ee.Reducer.percentile([25])).normalizedDifference().unitScale(-0.05, 0.3) 88 | Map.addLayer(water.mask(water), { palette: palettes.cb.Greys[8].slice(4) }, 'water (AHN2)', false) 89 | 90 | 91 | // add water for AHN3 (2017) 92 | // var year2 = 2017 // Maasvlaakte 93 | var year2 = 2016 // Den Helder 94 | var images = assets.getImages(Map.getBounds(true), { missions: ['L8', 'S2'], filter: ee.Filter.date(year2 + '-01-01', (year2+1) + '-01-01'), resample: true }) 95 | var water = images.select(['green', 'nir']).reduce(ee.Reducer.percentile([25])).normalizedDifference().unitScale(-0.05, 0.3) 96 | Map.addLayer(water.mask(water), { palette: palettes.cb.Greys[8].slice(4) }, 'water (AHN3)', false) 97 | -------------------------------------------------------------------------------- /examples/palettes-test-multiple: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.LineString( 3 | [[5.413888688521411, 53.168906784111435], 4 | [5.415390730552872, 53.16897110070959]]); 5 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 6 | /* 7 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 8 | 9 | This work is licensed under the terms of the MIT license. 10 | For a copy, see . 11 | */ 12 | 13 | var palettes = require('users/gena/packages:palettes') 14 | var utils = require('users/gena/packages:utils') 15 | 16 | var dem = ee.Image("AHN/AHN2_05M_RUW"); 17 | //var dem = ee.Image('JAXA/ALOS/AW3D30_V1_1').select('MED').resample('bicubic') 18 | 19 | // dem = dem.convolve(ee.Kernel.gaussian(0.5, 0.3, 'meters')) 20 | 21 | var minMax = dem.reduceRegion(ee.Reducer.percentile([1, 99]), Map.getBounds(true), Map.getScale()).values() 22 | 23 | var min = ee.Number(minMax.get(0)) 24 | var max = ee.Number(minMax.get(1)) 25 | 26 | var exaggregate = 10 27 | var weight = 1.5 28 | var azimuth = 0 29 | var zenith = 25 30 | 31 | // Paired 32 | var styled = dem.visualize({ min: min, max: max, palette: palettes.colorbrewer.Paired[12] }) 33 | Map.addLayer(styled, {}, 'Paired, styled', false) 34 | 35 | 36 | 37 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 38 | Map.addLayer(hillshaded, {}, 'Paired, hillshaded', false) 39 | 40 | // Set1 41 | var styled = dem.visualize({ min: min, max: max, palette: palettes.colorbrewer.Set1[9] }) 42 | Map.addLayer(styled, {}, 'Set1, styled', false) 43 | 44 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 45 | Map.addLayer(hillshaded, {}, 'Set1, hillshaded', false) 46 | 47 | // BrBG 48 | var styled = dem.visualize({ min: max, max: min, palette: palettes.colorbrewer.BrBG[8] }) 49 | Map.addLayer(styled, {}, 'BrBG, styled', false) 50 | 51 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 52 | Map.addLayer(hillshaded, {}, 'BrBG, hillshaded') 53 | 54 | // Spectral 55 | var styled = dem.visualize({ min: max, max: min, palette: palettes.colorbrewer.Spectral[11] }) 56 | Map.addLayer(styled, {}, 'Spectral, styled', false) 57 | 58 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 59 | Map.addLayer(hillshaded, {}, 'Spectral, hillshaded', false) 60 | 61 | 62 | // Accent 8 63 | var styled = dem.visualize({ min: min, max: max, palette: palettes.colorbrewer.Accent[8] }) 64 | Map.addLayer(styled, {}, 'Accent 8, styled', false) 65 | 66 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 67 | Map.addLayer(hillshaded, {}, 'Accent 8, hillshaded', false) 68 | 69 | // Accent 3 70 | var styled = dem.visualize({ min: min, max: max, palette: palettes.colorbrewer.Accent[3] }) 71 | Map.addLayer(styled, {}, 'Accent 3, styled', false) 72 | 73 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 74 | Map.addLayer(hillshaded, {}, 'Accent 3, hillshaded', false) 75 | 76 | 77 | // show all palettes 78 | //palettes.showPalettes(7, palettes.colorbrewer) 79 | 80 | palettes.showPalettes(7, palettes.cmocean) 81 | 82 | // add a gradient bar 83 | var textProperties = { fontSize:16, textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2, outlineOpacity: 0.6 } 84 | 85 | var palette = palettes.colorbrewer.Paired[12] 86 | 87 | var style = require('users/gena/packages:style') 88 | 89 | var labels = ee.List.sequence(min, max, max.subtract(min).divide(5)) 90 | var gradient = style.GradientBar.draw(geometry, { 91 | min: min, max: max, palette: palette, labels: labels, format: '%.1f', text: textProperties, precision: 100 92 | }) 93 | Map.addLayer(gradient, {}, 'gradient bar (DEM)') 94 | -------------------------------------------------------------------------------- /examples/palettes-test-thumb: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var palettes = require('users/gena/packages:palettes') 9 | 10 | // See http://colorbrewer2.org for a full list of palettes 11 | palettes.showPalette('Spectral', palettes.colorbrewer.Spectral[5]) 12 | palettes.showPalette('RdYlGn', palettes.colorbrewer.RdYlGn[11].reverse()) 13 | palettes.showPalette('Paired', palettes.colorbrewer.Paired[10]) 14 | 15 | // See https://matplotlib.org/cmocean/ for a full list of palettes 16 | palettes.showPalette('Algae', palettes.cmocean.Algae[7]) 17 | palettes.showPalette('Phase', palettes.cmocean.Phase[7]) 18 | palettes.showPalette('Deep', palettes.cmocean.Deep[7]) 19 | -------------------------------------------------------------------------------- /examples/palettes-test-thumb-crameri: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var palettes = require('users/gena/packages:palettes') 9 | 10 | // see http://www.fabiocrameri.ch/colourmaps.php for docs on these palettes 11 | 12 | // 10, 25, 50 versions are supported 13 | palettes.showPalette('oleron 10', palettes.crameri.oleron[10]) 14 | palettes.showPalette('oleron 25', palettes.crameri.oleron[25]) 15 | palettes.showPalette('oleron 50', palettes.crameri.oleron[50]) 16 | 17 | // show all 18 | var paletteNames = ['acton', 'bamako', 'batlow', 'berlin', 'bilbao', 19 | 'broc', 'buda', 'cork', 'davos', 'devon', 'grayC', 'hawaii', 'imola', 20 | 'lajolla', 'lapaz', 'lisbon', 'nuuk', 'oleron', 'oslo', 'roma', 'tofino', 21 | 'tokyo', 'turku', 'vik'] 22 | 23 | paletteNames.forEach(function(palette) { 24 | palettes.showPalette(palette, palettes.crameri[palette][50]) 25 | }) 26 | -------------------------------------------------------------------------------- /examples/promise-test: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | // repository: https://code.earthengine.google.com/?accept_repo=users/gena/packages 9 | // file: promise-test 10 | 11 | var Promise = require('users/gena/packages:promise').Promise 12 | 13 | // async call 1, uses EE evaluate 14 | var p1 = new Promise(function(resolve, reject) { 15 | var x = ee.Number(1) 16 | 17 | x.evaluate(function(o) { 18 | resolve(o) 19 | }) 20 | }) 21 | 22 | // async call 2, uses EE evaluate 23 | var p2 = new Promise(function(resolve, reject) { 24 | var y = ee.Number(2) 25 | 26 | y.evaluate(function(o) { 27 | resolve(o) 28 | }) 29 | }) 30 | 31 | // just a string 32 | var p3 = Promise.resolve('Done!') 33 | 34 | // get results sequentially 35 | Promise.sequence([p1, p2, p3]).then(function(values) { 36 | // values are given in a predefined order, independently from the evaluation 37 | print(values) 38 | }) 39 | -------------------------------------------------------------------------------- /examples/style-test-frame-scalebar: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometryFrame = /* color: #d63000 */ee.Geometry.LineString( 3 | [[-120.1959228515625, 36.559325329091834], 4 | [-118.28704833984375, 37.77400521704548]]), 5 | geometryScalebar = /* color: #98ff00 */ee.Geometry.LineString( 6 | [[-118.70452880859375, 36.62214102821768], 7 | [-118.4490966796875, 36.622141028217705]]); 8 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 9 | /* 10 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 11 | 12 | This work is licensed under the terms of the MIT license. 13 | For a copy, see . 14 | */ 15 | 16 | Map.centerObject(geometryFrame, 9) 17 | 18 | var style = require('users/gena/packages:style') 19 | 20 | Map.setOptions(null, {'Publish': [{featureType: 'all', stylers: [{ color: '#ffffff'}]}]}) 21 | Map.addLayer(ee.Image(1), {palette:['ffffff'], opacity: 0.85}, 'white') 22 | 23 | var image = ee.ImageCollection('LANDSAT/LC8_L1T_TOA').filterBounds(geometryFrame).filterDate('2015-05-01', '2015-11-01').median() 24 | Map.addLayer(image.clip(geometryFrame.bounds()), {bands: ['B6', 'B5', 'B3'], min: 0.03, max:0.3}, 'image') 25 | 26 | var textProperties = { 27 | fontSize: 24, textColor: '000000', 28 | marginLeft: 25, marginRight: 10, marginTop: 10, marginBottom: 10 29 | } 30 | var frame = style.Frame.draw(geometryFrame.bounds(), { 31 | left: true, right: true, top: true, bottom: true, 32 | steps:5, size: 5, text: textProperties, format: '%.1f' 33 | }) 34 | Map.addLayer(frame, {}, 'frame') 35 | 36 | var scalebar = style.Scalebar.draw(geometryScalebar, {steps: 3, palette: ['5ab4ac', 'f5f5f5']}) 37 | Map.addLayer(scalebar, {}, 'scalebar') 38 | -------------------------------------------------------------------------------- /examples/style-test-gradientbar: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometryGradientBar = 3 | /* color: #d63000 */ 4 | /* shown: false */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[-104.93453767982349, 39.73211681120685], 12 | [-104.93453767982349, 39.731357722492966], 13 | [-104.90874555793629, 39.731357722492966], 14 | [-104.90874555793629, 39.73211681120685]]], null, false); 15 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 16 | var palettes = require('users/gena/packages:palettes') 17 | var style = require('users/gena/packages:style') 18 | var utils = require('users/gena/packages:utils') 19 | 20 | // INCOMPLETE 21 | // TODO: add scale, make it work for thumbnails as well 22 | 23 | Map.centerObject(geometryGradientBar) 24 | Map.addLayer(ee.Image(1), { palette: ['000000'] }, 'black', true, 0.5) 25 | 26 | // Paired 27 | var palette = palettes.crameri.roma[50].slice(25) 28 | 29 | var min = 0 30 | var max = 80 31 | 32 | print(Map.getScale()) 33 | 34 | // add a gradient bar 35 | var labels = ee.List.sequence(min, max, (max-min)/5) 36 | 37 | // var rect = ee.Geometry.Rectangle({ coords: [[0, 0], [100, 4]], geodesic: false }) 38 | 39 | var textProperties = { fontSize:16, textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2, outlineOpacity: 0.6 } 40 | 41 | var gradientBar = style.GradientBar.draw(geometryGradientBar, { 42 | min: min, max: max, palette: palette, labels: labels, format: '%.0f', text: textProperties 43 | }) 44 | 45 | Map.addLayer(gradientBar) 46 | 47 | // print(ui.Thumbnail(gradientBar.clip(rect.buffer(1000000)), { dimensions: '600x24'})) 48 | 49 | // var m = ui.Map(0, 0) 50 | 51 | // Map.add(m) 52 | // m.centerObject(rect) 53 | // m.addLayer(gradientBar) 54 | 55 | -------------------------------------------------------------------------------- /examples/style-test-gradientbar-scalebar: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometryGradientBar = 3 | /* color: #d63000 */ 4 | /* shown: false */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[-104.93453767982349, 39.73211681120685], 12 | [-104.93453767982349, 39.731357722492966], 13 | [-104.90874555793629, 39.731357722492966], 14 | [-104.90874555793629, 39.73211681120685]]], null, false), 15 | geometryScaleBar = 16 | /* color: #98ff00 */ 17 | /* shown: false */ 18 | /* displayProperties: [ 19 | { 20 | "type": "rectangle" 21 | } 22 | ] */ 23 | ee.Geometry.Polygon( 24 | [[[-104.93337896552906, 39.72541673952824], 25 | [-104.93337896552906, 39.72502065579493], 26 | [-104.90870264259205, 39.72502065579493], 27 | [-104.90870264259205, 39.72541673952824]]], null, false); 28 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 29 | /* 30 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 31 | 32 | This work is licensed under the terms of the MIT license. 33 | For a copy, see . 34 | */ 35 | 36 | // File: style-test-gradientbar 37 | // Package sources: https://code.earthengine.google.com/?accept_repo=users/gena/packages 38 | 39 | Map.centerObject(ee.FeatureCollection([geometryGradientBar, geometryScaleBar])) 40 | 41 | var palettes = require('users/gena/packages:palettes') 42 | var style = require('users/gena/packages:style') 43 | var utils = require('users/gena/packages:utils') 44 | 45 | var dem = ee.Image("USGS/NED"); 46 | 47 | var minMax = dem.reduceRegion(ee.Reducer.percentile([1, 99]), Map.getBounds(true), Map.getScale()).values() 48 | 49 | var min = ee.Number(minMax.get(0)) 50 | var max = ee.Number(minMax.get(1)) 51 | 52 | var exaggregate = 5 53 | var weight = 1.5 54 | var azimuth = 0 55 | var zenith = 45 56 | 57 | // Paired 58 | var palette = palettes.colorbrewer.Paired[12] 59 | var styled = dem.visualize({ min: min, max: max, palette: palette }) 60 | Map.addLayer(styled, {}, 'Paired, styled', false) 61 | 62 | var hillshaded = utils.hillshadeit(styled, dem, weight, exaggregate, azimuth, zenith) 63 | Map.addLayer(hillshaded, {}, 'Paired, hillshaded') 64 | 65 | var textProperties = { fontSize:16, textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2, outlineOpacity: 0.6 } 66 | 67 | // dim background 68 | Map.addLayer(ee.Image(1), {palette: ['ffffff']}, 'white', true, 0.5) 69 | 70 | // add a gradient bar 71 | var labels = ee.List.sequence(min, max, max.subtract(min).divide(5)) 72 | var gradient = style.GradientBar.draw(geometryGradientBar, { 73 | min: min, max: max, palette: palette, labels: labels, format: '%.0f', text: textProperties 74 | }) 75 | Map.addLayer(gradient, {}, 'gradient bar (DEM)') 76 | 77 | // add a scale bar 78 | var scale = style.ScaleBar.draw(geometryScaleBar, { 79 | steps:4, palette: ['5ab4ac', 'f5f5f5'], multiplier: 1000, format: '%.1f', units: 'km', text: textProperties 80 | }) 81 | Map.addLayer(scale, {}, 'scale bar') 82 | 83 | -------------------------------------------------------------------------------- /examples/style-test-northarrow: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #98ff00 */ee.Geometry.MultiPoint(); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var style = require('users/gena/packages:style') 12 | 13 | var pt = Map.getCenter() 14 | var scale = Map.getScale() 15 | var scaleFactor = 0.2 16 | var width = 2 17 | 18 | var northArrow = style.NorthArrow.draw(pt, scale, width, scaleFactor) 19 | Map.addLayer(northArrow, {}, 'north arrow', false) 20 | 21 | 22 | // a few more 23 | var arrows = ee.List.sequence(0.2, 1, 0.1).map(function(scaleFactor) { 24 | return style.NorthArrow.draw(pt, scale, width, scaleFactor) 25 | .set({ label: ee.Number(scaleFactor).format('%.1f') }) 26 | }) 27 | 28 | var animation = require('users/gena/packages:animation') 29 | animation.animate(arrows) 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/style-test-symbology: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var basins = ee.FeatureCollection("users/gena/water-niger/catchments-homogenized"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var style = require('users/gena/packages:style') 5 | var palettes = require('users/gena/packages:palettes') 6 | 7 | // WORK IN PROGRESS 8 | 9 | style.SetMapStyleDark() 10 | 11 | Map.centerObject(basins, 9) 12 | 13 | print(basins.first()) 14 | 15 | // add background 16 | Map.addLayer(ee.Image(1), { palette: ['black'] }, 'background', true, 0.7) 17 | 18 | // add features colored using DIST_SINK property 19 | // see https://github.com/gee-community/ee-palettes for a full list of color palettes 20 | Map.addLayer(style.Feature.histogram(basins, 'DIST_SINK', { palette: palettes.crameri.buda[50], width: 1, opacity: 0.6 }), {}, 'polygons') 21 | 22 | // add feature labels using PFAF_ID property 23 | Map.addLayer(style.Feature.label(basins, 'PFAF_ID', { textColor: 'ffffff', outlineColor: '000000', alignX: 'center', alignY: 'center' }), {}, 'labels') 24 | 25 | // add centroids 26 | Map.addLayer(basins.map(function(f) { return f.centroid(1) }).style({ pointSize: 2, width: 1, color: 'ffff00', fillColor: 'ffff0033'}), {}, 'centroids', false) 27 | -------------------------------------------------------------------------------- /examples/style-test-symbology-points: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var gradientBar = 3 | /* color: #d63000 */ 4 | /* shown: false */ 5 | /* displayProperties: [ 6 | { 7 | "type": "rectangle" 8 | } 9 | ] */ 10 | ee.Geometry.Polygon( 11 | [[[10.105460651028011, 47.25923211585435], 12 | [10.105460651028011, 47.22817481400357], 13 | [10.698464877712581, 47.22817481400357], 14 | [10.698464877712581, 47.25923211585435]]], null, false); 15 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 16 | var style = require('users/gena/packages:style') 17 | var palettes = require('users/gena/packages:palettes') 18 | 19 | style.SetMapStyleDark() 20 | 21 | var palette = palettes.cb.BrBG[11].reverse() 22 | 23 | Map.centerObject(gradientBar, 10) 24 | 25 | // sample some DEM points 26 | var table = ee.Image('JAXA/ALOS/AW3D30_V1_1').select('MED').sample({region: Map.getBounds(true), scale: Map.getScale(), numPixels: 100, geometries: true }) 27 | 28 | 29 | // add styled points 30 | var hist = style.Feature.histogram(table, 'MED', { palette: palette, pointSize: 10, width: 0 }) 31 | Map.addLayer(hist, {}, 'styled') 32 | 33 | // add labels 34 | var textProperties = { textColor: 'ffffff', fontSize: 14, outlineColor: '000000', format: '%.1f' } 35 | Map.addLayer(style.Feature.label(table, 'MED', textProperties), {}, 'labels', false) 36 | 37 | // add gradient bar 38 | var min = ee.Number(hist.get('min')) 39 | var max = ee.Number(hist.get('max')) 40 | var step = max.subtract(min).divide(4) 41 | var labels = ee.List.sequence(min, max, step) 42 | var equidistantPalette = hist.get('equidistantPalette') 43 | 44 | var gradient = style.GradientBar.draw(gradientBar, { 45 | min: min, max: max, palette: equidistantPalette, labels: labels, format: '%.1f', text: textProperties, scale: Map.getScale() 46 | }) 47 | Map.addLayer(gradient, {}, 'gradient bar') 48 | -------------------------------------------------------------------------------- /examples/text-dev-font.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | Map.setCenter(0, 0) 9 | 10 | var scale = Map.getScale() // best seen at native resolution 11 | 12 | function showFont(name) { 13 | var image = ee.Image("users/gena/fonts/" + name); 14 | var proj = image.projection() 15 | image = image.changeProj(proj, proj.scale(scale, -scale)) 16 | 17 | Map.addLayer(image, {}, name) 18 | } 19 | 20 | showFont('Arial10') 21 | showFont('Arial12') 22 | showFont('Arial14') 23 | showFont('Arial16') 24 | showFont('Arial18') 25 | showFont('Arial24') 26 | showFont('Arial32') 27 | showFont('Arial64') 28 | showFont('Consolas16') 29 | showFont('Consolas18') 30 | showFont('Consolas24') 31 | showFont('Consolas32') 32 | -------------------------------------------------------------------------------- /examples/text-test-align.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Polygon( 3 | [[[-98.54838765842106, -12.79114419304485], 4 | [-98.41320184545054, -9.300370119442855], 5 | [-102.14762787154905, -7.247324683929773], 6 | [-105.38626362230656, -6.59057934043231], 7 | [-107.63215638949589, -7.841915414862451], 8 | [-106.64638076018548, -15.058856984709623], 9 | [-98.53028336646764, -15.519552374242762]]]); 10 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 11 | var text = require('users/gena/packages:text') 12 | 13 | var str = 'Hello World!' 14 | var scale = Map.getScale() 15 | var props = { 16 | textColor: '000000', 17 | fontType: 'Arial', 18 | fontSize: 32, 19 | outlineColor: 'ffffff', 20 | 21 | alignX: 'center', // left | center | right 22 | alignY: 'center' // top | center | bottom 23 | } 24 | 25 | var pt = geometry.centroid(1) 26 | 27 | Map.addLayer(pt) 28 | 29 | var image = text.draw(str, pt, scale, props) 30 | 31 | Map.addLayer(image, {}, 'label') 32 | -------------------------------------------------------------------------------- /examples/text-test-all-fonts.js: -------------------------------------------------------------------------------- 1 | var geometry = /* color: #d63000 */ee.Geometry.Point([-122.78530847167968, 39.42475779445961]), 2 | geometry2 = /* color: #d63000 */ee.Geometry.Point([-122.84024011230468, 39.15266132010239]), 3 | geometry3 = /* color: #98ff00 */ee.Geometry.Point([-122.87869226074218, 38.82817512925302]), 4 | geometry4 = /* color: #0b4a8b */ee.Geometry.Point([-122.86770593261718, 38.558066690579494]), 5 | geometry5 = /* color: #ffc82d */ee.Geometry.Point([-121.90640222167968, 39.58581451510441]), 6 | geometry6 = /* color: #00ffff */ee.Geometry.Point([-121.90640222167968, 39.395048748192416]), 7 | geometry7 = /* color: #bf04c2 */ee.Geometry.Point([-121.91738854980468, 39.21227274582616]), 8 | geometry8 = /* color: #ff0000 */ee.Geometry.Point([-121.95034753417968, 39.03328686948669]), 9 | geometry9 = /* color: #00ff00 */ee.Geometry.Point([-121.95584069824218, 38.82817512925307]), 10 | geometry11 = /* color: #999900 */ee.Geometry.Point([-121.96682702636718, 38.43338849688759]), 11 | geometry12 = /* color: #009999 */ee.Geometry.Point([-121.99429284667968, 38.11858916930806]), 12 | geometry10 = /* color: #ff00ff */ee.Geometry.Point([-121.96682702636718, 38.5924226932436]); 13 | 14 | Map.centerObject(geometry, 8) 15 | var text = require('users/gena/packages:text'); 16 | 17 | var scale = Map.getScale() 18 | 19 | var infos = [ 20 | ['Consolas', 16, geometry], 21 | ['Consolas', 18, geometry2], 22 | ['Consolas', 24, geometry3], 23 | ['Consolas', 32, geometry4], 24 | ['Arial', 10, geometry5], 25 | ['Arial', 12, geometry6], 26 | ['Arial', 14, geometry7], 27 | ['Arial', 16, geometry8], 28 | ['Arial', 18, geometry9], 29 | ['Arial', 24, geometry10], 30 | ['Arial', 32, geometry11], 31 | ['Arial', 64, geometry12] 32 | ] 33 | 34 | function show(info) { 35 | var fontType = info[0] 36 | var fontSize = info[1] 37 | var pt = info[2] 38 | 39 | print(fontType, fontSize) 40 | 41 | var titleText = text.draw('Test V', pt, scale, { 42 | fontSize: fontSize, textColor: '000000', fontType: fontType, 43 | outlineColor: 'ffffff', outlineWidth: 2.5, outlineOpacity: 0.6 44 | }) 45 | 46 | Map.addLayer(titleText, {}, fontType + ' ' + fontSize) 47 | } 48 | 49 | infos.map(show) -------------------------------------------------------------------------------- /examples/text-test-annotate.js: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Polygon( 3 | [[[-108.544921875, 49.83798245308484], 4 | [-106.5234375, 52.908902047770255], 5 | [-113.59171297298622, 52.88037073584405], 6 | [-117.861328125, 54.31652324025826], 7 | [-121.4208984375, 53.30462107510271]]]); 8 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 9 | /* 10 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 11 | 12 | This work is licensed under the terms of the MIT license. 13 | For a copy, see . 14 | */ 15 | 16 | var text = require('users/gena/packages:text') 17 | 18 | function testGetLocation() { 19 | var bounds = geometry.bounds() 20 | Map.addLayer(bounds) 21 | 22 | var pt1 = text.getLocation(bounds, 'left', '20%', '1%') 23 | Map.addLayer(pt1, {color: 'green'}) 24 | 25 | var pt2 = text.getLocation(bounds, 'top', '50%', '5%') 26 | Map.addLayer(pt2, {color: 'red'}) 27 | 28 | var pt3 = text.getLocation(bounds, 'bottom', '50%', '5%') 29 | Map.addLayer(pt3, {color: 'blue'}) 30 | } 31 | 32 | testGetLocation() 33 | 34 | function testAnnotateImage() { 35 | Map.centerObject(geometry, 6) 36 | 37 | var scale = Map.getScale() 38 | var fontSize = 18 39 | 40 | 41 | var bounds = geometry.bounds() 42 | var image = ee.Image().paint(bounds) 43 | .set({ 'system:time_start': ee.Date('2000-01-01').millis() }) 44 | .set({ 'SUN_ELEVATION': 45 }) 45 | 46 | var annotations = [ 47 | { 48 | position: 'top', offset: '50%', margin: '5%', 49 | property: 'system:time_start', 50 | format: function(o) { return ee.Date(o).format('YYYY-MM-dd') }, 51 | scale: scale, 52 | fontType: 'Consolas', fontSize: 18 53 | }, 54 | { 55 | position: 'left', offset: '50%', margin: '2%', 56 | property: 'SUN_ELEVATION', 57 | format: function(o) { return ee.Number(o).format('%.1f degree') }, 58 | scale: scale, 59 | fontType: 'Consolas', fontSize: 18 60 | }, 61 | ] 62 | 63 | var vis = {forceRgbOutput: true} 64 | var results = text.annotateImage(image, vis, bounds, annotations) 65 | 66 | Map.addLayer(results, {}, 'annotated image') 67 | } 68 | 69 | testAnnotateImage() 70 | -------------------------------------------------------------------------------- /examples/text-test-debug: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var font = ee.Image("users/gena/fonts/Arial24"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | Map.setCenter(0, -20, 4) 5 | 6 | // make sure we will scale font to show on our map with 1:1 scale 7 | var proj = font.projection() 8 | var scale = proj.nominalScale().multiply(Map.getScale()) 9 | var projTarget = proj.scale(scale, scale.multiply(-1)) 10 | 11 | // show bitmap font 12 | Map.addLayer(font.changeProj(proj, projTarget)) 13 | 14 | // clip and translate a single character 15 | // return ee.Image(glyph).changeProj(proj, proj.translate(xpos, ypos).scale(scale, scale)) 16 | 17 | var coords = ee.Image.pixelCoordinates(projTarget); 18 | // var nxy = ll.floor().round().changeProj(ll.projection(), image.projection()); 19 | // var nx = nxy.select(0); 20 | // var ny = nxy.select(1); 21 | // var mask = nx.gte(xmin).and(nx.lt(xmax)).and(ny.gte(ymin)).and(ny.lt(ymax)); 22 | 23 | // return image.mask(mask).translate(ee.Number(xmin).multiply(-1).add(x), ee.Number(ymin).multiply(-1).subtract(y)); 24 | 25 | var nx = 1 26 | var ny = 5 27 | var size = 32 28 | var xy = coords.round() 29 | var x = xy.select(0) 30 | var y = xy.select(1) 31 | var mask = x.gte(size * nx).and(x.lt(size * (nx + 1))).and(y.gte(size * ny)).and(y.lt(size * (ny + 1))) 32 | Map.addLayer(mask.selfMask(), { palette: ['yellow' ] }, 'char', true, 0.8) -------------------------------------------------------------------------------- /examples/text-test-landsat.js: -------------------------------------------------------------------------------- 1 | var text = require('users/gena/packages:text') 2 | 3 | Map.setCenter(-104.48, 38.37, 6) 4 | 5 | // select images 6 | var bounds = Map.getBounds(true) 7 | var scale = Map.getScale() 8 | 9 | var images = ee.ImageCollection('LANDSAT/LC8_L1T_TOA').select([5,4,2]).filterBounds(bounds).filterDate('2015-01-01', '2015-01-7') 10 | 11 | // render annotated images 12 | function annotate(images) { 13 | return images.map(function(i) { 14 | var geom = i.select(0).geometry() 15 | var center = ee.List(geom.centroid().coordinates()) 16 | 17 | // add edge around image 18 | var edge = ee.Image(0).toByte().paint(geom, 1, 2) 19 | edge = edge.mask(edge) 20 | .visualize({palette:['cccc00'], opacity: 0.9}) 21 | 22 | // define text properties 23 | var props = { textColor: '000000', outlineColor: 'ffffff', outlineWidth: 2.5, outlineOpacity: 0.6} 24 | 25 | // draw text 26 | var pos = translate(center, 0.7, -0.4) 27 | var s = ee.String(i.get('DATE_ACQUIRED')) 28 | var textDate = text.draw(s, pos, scale, props) 29 | 30 | pos = translate(center, 0.7, -0.1) 31 | s = ee.String(i.get('SCENE_CENTER_TIME')).slice(0, 5) 32 | var textTime = text.draw(s, pos, scale, props) 33 | 34 | pos = translate(center, -0.1, 0.3) 35 | s = ee.String(i.get('CLOUD_COVER')).slice(0, 5) 36 | props.textColor = '0000aa' 37 | var textCloud = text.draw(s, pos, scale, props) 38 | 39 | return ee.ImageCollection([edge, textDate, textTime, textCloud]).mosaic() // merge results 40 | }) 41 | } 42 | 43 | // translate point coordinates by dx, dy 44 | function translate(pt, dx, dy) { 45 | var x1 = ee.Number(pt.get(0)).subtract(dx) 46 | var y1 = ee.Number(pt.get(1)).subtract(dy) 47 | 48 | return ee.Geometry.Point(ee.List([x1, y1])) 49 | } 50 | 51 | // add to map 52 | Map.addLayer(images, {}, 'images') 53 | Map.addLayer(annotate(images), {}, 'annotations') 54 | 55 | -------------------------------------------------------------------------------- /examples/text-test-simple.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var text = require('users/gena/packages:text') 9 | 10 | // dim background 11 | Map.addLayer(ee.Image(1), {palette:['000000'], opacity:0.7}, 'bg') 12 | 13 | // scale text font relative to the current map scale 14 | var scale = Map.getScale() * 2 15 | 16 | // draw text at map center 17 | var str = 'Hello, how are you?' 18 | var point = Map.getCenter() 19 | var text = text.draw(str, point, scale, {fontSize:32}) 20 | 21 | // add text as a raster layer 22 | Map.addLayer(text, {}, 'simple text') 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/text-test-stress.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var text = require('users/gena/packages:text') 9 | 10 | // dim background 11 | Map.addLayer(ee.Image(1), {palette:['000000'], opacity:0.7}, 'bg') 12 | 13 | // stress test, multiple strings 14 | var bounds = Map.getBounds(true) 15 | 16 | // sample multiple points and paint their coordinates 17 | var count = 50 18 | var samples = ee.Image.pixelLonLat().sample({region: bounds, numPixels: count, scale: 100, geometries: true}) 19 | Map.addLayer(samples, {color:'eeee40'}, 'points') 20 | 21 | // draw label using point coordinates 22 | function drawLabel(feature) { 23 | var str = toString(feature.geometry().coordinates()) 24 | return text.draw(str, feature.geometry(), Map.getScale()) 25 | } 26 | 27 | var labelsImage = ee.ImageCollection(samples.map(drawLabel)) 28 | 29 | var labelsLayer = ui.Map.Layer(labelsImage, {}, 'labels') 30 | Map.layers().add(labelsLayer) 31 | 32 | 33 | // update labels when image zoom changes 34 | Map.onChangeZoom(function(zoom) { 35 | labelsLayer.setEeObject(ee.ImageCollection(samples.map(drawLabel))) 36 | }) 37 | 38 | 39 | function toString(coord) { 40 | var x = ee.Number(coord.get(0)) 41 | var y = ee.Number(coord.get(1)) 42 | 43 | return x.format('%.2f').cat(', ').cat(y.format('%.2f')) 44 | } 45 | 46 | -------------------------------------------------------------------------------- /examples/thresholding-test: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var thresholding = require('users/gena/packages:thresholding') 12 | var animation = require('users/gena/packages:animation') 13 | 14 | // get images 15 | images = images 16 | .filterBounds(Map.getCenter()) 17 | .select(['B6', 'B5', 'B3'], ['swir', 'nir', 'green']) 18 | 19 | print('Image count: ', images.size()) 20 | 21 | // compute NDWI and thresholds 22 | var scale = Map.getScale() 23 | var bounds = Map.getBounds(true) 24 | var cannyThreshold = 0.7 25 | var cannySigma = 1 26 | var minValue = -0.2 27 | 28 | images = images.map(function(i) { 29 | i = i.resample('bilinear') 30 | 31 | var ndwi = i.normalizedDifference(['green', 'swir']) 32 | var th = thresholding.computeThresholdUsingOtsu(ndwi, scale, bounds, cannyThreshold, cannySigma, minValue) 33 | 34 | var water = ee.Image().mask(ndwi.gt(th)) 35 | .visualize({palette: ['3182bd'], opacity: 0.5}) 36 | 37 | var waterEdge = ee.Image(1).int().mask(ee.Algorithms.CannyEdgeDetector(ndwi.gt(th), 0.5, 0)) 38 | .visualize({palette: ['ffffff']}) 39 | 40 | return i.visualize({min: 0.05, max: 0.35}) 41 | .blend(water) 42 | .blend(waterEdge) 43 | .set({th: th}) 44 | .set({label: th.format('%.2f')}) 45 | }) 46 | 47 | // remove potentially bad images 48 | images = images.filter(ee.Filter.gt('th', -0.15)) 49 | 50 | // plot thresholds 51 | print(ui.Chart.feature.histogram(images, 'th')) 52 | 53 | // visualize 54 | animation.animate(images) -------------------------------------------------------------------------------- /examples/thresholding-test-ndwi: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | /* 5 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 6 | 7 | This work is licensed under the terms of the MIT license. 8 | For a copy, see . 9 | */ 10 | 11 | var thresholding = require('users/gena/packages:thresholding') 12 | var animation = require('users/gena/packages:animation') 13 | 14 | // get images 15 | images = images 16 | .filterBounds(Map.getCenter()) 17 | .filterDate('2019-01-01', '2020-01-01') 18 | .select(['B6', 'B5', 'B3'], ['swir', 'nir', 'green']) 19 | .map(function(i) { return i.resample('bicubic') }) 20 | 21 | print('Image count: ', images.size()) 22 | 23 | var scale = Map.getScale() 24 | var bounds = Map.getBounds(true) 25 | var cannyThreshold = 0.7 26 | var cannySigma = 1 27 | var minValue = -0.2 28 | 29 | // apply to a composite image first 30 | var image20 = images.reduce(ee.Reducer.percentile([20])).rename(['swir', 'nir', 'green']) 31 | var ndwi = image20.normalizedDifference(['green', 'nir']) 32 | var th = thresholding.computeThresholdUsingOtsu(ndwi, scale, bounds, cannyThreshold, cannySigma, minValue) 33 | var water = ee.Image().mask(ndwi.gt(th)) 34 | .visualize({palette: ['3182bd'], opacity: 0.5}) 35 | var waterEdge = ee.Image(1).int().mask(ee.Algorithms.CannyEdgeDetector(ndwi.gt(th), 0.5, 0)) 36 | .visualize({palette: ['ffffff']}) 37 | Map.addLayer(image20.visualize({min: 0.05, max: 0.35}).blend(water).blend(waterEdge), {}, '20% and water') 38 | 39 | 40 | // compute NDWI and thresholds for every image 41 | images = images.map(function(i) { 42 | i = i.resample('bilinear') 43 | 44 | var ndwi = i.normalizedDifference(['green', 'nir']) 45 | var th = thresholding.computeThresholdUsingOtsu(ndwi, scale, bounds, cannyThreshold, cannySigma, minValue) 46 | 47 | var water = ee.Image().mask(ndwi.gt(th)) 48 | .visualize({palette: ['3182bd'], opacity: 0.5}) 49 | 50 | var waterEdge = ee.Image(1).int().mask(ee.Algorithms.CannyEdgeDetector(ndwi.gt(th), 0.5, 0)) 51 | .visualize({palette: ['ffffff']}) 52 | 53 | return i.visualize({min: 0.05, max: 0.35}) 54 | .blend(water) 55 | .blend(waterEdge) 56 | .set({th: th}) 57 | .set({label: th.format('%.2f')}) 58 | }) 59 | 60 | // remove potentially bad images 61 | images = images.filter(ee.Filter.gt('th', -0.15)) 62 | 63 | 64 | // plot thresholds 65 | print(ui.Chart.feature.histogram(images, 'th')) 66 | 67 | // visualize 68 | // animation.animate(images) 69 | 70 | -------------------------------------------------------------------------------- /examples/tiler-test: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var geometry = /* color: #d63000 */ee.Geometry.Polygon( 3 | [[[-67.93074032573043, 35.46981488813701], 4 | [-66.1536238287353, 36.01338228347171], 5 | [-64.93898700752635, 35.870247281896674], 6 | [-61.918402961316474, 35.690906512945844], 7 | [-59.34915548456843, 32.86102419342828], 8 | [-58.55125375004707, 38.53920148140564], 9 | [-66.19887770267769, 37.7113914931089], 10 | [-67.16182659937084, 35.90904830460234], 11 | [-70.46072436226257, 35.5795448698411], 12 | [-70.7905135321381, 32.96740553173804], 13 | [-68.40946373914267, 30.78468785606502]]]); 14 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 15 | var tiler = require('users/gena/packages:tiler') 16 | 17 | Map.centerObject(geometry) 18 | 19 | function addTileBounds(zoom) { 20 | var tiles = tiler.getTilesForGeometry(geometry, zoom) 21 | 22 | Map.addLayer(tiles.style({ width: Math.max(1, 10 - zoom), fillColor: '00000022' }), {}, 'tiles ' + zoom) 23 | Map.addLayer(tiles, {}, 'tiles (features)' + zoom, false) // for inspection 24 | } 25 | 26 | [6, 7, 8, 9, 10].map(addTileBounds) 27 | -------------------------------------------------------------------------------- /examples/ui-test-transect: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var uiTools = require('users/gena/packages:ui') 9 | 10 | var tool = new uiTools.DrawTransectTool(Map) 11 | 12 | tool.onDraw(function(points) { 13 | print(points) 14 | }) 15 | 16 | 17 | // ui 18 | var button = ui.Button('Start Drawing') 19 | 20 | button.onClick(function() { 21 | if(!tool.active) { 22 | tool.startDrawing() 23 | button.setLabel('Stop Drawing') 24 | } else { 25 | tool.stopDrawing() 26 | button.setLabel('Start Drawing') 27 | } 28 | }) 29 | 30 | Map.add(button) -------------------------------------------------------------------------------- /examples/utils-test-fillGaps: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | var utils = require('users/gena/packages:utils') 9 | 10 | var colors_dem = ['006837', '1a9850', '66bd63', 'a6d96a', 'd9ef8b', 'ffffbf', 'fee08b', 'fdae61', 'f46d43', 'd73027', 'a50026', 'ffffff'] 11 | 12 | var addDem = function(dem, name, min, max, visible) { 13 | var im = dem.visualize({palette:colors_dem, min:min, max:max, opacity: 1.0}); 14 | Map.addLayer(utils.hillshadeRGB(im, dem, 1.4, 6.0, 35), {}, name, visible); 15 | } 16 | 17 | var dem = ee.Image('AHN/AHN2_05M_INT') // interpolated 18 | 19 | var min = -5 20 | var max = 10 21 | 22 | // original 23 | addDem(dem, 'AHN (land)', min, max, true) 24 | 25 | // filled 26 | var radius = 10 27 | var iterations = 4 28 | var demFilled = utils.fillGaps(dem, radius, iterations) 29 | addDem(demFilled, 'AHN fill', min, max, true) 30 | 31 | 32 | -------------------------------------------------------------------------------- /examples/utils-test-hexgrid: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | // repository: https://code.earthengine.google.com/?accept_repo=users/gena/packages 9 | // source: utils-test-hexgrid 10 | 11 | var utils = require('users/gena/packages:utils') 12 | 13 | var scale = Map.getScale() 14 | var crs = 'EPSG:3857' 15 | 16 | // generate seeds using a hexagonal grid (crs and scale are optional) 17 | var size = 35 // in scale points 18 | var grid = utils.generateHexagonalSeeds(size, crs, scale).focal_max(2) 19 | 20 | // distance from seed points 21 | var distance = grid.fastDistanceTransform().sqrt() 22 | 23 | // compute grid edges using SNIC 24 | var clusters = ee.Algorithms.Image.Segmentation.SNIC({ 25 | image: ee.Image(1), 26 | seeds: grid, 27 | compactness: 1, 28 | connectivity: 8, 29 | neighborhoodSize: 256 30 | }).select('clusters') 31 | 32 | Map.addLayer(clusters.randomVisualizer(), {}, 'clusters') 33 | 34 | Map.addLayer(ee.Image(1).mask(distance.divide(size).pow(6)), {palette: ['000000']}, 'grid (edges)') 35 | Map.addLayer(grid.mask(grid), {palette: ['ffff00']}, 'grid') 36 | -------------------------------------------------------------------------------- /examples/utils-test-hillshade: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var ahn2 = ee.Image("AHN/AHN2_05M_RUW"), 3 | alos = ee.Image("JAXA/ALOS/AW3D30_V1_1"), 4 | ned = ee.Image("USGS/NED"), 5 | alos2 = ee.Image("JAXA/ALOS/AW3D30/V2_2"), 6 | ahn3 = ee.Image("users/gena/AHN3_DSM"); 7 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 8 | var utils = require('users/gena/packages:utils') 9 | var palettes = require('users/gena/packages:palettes') 10 | 11 | var dem = alos.select('AVE_DSM') 12 | // var dem = ned 13 | // var dem = ahn3 14 | // var dem = ahn2 15 | 16 | dem = dem.rename('elevation').resample('bicubic') 17 | 18 | // Map.setCenter(5.92528, 50.9009, 17) 19 | 20 | var reducer = ee.Reducer.percentile([2, 98], ['min', 'max']) 21 | var bounds = Map.getBounds(true) 22 | var scale = Map.getScale() * 10 23 | var minMax = dem.reduceRegion(reducer, bounds, scale) 24 | 25 | var demStyled = dem.visualize({ 26 | min: minMax.get('elevation_min'), 27 | max: minMax.get('elevation_max'), 28 | palette: palettes.cb.BrBG[7] 29 | }) 30 | 31 | Map.addLayer(demStyled, {}, 'dem') 32 | 33 | var weight = 1.0 34 | var extrusion = 10 35 | var sunAzimuth = 315 36 | var sunElevation = 25 37 | var contrast = 0.1 38 | var brightness = 0 39 | var saturation = 1 40 | 41 | var demHillshaded = utils.hillshadeRGB(demStyled, dem, weight, extrusion, 42 | sunAzimuth, sunElevation, contrast, brightness, saturation, shadows) 43 | 44 | Map.addLayer(demHillshaded, {}, 'dem (hillshade)') 45 | 46 | var shadows = true 47 | 48 | var demHillshaded = utils.hillshadeRGB(demStyled, dem, weight, extrusion, 49 | sunAzimuth, sunElevation, contrast, brightness, saturation, shadows) 50 | 51 | Map.addLayer(demHillshaded, {}, 'dem (hillshade, shadows)') 52 | 53 | -------------------------------------------------------------------------------- /examples/utils-test-hillshade-multi: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("AHN/AHN2_05M_RUW"), 3 | dem2 = ee.Image("users/gena/AHN3_DSM"); 4 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 5 | dem = dem2 6 | var utils = require('users/gena/packages:utils') 7 | var palettes = require('users/gena/packages:palettes') 8 | 9 | Map.setOptions('HYBRID') 10 | // Map.setCenter(4.408241, 52.177595, 18) 11 | dem = dem.resample('bicubic') 12 | .convolve(ee.Kernel.gaussian(0.5, 0.25, 'meters')) 13 | 14 | // var palette = palettes.crameri.lisbon[25] 15 | // palettes.showPalette('lisbon', palette) 16 | 17 | // var palette = palettes.cb.Greys[9].reverse() 18 | // palettes.showPalette('greys', palette) 19 | 20 | // var palette = palettes.crameri.oleron[50] 21 | // palettes.showPalette('oleron', palette) 22 | 23 | var palette = palettes.crameri.roma[25].slice(0).reverse() 24 | palettes.showPalette('roma', palette) 25 | 26 | var palette = ['white'] 27 | 28 | var demRGB = dem.visualize({ min: -5, max: 5, palette: palette }) 29 | 30 | var weight = 0.6 // wegith of Hillshade vs RGB intensity (0 - flat, 1 - HS) 31 | var exaggeration = 5 // vertical exaggeration 32 | var azimuth = 315 // Sun azimuth 33 | var zenith = 30 // Sun elevation 34 | var brightness = -0.05 // 0 - default 35 | var contrast = 0.05 // 0 - default 36 | var saturation = 0.8 // 1 - default 37 | var castShadows = false 38 | 39 | // no shadows 40 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 41 | Map.addLayer(rgb, {}, 'DEM (no shadows)', false) 42 | 43 | // with shadows 44 | var castShadows = true 45 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 46 | Map.addLayer(rgb, {}, 'DEM', false) 47 | 48 | // var demRGB = dem.visualize({ min: -5, max: 5, palette: [palettes.crameri.roma[50][15]] }) 49 | var rgb2 = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth - 90, zenith + 30, contrast, brightness, saturation, castShadows) 50 | 51 | // var demRGB = dem.visualize({ min: -5, max: 5, palette: [palettes.crameri.roma[50][40]] }) 52 | var rgb3 = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth - 120, zenith + 25, contrast, brightness, saturation, castShadows) 53 | 54 | var rgb = rgb.multiply(0.6).add(rgb2.multiply(0.2)).add(rgb3.multiply(0.2)) 55 | Map.addLayer(rgb, {}, 'DEM') 56 | 57 | Map.addLayer(dem, {}, 'DEM (raw)', false) 58 | 59 | /* 60 | var frames = ee.List.sequence(5, 90, 1).map(function(zenith) { 61 | return utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 62 | }) 63 | 64 | 65 | var animation = require('users/gena/packages:animation') 66 | animation.animate(frames, { maxFrames: 90 }) 67 | */ -------------------------------------------------------------------------------- /examples/utils-test-hillshade-multi-alos: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("AHN/AHN2_05M_RUW"), 3 | dem2 = ee.Image("users/gena/AHN3_DSM"), 4 | alos = ee.ImageCollection("JAXA/ALOS/AW3D30/V3_2"); 5 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 6 | // dem = dem2 7 | dem = alos.select('DSM').mosaic().reproject(ee.Projection('EPSG:3857').atScale(30)).resample('bicubic') 8 | var utils = require('users/gena/packages:utils') 9 | var palettes = require('users/gena/packages:palettes') 10 | 11 | Map.setOptions('HYBRID') 12 | // Map.setCenter(4.408241, 52.177595, 18) 13 | dem = dem//.resample('bicubic') 14 | // .convolve(ee.Kernel.gaussian(0.5, 0.25, 'meters')) 15 | .convolve(ee.Kernel.gaussian(35, 30, 'meters')) 16 | 17 | // var palette = palettes.crameri.lisbon[25] 18 | // palettes.showPalette('lisbon', palette) 19 | 20 | // var palette = palettes.cb.Greys[9].reverse() 21 | // palettes.showPalette('greys', palette) 22 | 23 | // var palette = palettes.crameri.oleron[50] 24 | // palettes.showPalette('oleron', palette) 25 | 26 | var palette = palettes.crameri.roma[25].slice(0).reverse() 27 | palettes.showPalette('roma', palette) 28 | 29 | var palette = ['white'] 30 | 31 | var demRGB = dem.visualize({ min: -5, max: 5, palette: palette }) 32 | 33 | var weight = 0.7 // wegith of Hillshade vs RGB intensity (0 - flat, 1 - HS) 34 | var exaggeration = 5 // vertical exaggeration 35 | var azimuth = 315 // Sun azimuth 36 | var zenith = 25 // Sun elevation 37 | var brightness = -0.05 // 0 - default 38 | var contrast = 0.1 // 0 - default 39 | var saturation = 1 // 1 - default 40 | var castShadows = false 41 | 42 | // no shadows 43 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 44 | Map.addLayer(rgb, {}, 'DEM (no shadows)', false) 45 | 46 | // with shadows 47 | var castShadows = true 48 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 49 | Map.addLayer(rgb, {}, 'DEM', false) 50 | 51 | // var demRGB = dem.visualize({ min: -5, max: 5, palette: [palettes.crameri.roma[50][15]] }) 52 | var rgb2 = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth - 90, zenith + 30, contrast, brightness, saturation, castShadows) 53 | 54 | // var demRGB = dem.visualize({ min: -5, max: 5, palette: [palettes.crameri.roma[50][40]] }) 55 | var rgb3 = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth - 120, zenith + 25, contrast, brightness, saturation, castShadows) 56 | 57 | var rgb = rgb.multiply(0.6).add(rgb2.multiply(0.2)).add(rgb3.multiply(0.2)) 58 | Map.addLayer(rgb, {}, 'DEM') 59 | 60 | Map.addLayer(dem, {}, 'DEM (raw)', false) 61 | 62 | /* 63 | var frames = ee.List.sequence(5, 90, 1).map(function(zenith) { 64 | return utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 65 | }) 66 | 67 | 68 | var animation = require('users/gena/packages:animation') 69 | animation.animate(frames, { maxFrames: 90 }) 70 | */ -------------------------------------------------------------------------------- /examples/utils-test-hillshade-multi-water: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("AHN/AHN2_05M_RUW"), 3 | dem2 = ee.Image("users/gena/AHN3_DSM"), 4 | alos = ee.ImageCollection("JAXA/ALOS/AW3D30/V3_2"), 5 | ned = ee.Image("USGS/NED"), 6 | jrc = ee.Image("JRC/GSW1_3/GlobalSurfaceWater"), 7 | nasadem = ee.Image("NASA/NASADEM_HGT/001"), 8 | land = ee.Image("users/gena/land_polygons_image"); 9 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 10 | /* 11 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 12 | 13 | This work is licensed under the terms of the MIT license. 14 | For a copy, see . 15 | */ 16 | 17 | var utils = require('users/gena/packages:utils') 18 | var palettes = require('users/gena/packages:palettes') 19 | 20 | // dem = dem.resample('bicubic').convolve(ee.Kernel.gaussian(0.5, 0.25, 'meters')) 21 | // dem = dem2.resample('bicubic').convolve(ee.Kernel.gaussian(0.5, 0.25, 'meters')) 22 | // dem = ned.resample('bicubic').convolve(ee.Kernel.gaussian(10, 5, 'meters')) 23 | // dem = alos.select('DSM').mosaic().reproject(ee.Projection('EPSG:3857').atScale(30)).resample('bicubic').convolve(ee.Kernel.gaussian(35, 30, 'meters')) 24 | dem = nasadem.select('elevation').resample('bicubic').convolve(ee.Kernel.gaussian(35, 30, 'meters')) 25 | 26 | // var palette = palettes.crameri.lisbon[25] 27 | // palettes.showPalette('lisbon', palette) 28 | 29 | // var palette = palettes.cb.Greys[9].reverse() 30 | // palettes.showPalette('greys', palette) 31 | 32 | // var palette = palettes.crameri.roma[25].slice(0).reverse() 33 | // palettes.showPalette('roma', palette) 34 | 35 | var palette = palettes.crameri.oleron[50] 36 | palettes.showPalette('oleron', palette) 37 | 38 | // var palette = ['white'] 39 | 40 | var demRGB = dem.visualize({ min: -1000, max: 1000, palette: palette }) 41 | 42 | var water = jrc.select('occurrence').unmask(0).resample('bicubic').focal_mean(35, 'circle', 'meters').divide(100).max(land.mask().not()).selfMask().visualize({ palette: [palettes.crameri.roma[50][40]] }) 43 | demRGB = demRGB.blend(water) 44 | 45 | var weight = 0.6 // wegith of Hillshade vs RGB intensity (0 - flat, 1 - HS) 46 | var exaggeration = 3 // vertical exaggeration 47 | var azimuth = 315 // Sun azimuth 48 | var zenith = 10 // Sun elevation 49 | var brightness = 0 // 0 - default 50 | var contrast = 0.1 // 0 - default 51 | var saturation = 0.3 // 1 - default 52 | var castShadows = true 53 | 54 | var rgb = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth, zenith, contrast, brightness, saturation, castShadows) 55 | Map.addLayer(rgb, {}, 'DEM', false) 56 | 57 | // var demRGB = dem.visualize({ min: -5, max: 5, palette: [palettes.crameri.roma[50][15]] }) 58 | var rgb2 = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth - 90, zenith + 30, contrast, brightness, saturation, castShadows) 59 | 60 | // var demRGB = dem.visualize({ min: -5, max: 5, palette: [palettes.crameri.roma[50][40]] }) 61 | var rgb3 = utils.hillshadeRGB(demRGB, dem, weight, exaggeration, azimuth - 120, zenith + 25, contrast, brightness, saturation, castShadows) 62 | 63 | var rgb = rgb.multiply(0.6).add(rgb2.multiply(0.2)).add(rgb3.multiply(0.2)) 64 | Map.addLayer(rgb, {}, 'DEM (multi-look shading)') 65 | 66 | Map.addLayer(dem, {}, 'DEM (raw)', false) 67 | 68 | Map.setOptions('HYBRID') 69 | // Map.setCenter(-121.8093, 45.6445, 10) 70 | -------------------------------------------------------------------------------- /examples/utils-test-isolines: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("USGS/SRTMGL1_003"), 3 | alos = ee.Image("JAXA/ALOS/AW3D30/V2_2"); 4 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 5 | /* 6 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 7 | 8 | This work is licensed under the terms of the MIT license. 9 | For a copy, see . 10 | */ 11 | 12 | dem = alos.select('AVE_DSM') 13 | 14 | var utils = require('users/gena/packages:utils') 15 | var palettes = require('users/gena/packages:colorbrewer').Palettes 16 | 17 | Map.setCenter(114.1, -8.1, 12) 18 | 19 | var minMax = dem.reduceRegion({ reducer: ee.Reducer.percentile([2, 98]), geometry: Map.getBounds(true), scale: Map.getScale() }) 20 | 21 | minMax.evaluate(function(minMax) { 22 | print(minMax) 23 | 24 | var image = dem.resample('bicubic').convolve(ee.Kernel.gaussian(3, 2)) 25 | var levels = ee.List.sequence(minMax.AVE_DSM_p2, minMax.AVE_DSM_p98, (minMax.AVE_DSM_p98 - minMax.AVE_DSM_p2) / 20) 26 | 27 | var isolines = utils.getIsolines(image, levels) 28 | 29 | var palette = palettes.BrBG[11].reverse() 30 | 31 | Map.addLayer(ee.Terrain.hillshade(image.multiply(50), 315, 25), {min: -100, max: 350}, 'hillshade', true, 0.25) 32 | 33 | Map.addLayer(ee.Image(0), { palette: ['000000'] }, 'black', true, 0.75) 34 | 35 | Map.addLayer(isolines.mosaic(), {palette: palette, min: minMax.AVE_DSM_p2, max: minMax.AVE_DSM_p98}, 'isolines', true, 0.75) 36 | 37 | var levels2 = ee.List.sequence(minMax.AVE_DSM_p2, minMax.AVE_DSM_p98, (minMax.AVE_DSM_p98 - minMax.AVE_DSM_p2) / 5) 38 | var isolines2 = utils.getIsolines(image, levels2) 39 | 40 | Map.addLayer(isolines2.mosaic().focal_max(1), {palette: palette, min: minMax.AVE_DSM_p2, max: minMax.AVE_DSM_p98}, 'isolines (thick)', true, 0.75) 41 | 42 | Map.setOptions('SATELLITE') 43 | }) 44 | -------------------------------------------------------------------------------- /examples/utils-test-isolines-dynamic: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var dem = ee.Image("USGS/SRTMGL1_003"), 3 | alos = ee.Image("JAXA/ALOS/AW3D30/V2_2"); 4 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 5 | /* 6 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 7 | 8 | This work is licensed under the terms of the MIT license. 9 | For a copy, see . 10 | */ 11 | 12 | dem = alos.select('AVE_DSM') 13 | 14 | var utils = require('users/gena/packages:utils') 15 | var palettes = require('users/gena/packages:colorbrewer').Palettes 16 | 17 | // Map.setCenter(114.1, -8.1, 12) 18 | 19 | var minMax = dem.reduceRegion({ reducer: ee.Reducer.percentile([2, 98]), geometry: Map.getBounds(true), scale: Map.getScale() }) 20 | 21 | minMax.evaluate(function(minMax) { 22 | print(minMax) 23 | 24 | var image = dem.resample('bicubic').convolve(ee.Kernel.gaussian(3, 2)) 25 | var levels = ee.List.sequence(minMax.AVE_DSM_p2, minMax.AVE_DSM_p98, (minMax.AVE_DSM_p98 - minMax.AVE_DSM_p2) / 20) 26 | 27 | var isolines = utils.getIsolines(image, levels) 28 | 29 | var palette = palettes.BrBG[11].reverse() 30 | 31 | Map.addLayer(ee.Terrain.hillshade(image.multiply(50), 315, 25), {min: -100, max: 350}, 'hillshade', true, 0.5) 32 | 33 | Map.addLayer(ee.Image(0), { palette: ['000000'] }, 'black', true, 0.75) 34 | 35 | Map.addLayer(isolines.mosaic(), {palette: palette, min: minMax.AVE_DSM_p2, max: minMax.AVE_DSM_p98}, 'isolines', true, 0.75) 36 | 37 | var levels2 = ee.List.sequence(minMax.AVE_DSM_p2, minMax.AVE_DSM_p98, (minMax.AVE_DSM_p98 - minMax.AVE_DSM_p2) / 5) 38 | var isolines2 = utils.getIsolines(image, levels2) 39 | 40 | Map.addLayer(isolines2.mosaic().focal_max(1), {palette: palette, min: minMax.AVE_DSM_p2, max: minMax.AVE_DSM_p98}, 'isolines (thick)', true, 0.75) 41 | 42 | Map.setOptions('SATELLITE') 43 | }) 44 | -------------------------------------------------------------------------------- /examples/utils-test-peronamalik: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var s1 = ee.ImageCollection("COPERNICUS/S1_GRD"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var utils = require('users/gena/packages:utils') 5 | 6 | var image = s1.filterBounds(Map.getCenter()).first() 7 | 8 | Map.addLayer(image, { bands: ['VV', 'VH', 'VV'], min: -30, max: -5 }) 9 | 10 | var image2 = utils.peronaMalikFilter(image, 20, 2.5, 2) 11 | 12 | Map.addLayer(image2, { bands: ['VV', 'VH', 'VV'], min: -30, max: -5 }) 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/utils-test-profile: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var images = ee.ImageCollection("COPERNICUS/S2"), 3 | line = 4 | /* color: #d63000 */ 5 | /* shown: false */ 6 | ee.Geometry.LineString( 7 | [[-107.19901084637968, 33.26215915196785], 8 | [-107.17866897321073, 33.258857714299204], 9 | [-107.14244842267362, 33.24213329838942]]); 10 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 11 | /* 12 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 13 | 14 | This work is licensed under the terms of the MIT license. 15 | For a copy, see . 16 | */ 17 | 18 | var utils = require('users/gena/packages:utils') 19 | 20 | Map.centerObject(line) 21 | 22 | var image = ee.Image(images.filterBounds(line.centroid(1)).first()) 23 | 24 | var profile = utils.reduceImageProfile(image, line, ee.Reducer.mean(), Map.getScale()) 25 | 26 | print(ui.Chart.feature.byFeature(profile, 'distance')) 27 | -------------------------------------------------------------------------------- /examples/utils-test-stretchImage: -------------------------------------------------------------------------------- 1 | var utils = require('users/gena/packages:utils') 2 | 3 | Map.setCenter(-86.58, 34.58, 14) // comment out and zoom to a random location 4 | 5 | // oritinal image 6 | var image = ee.ImageCollection('COPERNICUS/S2') 7 | .filterBounds(Map.getCenter()) 8 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5)) 9 | .first() 10 | .resample('bicubic') 11 | .divide(10000) 12 | 13 | Map.addLayer(image, { bands: ['B4', 'B3', 'B2'], min: 0, max: 0.5 }, 'original') 14 | 15 | // stretched image (arguments provided as a dictionary {} are optional) 16 | var imageStretched = utils.stretchImage(image.select(['B4', 'B3', 'B2']), { 17 | percentiles: [1, 99], 18 | bounds: Map.getBounds(true), 19 | scale: Map.getScale() 20 | }) 21 | 22 | Map.addLayer(imageStretched, { bands: ['B4', 'B3', 'B2'], gamma: 1.2, min: 0, max: 1 }, 'stretched') 23 | -------------------------------------------------------------------------------- /examples/utils-test-video-export-parameters: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var bounds = 3 | /* color: #d63000 */ 4 | /* displayProperties: [ 5 | { 6 | "type": "rectangle" 7 | } 8 | ] */ 9 | ee.Geometry.Polygon( 10 | [[[-124.028125, 38.569383491202544], 11 | [-124.028125, 36.336986018561895], 12 | [-117.7, 36.336986018561895], 13 | [-117.7, 38.569383491202544]]], null, false); 14 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 15 | var utils = require('users/gena/packages:utils') 16 | 17 | var w = 1024 18 | var h = 768 19 | var o = utils.generateExportParameters(bounds, w, h, 'EPSG:3857') 20 | 21 | print(o.scale) 22 | 23 | Map.addLayer(o.bounds) 24 | 25 | // Export.video({ region: o.bounds, scale: o.scale, ... } 26 | -------------------------------------------------------------------------------- /examples/water-test: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | 7 | Use the following reference to cite this algorithm: 8 | 9 | Donchyts, G, Planetary-scale surface water detection from space, Ph.D. thesis, Delft University of Technology, 2018 10 | https://doi.org/10.4233/uuid:510bd39f-407d-4bb6-958e-dea363c5e2a8 11 | 12 | */ 13 | 14 | var water = require('users/gena/packages:water') 15 | 16 | // Map.setCenter(82.73, 21.726, 14) 17 | Map.setOptions('HYBRID') 18 | 19 | var region = Map.getBounds(true) 20 | var start = '2016-01-01' 21 | var stop = '2019-01-01' 22 | var palette = ["f7fbff","deebf7","c6dbef","9ecae1","6baed6","4292c6","2171b5","08519c","08306b"].reverse() 23 | var indexMin = -0.2 24 | var indexMax = 0.2 25 | 26 | var waterOccurrence = water.getWaterOccurrence(region, start, stop, indexMin, indexMax) 27 | 28 | // add composite median image as well 29 | var composite = ee.Image(waterOccurrence.get('WATER_COMPOSITE_MEDIAN')) 30 | Map.addLayer(composite, {min: 0, max: 0.5}, 'composite') 31 | 32 | // add black background 33 | Map.addLayer(ee.Image(1), { palette: ['000000'] }, 'black', true, 0.5) 34 | 35 | // add water occurrence computed on-the-fly 36 | Map.addLayer(waterOccurrence.mask(waterOccurrence.reduce(ee.Reducer.max()).multiply(2)), {min: 0, max: 1}, 'water occurrence (NDWI, NDVI, MNDWI') 37 | print('image count:', waterOccurrence.get('WATER_IMAGE_COUNT')) 38 | 39 | 40 | // add JRC water occurrence for a refference 41 | var waterOccurrence = ee.ImageCollection("JRC/GSW1_0/MonthlyHistory") 42 | .map(function(i) { 43 | i = i.unmask(0).resample('bicubic') 44 | return i.eq(2).addBands(i.neq(0).rename('hasData')) 45 | }) 46 | 47 | waterOccurrence = waterOccurrence.select('water').sum().divide(waterOccurrence.select('hasData').sum()) 48 | 49 | Map.addLayer(waterOccurrence.mask(waterOccurrence.multiply(2)), {min: 0, max: 1, palette: palette}, 'water occurrence (JRC)', false) 50 | -------------------------------------------------------------------------------- /examples/water-test-China: -------------------------------------------------------------------------------- 1 | /**** Start of imports. If edited, may not auto-convert in the playground. ****/ 2 | var table = ee.FeatureCollection("users/multifcer/three_gorges/threegorges_N"); 3 | /***** End of imports. If edited, may not auto-convert in the playground. *****/ 4 | var water = require('users/gena/packages:water') 5 | 6 | // Map.centerObject(table,8) 7 | // Map.setOptions('HYBRID') 8 | 9 | var region = table.geometry().bounds() 10 | var start = '1987-01-01' 11 | var stop = '1990-01-01' 12 | var palette = ["f7fbff","deebf7","c6dbef","9ecae1","6baed6","4292c6","2171b5","08519c","08306b"].reverse() 13 | var indexMin = 0 14 | var indexMax = 0.3 15 | 16 | var waterOccurrence = water.getWaterOccurrence(region, start, stop, indexMin, indexMax) 17 | // add composite median image as well 18 | var composite = ee.Image(waterOccurrence.get('WATER_COMPOSITE_MEDIAN')) 19 | Map.addLayer(composite.clip(table), {min: 0, max: 0.5}, 'composite') 20 | print(composite) 21 | // add water occurrence computed on-the-fly 22 | Map.addLayer(waterOccurrence.mask(waterOccurrence.multiply(2)).clip(table), {min: 0, max: 1, palette: palette}, 'water occurrence (MNDWI and NDWI)') 23 | 24 | print('image count:', waterOccurrence.get('WATER_IMAGE_COUNT')) 25 | 26 | Map.addLayer(ee.Image(waterOccurrence.mask(waterOccurrence.gte(0.50))), {palette:"00ff00"}, 'composite1') 27 | var a = ee.Image(waterOccurrence.mask(waterOccurrence.gte(0.50))).gte(0) 28 | 29 | var hand = ee.ImageCollection('users/gena/global-hand/hand-100') 30 | var hand30 = hand.mosaic().focal_mean(0.1).rename('elevation'); 31 | 32 | var hand1 = hand30.select('elevation').lte(20) 33 | var k=a.gte(0).updateMask(hand1).clip(table) 34 | Map.addLayer(k,{palette:'ff0000'},'handwater') 35 | var k1=k.eq(1).multiply(ee.Image.pixelArea()).multiply(0.000001); 36 | var stats1 = k1.reduceRegion({ 37 | reducer: ee.Reducer.sum(), 38 | geometry: table, 39 | scale: 30, 40 | maxPixels: 1e13 41 | 42 | }); 43 | print(stats1,'a'); -------------------------------------------------------------------------------- /src/cloud-utils: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | /*** 9 | * Detect cloud shadow by projection cloud (casting) using sun elevation/azimuth. 10 | * Example: https://code.earthengine.google.com/702e270c6f8a4d09cea2a027a49d3e2f 11 | * 12 | * θ - zenith, degrees 13 | * φ - azimuth, degrees 14 | */ 15 | function projectCloudShadow(cloudMask, cloudHeight, φ, θ) { 16 | cloudHeight = ee.Number(cloudHeight); 17 | 18 | // convert to radians 19 | var π = Math.PI; 20 | θ = ee.Number(0.5).multiply(π).subtract(ee.Number(θ).multiply(π).divide(180.0)); 21 | φ = ee.Number(φ).multiply(π).divide(180.0).add(ee.Number(0.5).multiply(π)); 22 | 23 | // compute shadow offset (vector length) 24 | var offset = θ.tan().multiply(cloudHeight); 25 | 26 | // compute x, y components of the vector 27 | var proj = cloudMask.projection(); 28 | var nominalScale = proj.nominalScale(); 29 | var x = φ.cos().multiply(offset).divide(nominalScale).round(); 30 | var y = φ.sin().multiply(offset).divide(nominalScale).round(); 31 | 32 | return cloudMask.changeProj(proj, proj.translate(x, y)).set('height', cloudHeight) 33 | } 34 | 35 | /*** 36 | * Casts cloud mask given a number of cloud heights and sun parameters. 37 | */ 38 | function castCloudShadows(cloudMask, cloudHeights, sunAzimuth, sunZenith) { 39 | return cloudHeights.map(function (cloudHeight) { 40 | return projectCloudShadow(cloudMask, cloudHeight, sunAzimuth, sunZenith); 41 | }); 42 | } 43 | 44 | /*** 45 | * Estimates cloud shadow mask from image sun parameters. 46 | */ 47 | function computeCloudShadowMask(sunElevation, sunAzimuth, cloudMask, options) { 48 | var maxCloudHeight = 8000 // in image pixel units 49 | var cloudHeightStep = 200 50 | var radiusDilate = 10 51 | var radiusErode = 3 52 | 53 | if(options) { 54 | maxCloudHeight = options.maxCloudHeight || maxCloudHeight 55 | cloudHeightStep = options.cloudHeightStep || cloudHeightStep 56 | radiusDilate = options.radiusDilate || radiusDilate 57 | radiusErode = options.radiusErode || radiusErode 58 | } 59 | 60 | // generate cloud heights 61 | var cloudHeights = ee.List.sequence(100, maxCloudHeight, cloudHeightStep); 62 | 63 | // cast cloud shadows 64 | var cloudShadowMask = ee.ImageCollection(castCloudShadows(cloudMask, cloudHeights, sunAzimuth, sunElevation)).max(); 65 | 66 | // remove clouds 67 | cloudShadowMask = cloudShadowMask.updateMask(cloudMask.not()); 68 | 69 | return cloudShadowMask; 70 | } 71 | 72 | exports.computeCloudShadowMask = computeCloudShadowMask 73 | 74 | 75 | 76 | 77 | /* 78 | // Load a cloudy Landsat scene and display it. 79 | var image = ee.Image('LANDSAT/LC08/C01/T1_RT_TOA/LC08_042035_20140216'); 80 | 81 | //Map.centerObject(cloudy_scene); 82 | Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 0.4}, 'TOA', true); 83 | 84 | // Add a cloud score band. It is automatically called 'cloud'. 85 | var cloudScore = ee.Algorithms.Landsat.simpleCloudScore(image).select('cloud'); 86 | 87 | // Create a mask from the cloud score and combine it with the image mask. 88 | var cloudMask = cloudScore.gt(70); 89 | 90 | Map.addLayer(cloudMask.mask(cloudMask), {palette: ['fb8072']}, 'cloud mask', false) 91 | 92 | // morphological opening 93 | var radiusErode = 3 94 | //cloudMask = cloudMask.not().fastDistanceTransform(radiusErode).sqrt().lte(radiusErode).not() 95 | var radiusDilate = 10 96 | //cloudMask = cloudMask.fastDistanceTransform().sqrt().lte(radiusDilate) 97 | 98 | Map.addLayer(cloudMask.mask(cloudMask), {palette: ['faa092']}, 'cloud mask clean', true, 0.5) 99 | 100 | var cloudUtils = require('users/gena/packages:cloud-utils') 101 | 102 | var sunElevation = image.get('SUN_ELEVATION') 103 | var sunAzimuth = image.get('SUN_AZIMUTH') 104 | var cloudShadows = cloudUtils.computeCloudShadowMask(sunElevation, sunAzimuth, cloudMask) 105 | 106 | Map.addLayer(cloudShadows.mask(cloudShadows), {palette: ['ffff00']}, 'cloud shadows') 107 | */ -------------------------------------------------------------------------------- /src/earth: -------------------------------------------------------------------------------- 1 | var web = ee.Projection('EPSG:3857') 2 | 3 | function ortho(lon, lat) { 4 | var str = ee.String('PROJCS["unnamed",GEOGCS["WGS 84",DATUM["unknown",SPHEROID["WGS84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Orthographic"],') 5 | .cat('PARAMETER["latitude_of_origin",') 6 | .cat(ee.Number(lat).format('%.1f')) 7 | .cat('],PARAMETER["central_meridian",') 8 | .cat(ee.Number(lon).format('%.1f')) 9 | .cat('],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1]]') 10 | 11 | return str 12 | } 13 | 14 | function getEarthImage(image, lon, lat, scale, zoom, opt_showCenter, opt_reproject) { 15 | var proj = ortho(lon, lat) 16 | 17 | if(opt_showCenter) { 18 | image = image.blend(getCenterImage(lon, lat)) 19 | } 20 | 21 | return image 22 | .reproject(ee.Projection('EPSG:4326').atScale(scale)) 23 | .reproject(proj, null, scale) 24 | .changeProj(proj, web.scale(zoom, zoom)) 25 | .set({ label: ee.Number(lon).format('%.1f').cat(', ').cat(ee.Number(lat).format('%.1f')) }) 26 | } 27 | 28 | function getCenterImage(lon, lat) { 29 | return ee.FeatureCollection([ee.Geometry.Point([lon, lat]).buffer(500000)]) 30 | .style({ color: 'ff0000', fillColor: 'ff000033', width: 2 }) 31 | } 32 | 33 | function Earth(lon, lat, options) { 34 | var scale = 50000 35 | var zoom = 3 36 | var showCenter = false 37 | 38 | if(options) { 39 | scale = options.scale || 50000 40 | zoom = options.zoom || 3 41 | 42 | if(typeof(options.showCenter) != undefined) { 43 | showCenter = options.showCenter 44 | } 45 | } 46 | 47 | var ne = ee.Image("users/gena/NE1_HR_LC_SR_W") 48 | 49 | var reproject = true 50 | 51 | var earthImage = getEarthImage(ne, lon, lat, scale, zoom, showCenter, reproject) 52 | 53 | var thumb = ui.Thumbnail(earthImage) 54 | 55 | thumb.style().set({ 56 | position: 'bottom-right', 57 | width: '250px', 58 | height: '250px', 59 | // backgroundColor: '#00000011', 60 | // border: '1px none', 61 | backgroundColor: '00000000', 62 | border: '0px none', 63 | padding: '0px', 64 | margin: '0px' 65 | }) 66 | 67 | thumb.setCenter = function(lon, lat) { 68 | thumb.setImage(getEarthImage(ne, lon, lat, scale, 3, true)) 69 | } 70 | 71 | thumb.getImageAt = function(pt, options) { 72 | options = ee.Dictionary(options) 73 | zoom = ee.Number(options.get('zoom', 1)) 74 | 75 | zoom = zoom.multiply(0.1) 76 | 77 | 78 | var proj = ee.Projection('EPSG:3857') 79 | var coords = pt.transform(proj).coordinates() 80 | 81 | var image = thumb.getImage() 82 | .changeProj(proj, proj.translate(coords.get(0), coords.get(1)).scale(zoom, zoom)) 83 | .clip(pt.buffer(ee.Number(20000000).multiply(zoom), 100000)) 84 | 85 | return image 86 | } 87 | 88 | this.thumb = thumb 89 | 90 | return thumb 91 | } 92 | 93 | exports.Earth = Earth 94 | 95 | exports.getEarthImage = getEarthImage -------------------------------------------------------------------------------- /src/gallery: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | /*** 9 | * Generates image collection gallery (rows x columns). 10 | * 11 | * var options = {proj: 'EPSG:3857', flipX: false, flipY: true } 12 | * var gallery = imageGallery(images, aoi, rows, columns, scale, options) 13 | * 14 | * Map.addLayer(gallery, {bands: ['swir', 'nir', 'blue'], min: min, max: max}, 'gallery (false-color)', true); 15 | */ 16 | exports.draw = function(images, region, rows, columns, scale, options) { 17 | scale = scale || Map.getScale() 18 | var options = {proj: 'EPSG:3857', flipX: false, flipY: true } 19 | 20 | var proj = ee.Projection('EPSG:3857', [scale, 0, 0, 0, -scale, 0]); 21 | var scale = proj.nominalScale(); 22 | 23 | var e = ee.ErrorMargin(scale); 24 | 25 | var bounds = region.transform(proj, e).bounds(e, proj); 26 | 27 | var count = ee.Number(columns * rows); 28 | 29 | images = images.limit(count); 30 | 31 | // number of images is less than grid cells 32 | count = count.min(images.size()); 33 | 34 | var ids = ee.List(images.aggregate_array('system:index')); 35 | 36 | var indices = ee.List.sequence(0, count.subtract(1)); 37 | 38 | var offsetsX = indices.map(function (i) { 39 | return ee.Number(i).mod(columns); 40 | }); 41 | var offsetsY = indices.map(function (i) { 42 | return ee.Number(i).divide(columns).floor(); 43 | }); 44 | 45 | var offsets = offsetsX.zip(offsetsY); 46 | 47 | var offsetByImage = ee.Dictionary.fromLists(ids, offsets); 48 | 49 | var coords = ee.List(bounds.coordinates().get(0)); 50 | 51 | var w = ee.Number(ee.List(coords.get(1)).get(0)).subtract(ee.List(coords.get(0)).get(0)); 52 | var h = ee.Number(ee.List(coords.get(2)).get(1)).subtract(ee.List(coords.get(0)).get(1)); 53 | 54 | var boundsImage = ee.Image().toInt().paint(bounds, 1).reproject(proj); 55 | 56 | // new region 57 | var ll = ee.List(coords.get(0)); 58 | var ur = [ee.Number(ll.get(0)).add(w.multiply(columns)), ee.Number(ll.get(1)).add(h.multiply(rows))]; 59 | 60 | var regionNew = ee.Geometry.Rectangle([ll, ur], proj, false); 61 | 62 | var mosaic = images.map(function (i) { 63 | var offset = ee.List(offsetByImage.get(i.get('system:index'))); 64 | var xoff = w.multiply(offset.get(0)).multiply(scale); 65 | var yoff = h.multiply(offset.get(1)).multiply(scale); 66 | 67 | i = i.mask(boundsImage.multiply(i.mask())).paint(bounds, 1, 1); 68 | 69 | return i.translate(xoff, yoff, 'meters', proj); 70 | }).mosaic(); 71 | 72 | return mosaic; 73 | }; 74 | -------------------------------------------------------------------------------- /src/image-view: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | // very experimental, decorates image to query various information (pixel coordinates, pixel values) 9 | 10 | function ImageView(image, opt_band) { 11 | var band = opt_band || 0 12 | 13 | this.image = image; 14 | 15 | this.image0 = image.select(band) 16 | 17 | // get image dimensions 18 | var dimensions = ee.Dictionary(ee.List(ee.Dictionary(ee.Algorithms.Describe(this.image0)).get('bands')).get(0)).get('dimensions') 19 | this.dimensions = ee.List(dimensions) 20 | 21 | this.sizex = ee.Number(this.dimensions.get(0)) 22 | this.sizey = ee.Number(this.dimensions.get(1)) 23 | 24 | var proj = this.image0.projection() 25 | this.proj = proj 26 | 27 | this.scale = proj.nominalScale() 28 | 29 | var coordsImage = ee.Image.pixelLonLat().reproject(proj) 30 | 31 | // extract lat/lon coordinates as a list 32 | var coordsList = coordsImage.reduceRegion({ 33 | reducer: ee.Reducer.toList(2), 34 | geometry: this.image0.geometry() 35 | }).values().get(0) 36 | 37 | coordsList = ee.List(coordsList) 38 | 39 | // convert coordinates to points and add to map 40 | var centers = coordsList.map(function(xy) { 41 | var geom = ee.Algorithms.GeometryConstructors.Point(xy) 42 | return ee.Feature(geom, {}) 43 | }) 44 | 45 | this.centers = ee.FeatureCollection(centers) 46 | } 47 | 48 | ImageView.prototype.getDimensions = function() { 49 | return this.dimensions 50 | } 51 | 52 | ImageView.prototype.getPixelCenters = function() { 53 | return this.centers 54 | } 55 | 56 | ImageView.prototype.getPixelValues = function() { 57 | return this.image.reduceRegion({ 58 | reducer: ee.Reducer.toList(), 59 | geometry: this.image.geometry(), 60 | scale: this.scale 61 | }) 62 | } 63 | 64 | ImageView.prototype.getPixelCenter = function(x, y) { 65 | return ee.Feature(this.centers.toList(1, this.sizex.multiply(y).add(x)).get(0)) 66 | } 67 | 68 | ImageView.prototype.getPixelValue = function(x, y) { 69 | return this.image.reduceRegion({ 70 | reducer: ee.Reducer.first(), 71 | geometry: this.getPixelCenter(x, y).geometry(), 72 | scale: this.scale, 73 | crs: this.proj.crs() 74 | }) 75 | } 76 | 77 | exports.ImageView = ImageView -------------------------------------------------------------------------------- /src/stat: -------------------------------------------------------------------------------- 1 | function dnorm(mean, sigma) { 2 | return function(x) { 3 | return ee.Number(x).subtract(mean).divide(ee.Number(sigma)).pow(2).multiply(-0.5).exp() 4 | .divide(ee.Number(sigma).multiply(0.5 * Math.PI)) 5 | } 6 | } 7 | 8 | function qnorm(mean, sigma) { 9 | return function(x) { 10 | return ee.Number(x).multiply(2).subtract(1).erfInv().multiply(ee.Number(sigma).multiply(Math.sqrt(2))).add(mean) 11 | } 12 | } 13 | 14 | exports.qnorm = qnorm 15 | 16 | exports.dnorm = dnorm 17 | 18 | 19 | 20 | function debug() { 21 | var data = ee.List.sequence(-5, 5, 0.1).map(dnorm(0, 1)) 22 | print(ui.Chart.array.values(data, 0).setChartType('AreaChart')) 23 | 24 | var e = 0.0000001 25 | var data = ee.List.sequence(0+e, 1-e, 0.0001).map(qnorm(0, 1)) 26 | print(ui.Chart.array.values(data, 0).setChartType('AreaChart')) 27 | } 28 | 29 | debug() -------------------------------------------------------------------------------- /src/tiler: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | exports.doc = "Provides utils to work with Spherical Mercator tiles (Slippy Map)" 9 | 10 | var TILE_SIZE = 256 11 | 12 | var ORIGIN = 2 * Math.PI * 6378137 / 2.0 13 | 14 | /*** 15 | * meters/pixel at the Equator 16 | */ 17 | function zoomToScale(zoom) { 18 | var C = 40075016.686 19 | var tileSize = 256 20 | var tileWidth = C * Math.cos(0) / Math.pow(2, zoom) 21 | var pixelWidth = tileWidth / tileSize 22 | 23 | return pixelWidth 24 | } 25 | 26 | function scaleToZoom(scale) { 27 | var tileSize = 256 28 | var tileWidth = scale * tileSize 29 | var C = 40075016.686 30 | var zoom = Math.log(C/tileWidth) / Math.log(2) 31 | 32 | return Math.ceil(zoom) 33 | } 34 | 35 | 36 | function pixelsToMeters(px, py, zoom) { 37 | var resolution = zoomToScale(zoom) 38 | 39 | var x = px * resolution - ORIGIN 40 | var y = py * resolution - ORIGIN 41 | 42 | return [x, y] 43 | } 44 | 45 | function metersToPixels(x, y, zoom) { 46 | var resolution = zoomToScale(zoom) 47 | var px = (x + ORIGIN) / res 48 | var py = (y + ORIGIN) / res 49 | 50 | return px, py 51 | } 52 | 53 | function degreesToTiles(lon, lat, zoom) { 54 | var tx = Math.floor((lon + 180) / 360 * Math.pow(2, zoom)) 55 | var ty = Math.floor((1 - Math.log(Math.tan(toRadians(lat)) 56 | + 1 / Math.cos(toRadians(lat))) / Math.PI) / 2 * Math.pow(2, zoom)) 57 | 58 | return [tx, ty] 59 | } 60 | 61 | function tilesToDegrees(tx, ty, zoom) { 62 | var lon = tx / Math.pow(2, zoom) * 360 - 180 63 | 64 | var n = Math.PI - 2 * Math.PI * ty / Math.pow(2, zoom) 65 | var lat = toDegrees(Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))) 66 | 67 | return [lon, lat] 68 | } 69 | 70 | function getTilesForGeometry(geometry, zoom, opt_Bounds) { 71 | var bounds = opt_Bounds || geometry 72 | bounds = ee.List(bounds.bounds().coordinates().get(0)) 73 | 74 | var ll = bounds.get(0).getInfo() // TODO: port to server-side 75 | var ur = bounds.get(2).getInfo() 76 | 77 | var tmin = degreesToTiles(ll[0], ll[1], zoom) 78 | var tmax = degreesToTiles(ur[0], ur[1], zoom) 79 | 80 | var tiles = [] 81 | for(var tx = tmin[0]; tx < tmax[0] + 1; tx++) { 82 | for(var ty = tmax[1]; ty < tmin[1] + 1; ty++) { 83 | var bounds = getTileBounds(tx, ty, zoom) 84 | 85 | var rect = ee.Geometry.Rectangle(bounds, 'EPSG:3857', false) 86 | 87 | tiles.push(ee.Feature(rect).set({ tx: tx, ty: ty, zoom: zoom })) 88 | } 89 | } 90 | 91 | return ee.FeatureCollection(tiles).filterBounds(geometry) 92 | } 93 | 94 | function getTileBounds(tx, ty, zoom) { 95 | ty = Math.pow(2, zoom) - ty - 1 // // TMS -> XYZ, flip y index 96 | 97 | var min = pixelsToMeters(tx * TILE_SIZE, ty * TILE_SIZE, zoom) 98 | var max = pixelsToMeters((tx + 1) * TILE_SIZE, (ty + 1) * TILE_SIZE, zoom) 99 | 100 | return [min, max] 101 | } 102 | 103 | function toRadians(degrees) { 104 | return degrees * Math.PI / 180; 105 | } 106 | 107 | function toDegrees(radians) { 108 | return radians * 180 / Math.PI 109 | } 110 | 111 | 112 | 113 | exports.zoomToScale = zoomToScale 114 | exports.scaleToZoom = scaleToZoom 115 | exports.pixelsToMeters = pixelsToMeters 116 | exports.metersToPixels = metersToPixels 117 | exports.degreesToTiles = degreesToTiles 118 | exports.tilesToDegrees = tilesToDegrees 119 | exports.getTilesForGeometry = getTilesForGeometry 120 | exports.getTileBounds = getTileBounds 121 | -------------------------------------------------------------------------------- /src/ui: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Gennadii Donchyts. All rights reserved. 3 | 4 | This work is licensed under the terms of the MIT license. 5 | For a copy, see . 6 | */ 7 | 8 | exports.doc = "Area and polyline drawing tools" 9 | 10 | // TODO: refactor into a single DrawGeometryTool 11 | // TODO: this has to be supported by the EE UI itself, client-side, instead of hacking here 12 | 13 | var DrawTransectTool = function(map) { 14 | this.map = map 15 | this.layer = ui.Map.Layer({name: 'transect', visParams: { color:'green' }}) 16 | this.selection = null 17 | this.active = false 18 | this.points = [] 19 | this.transect = null 20 | 21 | this.listenersFinished = [] 22 | this.listenersDraw = [] 23 | 24 | var tool = this; 25 | 26 | this.initialize = function() { 27 | this.map.onClick(this.onMouseClick) 28 | this.map.layers().add(this.layer) 29 | } 30 | 31 | this.startDrawing = function() { 32 | this.active = true 33 | this.points = [] 34 | 35 | this.map.style().set('cursor', 'crosshair'); 36 | this.layer.setShown(true) 37 | } 38 | 39 | this.stopDrawing = function() { 40 | tool.active = false 41 | tool.map.style().set('cursor', 'hand'); 42 | 43 | tool.transect = ee.Geometry.LineString(tool.points) 44 | tool.layer.setEeObject(tool.transect) 45 | 46 | tool.listenersFinished.map(function(listener) { 47 | listener(tool.transect) 48 | }) 49 | } 50 | 51 | /*** 52 | * Mouse click event handler 53 | */ 54 | this.onMouseClick = function(coords) { 55 | if(!tool.active) { 56 | return 57 | } 58 | 59 | tool.points.push([coords.lon, coords.lat]) 60 | 61 | var geom = tool.points.length > 1 ? ee.Geometry.LineString(tool.points) : ee.Geometry.Point(tool.points[0]) 62 | tool.layer.setEeObject(geom) 63 | 64 | var l = ee.Geometry.LineString([tool.points[0], tool.points[tool.points.length-1]]).length(1).getInfo() 65 | 66 | // stop manually, using stopDrawing() instead of this: 67 | 68 | // if(tool.points.length > 1 && l / Map.getScale() < 5) { 69 | // tool.stopDrawing() 70 | //} 71 | 72 | tool.listenersDraw.map(function(listener) { 73 | listener(tool.points) 74 | }) 75 | } 76 | 77 | /*** 78 | * Adds a new event handler, fired on feature selection. 79 | */ 80 | this.onFinished = function(listener) { 81 | tool.listenersFinished.push(listener) 82 | } 83 | 84 | /*** 85 | * Adds a new event handler, fired on draw. 86 | */ 87 | this.onDraw = function(listener) { 88 | tool.listenersDraw.push(listener) 89 | } 90 | 91 | this.initialize() 92 | } 93 | 94 | var DrawAreaTool = function(map) { 95 | this.map = map 96 | this.layer = ui.Map.Layer({name: 'area selection tool', visParams: { color:'yellow' }}) 97 | this.selection = null 98 | this.active = false 99 | this.points = [] 100 | this.area = null 101 | 102 | this.listeners = [] 103 | 104 | var tool = this; 105 | 106 | this.initialize = function() { 107 | this.map.onClick(this.onMouseClick) 108 | this.map.layers().add(this.layer) 109 | } 110 | 111 | this.startDrawing = function() { 112 | this.active = true 113 | this.points = [] 114 | 115 | this.map.style().set('cursor', 'crosshair'); 116 | this.layer.setShown(true) 117 | } 118 | 119 | this.stopDrawing = function() { 120 | tool.active = false 121 | tool.map.style().set('cursor', 'hand'); 122 | 123 | tool.area = ee.Geometry.Polygon(tool.points) 124 | tool.layer.setEeObject(tool.area) 125 | 126 | tool.listeners.map(function(listener) { 127 | listener(tool.area) 128 | }) 129 | } 130 | 131 | /*** 132 | * Mouse click event handler 133 | */ 134 | this.onMouseClick = function(coords) { 135 | if(!tool.active) { 136 | return 137 | } 138 | 139 | tool.points.push([coords.lon, coords.lat]) 140 | 141 | var geom = tool.points.length > 1 ? ee.Geometry.LineString(tool.points) : ee.Geometry.Point(tool.points[0]) 142 | tool.layer.setEeObject(geom) 143 | 144 | var l = ee.Geometry.LineString([tool.points[0], tool.points[tool.points.length-1]]).length(1).getInfo() 145 | 146 | if(tool.points.length > 1 && l / Map.getScale() < 5) { 147 | tool.stopDrawing() 148 | } 149 | } 150 | 151 | /*** 152 | * Adds a new event handler, fired on feature selection. 153 | */ 154 | this.onFinished = function(listener) { 155 | tool.listeners.push(listener) 156 | } 157 | 158 | this.initialize() 159 | } 160 | 161 | exports.DrawAreaTool = DrawAreaTool 162 | exports.DrawTransectTool = DrawTransectTool 163 | --------------------------------------------------------------------------------