Drawing selected features in Mapserver with mapscript

For those of you who are using Mapserver, you may have noticed a somewhat "weird" behaviour when drawing selected features that have been defined with combined symbols (multiple styles within the same class).
Let me explain: When you define multiple styles for a class in a layer in the mapfile and then you select/highlight the feature using mapscript, the highlight color only seems to apply to the last style used and not the whole (combined) symbol. For example if you got a class defined for a point layer as :

CLASS
STYLE
COLOR 138 138 138
SYMBOL 'triangle'
SIZE 15
END
STYLE
COLOR 255 0 0
SYMBOL "point"
SIZE 5
END
END

and where the "triangle" and "point" symbols are defined as:

SYMBOL
NAME "triangle"
TYPE VECTOR
POINTS
0 1
0.5 0
1 1
0 1
END
FILLED TRUE
STYLE
1 25 1 25
END
END
SYMBOL
NAME "point"
TYPE ELLIPSE
POINTS
1 1
END
FILLED TRUE
END

only the "Point" symbol will be drawn in the highlight color instead of both symbols. Since the last symbol is usually the smallest size, its not even visible the end user what has been highlighted. This also applies for line and polygon features. The situation is even worst for point features that are only defined with a bitmap image only. In these cases the highlight feature is not even getting drawn. This has been raised as Ticket #3190 with the mapserver team and is scheduled for the 6.0 release of Mapserver.

In the meantime though I have found an alternative way to highlight features, which gives much greater flexibility in defining and drawing selections. Basically, I am ignoring the QUERYMAP settings and dont use the mapObj.DrawQuery() method. Instead I define my own "selection" layers, one for each feature type (point, line, polygon) in the mapfile. Then, once I got a handle on the the selected recordset, I loop through it and draw the selected features one by one based on the corresponding "selection layer" using the shapeObj.draw() function. There is probably a performance hit doing this but so far I haven’t noticed it  even with largish (100’s of features) selections.

So how is this implemented? First I define my selection layers as:

# ———————————————————-
#    SELECTION LAYERS
# ———————————————————-
#
# Layer to draw line selections
LAYER
        NAME "selectedline"
        STATUS ON
        TYPE LINE
  TRANSPARENCY ALPHA
        TEMPLATE nofile.html
        CLASS
            STYLE
    COLOR 16 238 246
    OUTLINECOLOR 255 0 0
    WIDTH 5
   END
        END
END
# Layer to draw point selections
  LAYER
        NAME "selectedpoint"
        STATUS ON
        TYPE POINT
  TRANSPARENCY ALPHA
        TEMPLATE nofile.html
        CLASS
   SYMBOL "point"
   COLOR 16 238 246
   SIZE 10
        END
END
# Layer to draw polygon selections
LAYER
        NAME "selectedpoly"
        STATUS ON
        TYPE POLYGON
  TOLERANCE 10
        TRANSPARENCY ALPHA
        TEMPLATE nofile.html
        CLASS
   COLOR 16 238 246
     END
END

The code (in mapscript C#) to draw the selected features is:

//Draw the map to get a handle on the imageObj
imageObj image=aMapObj.draw();
layerObj active_layer = aMapObj.getLayer(active_layer_index);
//Open the layer
active_layer.open();
//Get the selection
resultCacheObj results = active_layer.getResults();
//Loop through selection and draw each feature
for (int iResultsNo = 0; iResultsNo < results.numresults; iResultsNo++)
{
int shapeInd = results.getResult(iResultsNo).shapeindex;
shapeObj shape = active_layer.getFeature(shapeInd, -1);
if (shape.type == (int)MS_SHAPE_TYPE.MS_SHAPE_POINT)
{ shape.draw(aMapObj, aMapObj.getLayerByName("selectedpoint"), image); }
else if (shape.type == (int)MS_SHAPE_TYPE.MS_SHAPE_LINE)
{ shape.draw(aMapObj, aMapObj.getLayerByName("selectedline"), image); }
else if (shape.type == (int)MS_SHAPE_TYPE.MS_SHAPE_POLYGON)
{ shape.draw(aMapObj, aMapObj.getLayerByName("selectedpoly"), image); }
}

where active_layer_index is the layer index in the mapfile.

Obviously, you can experiment with CLASS element in the the selection layers and create much more interesting effects when drawing the selections.
Hope this will help someone!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s