I'm using the google elevation API to get elevation data along a path on google maps which I am then plotting on a google visualization column chart.
My code to get the data is as follows:
function createUpdateProfile(){
var path=[];
for (var i = 0; i < markers.length; i++) {
path.push(markers[i].getPosition());
};
var elevator = new google.maps.ElevationService;
// Draw the path, using the Visualization API and the Elevation service.
displayPathElevation(path, elevator, map);
}
function displayPathElevation(path, elevator, map) {
elevator.getElevationAlongPath({
'path': path,
'samples': 256
}, plotElevation);
}
function plotElevation(elevations, status) {
var chartDiv = document.getElementById('elevation_chart');
if (status !== google.maps.ElevationStatus.OK) {
// Show the error code inside the chartDiv.
chartDiv.innerHTML = 'Cannot show elevation: request failed because ' +
status;
return;
}
// Create a new chart in the elevation_chart DIV.
var chart = new google.visualization.ColumnChart(chartDiv);
// Extract the data from which to populate the chart.
// Because the samples are equidistant, the 'Sample'
// column here does double duty as distance along the
// X axis.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Sample');
data.addColumn('number', 'Elevation');
for (var i = 0; i < elevations.length; i++) {
data.addRow(['', elevations[i].elevation]);
}
// Draw the chart using the data within its DIV.
chart.draw(data, {
height: 200,
legend: 'none',
titleY: 'Elevation (m)'
});
The data returned is in Metric (Meters), how can I convert the returned elevation data to feet and then send that to the chart?
To convert meters to feet, multiply by 3.28084 feet/meter
for (var i = 0; i < elevations.length; i++) {
data.addRow(['', elevations[i].elevation*3.28084]);
}
Related
We're looking for a way to get our data points that are inside a polygon using JavaScript HereMaps API
We're adding 4 datapoints to a ClusterLayer / ClusterProvider and a polygon to the map. 3 of the 4 points are within the drawn Polygon (data of the points: a, b, d). Point with data = c is not within the polygon (see jsfiddle)
We tried to use map.getObjectsWithin but this functions only returns the polygon. We assume that this is caused by the different layers.
What's the best way to get the datapoints which are in the bounds of the polygon?
We try to avoid additional dependencies to solve this issue.
quick demo:
http://jsfiddle.net/4dno0gu2/59/
We found this question, but there wasn't any example, no activity for a long time and no solution.
HereMap getObjectsWithin does not show objects in LocalObjectProvider
Yeah the method getObjectsWithin doesn't work for ObjectProvider although this implemented in JS API but simple this functionality is not a public method, apologies for it.
Short description of workaround:
obtain the bounding box of the polygon
request all types of objects where you interested in for this bounding box from the provider
(requestOverlays, requestSpatials, requestMarkers etc.) - in your case requestMarkers
filter out all objects which doesn't intersect with the polygon
Code:
/**
* Adds a polygon to the map
*
* #param {H.Map} map A HERE Map instance within the application
*/
function addPolygonToMap(map) {
var geoStrip = new H.geo.LineString(
[48.8, 13.5, 100, 48.4, 13.0, 100, 48.4, 13.5, 100]
);
var polygon = new H.map.Polygon(geoStrip, {
style: {
strokeColor: '#829',
lineWidth: 8
},
data: 'polygon'
});
//map.addObject(polygon);
return polygon;
}
function logObjectsInPolygon(map, polygon){
var geoPolygon = polygon.getGeometry();
map.getObjectsWithin(geoPolygon, (o) => {
console.log('found mapObjects: '+ o.length);
o.forEach(x=>{
if(typeof x.getData === 'function'){
console.log(x.getData());
}
});
});
}
function isPointInPolygon(testPoint, polygPoints) {
let result = false;
let j = polygPoints.length - 1;
for(i=0,len=j+1; i<len; i++){
let p = polygPoints[i];
let lP = polygPoints[j];
if(p.y < testPoint.y && lP.y >= testPoint.y || lP.y < testPoint.y && p.y >= testPoint.y){
if((p.x + (testPoint.y - p.y) / (lP.y - p.y) * (lP.x - p.x)) < testPoint.x){
result = !result;
}
}
j = i;
}
return result;
}
/**
* Boilerplate map initialization code starts below:
*/
//Step 1: initialize communication with the platform
var platform = new H.service.Platform({
apikey: 'H6XyiCT0w1t9GgTjqhRXxDMrVj9h78ya3NuxlwM7XUs',
useCIT: true,
useHTTPS: true
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over Europe
var map = new H.Map(document.getElementById('map'),
defaultLayers.raster.normal.map,{
center: {lat:48.5, lng:13.45},
zoom: 10
});
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Create the default UI components
var ui = H.ui.UI.createDefault(map, defaultLayers);
//this marker should go to clusters if there is more data points
var dataPoints = [];
dataPoints.push(new H.clustering.DataPoint(48.5, 13.45,{}, 'a'));
dataPoints.push(new H.clustering.DataPoint(48.5001, 13.45,{}, 'b'));
dataPoints.push(new H.clustering.DataPoint(48.5002, 13.51,{}, 'c')); // not in Polygon
dataPoints.push(new H.clustering.DataPoint(48.53, 13.45,{}, 'd'));
var clusteredDataProvider = new H.clustering.Provider(dataPoints);
var layer = new H.map.layer.ObjectLayer(clusteredDataProvider);
map.addLayer(layer);
// createPolygon to select clustered (noise) points
var polygon = addPolygonToMap(map);
let extPoly = polygon.getGeometry().getExterior();
let seqPointsPoly = [];
extPoly.eachLatLngAlt((lat, lng, alt, idy) => {
seqPointsPoly.push( {y: lat, x: lng});
});
console.log("seqPointsPoly:", seqPointsPoly);
map.addEventListener("tap", (e) => {
let pBbox = polygon.getBoundingBox();
let arrPnts = clusteredDataProvider.requestMarkers(pBbox);
for(let i=0,len=arrPnts.length; i<len; i++){
let m = arrPnts[i];
let p = {y: m.getGeometry().lat, x: m.getGeometry().lng};
let clustData = m.getData();
if(!clustData.getData){
console.log("cluster: is in polygon:", isPointInPolygon(p, seqPointsPoly));
} else if(clustData.getData){
console.log("nois: is in polygon:", clustData.getData(), m.getGeometry(), isPointInPolygon(p, seqPointsPoly));
}else{
console.log("unknown type");
}
}
console.log("clusteredDataProvider:", pBbox, clusteredDataProvider.requestMarkers(pBbox));
// Our expected logging is: points a, b, d
//logObjectsInPolygon(map, polygon);
});
Worked example (tap on map to start processing): http://jsfiddle.net/m1ey7p2h/1/
At the outset, I inform you that I am a novice javascript programmer. I'm writing an application to dynamically draw a circle marker on a map. I use the leaflet library. As the source, it uses data loaded from a csv file. The csv file consists of three columns: date, x coordinate, y coordinate. At the moment the map works in such a way that it draws all markers at one time.
var map = L.map("map");
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png").addTo(map);
map.setView([51.95, 19.55], 6);
var myRenderer = L.canvas({ padding: 0.02 });
for (var j=1; j<lines.length; j++)
{
var values = lines[j].split(';'); // Split up the comma seperated values
var x= values[2];
var y = values[3];
var data2 = values[1];
var markery2 = [];
markery2.push(y,x);
document.getElementById("demo").innerHTML =
"Data: " + data2;
console.log("JSON");
console.log(data2);
L.circleMarker(markery2, {
color: 'blue',
fillColor: 'blue',
fillOpacity: 0.2,
weight: 1,
radius: 3,
renderer: myRenderer
}).addTo(map).bindPopup('marker ' + j);
//Set up the data arrays
}
}
});
Ultimately, I would like to read records from specific dates, ascending and drawn in such a order on the map with a 3-second time interval
Welcome to SO!
Look for setTimeout.
Or it can be easier for you to begin with setInterval.
I want to create a loop, in my google chart, i have 200 points in the chart, and it moves 1 point to the right per second,but i want to repeat the chart when it reach all points.
here is my code of the chart:
function drawChart5() {
var options = {
'backgroundColor': 'transparent',
width: 1200,
height: 240,
animation: {
duration: 1000,
easing: 'in',
},
hAxis: {viewWindow: {min:0, max:200}}
};
var chart = new google.visualization.AreaChart(
document.getElementById('visualization'));
var data = new google.visualization.DataTable();
data.addColumn('string', 'x');
data.addColumn('number', 'y');
var MAX = 100;
var x=0;
var f=20;
var T= 1/f;
var PI = Math.PI;
var DT=T/MAX;
for (var i = 0; i < 2*MAX; i++)
{
x=(Math.sin((2*PI)*f*i*DT));
data.addRow([i.toString(), x]);
console.log(x)
}
function drawChart() {
google.visualization.events.addListener(chart, 'ready',
function() {
});
chart.draw(data, options);
}
setInterval(function()
{
options.hAxis.viewWindow.min += 1;
options.hAxis.viewWindow.max += 1;
chart.draw(data,options)
},2 000);
drawChart();
}
This is the chart
I would achieve the effect you are going for like this:
Use a DataView instead of a DataTable, and use DataView.setColumns() to create a calculated column that runs the formula defined above. As far as I can tell, the algorithm you use to calculate your values is deterministic, so all you need to run your calculations is the x-value and you can determine the y-value for any given position.
With this method, you'll never have to populate a DataTable yourself, because the chart uses your function to calculate the y-value on demand. Whatever range your chart displays, it will calculate the values it needs when the chart is drawn.
I have more than 1000 markers at 3 different location in my Map.
I read Lat and Long from a text file and render it in Google maps and create circle over them on the basis of country name. And count the number of markers in those circle.
Now what i am not able to do is?
(1) I have to print the text of count on those circle (How to do without using Cluster ?)
(2) When i zoom out circle overlaps . So whenever circle overlaps it should combine the 2 radius of these two circles and should make one big circle covering the markers of the two smaller (smaller 2 will now disappear resulting on total of marker on the bigger one only).
My full code to do this (http://prntscr.com/6kt30w) is :
$.ajax({
type: 'GET',
url: './App_Start/TextFile/latLongList3.txt',
dataType: 'text',
}).success(function (data)
{
var s2 = data.replace(/^.*$/, " ").replace(/\r\n/g, " ");
var array = s2.split(/[ ]+/g);
var test = [].concat.apply([], array.map(function (array) { return array.split(/\s+/); }))
var col1 = [];
var col2 = [];
var col3 = [];
var j = 0;
for (var i = 0; i <= test.length - 3; i = i + 3)
{
col1[j] = test[i];
col2[j] = test[i + 1];
col3[j] = test[i + 2];
var myLatlng = new google.maps.LatLng(col3[j], col2[j]);
marker = new google.maps.Marker(
{
position: myLatlng,
map: map,
title: 'Hello World! ' + col1[j]
});
markers.push(marker);
if (j > 0) {
LatLong[j] = myLatlng;
}
j++;
}
})
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I don't want to use MarkerClusterer because it is very small. Yes it's true that it will do the 2 tasks i want to accomplish but the problem i feel with it is when i have markers all over the country then MarkerClusterer just hovers over a very little part of the country whereas i want the circle to hover over all country wherever i have marker and it should have text on it. So if there is any alternative to make the size of cluster such that it cover all the markers in the entire country(because my 1 country is full of markers) and has text on it than any way to do this is welcomed too.
Could some one please help me in solving the 2 problems ?
I have to print the text of count on those circle (How to do without
using Cluster ?)
You can use the following to get count of marker from marker.length
var markers = [];
for (var i = 0; i < 100; i++) {
var latLng = new google.maps.LatLng(data.photos[i].latitude,
data.photos[i].longitude);
var marker = new google.maps.Marker({'position': latLng});
markers.push(marker);
}
To add the count to circle, you can look at this JSFiddel.
I still have to look more your second problem
Finally i found the solution of it.I simply used MarkerClusterer and got it done by increasing its size.
And it works perfectly for me.
I extend a polygon shape on the client. Please see my question (How to evenly adjust some area to polygon (extend a polygon)?) to understand what I exactly mean. I do all the calculations in browser and then send a result to server and store it in DB. I use this function (from here):
this.extendPolygon = function(polyline, offset) {
var distance = Number(offset) * 1000;
var numPts = polyline.getPath().getLength();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i< numPts; i++) {
bounds.extend(polyline.getPath().getAt(i));
}
var center = bounds.getCenter();
var extendedPolyPts = [];
for (var i=0; i< numPts; i++) {
var heading = google.maps.geometry.spherical.computeHeading(center,polyline.getPath().getAt(i));
var initialDist = google.maps.geometry.spherical.computeDistanceBetween(center,polyline.getPath().getAt(i));
var extendedDist = initialDist + distance;
var extendedPt = google.maps.geometry.spherical.computeOffset(center, extendedDist, heading);
extendedPolyPts.push(extendedPt);
}
extendedPoly = new google.maps.Polygon({
// map: map,
paths:extendedPolyPts,
fillColor:"#00FF00",
strokeWidth:2,
fillOpacity:0.4,
strokeColor:"#0000FF",
strokeOpacity:0.5
});
return extendedPoly;
};
But I'd like to do calculations on a server side. Is it possible to run the function on a server? It uses these functions of GM API:
google.maps.geometry.spherical.computeHeading
google.maps.LatLngBounds
polyline.getPath().getLength()
google.maps.geometry.spherical.computeDistanceBetween
google.maps.geometry.spherical.computeOffset
google.maps.Polygon