Download traffic flow data and weather data - here-api

I am looking to download the traffic flow data and the weather data having the conditions
Particular date
Particular location(zipcode or latitude/longitude or geolocations)
I have seen some examples in this link to collect data using quadkey, bounding box, and corridor. https://developer.here.com/documentation/examples/rest/traffic/traffic-flow-quadkey
My questions are
How could I specify the date or range of dates?
How could I get the quadkey, bounding box, and corridor of location?
I need the data of the previous day, it's not like historical, do I need a subscription for that

Please find the answers inline:
By default, traffic tiles show real-time traffic, representing the traffic situation at the time of the request.
However, it is also possible to request a traffic tile showing the typical traffic pattern for a specific time and day during the week. To get a traffic pattern tile, add a &time parameter to the request, specifying the date and time for which to display the traffic situation. Based on historic information, the tile displays a typical traffic situation for that date and time.
More information provided here:
https://developer.here.com/documentation/map-tile/dev_guide/topics/traffic-tiles.html
The traffic flow is explained based on color code explained here:
https://developer.here.com/documentation/traffic/dev_guide/topics/tiles.html
Green = Free flow of traffic: 0 <= JAM_FACTOR < 4
Yellow = Sluggish flow of traffic: 4 <= JAM_FACTOR < 8
Red = Slow flow of traffic: 8 <= JAM_FACTOR < 10
Black = Traffic stopped flowing or road closed: JAM_FACTOR = 10
(I) a quadkey is a string containing a numeric value. The value is obtained by interleaving the bits of the row and column coordinates of a tile in the grid at the given zoom level, then converting the result to a base-4 number (the leading zeros are retained). The length of a quadkey string (the number of digits/characters) equals the zoom level of the tile.
For example:
// Convert the column (x) and row (y) values
// to their binary (b) equivalents:
x = 3 -> 011b
y = 5 -> 101b
// Interleave the binary values (b), convert the
// combined result to a base-4 (q) number and
// finally convert that to a string:
quadkey = 100111b -> 213q -> "213"
Here is the Javascript example that calculates the quadkey:
--- input ---
xTile: 35210 // Column
yTile: 21493 // Row
z: 16 // Zoom Level
--- JavaScript ---
function tileXYToQuadKey(xTile, yTile, z) {
var quadKey = "";
for (var i = z; i > 0; i--) {
var digit = "0",
mask = 1 << (i - 1);
if ((xTile & mask) != 0) {
digit++;
}
if ((yTile & mask) != 0) {
digit = digit + 2;
}
quadKey += digit;
} // for i return quadKey;
return quadKey;
}
quadKey = tileXYToQuadKey(35210, 21493, 16);
--- output ---
quadKey = "1202102332221212"
(II) The query parameter bbox defines the latitudes and longitudes of the top left and bottom right corners of the bounding box. The optional query parameter response attributes requests that the response include additional information on the shape and the functional class of the roadway corresponding to the flow items.
The bbox can be obtained from the geocode & search API.
For example:
Request:
https://geocode.search.hereapi.com/v1/geocode?q=5+Rue+Daunou%2C+75000+Paris%2C+France
The response will have the map view containing the co-ordinates:
"mapView": {
"west": 2.33073,
"south": 48.86836,
"east": 2.33347,
"north": 48.87016
},
The detail information is explained here: https://developer.here.com/documentation/geocoding-search-api/dev_guide/topics/endpoint-geocode-brief.html
(III) Corridor Entrypoint represents sets of places along a route area sorted by distance from starting point of the route.
This information is available in the old search API
https://developer.here.com/documentation/places/dev_guide/topics_api/resource-browse-by-corridor.html
With the new GS7 API you can refer to this link:
https://developer.here.com/documentation/geocoding-search-api/dev_guide/topics/implementing-route.html
As mentioned in point 1, the traffic map tile is available for a given time by adding the parameter &time parameter to the query.

Related

Is it possible to retrieve full (structured) addresses for the specific POINT_ADDRESS tile using HERE Map Attributes API v8?

I'm trying to use HERE Map Attributes API to retrieve the addresses for some map area.
As far as I understood the layer I need is the POINT_ADDRESS layer (check the docs).
The problem is that the layer contains coordinates and identifiers only, but not the structured addresses:
[
{
"ADDRESS_POINT_ID": "334030589",
"LINK_ID": "1286528309",
"SIDE": "R",
"ADDRESSES": "ENGBN682",
"ADDRESS_TYPE": "1",
"BUILDING_NAMES": "ENGBNnull",
"DISPLAY_LAT": "-2751772",
"DISPLAY_LON": "15307500",
"ARRIVAL_LINK_ID": null,
"ARRIVAL_SIDE": null,
"LAT": "-2751797",
"LON": "15307488",
"TOPOLOGY_ID": "215602187",
"START_OFFSET": "8043"
},
...
]
So the question is: how to retrieve the structured address for every point from the POINT_ADDRESS layer? Should I use HERE Batch Geocoder API and perform reverse geocoding for these points? Or it's still possible to achieve that with Map Attributes API only?
On this link https://developer.here.com/documentation/content-map-attributes/dev_guide/topics/here-map-content.html are not all layers in the list.
Please see all layers on https://demo.support.here.com/pde .
In the weu region on https://demo.support.here.com/pde/layers?region=WEU&release=latest&url_root=pde.api.here.com
To retrieve the structured address you need additional layers ROAD_ADMIN_NAMES and ROAD_NAME
Then you request will be like: https://smap.hereapi.com/v8/maps/attributes.json?in=proximity:-27.51772,153.075001;r=100&layers=ROAD_NAME_FCn,ROAD_ADMIN_NAMES_FCn,POINT_ADDRESS&apikey=
Regarding docs on https://developer.here.com/documentation/content-map-attributes/api-reference.html
The parameter 'in' could be: proximity or bbox or corridor - for these in case for big areas you can get limitations due big data. Therefore some times it could be better use in=tile:...
Tile Ids you can get by these formulas:
tile size = 180° / 2^level [degree]
tileY = trunc((latitude + 90°) / tile size)
tileX = trunc((longitude + 180°) / tile size)
tileID = tileY * 2 * (2^level) + tileX
Or you can read this documentation https://demo.support.here.com/pde/indexes?region=WEU&release=latest&url_root=pde.api.here.com
How to get tileid by some index like:
https://smap.hereapi.com/v8/maps/index.json?layer=ROAD_GEOM_FCn&attributes=LINK_ID&values=1286528309,130742823
Then by tile request will be like:
https://smap.hereapi.com/v8/maps/attributes?apikey=&layers=POINT_ADDRESS,ROAD_NAME_FC4,ROAD_NAME_FC5,ROAD_ADMIN_NAMES_FC4,ROAD_ADMIN_NAMES_FC5&in=tile:46594870,11648411,46594870,11648411,46594870

Reclassify ranges in Google Earth Engine

I would like to reclassify Global Forest Data values i.e like
0 - 20 % --> 1
21 - 49 % --> 0.5
50 - 100 % --> 0
However, I wasn`t able to find how to do this for ranges in GEE. Explanation for reclassifying individual numbers can be found here:
https://sites.google.com/site/globalsnowobservatory/home/Presentations-and-Tutorials/short-tutorial/remap
but simple procedure for ranges (without decision trees) is hard to find.
Could someone provide a simple solution for this?
// Example from https://developers.google.com/earth-engine/resample
// Load a MODIS EVI image.
var modis = ee.Image(ee.ImageCollection('MODIS/006/MOD13A1').first())
.select('EVI');
// Get information about the MODIS projection.
var modisProjection = modis.projection();
// Load and display forest cover data at 30 meters resolution.
var forest = ee.Image('UMD/hansen/global_forest_change_2015')
.select('treecover2000');
// Get the forest cover data at MODIS scale and projection.
var forestMean = forest
// Force the next reprojection to aggregate instead of resampling.
.reduceResolution({
reducer: ee.Reducer.mean(),
maxPixels: 1024,
bestEffort:true
})
// Request the data at the scale and projection of the MODIS image.
.reproject({
crs: modisProjection
});
If you want to make binary decisions about pixel values, you can use the ee.Image.where() algorithm. It takes an image of boolean values to specify where in an image to replace pixels with another image. The tidiest way to use it for this application is to use the ee.Image.expression() syntax (rather than specifying several boolean and constant images):
var reclassified = forestMean.expression('b(0) <= 20 ? 1 : b(0) < 50 ? 0.5 : 0');
b(0) refers to the value of the first band of the input image, and ? ... : is the ?: conditional operator which returns the part between ? and : if the condition to the left is true, and the part to the right of the : if the condition is false. So, you can use a series of ? ... : to write out several conditions concisely.
Runnable example with this line.

Unable to extract List elements as integers using `getInfo`

I'm using reduceRegion to sum the number of water pixels determined by an NDWI. I want to do this on a collection of images to see change in water area over a period time.
The values are returned from the reduceRegion in the console and appear to be integers, but I am unable to extract them as such. This seems to be a common problem, but the solution is typically using getInfo function to bring these values over to client side. Unfortunately getInfo returns a null in this case.
The code below is for a collection of images OR a single image. The single image(image1) returns an image with an extra property(waterArea), and the mapped algorithm blows up(because the function is returning nulls).
I've also tried using getInfo on waterAg to potentially bring that list over to client side, however that returns the same List of objects that I don't want.
var image1 = ee.Image(leastcloud.first()).select(['B11','B8','B3'])
var stackarea = function(image){
var watermask = ee.Image(0)
var MNDWI = image.normalizedDifference(['B3','B11'])
watermask = watermask.where(MNDWI.gt(.31),1);
//sum of water pixels in an area
var sum = ee.Number(watermask.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: geometry,
scale: 20,
maxPixels: 1e9
}));
var clientSide = sum.getInfo()
var setArea = image.set('waterArea', clientSide)
return setArea
};
var single = stackarea(image1)
print(single)
var watermapped = filterSpot.map(stackarea)
var waterAg = watermapped.aggregate_array('waterArea')
print(waterAg)
I'm really not sure how to extract these values as numbers...
I'm hoping to get a list of numbers so that I can concatenate that array to other arrays(date of image, cloud pixel %, etc.)
reduceRegion returns a dictionary object, not a number-like object. Therefore, in your stackarea function, clientSide variable is a dictionary (i.e. an object), not a number.
The number that you're after is stored in the dictionary returned by the reduceRegion function. You can get your hand on that number by using a get function on this dictionary object:
var sum = watermask.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: geometry,
scale: 20,
maxPixels: 1e9
}).get('nd');
In this way, sum will be a server-side number that store the value you're after (There's no need to use ee.Number here as it does not help much).
In case you wonder about why using get('nd') but not get('somethingelse'), well it's the name of the band in your watermask image, and this name is the default band name given to the result of the normalizedDifference function.
And in my opinion, you don't even need to use the getInfo function which takes much more time to execute. Just delete the line var clientSide = sum.getInfo() and modify the next line into var setArea = image.set('waterArea', sum).
Hope this help.

Get word at position in Atom

From a linter provider, I receive a Point compatible array(line, column) where the error occured. Now I would like to hightlight the word surrounding that point, basically the result one would get if that exact point was double-clicked in the editor. Something like
const range = textEditor.getWordAtPosition(point)
Is what I hoped for, but couldn't find in the documentation.
Thanks for your help!
After looking around for a while, there seems to be no API method for the given need. I ended up writing a small helper function based upon this answer:
function getWordAtPosition(line, pos) {
// Perform type conversions.
line = String(line);
pos = Number(pos) >>> 0;
// Search for the word's beginning and end.
const left = Math.max.apply(null, [/\((?=[^(]*$)/,/\)(?=[^)]*$)/, /\,(?=[^,]*$)/, /\[(?=[^[]*$)/, /\](?=[^]]*$)/, /\;(?=[^;]*$)/, /\.(?=[^.]*$)/, /\s(?=[^\s]*$)/].map(x => line.slice(0, pos).search(x))) + 1
let right = line.slice(pos).search(/\s|\(|\)|\,|\.|\[|\]|\;/)
// The last word in the string is a special case.
if (right < 0) {
right = line.length - 1
}
// Return the word, using the located bounds to extract it from the string.
return str.slice(left, right + pos)
}
Here, the beginning of the word is determined by the latest occurance of one of the characters (),.[]; or a blank.
The end of the word is determined by the same characters, however here the first occurance is taken as a delimeter.
Given the original context, the function can the be called using the API method ::lineTextForBufferRow and the desired postion (column) as follows:
const range = getWordAtPosition(textEditor.lineTextForBufferRow(bufferRow), 10)

Is it possible to determine distance travel based on time for a calculated route

From a route returned in Nokia maps, is it possible to determine distance traveled based on time, using the speed limits of the returned route. I would like to find the position along the returned route in lat and long.
In other words I would like to start at a known point, travel 60 minutes along the route, and know the point I will be at. Then be able to repeat this for the entire route.
Keep a log of how much time you have accounted for. For the timeTravelled -
Subtract the time take for each leg until you are on the current leg.
On the current leg, subtract the time take for each manuever until you are on the current manuever
On the current manuever, take the Nth coordinate of the current shape so that the remainder of the time is accounted for
There are no times associated with the shape information, so the assumption here is that each coordinate is evenly spaced. So if you need to account for 40% of the time of the current manuever then you can assume that you have covered 40% of the shape.
Something like this:
function estimateLocation (myRoute, timeTravelled){
var timeSoFar = 0,
currentLeg = 0,
currentManeuver = 0;
while ( timeSoFar + myRoute.legs[currentLeg].travelTime < timeTravelled){
timeSoFar += myRoute.legs[currentLeg].travelTime;
currentLeg++
}
while ( timeSoFar + myRoute.legs[currentLeg].maneuvers[currentManeuver].travelTime < timeTravelled){
timeSoFar += myRoute.legs[currentLeg].maneuvers[currentManeuver].travelTime;
currentManeuver++;
}
console.log(currentLeg, currentManeuver);
var shapeIndex = Math.floor((timeTravelled - timeSoFar) * myRoute.legs[currentLeg].maneuvers[currentManeuver].shape.getLength()/ myRoute.legs[currentLeg].maneuvers[currentManeuver].travelTime);
return (myRoute.legs[currentLeg].maneuvers[currentManeuver].shape.get(shapeIndex));
}

Resources