Remove/Hide/Delete an array of features from Azure Map - javascript

This is a follow on questions from Azure Maps (with Turf.js) - can't get the 'points' from the SymbolLayer
I now have a function that loads the data "onclick" from a JSON location.
What I am trying to do is now Remove the data. A toggle-on / toggle-off function.
Full code is: https://espiritos.projectwebdev.co.uk/index-v1.0.8a.html
But the key function I am concerned with is:
$(document).on("click", ".toggleCounty.on", function(event) {
if ($(this).hasClass("on")) {
var elementsToRemove = "";
$(this).toggleClass("off");
$(this).toggleClass("on");
var countyID = $(this).attr("data-countyID");
var url = geoJsonData[countyID].url;
$.getJSON(url, function(data) {
var noOfFeatures = Object.keys(data.features).length;
console.log(noOfFeatures);
for (var i = 0; i < noOfFeatures; i++) {
console.log("[" + i + "]");
console.log(data.features[i]);
datasource.remove(data.features[i]);
// map.data.remove(data.features[i]);
debugger;
}
});
}
});
I do an API lookup from a variable "geoJsonData":
var geoJsonData = [
{
name: "Hertfordshire",
shown: "off",
url:
"https://www.naptan.projectwebdev.co.uk/api/v1/get/stoppoints?fields=all&format=geojson&filter=NptgLocalityRef|E0000708",
geomType: "points"
},
{
name: "Hampshire",
shown: "off",
url:
"https://www.naptan.projectwebdev.co.uk/api/v1/get/stoppoints?fields=all&format=geojson&filter=NptgLocalityRef|E0044074",
geomType: "points"
},
{
name: "Oxfordshire",
shown: "off",
url:
"https://www.naptan.projectwebdev.co.uk/api/v1/get/stoppoints?fields=all&format=geojson&filter=NptgLocalityRef|E0000708",
geomType: "points"
}
];
I load in the "features" from the JSON...
And then I just can't work out how to remove those features from the map.
I have popped a "debugger;" where the issue is.
I am extremely grateful for any guidance. Thank you.

It looks like in the first code block you are loading GeoJSON data from the web and then trying to remove it from a data source, but you never add it to the data source. That won't work. If you previously loaded the same data into the data source, I don't think that would work either since these are fundamentally different JSON object instances. The one way you can get this to work is to add unique ID's to each feature in your GeoJSON files. Then the data source can do a match on that. For example:
{
"type": "Feature",
"id": 1,
"geometry": {
"type": "Point",
"coordinates": [-0.61827807482, 51.537852954]
},
"properties": {
"AtcoCode": "040000000127",
"NaptanCode": "bucgjtjt",
"CommonName": "Farnham House",
"Street": "Farnham Lane",
"Indicator": "adj",
"NptgLocalityRef": "E0044074",
"GridType": "UKOS",
"Easting": "495927",
"Northing": "183010",
"StopType": "BCT",
"BusStopType": "MKD",
"TimingStatus": "OTH",
"CompassPoint": "SE",
"Degrees": "135",
"StopAreaRef": "",
"AdministrativeAreaRef": "70"
}
},
Note you will need to make sure all id's across all your files are unique.
Some other approaches you can consider;
If there is a property in each feature that can relate a feature back to its original file (i.e. "source": "Hertfordshire"), then you could us a filter in the layers to control what is rendered based on this property.
If you only ever load the data for one file at a time and remove all other data, then consider using the datasource.setShapes function. This will overwrite all data in the data source.
Update
I have put together a more in depth sample that shows toggling between different data sets. It looks like these data sets are small, so I load them the first time they are needed into the data source and leave them in there. Then to toggle I simply use a filter at the layer level. This makes it much faster to reload a data set a second time. This will work fine for data sets that are tens of thousands in size. If you are working with larger data sets, then removing the data might be something to consider. I also noticed when putting this sample together, the URL for the first and last data set you provided are the same (assuming this is an error).
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" type="text/css" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<script type='text/javascript'>
var map, datasource, layer;
var geoJsonData = [
{
name: "Hertfordshire",
shown: "off",
url:
"https://www.naptan.projectwebdev.co.uk/api/v1/get/stoppoints?fields=all&format=geojson&filter=NptgLocalityRef|E0000708",
geomType: "points"
},
{
name: "Hampshire",
shown: "off",
url:
"https://www.naptan.projectwebdev.co.uk/api/v1/get/stoppoints?fields=all&format=geojson&filter=NptgLocalityRef|E0044074",
geomType: "points"
},
{
name: "Oxfordshire",
shown: "off",
url:
"https://www.naptan.projectwebdev.co.uk/api/v1/get/stoppoints?fields=all&format=geojson&filter=NptgLocalityRef|E0000708",
geomType: "points"
}
];
function GetMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
center: [-0.76, 51.6],
zoom: 10,
view: 'Auto',
//Add your Azure Maps key to the map SDK. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
authOptions: {
authType: 'subscriptionKey',
subscriptionKey: '<Your Azure Maps Key>'
}
});
//Wait until the map resources are ready.
map.events.add('ready', function () {
//Create a data source and add it to the map.
datasource = new atlas.source.DataSource();
map.sources.add(datasource);
//Create a layer to render the points.
layer = new atlas.layer.BubbleLayer(datasource);
map.layers.add(layer);
loadDataSetPanel();
});
}
function loadDataSetPanel(){
var html = [];
for(var i=0;i<geoJsonData.length;i++){
html.push(`<input type="checkbox" onclick="toggleDataSet('${geoJsonData[i].name}')"> ${geoJsonData[i].name}<br/>`);
}
document.getElementById('dataSetPanel').innerHTML = html.join('');
}
function toggleDataSet(name){
var ds = getDataSetByName(name);
if(ds){
//Toggle the shown state of the data set.
ds.show = (typeof ds.show === undefined)? true : !ds.show;
//Update filter on data source.
updateFilter();
//Check to see if data set is loaded, if not, load it.
if(!ds.loaded){
loadDataSet(ds);
}
}
}
function loadDataSet(ds) {
//Fetch the data directly as we want to modify it before it is entered into the data source.
fetch(ds.url)
.then(r => r.json())
.then(r => {
var f = r.features;
//Enrich the features.
for(var i=0;i<f.length;i++){
//Make the AtcoCode the unique ID for each feature. This will allow for lookups and removal by ID.
f[i].id = f[i].properties.AtcoCode;
//Add the data set name as a property for each feature for filtering purposes.
f[i].properties.dataset = ds.name;
}
//Add the features to the data source.
datasource.add(f);
});
}
function updateFilter(){
var dataSetsToShow = [];
//Get the name of each data set that should be shown.
for(var i=0;i<geoJsonData.length;i++){
if(geoJsonData[i].show){
dataSetsToShow.push(geoJsonData[i].name);
}
}
if(dataSetsToShow.length === 0){
//If there is no layers to show, set filter to false.
layer.setOptions({ filter: ['literal', false] });
} else {
//Create a data driven filter to hide the
var filter = [
'match',
//Get the data set property.
['get', 'dataset'],
//See if it matches any of the data set names to show.
dataSetsToShow,
//If so, return true, to indicate the feature should be shown.
true,
//Else, return false to not render feature.
false
];
//Update the filter on the layer.
layer.setOptions({ filter: filter });
}
}
function getDataSetByName(name){
for(var i=0;i<geoJsonData.length;i++){
if(geoJsonData[i].name === name){
return geoJsonData[i];
}
}
return null;
}
</script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#myMap {
position: relative;
width: 100%;
height: 100%;
}
#dataSetPanel {
position: absolute;
left:10px;
top:10px;
background-color: white;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body onload="GetMap()">
<div id="myMap"></div>
<div id="dataSetPanel"></div>
</body>
</html>

Related

Using JQuery and online JSON data to populate JVectorMaps

I'm using JSON data to populate JVectorMaps (and others) directly. Up-to-date stats for most common indicators are available via json online - so this script should let you can pluck whatever data that you like quickly and easily. I just haven't quite figured out the formatting code yet as I am very new to JQuery & JS. I put a question mark where I'm stumped.
Ideally, the fetch and Data scripts could take an ind_id variable and label that presented any indicator on the Vector Map, and not just the one GDP (NY.GDP.MKTP.CD) indicator I used as an example here.
document.addEventListener('DOMContentLoaded', () => {
console.log("loaded")
fetchCountryData()
})
function fetchCountryData () {
fetch('http://api.worldbank.org/v2/country/all/indicator/NY.GDP.MKTP.CD?format=json&mrv=1&per_page=300)
//
.then(resp => resp.json())
.then(data => {
let country.id = data[1]
let value = data[1]
create-GDP-Data(country.id,value)
})
}
function create-GDP-Data(country.id,value){
let gdpData = ?
}
$('#world-map-gdp').vectorMap({
map: 'world_mill',
series: {
regions: [{
values: gdpData,
scale: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial'
}]
},
onRegionTipShow: function(e, el, code){
el.html(el.html()+' (GDP - '+gdpData[code]+')');
}
});
GDP Data (gdpData) should be formatted as follows:
var gdpData = {
"AF": 16.63,
"AL": 11.58,
"DZ": 158.97,
...
};
You are aware that the requested dataset is returning back a somewhat different data structure as the one needed for jVectorMap. So, what You need is a remapper from the incoming data to the latter.
To make this approach more flexible, my proposal is to use a straightforward remapper function, where You can pass-in the name of the incoming field, and receive back the value for that.
Please, see the comments inside my proposal below for further information:
DEMO: Dynamic loading of a jVectorMap region dataset
$(function() {
/* Handler for jQuery .ready() */
function mapper(data, key) {
/* Deep search for a key, return the value found. */
var keys = key.split('.'), value = data[keys.shift()];
for(var i=0, l=keys.length; i<l; i++) {value = value[keys[i]]}
return value;
}
function showMapValues(schema, map, values, min, max) {
var regions = map.series.regions[0];
/* Reset the scale min & max, allow recomputation. */
regions.params.min = min;
regions.params.max = max;
regions.setValues(values.regions);
map.dataSetName = schema.dataSetName;
map.dataSetFormat = schema.dataSetFormat;
}
function remapData(schema, map, data) {
var values = {regions: {}, markers: {}};
/* Loop over the returned dataset and invoke remap. */
$.each(data, function(i, item) {
var code = mapper(item, schema.countryCodeField),
value = mapper(item, schema.countryValueField) || 0;
/* Find out if this is a valid region inside the map. */
var isRegionCode = typeof map.regions[code] !== 'undefined';
/* Find out if this is a valid marker inside the map. */
var isMarkerCode = typeof map.markers[code] !== 'undefined';
/* Fill two separate datasets for regions & markers. */
if(isRegionCode) values.regions[code] = value;
if(isMarkerCode) values.markers[code] = value;
});
return values;
}
function fetchAlternateCountryData(schema, map) {
$.ajax({
url: schema.alternate,
dataType: 'json',
success: function(result) {
var dataSet = result[schema.dataSetIndex];
/* Dynamically update the map with the new local data */
showMapValues(schema, map, remapData(schema, map, dataSet));
}
});
}
function fetchCountryData(schema, map) {
$.ajax({
url: schema.url,
dataType: 'json',
data: schema.params,
success: function(result) {
var dataSet = result[schema.dataSetIndex];
if(dataSet) {
/* Dynamically update the map with the new remote data */
showMapValues(schema, map, remapData(schema, map, dataSet));
} else {
/* Manage "Invalid value" response */
fetchAlternateCountryData(schema, map);
}
},
error: function(request, textStatus, errorThrown) {
/* Manage some other trappable ajax errors */
fetchAlternateCountryData(schema, map);
}
});
}
var worldMap = new jvm.Map({
map: 'world_mill_en',
container: $('#world-map'),
zoomOnScroll: true,
regionsSelectable: false,
backgroundColor: "aliceblue",
markers: [], /* Initialize the map with empty markers */
series: {
regions: [{
values: {}, /* Initialize the map with empty region values */
scale: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial'
}],
/* Initialize the map with empty marker values */
markers: [{attribute: 'fill', scale: {}, values: []}]
},
onRegionTipShow: function(e, el, code){
var value = worldMap.series.regions[0].values[code],
formattedValue = new Intl.NumberFormat('en-US', worldMap.dataSetFormat).format(value);
el.text(el.text() + ' (' + worldMap.dataSetName + ': ' + formattedValue + ')');
}
});
/* Define the data type & the location of the relevant fields inside the incoming data */
var schema = {
url: 'https://api.worldbank.org/v2/country/all/indicator/NY.GDP.MKTP.CD',
params: 'format=json&mrv=1&per_page=300',
alternate: '/ind_MapData',
dataSetName: 'GDP',
dataSetFormat: {style: 'currency', currency: 'USD'},
dataSetIndex: 1,
countryCodeField: 'country.id',
countryValueField: 'value'
};
fetchCountryData(schema, worldMap);
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jvectormap#2.0.4/jquery-jvectormap.min.css" type="text/css">
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jvectormap#2.0.4/jquery-jvectormap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jvectormap#2.0.4/tests/assets/jquery-jvectormap-world-mill-en.js"></script>
</head>
<body>
<div id="world-map" style="width: 600px; height: 400px"></div>
</body>
</html>
Moreover:
Please pay attention: the original world map from jVectorMap doesn't include some tiny countries like Singapore, Liechtenstein and so on. They are simply too small, You would need to zoom-in a lot. The preferred solution for this problem is to place additional markers at their location. After that, You can set the incoming data for that markers accordingly.
See my answer here: jVectorMap - How to add marker dynamically
BTW, thanks to bjornd for the great jVectorMap.

Chart.js not drawing on mobile (safari/chrome) fine on desktop

I've got a piechart that works perfectly fine on desktop. It retrieves data from an AJAX request and stores the data/json it gets. Selected data is then pushed into the chart. I am using Thymeleaf & Spring in but thats not relevant here I believe.
Everything is rendered fine on my page when I access it through Safari or chrome on mobile, however the graph is not present.
I've tried changing responsive true/false, maintaingAspectRatio false/true, playing with other options provided in the chart.js documentation. Changed the viewport, set my width on the container of the canvas rather than the canvas it self and a whole bunch of other stuff.
Could it be due to the load order? i.e the page is loaded before it can actually get the information from the request? However, that would mean that it shouldn't be working on desktop either.
Here is some code
myGraph.js
$(document).ready(function () {
var id = $.url(2);
$.ajax({
url: "hosturl/a/b/" + id + "/c/d",
type: "GET",
dataType: "json",
success: function (data) {
console.log(data);
var count = [];
var days = [];
for (var i in data) {
days.push(data[i][1]);
count.push(data[i][0]);
}
var chartdata = {
labels: days,
datasets: [
{
label: "By day",
backgroundColor: "#4dc3ff",
borderWidth: 2,
hoverBackgroundColor: "#009",
hoverBorderColor: "#099",
hoverBorderWidth: 5,
data: count
}
]
};
var ctx = $("#daysGraph");
var pieChart = new Chart(ctx, {
type: 'pie',
data: chartdata,
options: {
responsive: true,
legend: {
display: true,
position: 'right',
labels: {
fontColor: "#000"
}
}
}
});
},
error: function (data) {
}
});
graph.html (most of the other html is cut out out, but this on its own doesn't work)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-
scale=1,maximum-scale=7"/>
<title>Hmm</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css"/>
<script src="../../javascript/Chart.min.js" th:href="#{/Chart.min.js}"/>
<script src="../../javascript/js-url-2.5.0/url.js" th:href="#{/url.js}" ></script >
<link rel="stylesheet" href="../static/css/graph.css" th:href="#{/css/graph.css}"/>
<script src="../../javascript/myGraph.js" th:href="#{/myGraph.js}" />
</head>
<body>
<div class="chart-container">
<canvas id="daysGraph" ></canvas>
</div>
</body>
</html>
graph.css
.chart-container {
position: relative;
margin: auto;
height: 80vh;
width: 80vw;
}
On the live server it looks like this
Any advice is welcome
Turned out there was something wrong with the api-route on mobile vs dektop relating to localhost. Therefore my data wasn't being fetched from the api and thus wouldn't populate the chart which is why it is not displaying on mobile. In other words, I was looking in the wrong places for an answer.
I've had similar problems myself, I resolved my issue by playing around with the borderWidth in order to get it working across all devices. Try changing it several times to see if it has any impact at all.

How can I put the differents functions of the script together in the same html page?

I want to use the DIV to display my report, so i see the icCube documentation icCube Web Reporting : Displaying a Report but when i try to apply it i'm confused about how can I putting the differents functions of the script to gather in the same html page , those are the functions:
The first Part
var ic3reporting = new ic3.Reporting({
noticesLevel: ic3.NoticeLevel.ERROR,
dsSettings: {
userName: "demo",
userPassword: "demo",
url: "http://localhost:8282/icCube/gvi"
}
});
ic3reporting.setupGVIConfiguration(function() {
ic3reporting.setupApplication({
mode: ic3.MainReportMode.REPORTING,
menu: ic3.MainReportMenuMode.OFF,
noticesLevel: ic3.NoticeLevel.ERROR,
container: $("#report-container")
});
});
The Second Part
var options = {
report: { name: 'My Report' },
mode: ic3.MainReportMode.EDITING_REPORTING,
menu: ic3.MainReportMenuMode.ON,
noticesLevel: ic3.NoticeLevel.INFO
};
ic3reporting.openReport(options, function() {
// your callback (I don't inderstand how can i putting this code)
});
I don't inderstand how can I put those parts to gather and
It's very important for me to build this script , That make the exportation of the report easier than before.
You can use these parts together in such way:
<!doctype html>
<head lang="en">
<meta charset="utf-8">
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%
}
</style>
</head>
<body>
<!-- 1. Define container for the report somewhere in html page -->
<div id="report-container"></div>
<!-- 2. Include reporting application scripts -->
<script src="http://localhost:8282/icCube/doc/ic3-report/app/reporting/js/loader/ic3bootstrap.js"></script>
<!-- 3. Initialization sequence -->
<script type="text/javascript">
var ic3root = "http://localhost:8282/icCube/doc/ic3-report/app/";
var ic3rootLocal = "http://localhost:8282/icCube/doc/ic3-report/app-local/";
// ic3reporting variable could be used globally, consider using array or different names here if
// you are going to show multiple report applications at the same time
var ic3reporting = null;
var options = {
root: ic3root,
rootLocal: ic3rootLocal,
// This function starts work just after initialization of reporting framework
callback: function () {
// 3.1 Create reporting instance with proper data source configuration
ic3reporting = new ic3.Reporting({
noticesLevel: ic3.NoticeLevel.ERROR,
dsSettings: {
userName: "demo",
userPassword: "demo",
url: "http://localhost:8282/icCube/gvi"
}
});
// 3.2 This function setups connection to the configured datasource and calls callback when connection is ready
ic3reporting.setupGVIConfiguration(function () {
// 3.3 Here we have ready connection, time to show empty reporting application
var initialApplicationOptions = {
mode: ic3.MainReportMode.REPORTING,
menu: ic3.MainReportMenuMode.OFF,
noticesLevel: ic3.NoticeLevel.ERROR,
container: $("#report-container")
};
ic3reporting.setupApplication(initialApplicationOptions);
// 3.4 just after setupApplication we have ready to work reporting environment, we can open reports, switch modes, etc
// here we have open report sequence
var options = {report: {name: 'My Report'}};
ic3reporting.openReport(options, function () {
alert("Report opened successfully")
});
});
}
};
ic3ready(options);
</script>
</body>
</html>
This is the correcte code
<html>
<head lang="en">
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<!-- ic3 bootstrap javascript -->
<script src="http://localhost:8282/icCube/doc/ic3-report/app/reporting /js/loader/ic3bootstrap.js"></script>
<script type="text/javascript">
/**
* Location of the icCube reporting files; not necessarily co-located
* with this HTML page. For example, assuming this file is located within
* the "Docs" repository of a local icCube install, this path would be :
*
* /icCube/doc/ic3-report/app/reporting/
*/
var ic3root = "http://localhost:8282/icCube/doc/ic3-report/app/";
var ic3rootLocal = "http://localhost:8282/icCube/doc/ic3-report/app-local/";
var options = {
root: ic3root,
rootLocal: ic3rootLocal,
callback: function () {
var ic3reporting = new ic3.Reporting(
{
noticesLevel:ic3.NoticeLevel.ERROR,
dsSettings:{
userName:"demo",
userPassword:"demo",
url: "http://localhost:8282/icCube/gvi"
}
});
ic3reporting.setupGVIConfiguration(function () {
ic3reporting.setupApplication(
{
mode:ic3.MainReportMode.REPORTING,
menu:ic3.MainReportMenuMode.OFF,
noticesLevel:ic3.NoticeLevel.ERROR,
container:$(".ic3-report-content-container")
});
var options = {
report:{
name:'rapportest'
},
mode:ic3.MainReportMode.EDITING_REPORTING,
menu:ic3.MainReportMenuMode.OFF,
noticesLevel:ic3.NoticeLevel.INFO
};
ic3reporting.openReport(options, function () {
alert("Report opened successfully")
});
});
}
};
ic3ready(options);
</script>
<div class="ic3-report-content-container" style="border:solid 1px red;"></div>

Cesium live update of a point?

I am currently working on a live tracking application for Cesium, but am having some issues when I display the point in the browser.
So far my Cesium viewer receives the data from the server (in JSON format) and displays the point properly on the map, but the only way to have it update the location on the map is to refresh the page. Note that the location.json file it is reading the location from is being updated with a new location every second or so from the server.
Now I figured it would do this, as the client side code has no "update" function to dynamically change the point location on the map.
So what is the easiest way to have Cesium constantly update the point on the map, without the user constantly refreshing the page? Based on my research I have found some examples that involve streaming of CZML files or making my JSON into a data source, but these seem a bit complex for what seems to be a simple task. Is there not a simple "update" function that will change the point dynamically?
Here is my client side code:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8">
<!-- Tell IE to use the latest, best version (or Chrome Frame if pre-IE11). -->
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Hello World!</title>
<script src="../Build/Cesium/Cesium.js"></script>
<style>
#import url(../Build/Cesium/Widgets/widgets.css);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
var viewer = new Cesium.Viewer('cesiumContainer');
Cesium.loadJson('/location.json').then(function(data) {
console.log(data);
viewer.entities.add({
name : data.name,
position : Cesium.Cartesian3.fromDegrees(data.lon, data.lat),
point : {
pixelSize : 5,
color : Cesium.Color.RED,
outlineColor : Cesium.Color.WHITE,
outlineWidth : 2
},
label : {
text : data.name,
font : '14pt monospace',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth : 2,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
pixelOffset : new Cesium.Cartesian2(0, -9)
}
});
viewer.zoomTo(viewer.entities);
});
</script>
</body>
</html>
If you need any more information from me, I will be happy to provide it.
Thanks!
You will need to keep a reference to each of this points and then simply update that elements position according to some unique id. If a name is unique then you can use that, otherwise you need to implement some way to identify each point after update.
You can check if the point is a new one or existing one in a loadJSON callback function by calling var currentPoint = viewer.entities.getById(data.id). Then you can choose which one of these function will you call. First one for new points (when currentpoint == undefined):
function addNewPoint(
var point = new Cesium.Entity(
{
id : data.id,
name : data.name,
position : Cesium.Cartesian3.fromDegrees(data.lon, data.lat),
point : {
pixelSize : 5,
color : Cesium.Color.RED,
outlineColor : Cesium.Color.WHITE,
outlineWidth : 2
},
label : {
text : data.name,
font : '14pt monospace',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth : 2,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
pixelOffset : new Cesium.Cartesian2(0, -9)
}
}
);
viewer.entities.add(point);
);
Otherwise you call updatePoint function that will just update position
function updatePosition(currentPoint, data)
{
var newPos = new Cesium.Cartesian3.fromDegrees(data.lon, data.lat);
currentPoint.position = newPos;
}

How obtain the length of a route?

how can i get the length of a route?
I have been looking at this basic code of a route from a to b:
// Get the DOM node to which we will append the map
var mapContainer = document.getElementById("mapContainer");
// Create a map inside the map container DOM node
var map = new nokia.maps.map.Display(mapContainer, {
// Initial center and zoom level of the map
center: [52.51, 13.4],
zoomLevel: 7,
// We add the behavior component to allow panning / zooming of the map
components:[new nokia.maps.map.component.Behavior()]
}),
router = new nokia.maps.routing.Manager(); // create a route manager;
// The function onRouteCalculated will be called when a route was calculated
var onRouteCalculated = function (observedRouter, key, value) {
if (value == "finished") {
var routes = observedRouter.getRoutes();
//create the default map representation of a route
var mapRoute = new nokia.maps.routing.component.RouteResultSet(routes[0]).container;
map.objects.add(mapRoute);
//Zoom to the bounding box of the route
map.zoomTo(mapRoute.getBoundingBox(), false, "default");
} else if (value == "failed") {
alert("The routing request failed.");
}
};
/* We create on observer on router's "state" property so the above created
* onRouteCalculated we be called once the route is calculated
*/
router.addObserver("state", onRouteCalculated);
// Create waypoints
var waypoints = new nokia.maps.routing.WaypointParameterList();
waypoints.addCoordinate(new nokia.maps.geo.Coordinate(52.51652540955727, 13.380154923889933));
waypoints.addCoordinate(new nokia.maps.geo.Coordinate(52.52114106145058,13.40921934080231));
/* Properties such as type, transportModes, options, trafficMode can be
* specified as second parameter in performing the routing request.
* See for the mode options the "nokia.maps.routing.Mode" section in the developer's guide
*/
var modes = [{
type: "shortest",
transportModes: ["car"],
options: "avoidTollroad",
trafficMode: "default"
}];
// Calculate the route (and call onRouteCalculated afterwards)
router.calculateRoute(waypoints, modes);shortest
When the route is successfully calculated, the call-back function holds an array of one or more routes.
Code:
var routes = observedRouter.getRoutes();
Each of these holds a route summary, where you can obtain useful info about the route.
Code:
alert ("Route Length = " + routes[0].totalLength + " m.");
alert ("As the crow flies = " + routes[0].waypoints[0].mappedPosition.distance(routes[0].waypoints[1].mappedPosition) + " m.");
(Obviously you'll need to use waypoints.length -1 for a calculation with stop-overs)
Here is your code example, with the extra two lines added, You need to use your own app id and token to get it to work.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
Example from Nokia Maps API Playground, for more information visit http://api.maps.nokia.com
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=7; IE=EmulateIE9"/>
<base href="http://developer.here.net/apiexplorer/examples/api-for-js/routing/map-with-route-from-a-to-b.html" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Nokia Maps API Example: Add route from A to B</title>
<meta name="description" content="Routing Manager offers the ability to request a route with various modes between two points"/>
<meta name="keywords" content="routing, services, a to b, route, direction, navigation"/>
<!-- For scaling content for mobile devices, setting the viewport to the width of the device-->
<meta name=viewport content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<!-- Styling for example container (NoteContainer & Logger) -->
<link rel="stylesheet" type="text/css" href="http://developer.here.net/apiexplorer/examples/templates/js/exampleHelpers.css"/>
<!-- By default we add ?with=all to load every package available, it's better to change this parameter to your use case. Options ?with=maps|positioning|places|placesdata|directions|datarendering|all -->
<script type="text/javascript" charset="UTF-8" src="http://api.maps.nokia.com/2.2.3/jsl.js?with=all"></script>
<style type="text/css">
html {
overflow:hidden;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
width: 100%;
height: 100%;
position: absolute;
}
#mapContainer {
width: 100%;
height: 100%;
left: 0;
top: 0;
position: absolute;
}
</style>
</head>
<body>
<div id="mapContainer"></div>
<script type="text/javascript" id="exampleJsSource">
/* Set authentication token and appid
* WARNING: this is a demo-only key
* please register on http://api.developer.nokia.com/
* and obtain your own developer's API key
*/
nokia.Settings.set("appId", "YOUR APP ID");
nokia.Settings.set("authenticationToken", "YOUR TOKEN");
// Get the DOM node to which we will append the map
var mapContainer = document.getElementById("mapContainer");
// Create a map inside the map container DOM node
var map = new nokia.maps.map.Display(mapContainer, {
// Initial center and zoom level of the map
center: [52.51, 13.4],
zoomLevel: 7,
// We add the behavior component to allow panning / zooming of the map
components:[new nokia.maps.map.component.Behavior()]
}),
router = new nokia.maps.routing.Manager(); // create a route manager;
// The function onRouteCalculated will be called when a route was calculated
var onRouteCalculated = function (observedRouter, key, value) {
if (value == "finished") {
var routes = observedRouter.getRoutes();
//create the default map representation of a route
var mapRoute = new nokia.maps.routing.component.RouteResultSet(routes[0]).container;
map.objects.add(mapRoute);
//Zoom to the bounding box of the route
map.zoomTo(mapRoute.getBoundingBox(), false, "default");
alert ("Route Length = " + routes[0].totalLength + " m.");
alert ("As the crow flies = "
routes[0].waypoints[0].mappedPosition.distance(
routes[0].waypoints[1].mappedPosition) + " m.");
} else if (value == "failed") {
alert("The routing request failed.");
}
};
/* We create on observer on router's "state" property so the above created
* onRouteCalculated we be called once the route is calculated
*/
router.addObserver("state", onRouteCalculated);
// Create waypoints
var waypoints = new nokia.maps.routing.WaypointParameterList();
waypoints.addCoordinate(new nokia.maps.geo.Coordinate(52.51652540955727, 13.380154923889933));
waypoints.addCoordinate(new nokia.maps.geo.Coordinate(52.52114106145058, 13.40921934080231));
/* Properties such as type, transportModes, options, trafficMode can be
* specified as second parameter in performing the routing request.
*
* See for the mode options the "nokia.maps.routing.Mode" section in the developer's guide
*/
var modes = [{
type: "shortest",
transportModes: ["car"],
options: "avoidTollroad",
trafficMode: "default"
}];
// Calculate the route (and call onRouteCalculated afterwards)
router.calculateRoute(waypoints, modes);
</script>
</body>
</html>

Categories

Resources