Monday, November 2, 2009

Getting the attributes of an OpenLayer.Feature.Point that has been clustered in a OpenLayers.Layer.Vector layer

I encountered this problem and spent a day trying to understand how it worked. I have figured it out and am sharing my understanding with everyone.

Issue
------------
I had a GeoJSON parser that parsed the following geojson file:

{
"type": "FeatureCollection",
"features": [
{"type":"Feature", "id":"computer1", "properties":{"trial":"test"}, "geometry":{"type":"Point", "coordinates":[143, -35.91]}},
{"type":"Feature", "id":"computer2", "properties":{"trial":"test"}, "geometry":{"type":"Point", "coordinates":[144, -37.81667]}}
]
}

Once the GeoJSON parser parsed the file and created 2 OpenLayer.Feature.Points, these points were parsed to the OpenLayers.Layer.Vector object that implemented the clustering strategy.

Now, since the two points were within a close distance (specified by me), they were clustered and only one top level feature point was displayed on the map.

I wanted to get the 'id' and 'properties' (as in the GeoJSON file above) of each of the two points (when I zoomed into the map). However, I could not get it. It seemed to me, back then, that the GeoJSON parser had somehow overriden the properties I added into the "properties":{} field (in the above geojson file) with the 'count' property of the clustering Vector layer.

Hence, the question was, how do I get the attributes and ID of each point in the map (as in the geojson file).


Fix
----
feature.cluster solved the problem.

For other users who come across this problem, try to get the attributes of a point (specified in the geojson file in the 'properties' list) by using
feature.cluster[0].attributes.

Basically, this is what happens when the geojson fileabove is parsed by OpenLayers.Format.GeoJSON parser and added as OpenLayers.Vector.Feature objects into a OpenLayers Vector layer (that performs the clustering strategy):
1. GeoJSON file is read by the GeoJSON parser.
2. Parser creates OpenLayers.Vector.Feature objects for each string.
3. These OpenLayers.Vector.Feature objects are then added to the OpenLayers Vector layer
4. OpenLayers Vector layer performs clustering strategy
5. Each feature point that appears on the map is the top-level feature point (for a group of clusters). The attributes for this feature point is:

undefinedlayer value :[object Object]
lonlat value :null
data value :[object Object]
id value :OpenLayers.Feature.Vector_201
geometry value :POINT(15918687.18122222 -4288244.5663272375)
state value :null
attributes value :[object Object]
style value :null
cluster value :[object Object],[object Object],[object Object] //this indicates that this cluster point has three feature objects underneath it
renderIntent value :select
marker value :null

6. As it can be seen above, there is a 'cluster' property that holds 3 objects (being the three points). Hence, if you drill down to the 'cluster' property (i.e. feature.cluster[0]), it will give you the attributes of the first object in the cluster (being the point):

undefined0 value :[object Object]
layer value :null
lonlat value :null
data value :[object Object]
id value :OpenLayers.Feature.Vector_197
geometry value :POINT(8218510.393273033 -2699238.272071229)
state value :null
attributes value :[object Object]
style value :null
fid value :computer14
marker value :null

7. From the above, it can be seen that the 'id' property from the geojson file has been mapped to the 'fid' key of the feature point object. You can also see that the 'attributes' key holds an [object Object]. If you do feature.cluster[0].attributes.trial , it will display the 'trial' property and value that you specified in the geojson file (i.e. 'test').

Hence, adding as many property-value pairs in the GeoJSON file is easy as the GeoJSON parser just parsers the property-value pairs and enters the data into feature point object attributes that are beneath the top-level cluster point (it does not override the properties as I initially thought).

2 comments:

  1. hallo.
    Id like to ask you if you could explain to me in more details how can I get atribute values from geojson.
    I use GeoExt.data.featurestore to call php script which select vector data and return it like geojson.
    I enclosed also part of my code but Im not sure if it is right and also dont know how to get only atribute values of lentgh fields.
    thanks in advance for help...

    Jozef

    var store = new GeoExt.data.FeatureStore({
    layer: route_layer,
    fields: [
    {name: 'length'}
    ],
    proxy: new GeoExt.data.ProtocolProxy({
    protocol: new OpenLayers.Protocol.HTTP({
    url: './php/pgrouting.php',
    format: new OpenLayers.Format.GeoJSON({
    internalProjection: epsg_900913,
    externalProjection: epsg_4326
    }),
    }),

    }),
    listeners: {
    load: function () {
    alert ('STORE :' + store);
    //alert('dlzka trasy TEST:'+store.getCount());
    function printObject(o) {
    var out = '';
    for (var p in o) {
    out += p + ': ' + o[p] + ' || ';
    }
    alert(out);
    };
    printObject(store);
    }
    }
    });

    ReplyDelete
  2. Great find, but what if instead of working with Point features, I'm working with Polygon features?? Any idea how I could access its attributes?

    I've been able to do it in the onClick function, but that's only because the parameter is "feature". .. no idea how that works. Haven't been able to do something like:

    layer1.features[0].attributes.value = ?

    Any idea how this could be done?

    ReplyDelete

Thank you for your comment.