[GIS] How to nest GeoJSON features based on their geometry in javascript

d3geojsonjavascript

I have a GeoJson object with polygon features. Some of them have same geometry.
They look like this:

squareData = {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },

"features": [
{ "type": "Feature", "properties": { "gid": 2196272, "acq_date": "2014\/08\/29", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -179.5, -18.5 ], [ -178.5, -18.5 ], [ -178.5, -17.5 ], [ -179.5, -17.5 ], [ -179.5, -18.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 2492600, "acq_date": "2014\/07\/09", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 2446209, "acq_date": "2014\/07\/18", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 1562738, "acq_date": "2014\/07\/25", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 476723, "acq_date": "2014\/07\/27", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
...
] 
}

I want to nest them based on geometry values, to get an object like this one:

nestedData = [
{
  "key": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] },
  "values": [
{ "type": "Feature", "properties": { "gid": 2492600, "acq_date": "2014\/07\/09", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 2446209, "acq_date": "2014\/07\/18", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 1562738, "acq_date": "2014\/07\/25", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } },
{ "type": "Feature", "properties": { "gid": 476723, "acq_date": "2014\/07\/27", "firenum": "1" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ], [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ] } }
] },
{ "key": ..., "values": [...] },
...
]

I've nested this data by acq_date property using d3.nest() function, but it doesn't seem to work on geometry property. Every geometry is considered an "Object", so I'm getting all features inside the first array element. I'm doing it in browser, so I need a solution in JavaScript.

Best Answer

You need to refer to the geometry.coordinates of the data object (d). So, given, something looking like this, ie, referencing the features array directly from you original featureCollection for brevity (ie, equivalent to squareData.features):

var features =  [
 { "type": "Feature", "properties": 
      { "gid": 2196272, "acq_date": "2014\/08\/29", "firenum": "1" },    
       "geometry": { "type": "Polygon", "coordinates": [ [ [ -179.5, -18.5 ],
            [ -178.5, -18.5 ], [ -178.5, -17.5 ], [ -179.5, -17.5 ], [ -179.5, -18.5 ] ] ] 
  } 
},
 { "type": "Feature", "properties": 
     { "gid": 2492600, "acq_date": "2014\/07\/09", "firenum": "1" },
      "geometry": { "type": "Polygon", "coordinates": [ [ [ -164.5, 54.5 ],
            [ -163.5, 54.5 ], [ -163.5, 55.5 ], [ -164.5, 55.5 ], [ -164.5, 54.5 ] ] ]
     } 
   }
];

You can write something like:

 var nest = d3.nest()
    .key(function(d) {return d.geometry.coordinates})
    .entries(features);

 console.log(JSON.stringify(nest, null, 2));

Here is a jsFiddle, which is clearly showing a group with multiple entries for the Polygon starting with the point [-164.5, 54.5]. The pretty print comes from the 3rd parameter to JSON.stringify and attaching it to an HTML pre element.

To use with your original FeatureCollection, just reference squareFeatures.features in the entries function.