[mapguide-commits] r5400 - in trunk/MgDev/Web/src: . HttpHandler

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Nov 23 21:40:39 EST 2010


Author: liuar
Date: 2010-11-23 18:40:39 -0800 (Tue, 23 Nov 2010)
New Revision: 5400

Modified:
   trunk/MgDev/Web/src/HttpHandler/HttpWmsGetFeatureInfo.cpp
   trunk/MgDev/Web/src/HttpHandler/HttpWmsGetMap.cpp
   trunk/MgDev/Web/src/HttpHandler/Makefile.am
   trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp
   trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.h
   trunk/MgDev/Web/src/WebTier.sln
Log:
Ticket #1520 Bounding Box value doesn't affect the view of WMS Server

If a request contains a BBox whose area does not overlap at all with the <BoundingBox> element in the service metadata for the requested layer, the server shall return empty content (that is, a blank map or an graphic elemenet file with no elements) for that map. Any features that are partly or entirely contained in the Bounding Box shall be returned in the appropriate format. 

According to OGC WMS specification, MapGuide should apply a spatial filter on the request layers. Features out of the <Boundingbox> which specified by users should not appear on the WMS layer. 

This might bring MapGuide some performace issues, so I also optimized the process: if the request boundingbox within the user specified boundingbox, no spatial filter will be applied. 

In order to apply spatial filter on wms layers, I created wms layers in session repository and updated their layer definitions. 




Modified: trunk/MgDev/Web/src/HttpHandler/HttpWmsGetFeatureInfo.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpWmsGetFeatureInfo.cpp	2010-11-23 10:06:48 UTC (rev 5399)
+++ trunk/MgDev/Web/src/HttpHandler/HttpWmsGetFeatureInfo.cpp	2010-11-24 02:40:39 UTC (rev 5400)
@@ -187,9 +187,17 @@
     {
         // Get an instance of the resource service
         Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
+        // Get an instance of the feature service
+        Ptr<MgFeatureService> featureService = (MgFeatureService*)CreateService(MgServiceType::FeatureService);
 
+        // Create session
+        Ptr<MgUserInformation> userInfo = m_siteConn->GetUserInfo();
+        Ptr<MgSite> site = m_siteConn->GetSite();
+        STRING session = site->CreateSession();
+        userInfo->SetMgSessionId(session);
+
         // Get an MgMap object corresponding to the request params
-        Ptr<MgMap> map = MgWmsMapUtil::GetMap(*wmsServer, m_layerDefIds, m_bbox, m_crs, m_width, m_height, resourceService);
+        Ptr<MgMap> map = MgWmsMapUtil::GetMap(*wmsServer, m_layerDefIds, m_bbox, m_crs, m_width, m_height, resourceService, featureService, session);
 
         // Create Rendering Service instance
         Ptr<MgRenderingService> service = (MgRenderingService*)(CreateService(MgServiceType::RenderingService));

Modified: trunk/MgDev/Web/src/HttpHandler/HttpWmsGetMap.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpWmsGetMap.cpp	2010-11-23 10:06:48 UTC (rev 5399)
+++ trunk/MgDev/Web/src/HttpHandler/HttpWmsGetMap.cpp	2010-11-24 02:40:39 UTC (rev 5400)
@@ -163,6 +163,8 @@
         {
             // Get an instance of the resource service
             Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
+            // Get an instance of the resource service
+            Ptr<MgFeatureService> featureService = (MgFeatureService*)CreateService(MgServiceType::FeatureService);
 
             // Get the background color
             Ptr<MgColor> bkColor = MgWmsMapUtil::GetBackgroundColor(m_bgColor, m_transparent);
@@ -170,10 +172,15 @@
             // Get the extents
             Ptr<MgEnvelope> extents = MgWmsMapUtil::GetExtents(m_bbox);
 
-            
+            // Create session
+            Ptr<MgUserInformation> userInfo = m_siteConn->GetUserInfo();
+            Ptr<MgSite> site = m_siteConn->GetSite();
+            STRING session = site->CreateSession();
+            userInfo->SetMgSessionId(session);
+
             // Get a map object corresponding to the request parameters
             Ptr<MgMap> map = MgWmsMapUtil::GetMap(wms, m_layerDefIds, m_bbox, m_crs,
-                m_width, m_height, resourceService);
+                m_width, m_height, resourceService, featureService, session);
             map->SetWatermarkUsage(MgMap::WMS);
 
             // Get the image format

Modified: trunk/MgDev/Web/src/HttpHandler/Makefile.am
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/Makefile.am	2010-11-23 10:06:48 UTC (rev 5399)
+++ trunk/MgDev/Web/src/HttpHandler/Makefile.am	2010-11-24 02:40:39 UTC (rev 5400)
@@ -282,11 +282,15 @@
     -lMgGeometry \
     -lMgPlatformBase \
     -lMgMapGuideCommon \
-    -llib_json
+    -llib_json \
+    -lMdfModel \
+    -lMdfParser
 
 libMgHttpHandler_la_LDFLAGS = -release $(PACKAGE_VERSION) \
     -L../../../Common/Foundation \
     -L../../../Common/Geometry \
     -L../../../Common/PlatformBase \
     -L../../../Common/MapGuideCommon \
-    -L../../../Oem/jsoncpp/lib
+    -L../../../Oem/jsoncpp/lib \
+    -L../../../Common/MdfModel \
+    -L../../../Common/MdfParser

Modified: trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp	2010-11-23 10:06:48 UTC (rev 5399)
+++ trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp	2010-11-24 02:40:39 UTC (rev 5400)
@@ -17,6 +17,9 @@
 
 #include "HttpHandler.h"
 #include "WmsMapUtil.h"
+#include "VectorLayerDefinition.h"
+#include "GridLayerDefinition.h"
+#include "../../../Common/MdfParser/SAX2Parser.h"
 
 //static map<STRING, STRING> srsMappings;
 //static bool InitializeSrsMappings();
@@ -103,7 +106,7 @@
 /// </returns>
 MgMap* MgWmsMapUtil::GetMap(MgOgcWmsServer& oWms,
     MgStringCollection* layerDefIds, CREFSTRING bbox, CREFSTRING sSRS,
-    INT32 width, INT32 height, MgResourceService* resourceService)
+    INT32 width, INT32 height, MgResourceService* resourceService, MgFeatureService* featureService, CREFSTRING sSession)
 {
     // Get the requested map extents
     Ptr<MgEnvelope> extents = GetExtents(bbox);
@@ -124,6 +127,7 @@
     double scale = realWorldWidthMeters / imageWidthMeters;
     map->SetViewScale(scale);
 
+    Ptr<MgWmsLayerDefinitions> layerDefs = MgHttpWmsGetCapabilities::GetLayerDefinitions(*resourceService, layerDefIds);
     // Add the requested layers
     if (NULL != layerDefIds && layerDefIds->GetCount() > 0)
     {
@@ -133,11 +137,139 @@
         {
             Ptr<MgResourceIdentifier> resId = new MgResourceIdentifier(layerDefIds->GetItem(i));
             Ptr<MgLayer> mgLayer = new MgLayer(resId, resourceService);
+            
+            STRING layerPath = resId->GetPathname(true);
+            Ptr<MgResourceIdentifier> wmsLayerResId = new MgResourceIdentifier(L"Session:"+ sSession + L"//" + layerPath);
 
-            mgLayer->SetName(resId->GetPathname(false));
-            mapLayers->Add(mgLayer);
-            mgLayer->SetSelectable(true);
-            mgLayer->ForceRefresh();
+            // OGC 06-042 section 7.3.3.6
+            // If a request contains a BBox whose area does not overlap at all with the <BoundingBox> element in the 
+            // service metadata for the requested layer, the server shall return empty content (that is, a blank map 
+            // or an graphic elemenet file with no elements) for that map. Any features that are partly or entirely 
+            // contained in the Bounding Box shall be returned in the appropriate format
+            if(layerDefs->Next())
+            {
+                // Get user defined boundingbox 
+                MgUtilDictionary currentDef(NULL);
+                layerDefs->GenerateDefinitions(currentDef);
+                STRING layerBounds = currentDef[L"Layer.Bounds"];
+                Ptr<MgStringCollection> wmsLayerBoundingbox = GetWMSlayerBoundingbox(sSRS, layerBounds);
+                STRING sMinX, sMinY, sMaxX, sMaxY;
+               
+                ASSERT(4 == wmsLayerBoundingbox->GetCount());
+                if(4 == wmsLayerBoundingbox->GetCount())
+                {
+                    sMinX = wmsLayerBoundingbox->GetItem(0);
+                    sMinY = wmsLayerBoundingbox->GetItem(1);
+                    sMaxX = wmsLayerBoundingbox->GetItem(2);
+                    sMaxY = wmsLayerBoundingbox->GetItem(3);
+                }
+                else
+                {
+                    sMinX = L"0";
+                    sMinY = L"0";
+                    sMaxX = L"0";
+                    sMaxY = L"0";
+                }
+
+                Ptr<MgCoordinate> lowerLeftCoord = extents->GetLowerLeftCoordinate();
+                Ptr<MgCoordinate> upperRightCoord = extents->GetUpperRightCoordinate();
+                double mapMinX = lowerLeftCoord->GetX();
+                double mapMinY = lowerLeftCoord->GetY();
+                double mapMaxX = upperRightCoord->GetX();
+                double mapMaxY = upperRightCoord->GetX();
+
+                // Optimization...
+                // If the request boundingbox (map boundingbox) within the user defined boundingbox (wms layer boundingbox),
+                // spatial query on the layer should be ignored. Just reuse the original layer's layer definition
+                if(mapMinX >= MgUtil::StringToDouble(sMinX) && mapMinY >= MgUtil::StringToDouble(sMinY)
+                    && mapMaxX <= MgUtil::StringToDouble(sMaxX) && mapMaxY <= MgUtil::StringToDouble(sMaxY))
+                {
+                    wmsLayerResId = resId;
+                }
+                else
+                {
+                    // Get layer definition from the original layer
+                    auto_ptr<MdfModel::LayerDefinition> layerDef;
+                    layerDef.reset(mgLayer->GetLayerDefinition(resourceService,resId));
+                    MdfModel::VectorLayerDefinition* vl = dynamic_cast<MdfModel::VectorLayerDefinition*>(layerDef.get());
+                    MdfModel::GridLayerDefinition* gl = dynamic_cast<MdfModel::GridLayerDefinition*>(layerDef.get());
+
+                    // Spatial filter
+                    STRING filter;
+
+                    // Vector Layer
+                    if(NULL != vl)
+                    {
+                        filter = vl->GetFilter();
+                    }
+                    // Grid Layer
+                    if(NULL != gl)
+                    {
+                        filter = gl->GetFilter();
+                    }
+
+                    
+                    Ptr<MgResourceIdentifier> fsId = new MgResourceIdentifier(mgLayer->GetFeatureSourceId());
+                    STRING qualifiedName = mgLayer->GetFeatureClassName();
+
+                    int pos = qualifiedName.find(L":");
+                    STRING schemaName = qualifiedName.substr(0,pos);
+                    STRING className = qualifiedName.substr(pos+1,qualifiedName.length()-pos-1);
+
+                    Ptr<MgClassDefinition> classDef = featureService->GetClassDefinition(fsId,schemaName,className);
+                    Ptr<MgPropertyDefinitionCollection> propDefCol = classDef->GetProperties();
+
+                    // filter on every geometric properties
+                    for(int i =0; i<propDefCol->GetCount(); i++)
+                    {
+                        Ptr<MgPropertyDefinition> prop = propDefCol->GetItem(i);
+                        if(prop->GetPropertyType() == MgFeaturePropertyType::GeometricProperty)
+                        {
+                            STRING propName = prop->GetName();
+                            
+                            STRING boundingboxGeom = L"GeomFromText('POLYGON((" 
+                                                        + sMinX + L" " + sMinY + L","
+                                                        + sMaxX + L" " + sMinY + L","
+                                                        + sMaxX + L" " + sMaxY + L","
+                                                        + sMinX + L" " + sMaxY + L","
+                                                        + sMinX + L" " + sMinY + L"))')";
+                            if(filter.empty())
+                            {
+                                filter = L"( " + propName + L" ENVELOPEINTERSECTS " + boundingboxGeom + L" )";
+                            }
+                            else
+                            {
+                                filter += L" AND ( " + propName + L" ENVELOPEINTERSECTS " + boundingboxGeom + L" )";
+                            }
+                        }
+                    }
+
+                     // Vector Layer
+                    if(NULL != vl)
+                    {
+                        vl->SetFilter(filter);
+                    }
+                    // Grid Layer
+                    if(NULL != gl)
+                    {
+                        gl->SetFilter(filter);
+                    }
+
+                    MdfParser::SAX2Parser parser;
+                    std::string content = parser.SerializeToXML(layerDef.get(), NULL);
+
+                    Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)content.c_str(), (INT32)content.length());
+                    Ptr<MgByteReader> byteReader = byteSource->GetReader();
+
+                    resourceService->SetResource(wmsLayerResId,byteReader,NULL);
+                }
+            }
+
+            Ptr<MgLayer> mgWmsLayer = new MgLayer(wmsLayerResId, resourceService);
+            mgWmsLayer->SetName(resId->GetPathname(false));
+            mapLayers->Add(mgWmsLayer);
+            mgWmsLayer->SetSelectable(true);
+            mgWmsLayer->ForceRefresh();
         }
     }
 
@@ -329,3 +461,56 @@
     sSRS = MgUtil::ToUpper(sSRS);
     sSRS = MgUtil::ReplaceString(sSRS,L"URN:OGC:DEF:CRS:EPSG:",L"EPSG");
 }
+
+MgStringCollection* MgWmsMapUtil::GetWMSlayerBoundingbox(STRING sSrs, STRING layerBounds)
+{
+    // return value which specified the boundingbox of user defined boundingbox
+    Ptr<MgStringCollection> wmsLayerBoundingbox = new MgStringCollection();
+
+    // Looking for all <Bounds> elements from layerBounds
+    // Example: <Bounds SRS="EPSG:4326" west="-87.74" south="43.68" east="-87.69" north="43.815"/>
+    Ptr<MgStringCollection> bounds = new MgStringCollection();
+    int pos = 0;
+    while(layerBounds.find(L"<Bounds",pos) != STRING::npos)
+    {
+        pos += 7; // pos+7 to the first character after <Bounds
+        int endPos = layerBounds.find(L"/>",pos); 
+        bounds->Add(layerBounds.substr(pos,endPos-pos));
+    }
+
+    // Looking for the boundingbox defined with specified SRS
+    for(int i = 0; i<bounds->GetCount(); i++)
+    {
+        STRING bound = bounds->GetItem(i);
+
+        //Find SRS value from Bounds element 
+        int startPos = bound.find(L"SRS=\"");
+        int endPos = bound.find(L"\"",startPos+5); // pos+5 to the first character after SRS="
+        STRING srs = bound.substr(startPos+5,endPos-startPos-5);
+
+        if(MgUtil::ToUpper(srs) == MgUtil::ToUpper(sSrs))
+        {
+            //Find west value from Bounds element 
+            startPos = bound.find(L"west=\"");
+            endPos = bound.find(L"\"",startPos+6); // pos+6 to the first character after west="
+            wmsLayerBoundingbox->Add(bound.substr(startPos+6,endPos-startPos-6));
+
+            //Find south value from Bounds element 
+            startPos = bound.find(L"south=\"");
+            endPos = bound.find(L"\"",startPos+7); // pos+7 to the first character after south="
+            wmsLayerBoundingbox->Add(bound.substr(startPos+7,endPos-startPos-7));
+
+            //Find east value from Bounds element 
+            startPos = bound.find(L"east=\"");
+            endPos = bound.find(L"\"",startPos+6); // pos+6 to the first character after east="
+            wmsLayerBoundingbox->Add(bound.substr(startPos+6,endPos-startPos-6));
+
+            //Find north value from Bounds element 
+            startPos = bound.find(L"north=\"");
+            endPos = bound.find(L"\"",startPos+7); // pos+7 to the first character after north="
+            wmsLayerBoundingbox->Add(bound.substr(startPos+7,endPos-startPos-7));
+        }
+    }
+
+    return wmsLayerBoundingbox.Detach();
+}

Modified: trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.h
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.h	2010-11-23 10:06:48 UTC (rev 5399)
+++ trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.h	2010-11-24 02:40:39 UTC (rev 5400)
@@ -28,7 +28,7 @@
 
     static MgMap* GetMap(MgOgcWmsServer& wms,
         MgStringCollection* layerDefIds, CREFSTRING bbox, CREFSTRING sSRS,
-        INT32 width, INT32 height, MgResourceService* resourceService);
+        INT32 width, INT32 height, MgResourceService* resourceService, MgFeatureService* featureService, CREFSTRING sSession);
 
     static MgEnvelope* GetExtents(CREFSTRING bbox);
 
@@ -49,6 +49,8 @@
     static void ReverseCoords(double& coord1, double& coord2);
     // Help method to convert URN SRS(urn:ogc:def:crs:EPSG::4326) to EPSG SRS (EPSG:4326)
     static void ProcessURNSrs(REFSTRING sSRS);
+    // Help method to get user defined WMS boundingbox with particular SRS
+    static MgStringCollection* GetWMSlayerBoundingbox(STRING sSrs, STRING layerBounds);
 };
 
 #endif  // _FS_WMS_MAP_UTIL_H

Modified: trunk/MgDev/Web/src/WebTier.sln
===================================================================
--- trunk/MgDev/Web/src/WebTier.sln	2010-11-23 10:06:48 UTC (rev 5399)
+++ trunk/MgDev/Web/src/WebTier.sln	2010-11-24 02:40:39 UTC (rev 5400)
@@ -50,9 +50,11 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpHandler", "HttpHandler\HttpHandler.vcproj", "{78619D0E-D3F9-4DDF-B90E-F99CB03DFC44}"
 	ProjectSection(ProjectDependencies) = postProject
 		{F7334B1B-0EFA-47E3-8E66-DF158E61B7E4} = {F7334B1B-0EFA-47E3-8E66-DF158E61B7E4}
+		{85882748-DD71-4D2B-9E5A-03AF8C8D91B7} = {85882748-DD71-4D2B-9E5A-03AF8C8D91B7}
 		{A82ADC7D-4DA4-42F2-9BF6-DF5DCFB44425} = {A82ADC7D-4DA4-42F2-9BF6-DF5DCFB44425}
 		{5287A594-4D4F-43FE-A281-E279AB708CF1} = {5287A594-4D4F-43FE-A281-E279AB708CF1}
 		{D954DAAC-E305-40CE-B3F3-C229A0BEF4F0} = {D954DAAC-E305-40CE-B3F3-C229A0BEF4F0}
+		{C50254F2-654A-48DE-AF5B-20605AEF8D10} = {C50254F2-654A-48DE-AF5B-20605AEF8D10}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebApp", "WebApp\WebApp.vcproj", "{B797917B-6842-467C-8B14-E00B76A91247}"



More information about the mapguide-commits mailing list