I have two object with some similer key values osmstartnode and osmendnode. i want to merge these two object and get the final object with new value having congestion_level.
First object
var object = [{
osmstartnode: 370705004,
osmendnode: 1369956654,
congestion_level: 1
},
{
osmstartnode: 42469049,
osmendnode: 42469053,
congestion_level: 2
}
];
Second object
var roadobjt = [{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-74.0048445, 40.7124759],
[-74.0048533, 40.71245],
[-74.0048604, 40.7124243],
[-74.0048578, 40.7123974],
[-74.0048468, 40.7123722],
[-74.0048252, 40.7123472],
[-74.0045725, 40.7121422]
]
},
properties: {
"osmhighway": "motorway_link",
"osmoneway": "yes",
"osmwayid": 5669636,
"osmstartnode": 370705004,
"osmendnode": 1369956654,
"speed_mean_mph": 16,
"pct_from_freeflow": 72,
"speed_freeflow_mph": 22
}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-73.99866284812883, 40.59729307801823],
[-73.99879364640618, 40.59716957964474],
[-73.99913817998096, 40.596844447960684],
[-73.99931411513008, 40.596676614430145]
]
},
properties: {
"osmname": "Bay Parkway",
"osmhighway": "primary",
"osmoneway": "no",
"osmwayid": 5675398,
"osmstartnode": 42469049,
"osmendnode": 42469053,
"speed_mean_mph": 20,
"pct_from_freeflow": 67,
"speed_freeflow_mph": 29
}
}
];
to merge use:
var object = [{
osmstartnode: 370705004,
osmendnode: 1369956654,
congestion_level: 1
},
{
osmstartnode: 42469049,
osmendnode: 42469053,
congestion_level: 2
}
];
into properties of:
var roadobjt = [{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-74.0048445, 40.7124759],
[-74.0048533, 40.71245],
[-74.0048604, 40.7124243],
[-74.0048578, 40.7123974],
[-74.0048468, 40.7123722],
[-74.0048252, 40.7123472],
[-74.0045725, 40.7121422]
]
},
properties: {
"osmhighway": "motorway_link",
"osmoneway": "yes",
"osmwayid": 5669636,
"osmstartnode": 370705004,
"osmendnode": 1369956654,
"speed_mean_mph": 16,
"pct_from_freeflow": 72,
"speed_freeflow_mph": 22
}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-73.99866284812883, 40.59729307801823],
[-73.99879364640618, 40.59716957964474],
[-73.99913817998096, 40.596844447960684],
[-73.99931411513008, 40.596676614430145]
]
},
properties: {
"osmname": "Bay Parkway",
"osmhighway": "primary",
"osmoneway": "no",
"osmwayid": 5675398,
"osmstartnode": 42469049,
"osmendnode": 42469053,
"speed_mean_mph": 20,
"pct_from_freeflow": 67,
"speed_freeflow_mph": 29
}
}
];
use :
roadobjt.map((r, i) => { r.properties = Object.assign(r.properties, object[i]); return r;})
results:
[{"type":"Feature","geometry":{"type":"LineString","coordinates":[[-74.0048445,40.7124759],[-74.0048533,40.71245],[-74.0048604,40.7124243],[-74.0048578,40.7123974],[-74.0048468,40.7123722],[-74.0048252,40.7123472],[-74.0045725,40.7121422]]},"properties":{"osmhighway":"motorway_link","osmoneway":"yes","osmwayid":5669636,"osmstartnode":370705004,"osmendnode":1369956654,"speed_mean_mph":16,"pct_from_freeflow":72,"speed_freeflow_mph":22,"congestion_level":1}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[-73.99866284812883,40.59729307801823],[-73.99879364640618,40.59716957964474],[-73.99913817998096,40.596844447960684],[-73.99931411513008,40.596676614430145]]},"properties":{"osmname":"Bay Parkway","osmhighway":"primary","osmoneway":"no","osmwayid":5675398,"osmstartnode":42469049,"osmendnode":42469053,"speed_mean_mph":20,"pct_from_freeflow":67,"speed_freeflow_mph":29,"congestion_level":2}}]
Related
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-77.155585,
40.056708,
0
],
[
-77.150315,
40.04536,
0
]
]
]
},
"id": 42001030101,
"Households": 1000,
"Income": 74597
},
I am using the google maps JS API. I cannot use the getProperty function because the data doesn't have the properties grouped together.
How can I access each of these pieces of data?
Here is what I tried before I realized that you can't use the properties function.
map.data.setStyle(
function(feature){
let income = feature.getProperty('Income');
let color = 'blue';
if (income > 10000){
color = 'red'
}
return {
fillColor: color,
//strokeColor: "green",
strokeWeight: 0.3,
};
}
);
According to the geojson spec:
A Feature object has a member with the name "properties". The value
of the properties member is an object (any JSON object or a JSON null
value).
As your feature doesn't have a properties member, you can 'repair' it so that any member that is neither type nor geometry is bundled as a member of properties.
This should enable your existing code using feature.getProperty().
const data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-77.155585, 40.056708, 0],
[-77.150315, 40.04536, 0]
]
]
},
"id": 42001030101,
"Households": 1000,
"Income": 74597
}
]
}
const repairGeoJsonProps = (fc) => {
return {
"type": "FeatureCollection",
"features": fc.features.map(ftr => {
const props = Object.entries(ftr).filter(k => ["type", "geometry"].indexOf(k[0]) < 0);
return {
"type": ftr.type,
"geometry": ftr.geometry,
"properties": Object.fromEntries(props)
}
})
}
}
console.log(repairGeoJsonProps(data));
I want to do some classification from json data based by the data value.
I'm using some code that i get by another answer from stackvlow,
this is how i load the data :
How to count JSON objects
and this is the code that i use to do classification :
How can I use for loop to count numbers?
Load the json,
const object1 = {
"type": "FeatureCollection",
"name": "nitrogen_2019",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 0,
"n_mean": 2
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
},
{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 1,
"n_mean": 3
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
},
{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 2,
"n_mean": 4
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
},
{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 13,
"n_mean": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
}
]};
This is the counting code,
function countbad(limit){
var a = 0
var b = 0
for (var i = 0; i < limit; i +=1){
if (Object.keys(object1.features[i].properties.n_mean) < 3){
a = a + 1
} else {
b = b + 1
}
}
console.log( a + " bad")
console.log( b + " good")}
countbad(Object.keys(object1.features).length);
But It gives me the incorrect results. Is there any problem with my code? is there any simple method to do classification data in json?
Firstly Your JSON is not valid as you are missing commas in the feature > properties.
Also If I correctly tried to understand your problem then I suggest you to use available js methods like forEach in this case.
const object1 = {
"type": "FeatureCollection",
"name": "nitrogen_2019",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 0,
"n_mean": 2
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
},
{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 1,
"n_mean": 3
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
},
{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 2,
"n_mean": 4
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
},
{
"type": "Feature",
"properties": {
"xcoord": 72,
"ycoord": 92,
"grid": 13,
"n_mean": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
]
]
}
}
]}
function countbad(){
let a = 0
let b = 0
object1.features.forEach(e => {
if(e.properties.n_mean < 3)
a++
else
b++
})
console.log( a + " bad")
console.log( b + " good")
}
countbad();
function countbad(object1){
var a = 0
var b = 0
for (var i = 0; i < limit; i +=1){
if (object1.features[i].properties.n_mean) < 3){
a = a + 1
} else {
b = b + 1
}
}
console.log( a + " bad")
console.log( b + " good")
}
countbad(object1);
I'm trying to use the leaflet API to display data about Coral Reef locations across the world. I originally downloaded a shapefile (.shp), and converted it to GeoJSON using QGIS. I put the data in my project folder, but when I attempted to display this data on leaflet through an Ajax request, the browser took a very long time to load and eventually return a not responding message. However, I could see that the markers would appearing on the map, albeit it very slowly. Is there any way to create a smaller file, or load the data more efficiently so it doesn't make the entire site unusable?
My Ajax request looked like this:
$.ajax({
type: 'GET',
url: './coldwater.geojson',
dataType: 'json',
data: data,
success: function (data) {
L.geoJSON(data).addTo(mymap);
}, error: function(){
console.log('Couldn\'t load data');
}
});
Here's a snippet of the geoJSON
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -75.116700000304718, 18.283300000094982 ], [ -75.116699858211859, 18.283301156623111 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -34.850000000399632, 9.01670000040474 ], [ -34.849996660317572, 9.016695959750791 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -34.850000000399632, 9.01670000040474 ], [ -34.849996660317572, 9.016695959750791 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -81.166699999905006, 23.983300000394763 ], [ -81.166699953140267, 23.983303104854429 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.549997733808311, 26.649999766076405 ], [ -79.416700222836994, 27.166696245435446 ], [ -79.416700222836994, 27.283302340130945 ], [ -79.416699999805132, 27.283300000094982 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -78.683303107752181, 27.416698775628049 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.216699996607531, 24.099999131754601 ], [ -78.850001440414133, 26.516702255105031 ], [ -78.39999868309269, 26.583297050818317 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -77.083301298815854, 25.166702977260627 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.233301481578053, 27.216698550297906 ], [ -79.216699996607531, 27.300002749627254 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.549997733808311, 26.649999766076405 ], [ -79.416700222836994, 27.166696245435446 ], [ -79.416699999805132, 27.166700000104981 ], [ -79.366697917974477, 27.533295877103114 ] ] } },
Would it be better to use the google maps API?
Or is there a better way to insert a shapefile into a leaflet map?
ps: if this isn't appropriate or is off topic let me know. I'm new to posting on stackoverflow
I am trying to move the element height of an entity that is loaded from a geojson file in cesium.js. I'm using the example App.js file from Cesium Workshop/
How would I modify the code below to adjust the height of the data entities so that they are pinned to the elevation of the terrain. The geojson file that I have has an altitude value of 0. This altitude needs to match the terrain at that location. When I render this data many of the points are under the terrain. I assume I also need to lookup the terrain height, convert the data to Cartesian coordinated back and forth to polar coordinates to add the offset into the entity.
var geojsonOptions = {
clampToGround : true
};
var testLinePromise = Cesium.GeoJsonDataSource.load('./Source/SampleData/testLines.geojson', geojsonOptions);
// Save an new entity collection of neighborhood data
var testLines;
testLinePromise.then(function(dataSource) {
// Add the new data as entities to the viewer
viewer.dataSources.add(dataSource);
testLines = dataSource.entities;
// Get the array of entities
var testLineEntities = dataSource.entities.values;
for (var i = 0; i < testLineEntities.length; i++) {
var entity = testLineEntities[i];
if (Cesium.defined(entity.polygon)) {
// Tells the polygon to color the terrain. ClassificationType.CESIUM_3D_TILE will color the 3D tileset, and ClassificationType.BOTH will color both the 3d tiles and terrain (BOTH is the default)
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
// Generate Polygon center
var polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
entity.position = polyCenter;
// Generate labels
entity.label = {
text : entity.name,
showBackground : true,
scale : 0.6,
horizontalOrigin : Cesium.HorizontalOrigin.CENTER,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
distanceDisplayCondition : new Cesium.DistanceDisplayCondition(10.0, 8000.0),
disableDepthTestDistance : 100.0
};
}
}
});
Here is the geojson file
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "623dd9c1-26cb-4248-8e41-ebc8c3a16af5",
"description": "descr A",
"company": "ACME"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-114.5305072,
20.61238237,
0
],
[
-111.9486,
10.46916111,
0
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "15966b86-26d0-4e0b-ba6e-7fa0c98bfe5e",
"description": "descr C",
"company": "ACME"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-135.9989702,
45.7677603,
0
],
[
-134.5305072,
50.61238237,
0
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "00ca37f5-de78-4d5b-88b5-d39808ff8143",
"description": "descr D",
"company": "ACME"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-125.9989702,
65.7677603,
0
],
[
-129.0238961,
67.96685,
0
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "22e5e02f-fa43-445e-a2eb-29ad760a964c",
"description": "descr E",
"company": "ACME"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-105.9989702,
55.7677603,
0
],
[
-100.7366501,
55.67798889,
0
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "c4aefe46-a2a6-4a97-ac36-571c9e370d31",
"description": "descr A",
"company": "ACME"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-111.994653,
78.84398434,
0
],
[
-128.4816326,
16.68839404,
0
]
]
}
}
]
}
I have a map with Geojson polygons where each polygon is identified by a unique ID. I have a separate Geojson of point markers where each point is associated with a polygon with the same polygon ID, as well as a unique identifier for each individual point.
The initial map display is of only polygons. Each polygon click will display the points that are associated with the clicked polygon. When a new polygon is clicked, I want to plot the points associated with the new polygon while simultaneously removing the previously plotted points. So each time the user clicks a polygon, ONLY points within that polygon are ever displayed.
Here is some minimally reproducible code: https://jsfiddle.net/3v7hd2vx/1146/
var polys = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"stroke": "#555555",
"stroke-width": 2,
"stroke-opacity": 1,
"fill": "#555555",
"fill-opacity": 0.5,
"polygon": "one"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-87.33032226562499,
37.90953361677018
],
[
-85.374755859375,
37.90953361677018
],
[
-85.374755859375,
39.036252959636606
],
[
-87.33032226562499,
39.036252959636606
],
[
-87.33032226562499,
37.90953361677018
]
]
]
}
},
{
"type": "Feature",
"properties": {
"stroke": "#555555",
"stroke-width": 2,
"stroke-opacity": 1,
"fill": "#555555",
"fill-opacity": 0.5,
"polygon": "two"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-85.3857421875,
37.90953361677018
],
[
-83.3642578125,
37.90953361677018
],
[
-83.3642578125,
39.04478604850143
],
[
-85.3857421875,
39.04478604850143
],
[
-85.3857421875,
37.90953361677018
]
]
]
}
},
{
"type": "Feature",
"properties": {
"stroke": "#555555",
"stroke-width": 2,
"stroke-opacity": 1,
"fill": "#555555",
"fill-opacity": 0.5,
"polygon": "three"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-87.34130859375,
36.90597988519294
],
[
-83.3642578125,
36.90597988519294
],
[
-83.3642578125,
37.91820111976663
],
[
-87.34130859375,
37.91820111976663
],
[
-87.34130859375,
36.90597988519294
]
]
]
}
}
]
};
var pts = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"marker-color": "#7e7e7e",
"marker-size": "medium",
"marker-symbol": "",
"id": "one",
"animal": "bear"
},
"geometry": {
"type": "Point",
"coordinates": [
-86.72607421875,
38.77121637244273
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#7e7e7e",
"marker-size": "medium",
"marker-symbol": "",
"id": "one",
"animal": "fish"
},
"geometry": {
"type": "Point",
"coordinates": [
-86.583251953125,
38.487994609214795
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#7e7e7e",
"marker-size": "medium",
"marker-symbol": "",
"id": "two",
"animal": "tiger"
},
"geometry": {
"type": "Point",
"coordinates": [
-84.276123046875,
38.38472766885085
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#7e7e7e",
"marker-size": "medium",
"marker-symbol": "",
"id": "two",
"animal": "lizard"
},
"geometry": {
"type": "Point",
"coordinates": [
-85.067138671875,
38.70265930723801
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#7e7e7e",
"marker-size": "medium",
"marker-symbol": "",
"id": "three",
"animal": "dog"
},
"geometry": {
"type": "Point",
"coordinates": [
-83.880615234375,
37.483576550426996
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#7e7e7e",
"marker-size": "medium",
"marker-symbol": "",
"id": "three",
"animal": "horse"
},
"geometry": {
"type": "Point",
"coordinates": [
-85.93505859374999,
37.709899354855125
]
}
}
]
};
var map = L.map("map", {
center: [37.5, -85],
zoom: 7
});
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png").addTo(map);
var defaultStyle = {
fillColor: "whitesmoke",
color: "#171717",
fillOpacity: 1,
weight: 1
};
// create polygon geojson, add to map
var polyJson = L.geoJson(polys, defaultStyle).addTo(map);
// empty layer group to add markers to
var layerGroup = L.layerGroup();
// loop through polygon layers for events
polyJson.eachLayer(function(layer){
// zoom to bbox on each polygon click
layer.on("click", function(e){
var bbox = e.target.getBounds();
var sw = bbox.getSouthWest();
var ne = bbox.getNorthEast();
map.fitBounds([sw, ne]);
// the clicked polygon identifier
var clickedPoly = e.target.feature.properties.polygon;
// pts added to map when they match the clickedpoly id
L.geoJson(pts, {
pointToLayer: function(feature, latlng){
if(feature.properties.id === clickedPoly){
var clicked = L.circleMarker(latlng, {
color: "red"
}).addTo(map).addTo(layerGroup);
}
}
});
});
});
polyJson.on("click", function(){
if(map.hasLayer(layerGroup)){
map.removeLayer(layerGroup);
}else{
map.addLayer(layerGroup);
//layerGroup.removeLayers();
}
});
In this example, the entire layerGroup of points is removed every other click based on the conditional statement at the end of the code block. But each new click continues to append markers to the layerGroup, so ALL selected markers are displayed every other click.
My inclination is to have each "group" of markers named by the polygon that they lie within, so when displayed markers do not match the currently clicked polygon ID, they will be removed both from the map AND from the layerGroup. I've worked extensively with Leaflet in R, but I'm not sure how to accomplish this in JS (or if the logic is even the same in the different languages). I can't manually define each layer because I'll be iterating through many dynamically loaded polygons and points.
One simple way to fill your layer with teh desired points would be to:
make your layerGroup a permanent layer,
empty this layer when the user clicks on a polygon with layerGroup.clearLayers()
fill layerGroup with the valid markers (determined by the filter property) and let Leaflet handle the markers without interfering with pointToLayer.
Basically, simplify things:).
For example:
layer.on("click", function(e){
var bbox = e.target.getBounds();
var sw = bbox.getSouthWest();
var ne = bbox.getNorthEast();
map.fitBounds([sw, ne]);
// the clicked polygon identifier
var clickedPoly = e.target.feature.properties.polygon;
layerGroup.clearLayers();
layerGroup.addLayer(L.geoJson(pts, {
pointToLayer: function(feature, latlng){
return L.circleMarker(latlng, {
color: "red"
});
},
filter: function (feature) {
return feature.properties.id === clickedPoly;
}
}));
});
And a demo https://jsfiddle.net/3v7hd2vx/1147/