I'm trying to determine if a point is inside a polygon using TurfJS.
But I'm getting unexpected results.
In first place, I tested this simple code and works well.
The intersection is true because the point pt0 is one the points in the polygon.
var pt0 = turf.point([1, 1]);
var poly0 = turf.polygon([
[
[-1, -1],
[-1, 1],
[1, 1],
[-1, -1]
]
]);
var inter0 = turf.intersect(poly0,pt0); // TRUE
var inside0 = turf.inside(pt0,poly0); // FALSE
The next code is very similar, but the intersection returns undefined, while the tested point also belongs to the polygon.
var polygon1 = turf.polygon([
[-56.14700317382812,-33.179944977396694],
[-56.14502906799316,-33.16895330313461],
[-56.13266944885254,-33.174557074027],
[-56.14700317382812,-33.179944977396694]
]);
var point1 = turf.point([-56.13266944885254,-33.174557074027]);
var inter1 = turf.intersect(polygon1,point1); // UNDEFINED
var inside1 = turf.inside(point1,polygon1); // FALSE
Here is a JSFiddle.
Related
I'm using Cesium in 2D mode.
This is the code I'm using to take the terrain height at mouse position:
cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic( position );
var longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(10);
var latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(10);
mapPointerLatitude = latitudeString.slice(-15);
mapPointerLongitude = longitudeString.slice(-15);
var tempHeight = cartographic.height;
if( tempHeight < 0 ) tempHeight = 0;
mapPointerHeight = tempHeight.toFixed(2);
Where position came from a Cesium.ScreenSpaceEventType.MOUSE_MOVE event:
if ( mapStyle === '2D' ) {
var position = viewer.camera.pickEllipsoid(movement.endPosition, scene.globe.ellipsoid);
if (position) {
return position;
}
}
if ( mapStyle === '3D' ) {
var ray = viewer.camera.getPickRay(movement.endPosition);
var position = viewer.scene.globe.pick(ray, viewer.scene);
if (Cesium.defined(position)) {
return position;
}
}
When the map is in 3D mode (Cesium.SceneMode.SCENE3D) I have the height value in tempHeight but when the map is in Cesium.SceneMode.SCENE2D this value is always zero. What I'm doing wrong?
EDIT
Don't know if this is the best way but I get it to work putting my code inside this:
cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic( position );
var positions = [ cartographic ];
var promise = Cesium.sampleTerrain(terrainProvider, 11, positions);
Cesium.when(promise, function( updatedPositions ) {
// PUT ALL HERE
});
You can actually try Cesium.sampleTerrainMostDetailed to get more precise altitude.
// Query the terrain height of two Cartographic positions
const terrainProvider = Cesium.createWorldTerrain();
const positions = [
Cesium.Cartographic.fromDegrees(86.925145, 27.988257),
Cesium.Cartographic.fromDegrees(87.0, 28.0)
];
Cesium.sampleTerrainMostDetailed(terrainProvider, positions).then((updatedPositions) => {
// positions[0].height and positions[1].height have been updated.
// updatedPositions is just a reference to positions.
})
https://cesium.com/learn/cesiumjs/ref-doc/global.html?classFilter=sample#sampleTerrainMostDetailed
I am a beginner in Google Earth Engine code and am trying to apply the SLC-gap code to Landsat 7 Surface Reflectance images. Using resources available on StackOverflow, I generated the code below; however, when I bring the images into QGIS, there still appear to be gaps. Is my code incorrect or did I not properly apply it to the images?
First, I masked the clouds based on the pixel_qa band of Landsat SR data:
var cloudMaskL7 = function(image) {
var qa = image.select('pixel_qa');
var cloud = qa.bitwiseAnd(1 << 5)
.and(qa.bitwiseAnd(1 << 7))
.or(qa.bitwiseAnd(1 << 3));
Then, I removed edge pixels that don't occur in all bands:
var mask2 = image.mask().reduce(ee.Reducer.min());
return image.updateMask(cloud.not()).updateMask(mask2);
};
var l7 = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
.filterDate('2004-09-15', '2004-12-31')
.map(cloudMaskL7);
var visParams = {
bands: ['B3', 'B2', 'B1'],
min: 0,
max: 3000,
gamma: 1.4,
};
Map.setCenter(36.197, 31.701,7);
Map.addLayer(l7.median(), visParams);
Then, I mapped the function over one year of Landsat 7 TOA data and took the median and mapped it for Jordan.
var composite = l7.map(cloudMaskL7)
.median();
Map.setCenter(36.124, 31.663);
Map.addLayer(composite, {bands: ['B4', 'B3', 'B2'], max: 0.3});
Then, I tried to fill the SLC Landsat 7 gaps by applying the USGS L7 Phase-2 Gap filling protocol, using a single kernel size.
var MIN_SCALE = 1/3;
var MAX_SCALE = 3;
var MIN_NEIGHBORS = 144;
var GapFill = function(src, fill, kernelSize) {
var kernel = ee.Kernel.square(kernelSize * 30, 'meters', false);
var common = src.mask().and(fill.mask());
var fc = fill.updateMask(common);
var sc = src.updateMask(common);
Then, I found the primary scaling factors with a regression and interleaved the bands for the regression (assumes the bands have the same names).
var regress = fc.addBands(sc);
regress = regress.select(regress.bandNames().sort());
var fit = regress.reduceNeighborhood(ee.Reducer.linearFit().forEach(src.bandNames()), kernel, null, false);
var offset = fit.select('.*_offset');
var scale = fit.select('.*_scale');
Then, I found the secondary scaling factors using just means and stddev.
var reducer = ee.Reducer.mean().combine(ee.Reducer.stdDev(), null, true);
var src_stats = src.reduceNeighborhood(reducer, kernel, null, false);
var fill_stats = fill.reduceNeighborhood(reducer, kernel, null, false);
var scale2 = src_stats.select('.*stdDev').divide(fill_stats.select('.*stdDev'));
var offset2 = src_stats.select('.*mean').subtract(fill_stats.select('.*mean').multiply(scale2));
var invalid = scale.lt(MIN_SCALE).or(scale.gt(MAX_SCALE));
scale = scale.where(invalid, scale2);
offset = offset.where(invalid, offset2);
I applied the scaling and mask off pixels that didn't have enough neighbors.
var count = common.reduceNeighborhood(ee.Reducer.count(), kernel, null, true, 'boxcar');
var scaled = fill.multiply(scale).add(offset)
.updateMask(count.gte(MIN_NEIGHBORS));
return src.unmask(scaled, true);
};
var source = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR');
var fill = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR');
I loaded a table of boundaries and filter.
var Jordan = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')
.filter(ee.Filter.or(
ee.Filter.eq('country_co', 'JO')));
var clippedJordan = composite.clipToCollection(Jordan);
I displayed the results for Jordan; however, the SLC gaps appear not to be filled. I proceed to calculate the MSAVI2 values using these images, so the remaining gaps influence the results.
var mc = Map.setCenter(36.274, 31.682, 6);
var visParams = {bands: ['B3', 'B2', 'B1']};
Map.addLayer(clippedJordan, visParams, 'clipped composite');
Any advice would be greatly appreciated!
I am not up on the latest Landsat 7 gap-filling technology for SLC-off imagery, but here is a greatly simplified version of what you were trying to do. I removed a lot of (unnecessary?) stuff, increased the kernel size by a lot, and increased the timeframe over which the median replacement is generated. It might get close to what you want:
var cloudMaskL7 = function(image) {
var qa = image.select('pixel_qa');
var cloud = qa.bitwiseAnd(1 << 5)
.and(qa.bitwiseAnd(1 << 7))
.or(qa.bitwiseAnd(1 << 3));
var mask2 = image.mask().reduce(ee.Reducer.min());
return image.updateMask(cloud.not()).updateMask(mask2);
};
var l7 = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
.map(cloudMaskL7);
var kernelSize = 10;
var kernel = ee.Kernel.square(kernelSize * 30, 'meters', false);
var GapFill = function(image) {
var start = image.date().advance(-1, 'year');
var end = image.date().advance(1, 'year');
var fill = l7.filterDate(start, end).median();
var regress = fill.addBands(image);
regress = regress.select(regress.bandNames().sort());
var fit = regress.reduceNeighborhood(ee.Reducer.linearFit().forEach(image.bandNames()), kernel, null, false);
var offset = fit.select('.*_offset');
var scale = fit.select('.*_scale');
var scaled = fill.multiply(scale).add(offset);
return image.unmask(scaled, true);
};
// TESTING CODE
var point = ee.Geometry.Point(36.124, 31.663);
Map.centerObject(point, 11);
var check = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
.filterBounds(point)
.filterDate('2004-09-15', '2004-12-31');
var checkImage = ee.Image(check.first());
var visParams = {bands: ['B4', 'B3', 'B2'], min: 200, max: 5500};
Map.addLayer(checkImage, visParams, 'source');
// Test composite.
var checkStart = checkImage.date().advance(-1, 'year');
var checkEnd = checkImage.date().advance(1, 'year');
var composite = l7.filterDate(checkStart, checkEnd).median();
Map.addLayer(composite, visParams, 'median');
// Rough implementation for comparison.
var replaced = checkImage.unmask(composite);
Map.addLayer(replaced, visParams, 'simple');
// Fancy implementation.
var filled = ee.Image(check.map(GapFill).first());
Map.addLayer(filled, visParams, 'filled');
EDIT: The answer now shows how to map this over a collection. Watch out, because I don't know how well this will scale. If you decide to map it over a big area or long time series, you've been warned.
i created three arrays and each of them has their own sets of questions in it. is it possible to shuffle that three arrays everytime the game starts? so that the user will have to answer different sets of question everytime he clicks for a new game.
See for example:
Randomize or shuffle an array
as3 random array - randomize array - actionscript 3
The second one has a nice cheeky little use of Array.sort():
var arr:Array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function randomize (a:*, b:*):int
{
return (Math.random() > .5) ? 1 : -1;
}
trace(arr.sort(randomize));
To shuffle the 3 arrays you could create 3 other arrays that will serve to hold the shuffled values.
var arr1:Array = [1, 2, 3, 4, 5];
var sorted1:Array = new Array(arr1.length);
var arr2:Array = [1, 2, 3, 4, 5];
var sorted2:Array = new Array(arr2.length);
var arr3:Array = [1, 2, 3, 4, 5];
var sorted3:Array = new Array(arr3.length);
randomPos:Number = 0;
you could then create a function that takes the value from one array and place it into a new shuffled array.
function shuffleArray(x, y){
for(var i:int = 0; i < y.length; i++){
randomPos = int(Math.random() * x.length);
y[i] = x.splice(randomPos, 1)[0];
}
}
Then you would call the suffleArray function on each set of arrays:
shuffleArray(arr1, sorted1);
shuffleArray(arr2, sorted2);
shuffleArray(arr3, sorted3);
I hope this helps.
I can draw multiple lines on the canvas; they are added to the layer using drawScene
dlayerA1.add(line);
line.getPoints()[0].x = mousePos.x;
line.getPoints()[0].y = mousePos.y;
line.getPoints()[1].x = mousePos.x;
line.getPoints()[1].y = mousePos.y;
moving = true;
dlayerA1.drawScene();
http://jsfiddle.net/user373721/xzEad/1/.
Is there a way to delete individual line?
Currently, you'll have to modify the points array like this:
line.getPoints()[0].splice(index, 1);
Since arrays are modified by reference, modifying the returned array modifies the "source of truth" points array attr
I assigned a unique id to each object and used the following to delet it when click on it:
r = r + 1;
var mousePos = stage1.getMousePosition();
rectA1 = new Kinetic.Rect({
x: mousePos.x - rOffset,
y: mousePos.y - rOffset,
width: 0,
height: 0,
stroke: 'red',
strokeWidth: 4,
id:"rectA" + r
});
rectA1.setListening(true);
myRect1[r] = rectA1;
background1.add(myRect1[r]);
//start point and end point are the same
rectA1.setX(mousePos.x - rOffset);
rectA1.setY(mousePos.y - rOffset);
rectA1.setWidth(0);
rectA1.setHeight(0);
moving = true;
background1.drawScene();
myRect1[r].on("click", function () {
this.remove();
});
My solution is based on this good answer: How to select an object in kinetic.js?
I am developing a tree game and having dots to add branches on the tree, I want to enhance it for e.g. when one dot get a click then it display other dots within a particular radius around it.
From the description you've given, I think you are looking for Distance Formula.
Sqrt((y2-y1)^2 + (x2-x1)^2)
For example:
You have a radius defined and an array of dots:
var radius:int = 20;
var myDots = new Array ({'x':0, 'y': 0}, {'x': 5, 'y': 5}, {'x': 10, 'y': 5}, {'x': 10, 'y': 5}, {'x': 10, 'y': 10});
The dot being clicked is (5,5) and suppose you have a determined radius r=20.
Now, to get all the dots withing the radius r, by iterating in the dots:
function getDotsWithinRadius(x,y){
for(var i= 0; i<myDots.length;i++){
var x2 = myDots[i].x;
var y2 = myDots[i].y;
var val = Math.sqrt(Math.pow(y2-y,2) + Math.pow(x2-x, 2));
if(val <=radious){
/*The dot is with the radius of the give location.
This is the place where you tell the current dot to show up or
something like that.
*/
}
}
}
I haven't tested the code but I really hope this gives you an understanding.