[mapguide-commits] r7492 - sandbox/jng/createruntimemap/Web/src/HttpHandler

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon May 13 05:29:10 PDT 2013


Author: jng
Date: 2013-05-13 05:29:10 -0700 (Mon, 13 May 2013)
New Revision: 7492

Modified:
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h
Log:
This submission contains the following changes:
 - Render layer icons inline if the icons request mask (2) is set. An optional ICONSPERSCALERANGE request parameter can be used to control how many inline icons per scale range to render (default is 25). If a scale range exceeds this number of rules, only icons the first and last rules are rendered inline, with every rule in between left blank. This mimics the "compressed" theme behaviour we currently have in the AJAX and Fusion viewers. Each rule contains enough information for the client application to defer load the missing icons via GETLEGENDIMAGE mapagent requests if required.

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp	2013-05-12 17:47:03 UTC (rev 7491)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp	2013-05-13 12:29:10 UTC (rev 7492)
@@ -18,6 +18,10 @@
 #include "HttpHandler.h"
 #include "HttpCreateRuntimeMap.h"
 #include "VectorLayerDefinition.h"
+#include "PointTypeStyle.h"
+#include "AreaTypeStyle.h"
+#include "LineTypeStyle.h"
+#include "CompositeTypeStyle.h"
 
 #define REQUEST_LAYER_STRUCTURE         1 /* Request layer and group structure */
 #define REQUEST_LAYER_ICONS             2 /* Request layer scale and icon information */
@@ -47,6 +51,11 @@
     else
         m_requestDataMask = MgUtil::StringToInt32(mask);
     m_iconLimitPerScaleRange = 25;
+    STRING sIconsPerScaleRange = params->GetParameterValue(MgHttpResourceStrings::reqMappingIconsPerScaleRange);
+    if (!sIconsPerScaleRange.empty())
+    {
+        m_iconLimitPerScaleRange = MgUtil::StringToInt32(sIconsPerScaleRange);
+    }
 }
 
 /// <summary>
@@ -85,6 +94,7 @@
     MG_HTTP_HANDLER_TRY()
 
     Ptr<MgMap> map = new MgMap();
+    Ptr<MgMappingService> mappingService = (MgMappingService*)CreateService(MgServiceType::MappingService);
     Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
 
     // Create a new session id if we don't have one
@@ -183,7 +193,6 @@
         //Build our LayerDefinition map for code below that requires it
         if ((m_requestDataMask & REQUEST_LAYER_ICONS) == REQUEST_LAYER_ICONS)
         {
-            Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
             Ptr<MgStringCollection> layerIds = new MgStringCollection();
             Ptr<MgLayerCollection> layers = map->GetLayers();
             for (INT32 i = 0; i < layers->GetCount(); i++)
@@ -248,14 +257,14 @@
         {
             STRING groupName = (*it);
             Ptr<MgLayerGroup> group = groups->GetItem(groupName);
-            CreateGroupItem(group, xml, layers, groups, layerDefinitionMap);
+            CreateGroupItem(mappingService, group, xml, layers, groups, layerDefinitionMap);
         }
 
         for (LayerNameList::iterator it = m_topLevelLayers.begin(); it != m_topLevelLayers.end(); it++)
         {
             STRING layerName = (*it);
             Ptr<MgLayerBase> layer = layers->GetItem(layerName);
-            CreateLayerItem(layer, xml, layers, layerDefinitionMap);
+            CreateLayerItem(mappingService, layer, xml, layers, layerDefinitionMap);
         }
     }
     xml.append("</RuntimeMap>");
@@ -277,7 +286,7 @@
     return byteReader.Detach();
 }
 
-void MgHttpCreateRuntimeMap::CreateGroupItem(MgLayerGroup* group, std::string& xml, MgLayerCollection* layers, MgLayerGroupCollection* groups, const LayerDefinitionMap& layerDefMap)
+void MgHttpCreateRuntimeMap::CreateGroupItem(MgMappingService* mappingService, MgLayerGroup* group, std::string& xml, MgLayerCollection* layers, MgLayerGroupCollection* groups, const LayerDefinitionMap& layerDefMap)
 {
     MG_HTTP_HANDLER_TRY()
 
@@ -287,7 +296,7 @@
     xml.append(MgUtil::WideCharToMultiByte(groupName));
     xml.append("</Name>\n");
     xml.append("<LegendLabel>");
-    xml.append(MgUtil::WideCharToMultiByte(group->GetLegendLabel()));
+    xml.append(MgUtil::WideCharToMultiByte(MgUtil::ReplaceEscapeCharInXml(group->GetLegendLabel())));
     xml.append("</LegendLabel>\n");
     xml.append("<ObjectId>");
     xml.append(MgUtil::WideCharToMultiByte(group->GetObjectId()));
@@ -314,7 +323,7 @@
             //Yes, we're using recursion. Stack overflow would probably only happen
             //if we have a map with several thousand level deep group hierarchy. So
             //for all intents and purposes: We're safe.
-            CreateGroupItem(childGroup, xml, layers, groups, layerDefMap);
+            CreateGroupItem(mappingService, childGroup, xml, layers, groups, layerDefMap);
         }
     }
     if (m_layerParentMap.find(groupName) != m_layerParentMap.end())
@@ -324,7 +333,7 @@
         {
             STRING childLayerName = (*it);
             Ptr<MgLayerBase> childLayer = layers->GetItem(childLayerName);
-            CreateLayerItem(childLayer, xml, layers, layerDefMap);
+            CreateLayerItem(mappingService, childLayer, xml, layers, layerDefMap);
         }
     }
     xml.append("</Group>");
@@ -332,7 +341,7 @@
     MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpCreateRuntimeMap.CreateGroupItem")
 }
 
-void MgHttpCreateRuntimeMap::CreateLayerItem(MgLayerBase* layer, std::string& xml, MgLayerCollection* layers, const LayerDefinitionMap& layerDefMap)
+void MgHttpCreateRuntimeMap::CreateLayerItem(MgMappingService* mappingService, MgLayerBase* layer, std::string& xml, MgLayerCollection* layers, const LayerDefinitionMap& layerDefMap)
 {
     MG_HTTP_HANDLER_TRY()
 
@@ -351,7 +360,7 @@
     xml.append(MgUtil::WideCharToMultiByte(layer->GetName()));
     xml.append("</Name>\n");
     xml.append("<LegendLabel>");
-    xml.append(MgUtil::WideCharToMultiByte(layer->GetLegendLabel()));
+    xml.append(MgUtil::WideCharToMultiByte(MgUtil::ReplaceEscapeCharInXml(layer->GetLegendLabel())));
     xml.append("</LegendLabel>\n");
     xml.append("<ObjectId>");
     xml.append(MgUtil::WideCharToMultiByte(layer->GetObjectId()));
@@ -406,6 +415,104 @@
                     MgUtil::DoubleToString(vsr->GetMaxScale(), sMaxScale);
                     xml.append(sMaxScale);
                     xml.append("</MaxScale>\n");
+
+                    double dScale = (vsr->GetMaxScale() + vsr->GetMinScale()) / 2.0;
+                    MdfModel::FeatureTypeStyleCollection* ftsc = vsr->GetFeatureTypeStyles();
+
+                    INT32 nIconCount = 0;
+                    for (INT32 j = 0; j < ftsc->GetCount(); j++)
+                    {
+                        MdfModel::FeatureTypeStyle* fts = ftsc->GetAt(j);
+                        if (fts->IsShowInLegend())
+                        {
+                            MdfModel::RuleCollection* rules = fts->GetRules();
+                            nIconCount += rules->GetCount();
+                        }
+                    }
+
+                    //This theme will be compressed if we're over the specified limit for this scale range
+                    bool bCompress = (nIconCount > m_iconLimitPerScaleRange);
+
+                    for (INT32 j = 0; j < ftsc->GetCount(); j++)
+                    {
+                        MdfModel::FeatureTypeStyle* fts = ftsc->GetAt(j);
+                        if (!fts->IsShowInLegend())
+                            continue;
+
+                        MdfModel::PointTypeStyle*       pts = dynamic_cast<MdfModel::PointTypeStyle*>(fts);
+                        MdfModel::LineTypeStyle*        lts = dynamic_cast<MdfModel::LineTypeStyle*>(fts);
+                        MdfModel::AreaTypeStyle*        ats = dynamic_cast<MdfModel::AreaTypeStyle*>(fts);
+                        MdfModel::CompositeTypeStyle*   cts = dynamic_cast<MdfModel::CompositeTypeStyle*>(fts);
+                        
+                        INT32 geomType = 0;
+                        if (pts)
+                            geomType = 1;
+                        else if (lts)
+                            geomType = 2;
+                        else if (ats)
+                            geomType = 3;
+                        else if (cts)
+                            geomType = 4;
+                        INT32 catIndex = 0;
+
+                        MdfModel::RuleCollection* rules = fts->GetRules();
+                        for (INT32 r = 0; r < rules->GetCount(); r++)
+                        {
+                            MdfModel::Rule* rule = rules->GetAt(r);
+                            bool bRequestIcon = false;
+                            if (!bCompress)
+                            {
+                                bRequestIcon = true;
+                            }
+                            else //This is a compressed theme
+                            {
+                                bRequestIcon = (r == 0 || r == rules->GetCount() - 1); //Only first and last rule
+                            }
+
+                            xml.append("<Rule>\n");
+                            //GeometryType and ThemeCategory are required so that deferred icon requests can be made
+                            //back to the mapagent, especially if we exceed the icons-per-scale-range limit
+                            xml.append("<GeometryType>");
+                            std::string sGeomType;
+                            MgUtil::Int32ToString(geomType, sGeomType);
+                            xml.append(sGeomType);
+                            xml.append("</GeometryType>\n");
+                            xml.append("<ThemeCategory>");
+                            std::string sThemeCat;
+                            MgUtil::Int32ToString(catIndex, sThemeCat);
+                            xml.append(sThemeCat);
+                            xml.append("</ThemeCategory>\n");
+                            xml.append("<LegendLabel>");
+                            xml.append(MgUtil::WideCharToMultiByte(MgUtil::ReplaceEscapeCharInXml(rule->GetLegendLabel())));
+                            xml.append("</LegendLabel>\n");
+                            xml.append("<Filter>");
+                            xml.append(MgUtil::WideCharToMultiByte(MgUtil::ReplaceEscapeCharInXml(rule->GetFilter())));
+                            xml.append("</Filter>\n");
+                            if (bRequestIcon)
+                            {
+                                xml.append("<Icon>");
+                                //TODO: We should have a batched form of this API
+                                Ptr<MgByteReader> iconReader = mappingService->GenerateLegendImage(layerDefId, dScale, 16, 16, MgImageFormats::Png, geomType, catIndex);
+                                xml.append("<MimeType>");
+                                //BUG? No mime type in the MgByteReader
+                                xml.append(MgUtil::WideCharToMultiByte(MgMimeType::Png));
+                                //xml.append(MgUtil::WideCharToMultiByte(iconReader->GetMimeType()));
+                                xml.append("</MimeType>\n");
+                                xml.append("<Content>");
+                                Ptr<MgByteSink> sink = new MgByteSink(iconReader);
+                                Ptr<MgByte> bytes = sink->ToBuffer();
+                                Ptr<MgMemoryStreamHelper> streamHelper = new MgMemoryStreamHelper((INT8*) bytes->Bytes(), bytes->GetLength(), false);
+                                std::string b64 = streamHelper->ToBase64();
+                                xml.append(b64);
+                                xml.append("</Content>\n");
+                                xml.append("</Icon>");
+                            }
+                            xml.append("</Rule>\n");
+
+                            catIndex++;
+                        }
+                    }
+
                     xml.append("</ScaleRange>\n");
                 }
             }

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h	2013-05-12 17:47:03 UTC (rev 7491)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h	2013-05-13 12:29:10 UTC (rev 7492)
@@ -66,8 +66,8 @@
 
 private:
     MgByteReader* BuildRuntimeMapXml(MgResourceIdentifier* mdfId, CREFSTRING mapName);
-    void CreateGroupItem(MgLayerGroup* group, std::string& xml, MgLayerCollection* layers, MgLayerGroupCollection* groups, const LayerDefinitionMap& layerDefMap);
-    void CreateLayerItem(MgLayerBase* layer, std::string& xml, MgLayerCollection* layers, const LayerDefinitionMap& layerDefMap);
+    void CreateGroupItem(MgMappingService* mappingService, MgLayerGroup* group, std::string& xml, MgLayerCollection* layers, MgLayerGroupCollection* groups, const LayerDefinitionMap& layerDefMap);
+    void CreateLayerItem(MgMappingService* mappingService, MgLayerBase* layer, std::string& xml, MgLayerCollection* layers, const LayerDefinitionMap& layerDefMap);
 
     STRING m_mapDefinition;
     INT32 m_requestDataMask;

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp	2013-05-12 17:47:03 UTC (rev 7491)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp	2013-05-13 12:29:10 UTC (rev 7492)
@@ -218,6 +218,7 @@
 const STRING MgHttpResourceStrings::reqMappingType = L"TYPE";
 const STRING MgHttpResourceStrings::reqMappingThemeCategory = L"THEMECATEGORY";
 const STRING MgHttpResourceStrings::reqMappingRequestedFeatures = L"REQUESTEDFEATURES";
+const STRING MgHttpResourceStrings::reqMappingIconsPerScaleRange = L"ICONSPERSCALERANGE";
 
 // Predefined Rendering Service Request Parameters
 const STRING MgHttpResourceStrings::reqRenderingMapDefinition = L"MAPDEFINITION";

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h	2013-05-12 17:47:03 UTC (rev 7491)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h	2013-05-13 12:29:10 UTC (rev 7492)
@@ -154,6 +154,7 @@
     static const STRING reqMappingType;
     static const STRING reqMappingThemeCategory;
     static const STRING reqMappingRequestedFeatures;
+    static const STRING reqMappingIconsPerScaleRange;
 
     // PREDEFINED RENDERING REQUEST PARAMETERS
     static const STRING reqRenderingMapDefinition;



More information about the mapguide-commits mailing list