Leaflet: iterate through data for custom markers - loops

I need your help with custom markers in Leaflet. I need custom markers that correspond with the data entries. Here is a data SAMPLE csv that looks like this:
result
display_na
lat
long
AV
14, Amsterdamer Straße, Leopoldkiez, Wedding, Mitte, Berlin, 13347, Deutschland
13.3574034
52.5517197
VK
Seestraße, Wedding, Mitte, Berlin, 13351, Deutschland
52.541301
13.3341968
This is my code by now
// create 3 types of markers in 3 colors
var LeafIcon = L.Icon.extend({
options: {
iconSize: [38, 95],
iconAnchor: [22, 94],
popupAnchor: [-3, -76],
},
});
// Read markers data from data.csv
$.get("./data.csv", function (csvString) {
// Use PapaParse to convert string to array of objects
var data = Papa.parse(csvString, { header: true, dynamicTyping: true }).data;
var greenIcon = new LeafIcon({ iconUrl: "greeb.png" }),
yellowIcon = new LeafIcon({ iconUrl: "yellow.png" }),
redIcon = new LeafIcon({ iconUrl: "red.png" });
// For each row in data, create a marker and add it to the map
// For each row, columns `Latitude`, `Longitude`, and `Title` are required
for (var i in data) {
var row = data[i];
var marker = L.marker([row.lat, row.long], {
opacity: 1,
}).bindPopup(row.display_na);
L.marker([row.lat, row.long])
.addTo(map)
.bindPopup(row.display_na)
.openPopup();
}
});
It's not working. Can you tell me where my failure lies? I have 3 types of markers
greenIcon
yellowIcon
redIcon
The color of the marker corresponds with the row result. If the result value in the csv is AV then the marker should be greenIcon. That's the idea.
Than you for, looking forward to your suggestions!

You are close. First you need a ternary or an if statement to check csv's result value as you mention when instantiating a marker. It accepts an object which has some options including icon key. Using that you can define a different icon apart from the predefined
for (var i in data) {
var row = data[i];
const marker = L.marker([row.lat, row.long], {
icon: row.result === "AV" ? greenIcon : blueIcon
})
.addTo(map)
.bindPopup(row.display_na)
.openPopup();
}
Moreover your csv should be in the form of:
result,display_na,lat,long
AV,14 Amsterdamer Straße Leopoldkiez Wedding Mitte Berlin 13347 Deutschland,52.5517197,13.3574034
VK,Seestraße Wedding Mitte Berlin 13351 Deutschland,52.541301,13.3341968
You need to have commas only when separating each column values otherwise it is considered a different column value.
Demo

Related

Feeding array to json for use in turf.polygon, structure problems

I have a linestring and a polygon and I am using turf.booleanIntersect() to determine if the line goes through the polygon. The example that i have tested and works is:
var poly1 = turf.polygon([
[
[148.535693, -29.6],
[154.553967, -29.64038],
[154.526554, -33.820031],
[148.535693, -33.6],
[148.535693, -29.6]
]
]);
//const p1 = L.geoJSON(poly1).addTo(mymap);
console.log("TEST: " + turf.booleanIntersects(line, poly1));
In my real code I read the polygon values from a file and need to insert them into an array which needs to be converted into a "GeoJSON Feature or Geometry" (from webpage).
I am having trouble getting the array to json convert correct.
var polygonlines = [];
var start = [long,lat];
polygonlines.push([start]); //add multiple of these points to the to polygonlines array
//create my json
var geojsonPolygon =
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": polygonlines
}
}
var turfpolygon = turf.polygon(geojsonPolygon.data.geometry.coordinates); //ERROR HERE
const p2 = L.geoJSON(turfpolygon).addTo(mymap);
var result = turf.booleanIntersects(line, turfpolygon)
The error I get is "Uncaught Error Error: Each LinearRing of a Polygon must have 4 or more Positions."
I can't quite get the structure of the geojsonPolygon correct. I think that it is look at geojsonPolygon Array(1) in attached picture instead of Array(10), but I can't work out how to fix it.
Would love some help getting this structure fixed. Thank you :)
p.s. please ignore values of lat/longs, just examples.
I have seen this question but it hasn't helped How to feed JSON data of coordinates to turf.polygon?
Ongoing answer..., content and code will be edited.
Here is a LIVE demo code that you can run to see how it works. It may help to answer you question.
Usage:
click Run code snippet button
click Full page in top-right corner to see map and console
//Using turf_polygon object style
var poly1 = turf.polygon([
[
[148.535693, -29.6],
[154.553967, -29.64038],
[154.526554, -33.820031],
[148.535693, -33.6],
[148.535693, -29.6]
]
]);
// Using geojson style data
// Coordinates are slightly different from poly1
// This can be used as a good example to compare/contrast with your implementation
// This geojson of poly2 works, you can see it on the map.
var poly2 = {
type: "Feature",
properties: { id: 102, name: "Poly_2" },
geometry: {
type: "Polygon",
coordinates: [
[
[148, -29],
[154, -29],
[154, -33],
[148, -33],
[148, -29]
]
]
}
};
var line12 = turf.lineString([[144, -30], [153, -31.8], [159, -32]]);
var line34 = turf.lineString([[144, -20], [160, -30]]);
/* Init and draw Leaflet map */
var map;
function initMap(coords, zoom) {
// initialize map container
map = L.map("mapid").setView(coords, zoom);
// get the stamen toner-lite tiles
var Stamen_Toner = L.tileLayer(
"https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.{ext}",
{
attribution:
'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap',
subdomains: "abcd",
minZoom: 0,
maxZoom: 20,
ext: "png"
}
);
// add the tiles to the map
Stamen_Toner.addTo(map);
//disable scroll wheel zoom
map.scrollWheelZoom.disable();
}
/* Leaflet use (lat,long) */
var coordinates = [-30, 150]; //[lat,long]
var zoom = 5;
initMap(coordinates, zoom);
//Add polygons and lines
L.geoJson(turf.featureCollection([poly1, poly2, line12, line34])).addTo(map);
// Intersection op
var result1 = turf.booleanIntersects(line12, poly1); //True
var result2 = turf.booleanIntersects(line34, poly1); //False
console.log(result1, result2);
//EOF
#mapid { height: 480px; width: 800px}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Turf.js/6.5.0/turf.min.js"></script>
<div id="mapid"></div>
How to get the polygonline array into geojson for use in turf polygon:
var polygonlines = [];
//these 2 lines occur multiple times in a loop
{
var start = [vol.lines[k].start.lng, vol.lines[k].start.lat];
polygonlines.push(start);
}
var geojsonPolygon =
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [polygonlines]
}
var turfpolygon = turf.polygon(geojsonPolygon.geometry.coordinates);
turf.booleanIntersects(line, turfpolygon)

Having problem to desctructure my data on React

The upcomingWork contains my apis data. What I want here is to insert this as an array to display it on my calendar, below are the example of structured data I want.
Actually, the upcomingWork contains a lot of attributes but I just want to get those three attributes to display on my calendar.
const data = upcomingWork.map(u => u.id && u.title && u.created_at);
Example of array that I want to create from data.
const events = [
{
id: 1,
title: 'My event',
start: new Date(2020, 4, 8, 10, 0),
end: new Date(2020, 4, 8, 14, 0),
},
];
The map that you have will simply set every value to either true if all values are truey or false if any of them are falsey. if you want to extract those 3 values just change the map to this:
const data = upcomingWork.map(({id, title, created_at}) => ({id, title, created_at}))
Whatever you returned is not going to give you any desired data.
I think you misunderstood the map method of Array.
Instead you should use map like:
const data = upcomingWork.map(u => {
const {id, title, created_at} = u;
return {
id,
title,
created_at
}
});
const data = upcomingWork.map(u => {
return { id: u.id, title: u.title };
});
Your upcomingWork.map doesn't create an object at all, so it has no chance of creating the expected data. Instead, you can map appropriate properties of the u object to the new keys in a new object you create.
const events = upcomingWork.map(u => ({
id: u.id,
title: u.title,
start: u.created_at,
end: u.end //change the u.end to whatever property you have in your data
}));
(the new object has to be wrapped in () to ensure JS interprets it as a value, not a function body)

Combining Two Arrays To One in NodeJS

I want to create Excel file that consist of 2 arrays of data with ExcelJS.
I can create the Excel file:
var Excel = require('exceljs');
var workbook = new Excel.Workbook();
var sheet = workbook.addWorksheet('My Sheet', {properties:{tabColor:{argb:'FFC0000'}}});
I can add column headers:
sheet.columns = [{key:"date", header:"Date"}, {key: "quantity", header: "Quantity"}]
I got 2 arrays for these columns:
array_date = [2018-01-04, 2018-01-06, 2018-01-08, 2018-01-09]
array_quantity = [25, 32, 54, 48]
I want to combine these 2 arrays to one array like this:
var merged = [{date:"2018-01-04", quantity:25}
, {date:"2018-01-06", quantity:32}
, {date:"2018-01-08", quantity:42}
, {date:"2018-01-09", quantity:48}];
If I can combine, I able to add as row for every data:
for(i in merged){
sheet.addRow(merged[i]);
}
Then I can create the Excel File:
workbook.xlsx.writeFile("some.xlsx").then(function() {
console.log("xls file is written.");
});
How can I combine two arrays to one If they are ordered? Also, I'm wondering is this the best approach to create excel file in NodeJS?
You can create the new array with
var array_date = ["2018-01-04", "2018-01-06", "2018-01-08", "2018-01-09"];
var array_quantity = [25, 32, 54, 48];
var merged = array_date.map((date, i) => ({
date,
quantity: array_quantity[i],
}));
array_date = [2018-01-04, 2018-01-06, 2018-01-08, 2018-01-09]
array_quantity = [25, 32, 54, 48]
var merged=[];
for(var i=0;i<array_date.length;i++){
merged.push({date:array_date[i], quantity:array_quantity[i]});
}
console.log(merged);

sending json to d3js graph

I have a series of stored JSON objects(below) being sent out my html page via angular,
the issue I have is getting the information from angular out to my d3.js graph.(i think i need to convert them from JSON to normal values
for my x axis data to be graphed)
{ __v: 0, temp: 328, _id: 56e9417d6a8a307819c3e598 },
{ __v: 0, temp: 328, _id: 56e9417d6a8a307819c3e599 },
{ __v: 0, temp: 328, _id: 56e9417d6a8a307819c3e600 },
{ __v: 0, temp: 328, _id: 56e941826a8a307819c3e59a }
the below $http request received the data from app.js.
the y axis is sales(value of objects) and the x axis is hour(amount of entries from database to display)
$http.get('/solution-two/data3').success(function (data) {
var hour=$scope.salesData3.length+1;
var sales= data;
$scope.salesData3.push({hour: hour, sales:sales});
});
I have the array starting off with an array which gets the info sent in to the http request
$scope.salesData3=[
{hour: 1,sales: 280}];
salesData3 is the name of my d3.js graph, so in summary i think i need to defice my length of hour variable with the length of database entries
and sales variable needs to accept the JSON objects from the database, would i be correct?
thanks for reading
If I understood your question clearly, you are looking for the structure in which you can send the data in JSON to D3 ?
If you are plotting a line graph of sales vs hour, then you do not need to check for the length of the hour. Instead D3 has methods to detect the time format, which can be used to assign it to the X-Axis.
x = d3.scale.linear().range([0, width]);
y = d3.time.scale().range([height, 0]);
// Set the X axis domain with time
y.domain(d3.extent(salesData3, function (d) {
return d.sales;
}));
valueLine = d3.svg.line()
.x(function (d) {
return x(d.hour);
})
.y(function (d) {
return y(d.sales);
});
svg.append("path")
.attr("class", "CLASS_NAME")
.attr("id", curveId)
.attr("d", valueLine(salesData3));
This link has an example on how you can use a JSON array and pass it as a data to the x and y axis https://www.dashingd3js.com/using-json-to-simplify-code
Nice link which explains the task of formatting the time http://www.d3noob.org/2012/12/formatting-date-time-on-d3js-graph.html & http://jsfiddle.net/robdodson/KWRxW/

openlayers 3 IGC source from text

I am using openlayers 3 and I am looking for a way to load track data not from urls, but directly by adding text to vectorsource IGC. I have the data with coordinates and times as arrays. What format is right? So, insted of this:
var vectorSource = new ol.source.IGC({
projection: 'EPSG:3857',
urls: [
'data/igc/Clement-Latour.igc',
'data/igc/Damien-de-Baenst.igc',
'data/igc/Sylvain-Dhonneur.igc',
'data/igc/Tom-Payne.igc',
'data/igc/Ulrich-Prinz.igc'
]
});
I'd like to use something like this (not sure about the format):
var vectorSource = new ol.source.IGC({
projection: 'EPSG:3857',
text: [
array1,
array2,
array3 // or arrayall with all three arrays, or text.. What is correct?
]
});
For more control and flexibility you can use an ol.source.Vector and an ol.format.IGC instead of the "convenient" ol.source.IGC. For example:
var source = new ol.source.Vector();
var format = new ol.format.IGC();
var readOptions = {featureProjection: 'EPSG:3857'};
var features = [
format.readFeature(text1, readOptions),
format.readFeature(text2, readOptions),
format.readFeature(text3, readOptions)
];
source.addFeatures(features);
var layer = new ol.layer.Vector({source: source});

Resources