I have to use XMLHttpRequest to grab a kml file, because I cannot directly make changes to the KML and needed to draw out polygons with their own separate infowindows with details on them that is stored in the KML but not as a description tag or anything like that so I couldn't just grab it easily. I managed to do this, and the polygons display and the infowindows work. Its a sizable program so I didn't display it here, but basically when I load the getKML function of mine, it would not work in the development environment or present issues. Whereas it would work well on my localhost.
This is the error message I keep getting:
Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://someURL/polygons_live.kml'.
Heres the code, you really only need the first couple lines to look at because thats where xmlhttprequest is used, also excuse me for the messy code, still an intern and refactoring:
/** Calls using xmlhttprequest to grab the kml file
* and later prints it out as one or more polygons
*/
function getKML(kmlUrl) {
var xmlRequest = new XMLHttpRequest();
xmlRequest.open("GET", kmlUrl, false);
xmlRequest.send();
xmlDoc = xmlRequest.responseXML;
var x = xmlDoc.getElementsByTagName("Placemark");
// travels through each Placemark tag in the kml files
var outage_time, restoration_time, event_number_value, fillColour, borderColour;
var objArray = [];
for (var i = 0; i < x.length; i++) {
// uses momentjs api to create human readable dates
var date_format = "MMM DD, hh:mm a";
// gets the event number
event_number_value = x[i].getElementsByTagName("SimpleData")[2].childNodes[0].nodeValue;
// gets outage start time
var outage_time_value = x[i].getElementsByTagName("SimpleData")[3].childNodes[0].nodeValue;
var outage_time_moment = moment(outage_time_value);
outage_time = outage_time_moment.format(date_format);
// gets estimated restoration time
var restoration_time_value = x[i].getElementsByTagName("SimpleData")[5].childNodes[0].nodeValue;
// checks to see if we have a restoration time or not
if (restoration_time_value === "2001-01-01T00:00:00") {
restoration_time = "Not yet determined";
} else {
var restoration_time_moment = moment(restoration_time_value);
restoration_time = restoration_time_moment.format(date_format);
}
// gets the coordinates of the polygon
var coords = x[i].getElementsByTagName("coordinates")[0].childNodes[0].nodeValue;
var coordinate = coords.split(",0 ");
var coordJoined = coordinate.join();
var coordAgain = coordJoined.split(",");
// gets the colour of the polygon
var colour = x[i].getElementsByTagName("styleUrl")[0].childNodes[0].nodeValue;
// determines the colour out of yellow, orange and red
if (colour === "#Style1") {
fillColour = '#f1c40f';
borderColour = '#f1c40f';
} else if (colour === "#Style2") {
fillColour = '#e67e22';
borderColour = '#e67e22';
} else {
fillColour = '#c0392b';
borderColour = '#c0392b';
}
// creates objects and adds it to array to be later used as data
var obj = {
eventID : event_number_value,
offTime : outage_time,
restoreTime : restoration_time,
fill : fillColour,
borderCol : borderColour
};
objArray.push(obj);
// create a LatLng array out of the coordinate string
var polygonCoords = new Array();
var j = 0;
var z = j + 1;
//var firstCoord = new google.maps.LatLng();
while (z < coordAgain.length) {
// adds the first and last latLng to the array of polygonCoords
if ((j % 2) == 0) {
var co1 = parseFloat(coordAgain[z]);
var co2 = parseFloat(coordAgain[j]);
var newLatLng = new google.maps.LatLng(co1, co2);
polygonCoords.push(newLatLng);
} else {
var co1 = parseFloat(coordAgain[j]);
var co2 = parseFloat(coordAgain[z]);
var newLatLng = new google.maps.LatLng(co1, co2);
polygonCoords.push(newLatLng);
}
j++;
z++;
}
//removes last coordinate as its useless as its not a number
polygonCoords.pop();
/** Adds the polygon to a polygon array
* and maps it onto the map
*/
var newPoly = new google.maps.Polygon({
paths : polygonCoords,
strokeColor : objArray[i].borderCol,
strokeOpacity : 0.35,
strokeWeight : 2,
fillColor : objArray[i].fill,
fillOpacity : 0.35
})
newPoly.setMap(map);
newPoly.set("eventNum", objArray[i].eventID);
newPoly.set("offTime", objArray[i].offTime);
newPoly.set("resTime", objArray[i].restoreTime);
google.maps.event.addListener(newPoly, 'click',
attachInfoWindow(newPoly));
polyArray.push(newPoly);
}
}
Update 1: I actually found this error later on appearing in my console:
XMLHttpRequest cannot load https://someurl/polygons_live.kml. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://someurl' is therefore not allowed access.
Its a cross-domain request issue, I'm going to start using relative addresses to point to when grabbing my kml.
It resolved my issue.
Related
There are four tiles (path:41,row:35/path:41,row:36/path:42,row:35/path:42,row:36) of LANDSAT 8 surface reflectance that cover my study area. I want to remove only images(tile) with path 42 and row 36 from this collection. How can I do that?
Here is my code:
Map.centerObject(table);
Map.addLayer(table);
var sd = '2015-01-01';//Start Date
var ed = '2016-01-01';//End Date
var suro = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(table)
.filterDate(sd,ed)
//.filter(ee.Filter.and(ee.Filter.notEquals('WRS_PATH',42),ee.Filter.notEquals('WRS_ROW',36)))
.filter(ee.Filter.lt('CLOUD_COVER', 45));
var sur = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(table)
.filterDate(sd,ed)
//.filter(ee.Filter.and(ee.Filter.notEquals('WRS_PATH',42),ee.Filter.notEquals('WRS_ROW',36)))
.filter(ee.Filter.lt('CLOUD_COVER', 45))
//Map a function to mask clouds and negative values
.map(function(img){
var idd = img.id();
// Bits 3 and 5 are cloud shadow and cloud, respectively.
var cloudShadowBitMask = 1 << 3;
var cloudsBitMask = 1 << 5;
// Get the pixel QA band.
var qa = img.select('pixel_qa');
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
// Return the masked image, scaled to reflectance, without the QA bands.
var img2 = img.updateMask(mask).multiply(0.0001).select("B1").rename(idd);
//Mask negative values from images
var mask2 = img2.gt(0);
return img2.multiply(mask2);
})
.toBands()
.clip(table);
Map.addLayer(sur);
var imColl_sur = sur.getInfo().bands;
print(imColl_sur);
print(imColl_sur.length);
for (var i = 0; i < imColl_sur.length; i++) {
//Image Load
var im = sur.select(imColl_sur[i]["id"]);
//var id = imColl_sur[i]["id"];
//var im = ee.Image.load(id);
//Image Properties from original collection
var idl = suro.getInfo().features[i]["properties"]["LANDSAT_ID"];
var st = suro.getInfo().features[i]["properties"]["SENSING_TIME"];
var sza = (suro.getInfo().features[i]["properties"]["SOLAR_ZENITH_ANGLE"])
.toString();
//Download
Export.image.toDrive({
image: im,
description: 'L8_surReflectance_B1_'+idl.slice(10,26)
+st.slice(11,13)+st.slice(14,16)+'_'
+sza.slice(0,2)+sza.slice(3,8),
scale: 30,
region: table,
maxPixels: 1e9
});
}
Edit:
Combining filters probably works somehow, and would be more elegant.
But you can use a second approach: create a new metadata variable combining ROW and PATH, and filter based on it:
var geometry = ee.Geometry({"type":"Polygon","coordinates":[[[-98.01249999999999,41.430123208731864],[-98.01249999999999,38.809492348693325],[-92.03593749999999,38.809492348693325],[-92.03593749999999,41.430123208731864]]],"geodesic":false,"evenOdd":true})
var sd = '2015-01-01';//Start Date
var ed = '2016-01-01';//End Date
var suro = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(geometry)
.filterDate(sd,ed)
.map(function(image){
return image.set({'WRS_PATHROW':{'path':image.get('WRS_PATH'),
'row':image.get('WRS_ROW')}
})})
.filter(ee.Filter.neq('WRS_PATHROW', {'path':25, 'row':32}))
You can combine two filters with an ee.Filter.and to remove any images that have WRS_PATH=21 and WRS_ROW=32:
var filters = ee.Filter.and(
ee.Filter.neq('WRS_PATH',21),
ee.Filter.neq('WRS_ROW',32)
);
var suro = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(geometry)
.filterDate(sd,ed)
.filter(filters);
In my Project, I have multiple Graphs (max 15 of different plots like Bar , Chart , Bubble, Line) that are being plotted using javascript (Open/SAP UI-5) in HTML5 below is the code for the same
press: function() {
var arrCanvas = document.getElementsByTagName("canvas");
for(var i=0; i<arrCanvas.length; i++){
var canvas = arrCanvas[i];
if(canvas.width!==0 && (typeof imageNames[i] !== 'undefined')){
var imageDetail = {};
var uint8ArrayClamped = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
imageDetail.byteData = uint8ArrayClamped;
imageDetail.title = "graph-"+i;
imageDetail.height = canvas.height;
imageDetail.width = canvas.width;
arrImageByte.push(imageDetail);
}
}
}
When I pass this arrImageByte to Ajax call the browser (tested on chrome) crashes with "oh snap" message.
while adding below line to the code
press: function() {
var arrCanvas = document.getElementsByTagName("canvas");
for(var i=0; i<arrCanvas.length; i++){
var canvas = arrCanvas[i];
if(canvas.width!==0 && (typeof imageNames[i] !== 'undefined')){
var imageDetail = {};
var uint8ArrayClamped = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
//I belive somwhow This does the trick
imageDetail.byteData = [].slice.call(uint8ArrayClamped);
imageDetail.title = "graph-"+i;
imageDetail.height = canvas.height;
imageDetail.width = canvas.width;
arrImageByte.push(imageDetail);
}
}
}
Copying the unit8ArrayClamped into another empty array does the trick, now the code work and REST is being called, I wonder why this is happening?
but again copying such a huge data into another takes time and for multiple graphs, it takes almost 6-7 seconds, how to reduce this to minimal?
Is there another approach besides copying the byte array into another new array?
I am trying to do something like : https://github.com/IvanSanchez/Leaflet.Polyline.SnakeAnim/blob/master/demo-group.gif
where I have multiple markers.
In the example code https://github.com/IvanSanchez/Leaflet.Polyline.SnakeAnim/blob/master/demo-group.html
each location has been manually added using
var trd = [63.5, 11],
mad = [40.5, -3.5],
lnd = [51.5, -0.5],
ams = [52.3, 4.75],
vlc = [39.5, -0.5];
var route = L.featureGroup([
L.marker(trd),
L.polyline([trd, ams]),
L.marker(ams),
L.polyline([ams, lnd]),
L.marker(lnd),
L.polyline([lnd, mad]),
L.marker(mad),
L.polyline([mad, vlc]),
L.marker(vlc)
]);
My question is, if I have many markers (e.g. 500 markers), how can I create the route without manually adding each marker and polyline to the L.featureGroup.
var bounds = new L.LatLngBounds();
for (var i = 0; i < mTool.length; i++) {
var loc = new L.LatLng(mTool[i].lat, mTool[i].lon);
bounds.extend(loc);
var marker = new L.Marker(loc);
map.addLayer(marker);
}
map.fitBounds(bounds);
EDIT: What you want to do is provided by the same github project of IvanSanchez. Please read demo.html instead of demo-group.html
This is easily done by looping through an array of markers, as you rightly hinted at it. The code could be as below:
var markers = [[63.5, 11],
[40.5, -3.5],
[51.5, -0.5],
[52.3, 4.75],
[39.5, -0.5]];
var route = L.featureGroup().addTo(map);
var n = markers.length;
for (var i = 0; i < n-1; i++) {
var marker = new L.Marker(markers[i]);
var line = new L.polyline([markers[i],markers[i+1]]);
route.addLayer(marker);
route.addLayer(line);
};
route.addLayer(new L.Marker(markers[n-1]));
map.fitBounds(route.getBounds());
I created a working example on gist (here).
How can I obtain driving length between two stops in ArcGIS? I'm placing route from RouteTask service on a map and want to get lengths from that response too. I've thought about doing some iteration in DirectionsFeatureSet, but I already see that what I'm doing is complete nonsense.
var directions = solveResult[0].directions;
console.log(directions);
var length = 0;
var location = 0;
var obj = {};
$.each(directions.features, function (ind, val) {
var txt = val.attributes.text;
var indexOfLocation = txt.indexOf('Location');
if (indexOfLocation != -1) {
var digitTransform = txt.substring(indexOfLocation + 9);
var digit = "";
for (var i = 0; i < digitTransform.length; i++) {
var char = digitTransform[i];
if (isNumber(char)) {
digit += char;
} else break;
}
}
});
That's what I already did and that makes no sense.
In Google Maps API it's clear - every leg has it's own length. In ArcGIS responses I see no such easy approach.
The length is available as an attribute of each returned feature. So, given your directions variable, the following would give you the length of the first leg of the route:
directions.features[0].attributes.length
How to compare 2 well known text points in javascript?
For example if the points are a = POINT(78.067606 12.994332) , b=POINT(78.067606 12.994332) ,
then if we compare (a==b) it gives false,instead of true . Why?
Any help?
You can compare WKT of points (that's just comparision of two strings):
var p1 = new OpenLayers.Geometry.Point(10.123, 10.456);
var p2 = new OpenLayers.Geometry.Point(10.123, 10.456);
var wkt1 = p1.toString();
var wkt2 = p2.toString();
if (wkt1 == wkt2)
alert('Works as expected!');
Sometimes points may be very close to each other, but their coordinates may be slightly different. Another option is to control distance between geometries:
var p1 = new OpenLayers.Geometry.Point(10.123, 10.456);
var p2 = new OpenLayers.Geometry.Point(10.124, 10.457);
var allowedDist = 0.002;
var dist = p1.distanceTo(p2);
if (dist < allowedDist)
alert('Points are close enough');