开发者

How to process layer templates using mapscript to respond to a WMS GetFeatureInfo request

I'm trying to handle GetFeaturInfo WMS requests using c# mapscript. Prior to using mapscript our software passed WMS requests through to a CGI mapserver hosted on IIS. This processed a html template associated with each queried layer and substituted a number of tokens within the template for data.

We cannot use the mapserver cgi implementation so I'm attempting to reimplement this mechanism using mapscript via the C# mapscript mechanism.

The summary of the code I have so far is here. The problem with this is that the call to processQueryTemplate causes an AccessViolation Exception to be thrown.

public string GetFeatureInfoFromWMS(NameValueCollection WMSqueryString)
{
    //Set the projection library environment variable used by mapscript.dll
    Environment.SetEnvironmentVariable("PROJ_LIB", ProjectionLibraryPath);

    string output = string.Empty;

    try
    {
        using (mapObj map = new mapObj(MapFile))
        {
            //Add aditional layer specific params - ie location of plugins etc
            ProcessLayers(map, WMSqueryString);

            map.web.metadata.set("wms_onlineresource", WMSOnlineResourceURL);

            string xVal = WMSqueryString["X"];
            string yVal = WMSqueryString["Y"];

            if (xVal == null || yVal == null)
            {
                throw new ArgumentNullException("The X or Y point value has not been suppplied in the GetFeatureInfo request");
            }

            double pointX = 0.0;
            double pointY = 0.0;

            try 
            {           
                pointX = Convert.ToDouble(xVal);
                pointY = Convert.ToDouble(yVal);
            }
            catch (Exception e)
            {
                throw new ArgumentException("The X or Y point value supplied in the GetFeatureInfo request is not a valid decimal",e);
            }

            string layersQS = WMSqueryString["QUERY_LAYERS"];

            if (layersQS == null)
            {
                throw new ArgumentNullException("The QUERY_LAYERS parameter of the WMS GetFeatureInfo request is not specified correctly");
            }

            //Load the parameters from the wms request into the map
            using (OWSRequest request = new OWSRequest())
            {
                for (int i = 0; i < WMSqueryString.Count; i++)
                {
                    request.setParameter(WMSqueryString.GetKey(i), WMSqueryString.Get(i));
                }

                string wmsVersion = WMSqueryString["VERSION"];

                if (wmsVersion == null || wmsVersion == string.Empty) wmsVersion = DEFAULT_WMS_VERSION;

                map.loadOWSParameters(request, wmsVersion);
            }

            //Reproject X & Y pixel co-ordinates in map co-ordintes.
            double minX = map.extent.minx;
            double maxX = map.extent.maxx;
            double geoX = minX + ((pointX / (double)map.widt开发者_StackOverflowh) * (maxX - minX));

            double minY = map.extent.miny;
            double maxY = map.extent.maxy;
            double geoY = maxY - ((pointY / (double)map.height) * (maxY - minY));

            string[] queryLayers = layersQS.Split(',');

            using (pointObj point = new pointObj(geoX, geoY, 0, 0))
            {
                foreach (string layerName in queryLayers)
                {
                    using (layerObj layer = map.getLayerByName(layerName))
                    {
                        int queryResult = layer.queryByPoint(map, point, (int)MS_QUERY_MODE.MS_QUERY_SINGLE, -1);
                    }
                }
            }

            map.prepareQuery();

            string[] names = { "Token1" };
            string[] values = { "Value1" };

            //BANG!!!!!!
            output = map.processQueryTemplate(names, values, 10);
        }
        return output;
    }
    catch (Exception ex)
    {
        throw;
    }
}

The associated map file is as follows:

    MAP

#
# Start of map file
#
NAME esdm
STATUS ON
TEMPLATEPATTERN "."
SIZE 400 600
UNITS meters
EXTENT 0 0 800000 1200000

IMAGECOLOR 255 255 255
FONTSET fonts.txt
#DEBUG ON
IMAGETYPE PNG

  PROJECTION
        "init=epsg:27700"
  END


    OUTPUTFORMAT
        NAME "png"
        DRIVER "GD/PNG"
        IMAGEMODE RGBA
        MIMETYPE image/png
        EXTENSION png
        TRANSPARENT ON
    END

#  OUTPUTFORMAT
#    NAME "imagemap"
#    MIMETYPE text/html; driver=imagemap
#    DRIVER "imagemap"
#  END 



#
# Start of web interface definition (including WMS enabling metadata)
#
WEB

    METADATA
        "wms_title" "SQL mapping data"
        "wms_srs"  "EPSG:27700 EPSG:4326 EPSG:54004 EPSG:54005 EPSG:900913"
        "wms_feature_info_mime_type" "text/plain"
        "wms_include_items" "all"
    END
END

INCLUDE "mapSymbols.inc"

# BARSActions Point Layer
#-----------------------------------------------------------------------------------------
LAYER
  NAME "Actions"
MAXSCALEDENOM 100000000
MINSCALEDENOM 0
  METADATA        
    "wms_title"  "BARSActions"
    "wfs_title"  "BARSActions"
    "wms_srs"  "EPSG:27700"
  END
  CONNECTIONTYPE PLUGIN
  PLUGIN "SQLPlugin" 
  DATA "geom from MapLoadTest USING UNIQUE ActionId USING SRID=27700"
  FILTER "(OrgUnitId = 1 AND %ActionStatusID% AND %ActionTypeID% AND %AreaIDST(geom)%)"

  TYPE POINT
  STATUS ON
  TOLERANCE 50
  TEMPLATE "barsTemplate.htm"

  CLASS
    COLOR 0 0 255 
    OUTLINECOLOR 0 0 0
    SYMBOL 'star'
    SIZE 15
    #MAXSIZE 6
    #MINSIZE 3
  END # end of class object

  PROJECTION
        "init=epsg:27700"
  END
  DUMP True
END # end of layer object


# BARSActions Polygon Layer
#-----------------------------------------------------------------------------------------
LAYER
  NAME "ActionsPolygons"

MAXSCALEDENOM 100000000
MINSCALEDENOM 0
  METADATA        
    "wms_title"  "BARSActionsPolygons"
    "wfs_title"  "BARSActionsPolygons"
    "wms_srs"  "EPSG:27700"
  END
  CONNECTIONTYPE PLUGIN
  PLUGIN "SQLPlugin"
  DATA "geom from MapLoadTest USING UNIQUE ActionId USING SRID=27700"
  FILTER "(OrgUnitId = 2 AND ActionID = 200 AND %ActionStatusID% AND %ActionTypeID% AND %AreaIDST(geom)%)"

  TYPE POLYGON
  STATUS ON
  TOLERANCE 50
  TEMPLATE "barsTemplate.htm"

  CLASS
    COLOR 0 0 255 
    OUTLINECOLOR 0 0 0
  END # end of class object

  PROJECTION
        "init=epsg:27700"
  END
  DUMP True
END # end of layer object

END # Map File

Various items in the map file are tokenised (ie the sql plugin location and the filters applied to the data) This is handled by the call to ProcessLayers in the previous method. This mechanism doesn't appear to cause any problems when drawing maps. The call to queryByPoint works. It returns a success and the query run against the sql db returns expected data.

I'm unsure where to proceed from here and what else needs to be done to produce the output from the templates. I was expecting the call to processQueryTemplate to return the populated templetes. I also don't quite know what prepareQuery is supposed to do.

Cheers


Never figured out how to get the templates to work. However I managed to get the database ID's of the shapes returned by the query. I then use these to prepare the HTML result elsewhere.

Note that I'm using map.querybypoint to deal with situations where there are layer groups (in which case the layergroup name will come across as the layer name in the wms request.

/// <summary>
/// Handles a GetFeature info request and returns matching ActionID's.
/// </summary>
/// <param name="WMSqueryString">The WM squery string.</param>
/// <returns>A list of matching action ID's.</returns>
/// <exception cref="ArgumentNullException">Thrown if the X or Y point values are not supplied in the WMS GetFeatureInfo request</exception>
/// <exception cref="ArgumentException">Thrown in the X or Y point values supplied in the WMS GetFeatureInfo request cannot be converted to valid doubles</exception>
public List<int> GetFeatureInfoActionID(NameValueCollection WMSqueryString)
{
    //Set the projection library environment variable used by mapscript.dll
    Environment.SetEnvironmentVariable("PROJ_LIB", ProjectionLibraryPath);

    try
    {
        List<int> resultsList = new List<int>();

        using (mapObj map = new mapObj(MapFile))
        {
            ProcessLayers(map, WMSqueryString);

            map.web.metadata.set("wms_onlineresource", WMSOnlineResourceURL);

            //Load the parameters from the wms request into the map
            using (OWSRequest request = new OWSRequest())
            {
                for (int i = 0; i < WMSqueryString.Count; i++)
                {
                    request.setParameter(WMSqueryString.GetKey(i), WMSqueryString.Get(i));
                }

                string wmsVersion = WMSqueryString["VERSION"];

                if (wmsVersion == null || wmsVersion == string.Empty) wmsVersion = DEFAULT_WMS_VERSION;

                map.loadOWSParameters(request, wmsVersion);
            }

            string xVal = WMSqueryString["X"];
            string yVal = WMSqueryString["Y"];

            if (xVal == null || yVal == null)
            {
                throw new ArgumentNullException("The X or Y point value has not been suppplied in the GetFeatureInfo request");
            }

            double pointX = 0.0;
            double pointY = 0.0;

            try 
            {            
                pointX = Convert.ToDouble(xVal);
                pointY = Convert.ToDouble(yVal);
            }
            catch (Exception e)
            {
                throw new ArgumentException("The X or Y point value supplied in the GetFeatureInfo request is not a valid decimal",e);
            }

            //Reproject X & Y pixel co-ordinates in map co-ordintes.
            double minX = map.extent.minx;
            double maxX = map.extent.maxx;
            double geoX = minX + ((pointX / (double)map.width) * (maxX - minX));

            double minY = map.extent.miny;
            double maxY = map.extent.maxy;
            double geoY = maxY - ((pointY / (double)map.height) * (maxY - minY));

            MS_RETURN_VALUE queryResult;

            using (pointObj point = new pointObj(geoX, geoY, 0, 0))
            {
                queryResult = (MS_RETURN_VALUE)map.queryByPoint(point, (int)MS_QUERY_MODE.MS_QUERY_MULTIPLE, -1);
            }

            if (queryResult != MS_RETURN_VALUE.MS_SUCCESS)
            {
                return null;
            }

            map.prepareQuery();

            for (int layerIndex = 0; layerIndex < map.numlayers; layerIndex++)
            {
                using (layerObj layer = map.getLayer(layerIndex))
                {
                    int resultCount = layer.getNumResults();
                    if (resultCount > 0)
                    {
                        layer.open();

                        for (int resultIndex = 0; resultIndex < resultCount; resultIndex++)
                        {
                            using (resultCacheMemberObj resultCache = layer.getResult(resultIndex))
                            {
                                int actionID = resultCache.shapeindex;
                                if (actionID != 0 && resultsList.Contains(actionID) == false)
                                {
                                    resultsList.Add(actionID);
                                }
                            }
                        }

                        layer.close();
                    }
                }
            }

        }
        return resultsList;
    }
    catch (Exception ex)
    {
        throw;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜