How to display individual images by each date in google earth engine? - google-earth-engine

I am new to google earth engine and not so familiar with javascript. I want to display the cleared images (B4,B3,B2 bands) of Sentinel 2 by each dates in layers (each layer represent each date). The code is shown as below, but always get error 'no Band 4, constant band'. Can anyone help me to solve this problem? Thanks!
var lakes=table.geometry();
Map.centerObject(lakes, 15);
function maskS2clouds(image) {
var qa = image.select('QA60');
// Bits 10 and 11 are clouds and cirrus, respectively.
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
.and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
var start = ee.Date('2015-06-20');
var finish = ee.Date('2018-06-01');
var collection = ee.ImageCollection('COPERNICUS/S2')
.filterDate(start, finish)
.filterBounds(lakes)
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10))
.map(maskS2clouds);
var rgbVis = {
min: 0.0,
max: 0.3,
bands: ['B4', 'B3', 'B2'],
};
function addImage(imageL) { // display each image in collection
var id = imageL.id;
var image = ee.Image(imageL.id);
Map.addLayer(image.select(['B4','B3','B2']).clip(lakes),rgbVis,id)
}
collection.evaluate(function(collection) { // use map on client-side
print(collection.features);
collection.features.map(addImage);
})

Related

How can I get a speeding profile using Here Maps Route Matching API?

We are using Here MapsRoute Matching API (https://developer.here.com/documentation/route-matching/dev_guide/index.html) to calculate the most sensible route based on many trace points.
We use the POST endpoint and we pass the tracepoints in GeoJSON format, including coordinates, timestamp and speed value for each point.
We would like to get the (estimated) speed of the vehicle in each of the links along the route.
This is an example of our request to the API:
https://routematching.hereapi.com/v8/calculateroute.json?routeMatch=1&mode=fastest;truck;traffic:disabled&routeAttributes=mo,wp,sm,fl,sp,sc&drivingReport=1&apiKey=whatever&alignToGpsTime=0&legAttributes=mn&linkAttributes=ma
We tried to use the remaining time and remaining distance attributes of each link to calculate the speed on each link, but the results dont correlate with the original trace points.
Is this the right approach to calculate a speeding profile of a route?
Please refer to the following codes to get the speed limits along the routes, more detailed code is available in the example.
function GPXParser(xmlDoc, map, draw)
{
this.xmlDoc = xmlDoc;
this.map = map;
this.trackcolor = "#ff00ff";
this.markercolor = "ff00ff";
this.trackwidth = 5;
this.mintrackpointdelta = 0.0001;
this.objectContainer = new H.map.Group();
this.pointsWithSpeed = [];
if(draw)
this.map.addObjects(this.objectContainer);
}
.....
var speed = 0;
var tmp = trackpoints[0].getElementsByTagName("speed")[0];
if(tmp && tmp.length != 0)
speed = tmp.childNodes[0].nodeValue;
speed = parseFloat(speed);
var heading = -1;
tmp = trackpoints[0].getElementsByTagName("course")[0];
if(tmp)
heading = tmp.childNodes[0].nodeValue;
heading = parseFloat(heading);
if(heading > 0)
this.pointsWithSpeed.push({coord: latlng, speed: speed, heading: heading});
else
this.pointsWithSpeed.push({coord: latlng, speed: speed});
for (var i=1; i < trackpoints.length; i++)
{
var lon = parseFloat(trackpoints[i].getAttribute("lon"));
var lat = parseFloat(trackpoints[i].getAttribute("lat"));
speed = 0;
tmp = trackpoints[i].getElementsByTagName("speed")[0];
if(tmp && tmp.length != 0)
speed = tmp.childNodes[0].nodeValue;
speed = parseFloat(speed);
....
if(heading > 0)
this.pointsWithSpeed.push({coord: latlng, speed: speed, heading: heading});
else
this.pointsWithSpeed.push({coord: latlng, speed: speed});
this.objectContainer.addObject(polyline);
lastlon = lon;
lastlat = lat;
}
}
}
GPXParser.prototype.GetPointsWithSpeed = function()
{
return this.pointsWithSpeed;
}

Google Earth Engine - Buffer around Cloud Mask Sentinel2

I'm trying to create a cloud free S2 Image. Now this code works, but I want to add a buffer of 20 or 30 meters around the cloud mask, because there still is the edge of the clouds in my image. [![Example image][1]][1]
* Function to mask clouds using the Sentinel-2 QA band
* #param {ee.Image} image Sentinel-2 image
* #return {ee.Image} cloud masked Sentinel-2 image
*/
function maskS2clouds(image) {
var qa = image.select('QA60');
// Bits 10 and 11 are clouds and cirrus, respectively.
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
.and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
// Map the function over one year of data and take the median.
// Load Sentinel-2 TOA reflectance data.
var dataset = ee.ImageCollection('COPERNICUS/S2_SR')
.filterDate('2019-07-01', '2019-07-30')
// Pre-filter to get less cloudy granules.
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 9))
.map(maskS2clouds);
var medianpixels = dataset.median()
var medianclipped = medianpixels.clip(geometry)
Map.addLayer(medianclipped,{
min: 0.0,
max: 0.3,
gamma: 1.7,
bands: ['B4', 'B3', 'B2'], }) ```
[1]: https://i.stack.imgur.com/HruSG.png

Which function is correct for cloud masking

I was writing a function to mask cloudy pixels of the Sentinel-2 data.
Function 1:
function cloudMask(image) {
var qa = image.select('QA60');
var cloudBitMask = 1 << 10; ###
var cirrusBitMask = 1 << 11; ###
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
Function 2:
function cloudMask(image) {
var qa = image.select('QA60');
var cloudBitMask = Math.pow(2, 10); ###
var cirrusBitMask = Math.pow(2, 11); ###
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
Which function is correct?
The difference between two functions is that how cloudBitMask and cirrusBitMask are defined.
Both functions are correct as they are doing exactly the same thing. Either 1 << 10 or Math.pow(2, 10) will result in a number with a value of 1024.
As we usually use both opaque cloud and cirrus cloud for cloud masking, I suggest keeping the code short and clear as below:
function cloudMask(image) {
var qa = image.select('QA60');
var allCloudBitMask = (1 << 10) + (1 << 11);
var mask = qa.bitwiseAnd(allCloudBitMask).eq(0);
return image.updateMask(mask);
}

Group an Array of Vectors according to certain Floors in Three.js

I have a list of Vectors which represent points on three different floors in three.js.
I am trying to group these vectors according to the floor they belong to. Is there a good formula to do this? Perhaps find height from on vector or something. Not sure how to go about this. Any help would be appreciated.
Thanks,
Rob
As Wilt said... Can't really help you without more info.
Still, if your floors are even and all stand on the xz plane (in my example), You may indeed check the points' height (position.y) against the floors'.
var container, renderer, scene, camera, controls;
var floors = [];
var points = [], materials = [], heights = [];
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
container = document.createElement('div');
document.body.appendChild(container);
container.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera + controls
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 50, 750);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
//floors
for(i=0; i<3; i++) {
var planeGeometry = new THREE.BoxGeometry(500, 500, 10, 10);
var planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff * Math.random(),
side: THREE.DoubleSide,
transparent: true,
opacity : 0.3,
depthWrite : false //get rid of coplanar glitches wall/floor
});
materials.push(planeMaterial);
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = Math.PI / 2;
//plane.rotation.y = Math.PI / 8; //Uncomment to see this doesn't work if the floors move, i.e. changing rotation/position. If this is what you need, just raycast from point to floor in the animation loop and count how many floors the ray goes through (intersects.length)
plane.position.y = 75*i;
heights.push(plane.position.y);
floors.push(plane);
scene.add(plane);
}
//wall
var height = heights[2];
var planeGeometry = new THREE.BoxGeometry(500, height+100, 10, 10);
var planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff * Math.random(),
side: THREE.DoubleSide,
transparent: true,
opacity:0.3,
depthWrite : false //get rid of coplanar glitches wall/floor
});
materials.push(planeMaterial);
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = heights[1]+45;
plane.position.z = -510/2;
scene.add(plane);
// points
for (i=0; i<200; i++) {
var sphereGeometry = new THREE.SphereGeometry(3, 32, 16);
var sphere = new THREE.Mesh(sphereGeometry);
sphere.position.x = Math.random() * 500 - 250;
sphere.position.y = Math.random() * 300 - 100;
sphere.position.z = Math.random() * 500 - 250;
scene.add(sphere);
points.push(sphere);
}
// events
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(event) {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function addSpheres() {
//addSpheres
for (i=0;i<200;i++) {
var that = points[i].position.y;
points[i].position.y = ( that < heights[0] ) ? 200 : that - 0.5;
if ( that > heights[0] && that < heights[1] ) points[i].material = materials[0];
if ( that < heights[2] && that > heights[1] ) points[i].material = materials[1];
if ( that > heights[2] ) points[i].material = materials[2];
points[i].material.needsUpdate = true;
}
}
function animate() {
controls.update();
addSpheres();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
Now, feel free to "group" these points according to your needs.
Please note that "vectors" are different from "points". Read more about the difference.
Raycasting would be the way to go if you had a more complex scene (moving floors/different planes, points moving in different directions).

Draw a circle with google maps api3 that doesn't resize

With google maps api2 I was drawing a circle using this code:
var markerPoint = currentMarker.getPoint();
var polyPoints = Array();
var mapNormalProj = G_NORMAL_MAP.getProjection();
var mapZoom = map.getZoom();
var clickedPixel = mapNormalProj.fromLatLngToPixel(markerPoint, mapZoom);
var polySmallRadius = 20;
var polyNumSides = 20;
var polySideLength = 18;
for (var a = 0; a<(polyNumSides+1); a++) {
var aRad = polySideLength*a*(Math.PI/180);
var polyRadius = polySmallRadius;
var pixelX = clickedPixel.x + 5 + polyRadius * Math.cos(aRad);
var pixelY = clickedPixel.y - 10 + polyRadius * Math.sin(aRad);
var polyPixel = new GPoint(pixelX,pixelY);
var polyPoint = mapNormalProj.fromPixelToLatLng(polyPixel,mapZoom);
polyPoints.push(polyPoint);
}
// Using GPolygon(points, strokeColor?, strokeWeight?, strokeOpacity?, fillColor?, fillOpacity?)
highlightCircle = new GPolygon(polyPoints,"#000000",2,0.0,"#FF0000",.5);
map.addOverlay(highlightCircle);
I've managed to transform this code to api3:
var markerPoint = currentMarker.getPosition();
var polyPoints = Array();
var mapNormalProj = map.getProjection();
var mapZoom = map.getZoom();
var clickedPixel = mapNormalProj.fromLatLngToPoint(markerPoint);
var polyRadius = 20;
var polyNumSides = 20;
var polySideLength = 18;
for (var a = 0; a<(polyNumSides+1); a++) {
var aRad = polySideLength*a*(Math.PI/180);
var pixelX = clickedPixel.x + 5 + (polyRadius * Math.cos(aRad));
var pixelY = clickedPixel.y - 10 + (polyRadius * Math.sin(aRad));
var polyPixel = new google.maps.Point(pixelX,pixelY);
var polyPoint = mapNormalProj.fromPointToLatLng(polyPixel);
polyPoints.push(polyPoint);
}
highlightCircle = new google.maps.Polygon({
paths: polyPoints,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
highlightCircle.setMap(map);
If you look more closely at the api3 example, the mapZoom variable is not used anywhere.
In api2, the code generates a small circle around my marker - around 35px radius. When I zoom into the map, the radius stays at 35px (because the zoom is taken into account).
With api3 on the other hand, I have a huge circle - more than 200px wide and when I zoom in, the circle becomes bigger and bigger.
It behaves the same way as the circle object available in api3.
What I want is just a small circle around my marker, that is not 100km in diameter, but just a few pixels around my marker (this circle acts like a hover element in html).
Any ideas how to achieve that?
You might have better luck using custom marker, not a circle. See "Vector Icon" from the documentation here: https://developers.google.com/maps/documentation/javascript/overlays#Icons
var marker = new google.maps.Marker({
position: new google.maps.LatLng(-25.363882, 131.044922),
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 10
},
draggable: true,
map: map
});
You're doing the calculation based on the Point plane which plane remains the same no matter what zoom level you are at. You probably mean to do the calculation using pixels.
The methods you are looking for are here. fromLatLngToContainerPixel and fromContainerPixelToLatLng or fromLatLngToDivPixel and fromDivPixelToLatLng.
This means you should probably wrap up that code into an OverlayView and call getProjection() on your map to get the projection and then use one set of those methods to do the calculation.

Resources