2011-02-18 60 views
2

我正在嘗試使用c#mapscript處理GetFeaturInfo WMS請求。在使用mapscript之前,我們的軟件將WMS請求傳遞給IIS上承載的CGI地圖服務器。這處理了與每個查詢圖層相關的html模板,並在模板中用數據代替了一些令牌。如何使用mapscript處理圖層模板以響應WMS GetFeatureInfo請求

我們不能使用mapserver cgi實現,所以我試圖通過C#mapscript機制使用mapscript來重新實現此機制。

我到目前爲止的代碼摘要就在這裏。問題在於,調用processQueryTemplate會導致引發AccessViolation異常。

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.width) * (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; 
    } 
} 

相關聯的映射文件如下:

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 

在地圖文件的各個項目標記化(即,SQL插件的位置和施加到該數據的過濾器)這是由呼叫處理到先前方法中的ProcessLayers。這種機制在繪製地圖時似乎不會造成任何問題。對queryByPoint的調用起作用。它將返回成功,並且針對sql數據庫運行的查詢將返回預期數據。

我不確定從哪裏開始從這裏開始,還需要做什麼才能生成模板的輸出。我期待着調用processQueryTemplate來返回填充的模板。我也不太清楚prepareQuery應該做什麼。

乾杯

回答

1

從來沒有想出如何讓模板工作。不過,我設法得到查詢返回的形狀的數據庫ID。然後,我使用這些來在其他地方準備HTML結果。

請注意,我使用map.querybypoint對付那裏有層組(在這種情況下,圖層組的名稱會遇到如WMS請求圖層名稱的情況。

/// <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; 
    } 
}