Center of polygon in gmap.net - polygon

I'm using Gmap.Get great mapping tools to develop an enterprise software. How to calculate center of polygon in Gmap.Net using polygon points?

Use following code to calculate center of polygon in Gmap.Net:
Private Function CalculateCenterOfPolygon(polyPoints As List(Of PointLatLng)) As PointLatLng
Dim centerPoint As New PointLatLng()
Dim sum As Integer = 0
Dim Lat As Double = 0
Dim Lng As Double = 0
For Each point As PointLatLng In polyPoints
sum += 1
Lat += point.Lat
Lng += point.Lng
Next
Lat = Lat / sum
Lng = Lng / sum
centerPoint.Lat = Lat
centerPoint.Lng = Lng
Return centerPoint
End Function

Calculate the RectLatLng with the polygon's points.
double lat = points.Max(item => item.Lat);
double lng = points.Min(item => item.Lng);
double height = lat - points.Min(item => item.Lat);
double width = points.Max(item => item.Lng) - lng;
var rect = new RectLatLng(lat, lng, width, height);
and rect.LocationMiddle is the center.

Related

Converting Aster L1T data radiance to surface reflectance in Google Earth Engine

I am working with ASTER images and I am trying to convert radiance values to reflectance. Currently, I converted DN values to radiance and I don't know what else to do. Also, I found a Landsat function, but I don't know if it works for this case. This is my code:
var AOI = ee.Geometry.Polygon([
[-75.01530862531565,9.762481145514606],[-74.58134866437815,9.762481145514606],
[-74.58134866437815,10.27637106477599],[-75.01530862531565,10.27637106477599]]);
var dataset = ee.ImageCollection('ASTER/AST_L1T_003')
.filter(ee.Filter.date('2000-01-01', '2020-10-30'))
.filterBounds(AOI)
.filterMetadata('CLOUDCOVER', 'less_than', 1)
.filter(ee.Filter.and(
ee.Filter.notNull(['GAIN_COEFFICIENT_B01']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B02']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B3N']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B04']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B05']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B06']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B07']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B08']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B09'])));
print(dataset)
// red and NIR channel digital numbers to at sensor radiance
function bands (img) {
var gainB1 = 0.676;
var gainB2= 0.708;
var gainB3N = 0.862;
var gainB4= 0.2174;
var gainB5 = 0.0696;
var gainB6= 0.0625;
var gainB7 = 0.0597;
var gainB8= 0.0417;
var gainB9 = 0.0318;
var rad_b1 = (img.select('B01').subtract(1)).multiply(gainB1);
var rad_b2 = (img.select('B02').subtract(1)).multiply(gainB2);
var rad_b3 = (img.select('B3N') .subtract(1)).multiply(gainB3N);
var rad_b4 = (img.select('B04').subtract(1)).multiply(gainB4);
var rad_b5 = (img.select('B05') .subtract(1)).multiply(gainB5);
var rad_b6 = (img.select('B06').subtract(1)).multiply(gainB6);
var rad_b7 = (img.select('B07').subtract(1)).multiply(gainB7);
var rad_b8 = (img.select('B08').subtract(1)).multiply(gainB8);
var rad_b9 = (img.select('B09').subtract(1)).multiply(gainB9);
return (rad_b1).addBands(rad_b2).addBands(rad_b3).addBands(rad_b4)
.addBands(rad_b5).addBands(rad_b6).addBands(rad_b7)
.addBands(rad_b8).addBands(rad_b9);
}
// add all selected bands with radiance values
var rad_bands =dataset.map(bands)
print(rad_bands)
function copyProps(index){
var source = ee.Image(dataset.toList(dataset.size()).get(index))
var dest = ee.Image(rad_bands.toList(rad_bands.size()).get(index))
var image = ee.Image(dest.copyProperties(source))
return image
}
var seq = ee.List.sequence(0, rad_bands.size().subtract(1))
print(seq)
var final_col = ee.ImageCollection(seq.map(copyProps))
https://code.earthengine.google.com/5b2dfc9b609ba5738be49ae2915d3980

Land-use classification using the Random Forest algorithm of the GEE

I am working on a land use classification program using the RS algorithm of the GEE platform. The codes are as the following link.
https://code.earthengine.google.com/7e99f1de58c1251bd9bff0ff7af9368b
Specific codes:
var table = ee.FeatureCollection("users/zongxuli/Jing_Jin_Ji");
//Set up bands and corresponding band names
var inBands = ee.List([1,2,3,4,5,7,6,'pixel_qa'])
var outBands = ee.List(['blue','green','red','nir','swir1','temp', 'swir2','pixel_qa'])
// Get Landsat data
var l8s = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
.filterDate(2019-01-01,2019-12-31)
.filterBounds(table)
.select(inBands,outBands)
.filter(ee.Filter.lt("CLOUD_COVER",10))
function getIndexes(image){
// Normalized Difference Vegitation Index(NDWI)
var ndvi = image.normalizedDifference(['nir','red']).rename("ndvi");
image = image.addBands(ndvi);
// Normalized Difference Snow Index(NDWI)
var ndsi = image.normalizedDifference(['green','swir1']).rename("ndsi");
image = image.addBands(ndsi);
// Normalized Difference Water Index(NDWI)
var ndwi = image.normalizedDifference(['nir','swir1']).rename("ndwi");
image = image.addBands(ndwi);
// add Enhanced Vegetation Indexes
var evi = image.expression('2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR' : image.select('nir'),
'RED' : image.select('red'),
'BLUE': image.select('blue') }).float();
image = image.addBands(evi.rename('evi'));
// Add Index-Based Built-Up Index (IBI)
var ibiA = image.expression('2 * SWIR1 / (SWIR1 + NIR)', {
'SWIR1': image.select('swir1'),
'NIR' : image.select('nir')}).rename(['IBI_A']);
var ibiB = image.expression('(NIR / (NIR + RED)) + (GREEN / (GREEN + SWIR1))', {
'NIR' : image.select('nir'),
'RED' : image.select('red'),
'GREEN': image.select('green'),
'SWIR1': image.select('swir1')}).rename(['IBI_B']);
var ibiAB = ibiA.addBands(ibiB);
var ibi = ibiAB.normalizedDifference(['IBI_A', 'IBI_B']);
image = image.addBands(ibi.rename('ibi'));
return(image);
}
function getTopography(image,elevation) {
// Calculate slope, aspect and hillshade
var topo = ee.Algorithms.Terrain(elevation);
// From aspect (a), calculate eastness (sin a), northness (cos a)
var deg2rad = ee.Number(Math.PI).divide(180);
var aspect = topo.select(['aspect']);
var aspect_rad = aspect.multiply(deg2rad);
var eastness = aspect_rad.sin().rename(['eastness']).float();
var northness = aspect_rad.cos().rename(['northness']).float();
// Add topography bands to image
topo = topo.select(['elevation','slope','aspect']).addBands(eastness).addBands(northness);
image = image.addBands(topo);
return(image);
}
// Get an image to train and apply classification to.
var image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(table)
.first();
// get bands
var bands=image.bandNames();
print(bands);
// integers starting from zero in the training data.
var label = 'lcode';
// Overlay the points on the imagery to get training.
var trainings = image.select(bands).sampleRegions({
collection: l8s, //.filterDate(2019-01-01,2019-12-31),
properties: [label],
scale: 30
});
// The randomColumn() method will add a column of uniform random
// numbers in a column named 'random' by default.
var sample = trainings.randomColumn();
var split = 0.7; // Roughly 70% training, 30% testing.
var training = sample.filter(ee.Filter.lt('random', split));
print(training.size());
// Random forest
var classifier = (ee.Classifier.smileRandomForest(15)
.train({
features: training,
classProperty: label,
inputProperties: bands
}));
var classified = image.classify(classifier);
print(classified);
So far, I always received the wrong message "Number (Error) Empty date ranges not supported for the current operation." when running the program. What am I doing wrong?
There is a quotation problem in image collection date filtering:
// Get Landsat data
var l8s = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
.filterDate(2019-01-01,2019-12-31)
.filterBounds(table)
.select(inBands,outBands)
.filter(ee.Filter.lt("CLOUD_COVER",10))
it must be:
// Get Landsat data
var l8s = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
.filterDate('2019-01-01','2019-12-31')
.filterBounds(table)
.select(inBands,outBands)
.filter(ee.Filter.lt("CLOUD_COVER",10))
And in training for classifier section:
// Overlay the points on the imagery to get training.
var trainings = image.select(bands).sampleRegions({
collection: l8s, //.filterDate(2019-01-01,2019-12-31),
properties: [label],
scale: 30 });
it must be :
// Overlay the points on the imagery to get training.
var trainings =
image.select(bands).sampleRegions({
collection: table,
properties: [label],
scale: 30 });

Create measure dictionary for area annotation in iText

The supposed value for this would is 15.2 sq cm. however, when annotation is moved, it becomes 0.04 sq cm.
I got this data from my application where area is computed as 9658.6572265625 and its calibration value is 0.00157889 which results in 15.2 value.
when the corresponding coordinates in pdf space are provided (see code below), the area computed is 5433.001953125.
so i compute the calibration value in pdf space like this.
ratio = area / pdfArea
pdfCalibrationValue = 0.00157889 * ratio;
the result is 0.002806911838696635. which if computed
5433.001953125 x 0.002806911838696635 = 15.2
so i am wondering why the result becomes 0.04.
Thoughts?
public class Test {
public static void main(String[] args) throws Exception {
PdfReader reader = new PdfReader("src.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("result.pdf"));
Rectangle location = new Rectangle(426.582f, 514.291f, 559.0f, 613.818f);
float[] floats = new float[] {
427.582f, 582.873f,
493.036f, 515.291f,
558.0f, 554.237f,
527.4f, 612.818f,
464.727f, 564.709f,
427.582f, 582.873f
};
PdfArray pdfVertices= new PdfArray(floats);
float calib = 0.002806911838696635f;
PdfAnnotation stamp = PdfAnnotation.createPolygonPolyline(stamper.getWriter(),
location, "15.2 sq cm", true, new PdfArray(pdfVertices));
stamp.setColor(BaseColor.RED);
stamp.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
stamp.put(PdfName.SUBTYPE, PdfName.POLYGON);
stamp.put(new PdfName("IT"), new PdfName("PolygonDimension"));
stamp.put(PdfName.MEASURE, createMeasureDictionary(calib));
stamper.addAnnotation(stamp, 1);
stamper.close();
reader.close();
}
private static PdfDictionary createMeasureDictionary(float pdfCalibrationValue) {
String unit = "cm";
PdfDictionary measureDictionary = new PdfDictionary();
measureDictionary.put(PdfName.TYPE, PdfName.MEASURE);
measureDictionary.put(PdfName.R, new PdfString("1 " + unit + " = 1 " + unit));
PdfDictionary xDictionary = new PdfDictionary();
xDictionary.put(PdfName.TYPE, PdfName.NUMBERFORMAT);
xDictionary.put(PdfName.U, new PdfString(unit));
xDictionary.put(PdfName.C, new PdfNumber(pdfCalibrationValue));
PdfArray xarr = new PdfArray();
xarr.add(xDictionary);
measureDictionary.put(PdfName.X, xarr);
PdfDictionary dDictionary = new PdfDictionary();
dDictionary.put(PdfName.TYPE, PdfName.NUMBERFORMAT);
dDictionary.put(PdfName.U, new PdfString(unit));
dDictionary.put(PdfName.C, new PdfNumber(1));
PdfArray darr = new PdfArray();
darr.add(dDictionary);
measureDictionary.put(PdfName.D, darr);
PdfDictionary aDictionary = new PdfDictionary();
aDictionary.put(PdfName.TYPE, PdfName.NUMBERFORMAT);
aDictionary.put(PdfName.U, new PdfString("sq " + unit));
aDictionary.put(PdfName.C, new PdfNumber(1));
PdfArray aarr = new PdfArray();
aarr.add(aDictionary);
measureDictionary.put(PdfName.A, aarr);
return measureDictionary;
}
}
You have calculated a factor to translate the areas:
the result is 0.002806911838696635. which if computed
5433.001953125 x 0.002806911838696635 = 15.2
But then you use this factor meant for areas unchanged as conversion factor in the X number format array.
The X number format array is the number format array for measurement of change along the x axis and, if Y is not present, along the y axis as well.
Thus, as you don't have a Y entry, your factor for areas must be the conversion factor in X squared!
In other words, use the square root of your area conversion factor as X conversion factor, i.e. replace
float calib = 0.002806911838696635f;
by
float calib = (float)Math.sqrt(0.002806911838696635);
The result now is much better:
But it is not exactly your 15.2 cm². Thus, I checked your numbers, and indeed, your value of 5433.001953125 for the polygone area is slightly off, it should be around 5388.9613.
Using this more correct value I replaced the line above again, this time by:
float calib = (float)Math.sqrt(15.2/5388.96);
and the result:

Google Earth Engine: Flatten a one-band ImageCollection into a multi-band single Image

I want to use supervised classification to classify a pattern that has a clear temporal pattern. For example, identifying stands of deciduous trees in a coniferous forest. NDVI would change overtime in the deciduous stands in a regular pattern that should be easily detectable. I assume there's an easy method to flatten the temporal dataset into a single image so that the bands in that image can be used in a classification algorithm. Maybe using .map(....)?
Here's some code to build the answer from:
var startDate = '2016-05-01';
var endDate = '2016-09-01';
var lng = -122.3424; var lat = 37.9344; //SF
var region = ee.Geometry.Point(lng, lat);
//Image Import
var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(region)
.filterDate(startDate,endDate);
// NDVI temporal
var ndvi = l8.map(function(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename("NDVI");
return ndvi;
});
Map.addLayer(ndvi,{},"NDVI Temporal"); // 8 images with 1 band
//NDVI FLATTENED??????? I want 1 image with 8 bands. The below code doesn't work...
var ndviFlat = ee.Image().addBands(ndvi.map(function(image){
var temp = image.select("NDVI");
return temp;
}));
From there, I will pass ndviFlat to .sampleRegions, which only works with Images not ImageCollections:
//Classification Model:
var points = ee.FeatureCollection([trainingPointsPos,trainingPointsNeg]).flatten();
var training = ndviFlat.sampleRegions({
collection: points,
properties: ['class'],
scale: 30
});
var trained = ee.Classifier.randomForest(20).train(training, 'class', bands);
classified = regLayers.select(bands).classify(trained);
Here's one way:
var startDate = '2016-05-01';
var endDate = '2016-09-01';
var lng = -122.3424;
var lat = 37.9344; //SF
var region = ee.Geometry.Point(lng, lat);
//Image Import
var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(region)
.filterDate(startDate, endDate);
var empty = ee.Image();
// NDVI temporal
var ndvi = ee.Image(l8.iterate(function(image, previous) {
var name = ee.String('NDVI_').cat(image.id());
var ndvi = image.normalizedDifference(['B5', 'B4']).rename(name);
return ee.Image(previous).addBands(ndvi);
}, empty));
// Remove the annoying non-band
ndvi = ndvi.select(ndvi.bandNames().remove('constant'));
Map.centerObject(region, 13);
Map.addLayer(ndvi, {}, 'ndvi');

How can I have the percentage instead of the Frequency in Google Earth Engine?

I asked this question on GIS StackExchange, but no luck so far. I think that maybe it belongs here.
I used the following script :
// define the var
var Catchment = /* color: 98ff00 */geometry;
var landcover = ee.Image('users/roynahas/ESACCI-LC-L4-LCCS-Map-300m-P5Y-2010-v161_RECLASS').select('b1');
// Clip the image to the polygon geometry and add it to the map
var landcover_clip = landcover.clip(Catchment);
var sld_intervals =
'<RasterSymbolizer>' +
'<ColorMap type="intervals" extended="false" >' +
'<ColorMapEntry color="#FFFF00" quantity="1" label="Agriculture"/>' +
'<ColorMapEntry color="#00FF00" quantity="2" label="Grassland and Shrubland"/>' +
'<ColorMapEntry color="#008000" quantity="3" label="Forest"/>' +
'<ColorMapEntry color="#00FFFF" quantity="4" label="Flooded"/>' +
'<ColorMapEntry color="#FF00FF" quantity="5" label="Urban areas"/>' +
'<ColorMapEntry color="#808080" quantity="6" label="Bare areas"/>' +
'<ColorMapEntry color="#0000FF" quantity="7" label="Water"/>' +
'<ColorMapEntry color="#FFFFFF" quantity="8" label="Permanent snow and ice"/>' +
'</ColorMap>' +
'</RasterSymbolizer>';
Map.addLayer(landcover_clip.sldStyle(sld_intervals), {}, 'IGBP classification styled');
// Print out the frequency of landcover occurrence for the polygon.
var frequency = landcover.reduceRegion({
reducer:ee.Reducer.frequencyHistogram(),
geometry:Catchment,
scale:300
});
print('landcover frequency', frequency.get('b1'));
To get the following console output:
So my question is : How can I have a percentage instead of a frequency? or in other words : Is there a percentage equivalent to ee.Reducer.frequencyHistogram() ?
I got the answer on another forum. Here it is:
// Import variables
var globcover = ee.Image("ESA/GLOBCOVER_L4_200901_200912_V2_3"),
geometry = /* color: d63000 */ee.Geometry.Polygon(
[[[-71.466064453125, 48.763431137917955],
[-71.378173828125, 48.89000369970676],
[-72.674560546875, 49.38952445158216],
[-73.179931640625, 49.106241774469055],
[-73.575439453125, 48.27588152743497],
[-72.83935546875, 48.10743118848039],
[-71.4935302734375, 48.17341248658084],
[-71.455078125, 48.56024979174331],
[-71.5374755859375, 48.68370757165362]]]);
// Extract the landcover band
var landcover = globcover.select('landcover');
// Clip the image to the polygon geometry
var landcover_roi = landcover.clip(geometry);
// Add a map layer of the landcover clipped to the polygon.
Map.addLayer(landcover_roi);
// Print out the frequency of landcover occurrence for the polygon.
var frequency = landcover.reduceRegion({
reducer:ee.Reducer.frequencyHistogram(),
geometry:geometry,
scale:1000
});
var dict = ee.Dictionary(frequency.get('landcover'));
var sum = ee.Array(dict.values()).reduce(ee.Reducer.sum(),[0]).get([0]);
var new_dict = dict.map(function(k,v) {
return ee.Number(v).divide(sum).multiply(100);
});
print('Land Cover (%)',new_dict);
Of course, the inputs (the land cover image and polygon layer) can be different.

Resources