2011-02-18 2 views
2

C# mapscript를 사용하여 GetFeaturInfo WMS 요청을 처리하려고합니다. mapscript를 사용하기 전에 우리 소프트웨어는 WMS 요청을 IIS에서 호스팅되는 CGI 맵 서버로 전달했습니다. 이렇게하면 각 쿼리 된 레이어와 연결된 html 템플릿이 처리되고 데이터 템플릿의 여러 토큰이 대체됩니다.mapscript를 사용하여 레이어 템플릿을 처리하여 WMS GetFeatureInfo 요청에 응답하는 방법

mapserver cgi 구현을 사용할 수 없으므로 mapscript를 사용하여이 메커니즘을 C# mapscript 메커니즘을 통해 다시 구현하려고합니다.

내가 지금까지 가지고있는 코드의 요약은 여기에 있습니다. 문제는 processQueryTemplate을 호출하면 AccessViolation Exception이 발생한다는 것입니다. 다음

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 

각종 항목 tokenised된다 (즉, SQL 플러그인 위치 데이터에 적용되는 필터)이 콜에 의해 처리 이전 방법에서 ProcessLayers로. 이 메커니즘은지도를 그릴 때 아무런 문제가없는 것처럼 보입니다. queryByPoint에 대한 호출이 작동합니다. 성공을 리턴하고 sql db에 대해 실행 된 조회는 예상 데이터를 리턴합니다.

여기서부터 진행해야 할 곳과 템플릿에서 출력물을 생성하기 위해 수행해야 할 작업이 무엇인지 확신 할 수 없습니다. populated templetes를 반환하기 위해 processQueryTemplate에 대한 호출을 기다리고있었습니다. 나는 또한 prepareQuery가 무엇을 해야하는지에 대해 잘 모릅니다.

건배

답변

1

서식 파일을 작동시키는 방법을 알지 못했습니다. 그러나 쿼리에서 반환 된 도형의 데이터베이스 ID를 가져올 수있었습니다. 그런 다음 이들을 사용하여 HTML 결과를 다른 곳에서 준비합니다. 내가 레이어 그룹합니다 (layergroup 이름이 WMS 요청에서 레이어 이름으로 건너되는 경우가있는 상황에 대처하기 위해 map.querybypoint을 사용하고

주.

/// <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; 
    } 
} 
관련 문제