[GIS] how to display polygons as points until certain zoom level

openlayers-2style

can somebody tell me how to display polygons as points until you zoom to some level. I'm speaking about OpenLayers.
So, for example, if the zoom level is less then 10 than it should display feature as a point and when you zoom to 10 or further it should display it as polygon with the shape it really has.

I've tried something like this:

var my_style = new OpenLayers.Style({
'fillColor': '#9900cc',
'fillOpacity': .8,
'strokeColor': '#330066',
'strokeWidth': 1,
'pointRadius': 4
});
var vector_style_map = new OpenLayers.StyleMap({
'default': my_style
});

map.events.register("zoomend", map, function () {
    if (map.getZoom() < 10) {
        console.log("zoom level is less then 10");
        layer.styleMap = vector_style_map;
    }
});

But it just paint my polygon with defined colors, it doesn't change the shape to point.
I'm probably missing something obvious but I would appreciate if you could help me.
Thanks

Best Answer

Openlayers displays the geometry that you provide to it. Therefore, if you provide a polygon, it is going to display a polygon no matter what scale you are zoomed to.

The way to get around this is to create a point layer that is created based on the centroid of your polygon. You can then modify the maxScale and minScale properties of the layers to turn off the Polygon layer when your zoom level is less than 10, and set the style for the Point layer to turn on when the zoom level is less than 10.

This code sample sets the zoom levels then adds two separate layers. The min/max Scale match the Scale levels set on the Map object.

map = new OpenLayers.Map(
    {
        allOverlays: false,
        projection: "EPSG:4269",
        maxExtent: bounds,
        scales:[600000,500000,400000,300000,200000,100000,50000,25000,20000,15000,10000,5000],        
        units: 'm'
    });

testpoints = new OpenLayers.Layer.Vector("WFS",
    {
        strategies : [new OpenLayers.Strategy.BBOX()],
        protocol : new OpenLayers.Protocol.WFS
            ({
                url : "test_url",
                featureType : "test:test_point",
                featureNS : "test_ns/test"
            }),
         maxScale:250000,
         minScale:15000
     });

testpoly = new OpenLayers.Layer.Vector("WFS",
    {
        strategies : [new OpenLayers.Strategy.BBOX()],
        protocol : new OpenLayers.Protocol.WFS
            ({
                url : "test_url",
                featureType : "test:test_poly",
                featureNS : "test_ns/test"
            }),
        maxScale:10000
    });

map.addLayer([testpoly,testpoint]);

This is possible to do on the fly assuming you are feeding your data from a spatial database like PostGIS. You would set up a view that is based off the ST_Centroid function, referencing your Polygon layer, and pulling whichever of the attributes you want. The benefit to this is that it is dynamic. As you update your polygon layer, this will update as well. Hat Tip to the OpenLayers forum for the idea: Display Point from Polygon

Here is sample SQL to create the view. You would modify to include your desired attribute fields in the view so you could access them through OpenLayers.

create view poly_centroid as select attribute1, attribute2, attribute3,
  st_centroid(ST_Transform(geom,4269))::geometry(point, 4269) as geom from poly_table;

Since I don't know what your existing projection is, I included a Transform to reproject your data to ` in the view.

On the other hand, if you are not using a spatial database, but instead are using shapefiles or other formats, you can do the same by using a different method to create a new layer of centroids for your polygons. You would have to ensure that an update method was in place so that they stayed in sync with your polygons.