[GIS] Create multiple vector layers by reading a GeoJSON file once in OpenLayers

geojsonlayersopenlayers-2

I am a begginner to OpenLayers, and my question is about making things more efficient.

My work is about displaying time-dependent weather elements on several point locations on the map. All these are initially stored in a MySQL database, and I use a PHP file to convert a (parameterized) query result into GeoJSON format. All the features are points with a pair of coordinates, but many properties (like name, temperature, dewpoint, wind direction, wind strength etc.) With a refreshing strategy, I manage to keep the elements up-to-date.

Each property is supposed to be displayed in a different layer on the map, so that the user can show or hide whatever finds or not necessary. There are a names' layer, a temperatures' layer, a dewpoints' layer and so on.

The way to create two of these layers can be presented at the last lines of the following code:

var wgs84 = new OpenLayers.Projection("EPSG:4326");
var mercator = new OpenLayers.Projection("EPSG:900913");

var myURL="http://localhost:8080/wxproj/wx-json.php";

var clustering = new OpenLayers.Strategy.Cluster({distance:40});
var refreshing = new OpenLayers.Strategy.Refresh({interval:1000});

var clusters = new OpenLayers.Layer.Vector("LIGHTNINGS", { 
    strategies: [clustering, refreshing, new OpenLayers.Strategy.Fixed()],
    styleMap: myLightningStyles,
    protocol: new OpenLayers.Protocol.HTTP({
        url: myURL,
        format: new OpenLayers.Format.GeoJSON({
            'internalProjection': mercator,
            'externalProjection' : wgs84 }),
        async: false
        })
    });

var stations = new OpenLayers.Layer.Vector("STATIONS", { 
    strategies: [new OpenLayers.Strategy.Fixed()],
    styleMap: myStationStyles,
    protocol: new OpenLayers.Protocol.HTTP({
        url: myURL,
        format: new OpenLayers.Format.GeoJSON({
            'internalProjection': mercator,
            'externalProjection' : wgs84 }),
        async: false
        })
    });

 map.addLayers([clusters, stations]);

The obvious drawback is that I have to call the same file "wx-json.php" several times, one for each layer, getting in almost all cases the same GeoJSON-formatted result exactly. While it is sufficient to call it once, every time needed, and then distribute the properties (and its values) to the layers (and their features, accordingly).

One thought about bypassing this result, is appending parameters to the URL, so that I get the GeoJSON-formatted features with one property at each call:

var myURL="http://localhost:8080/wxproj/wx-json.php?property=station";
var stations = new OpenLayers.Layer.Vector("STATIONS", { ... });

var myURL="http://localhost:8080/wxproj/wx-json.php?property=lightnings";
var clusters = new OpenLayers.Layer.Vector("LIGHTNINGS", { ... });

But I find it also consuming.

Is there any more efficient way to get the GeoJSON data only once and then create the layers with features according to each property?

Edit: I found a similar question that restates my own demand, that is a single GeoJSON file backing multiple Vector Layers. But, there is no code to understand how this is being done.


Well, it has been a month without some answer, so I suppose my question needs some refrase:

What I really need with OL is filling a number of overlay layers with features by reading once (in a period) a GeoJSON file.

I get each half-an-hour a different GeoJSON file, which corresponds to a lot of point features, each with a pair of coordinates and some properties. For each one of the properties, I create one overlay layer in OpenLayers. Essentially, there are the same points in all layers, but a different property is hightlighted for every layer.

The way I went so far, was reading the same GeoJSON file as many times as many are the layers. This way has been expressed in the first block of code above, at my first question one month ago: Each layer manages to get its own features reading for itself from the PHP file, which produces a GeoJSON format output.

However, this way is not desirable, because of the too many independent calls to the webserver, while the layers display essentially the same thing; what's more, if the PHP file changes its output in the meantime of layers' reading, the displayed result is prone to confusion.

My question is therefore about another way of loading my features. I want to read once, in a period say half-an-hour, the GeoJSON (output from the PHP) and get all my layers filled from this.

Best Answer

I finally managed to do my JSON call once and then fill all my necessary layers. Here are the basic aspects in code:

var wgs84 = new OpenLayers.Projection("EPSG:4326");
var mercator = new OpenLayers.Projection("EPSG:900913"); 
function init() {
  function Incorporate_Data(r) { /* Function inside init() */
     var x=r.priv.responseText;
     var arr=[ stations, temperatures, visibility, clouds ]; /* ARRAY OF MAP LAYERS TO BE FILLED */
     var j=new OpenLayers.Format.GeoJSON({'internalProjection':mercator,'externalProjection':wgs84});
     for(i in arr) {
        arr[i].destroyFeatures();
        arr[i].addFeatures(j.read(x));
        }
     }
/* define mapoptions here */
var map=new OpenLayers.Map(mapoptions);
/* define some base layer here */
var mainstyle=new OpenLayers.Style();
/* define mainstyle and more styles here */
var myStyles=new OpenLayers.Stylemap({"default":mainstyle});
/* define more stylemaps here */
var temperatures=new OpenLayers.Layer.Vector("TEMPERATURES", styleMap: tempStyles, renderers: ["Canvas"]});
/* define more of the layers here (such as visibility and clouds) */

var stations=new OpenLayers.Layer.Vector("STATIONS", {
   strategies: [
      new OpenLayers.Strategy.Refresh({interval:30000}),
      new OpenLayers.Strategy.BBOX(),
      new OpenLayers.Strategy.Fixed()], stylemap:myStyles,
      protocol: new OpenLayers.Protocol.HTTP({
         url: "http://localhost:8080/wxproj/wx-json.php",
         format: new OpenLayers.Format.GeoJSON({'internalProjection':mercator,'externalProjection':wgs84}),
         async:true,
         handleResponse: Incorporate_Data}),
      renderers: ["Canvas"]});

map.addLayers([baselayer, stations, temperature, visibility, clouds]);
map.setCenter(center,zoom);
}//init()

Although I think that there can be more efficient code, I hope that this works fine. I want to answer if it possible to keep the Incorporate_Data() function out of the init() function, and if the strategies for stations can be reduced. Any comments welcome.