[mapguide-commits] r7929 - in trunk/MgDev/Server/src: Services/Mapping UnitTesting

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Nov 25 22:36:14 PST 2013


Author: jng
Date: 2013-11-25 22:36:14 -0800 (Mon, 25 Nov 2013)
New Revision: 7929

Modified:
   trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.cpp
   trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.h
   trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp
   trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h
Log:
#2380: Update MgLegendPlotUtil to skip over empty layer groups (including children) when rendering a legend. This will reduce clutter if rendering a legend for a map that has lots of visible groups that have no visible layers in them. Previously, such empty groups are included. With this submission, such groups are omitted from the final image.

Includes unit tests to exercise such cases.

Modified: trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.cpp	2013-11-25 14:41:19 UTC (rev 7928)
+++ trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.cpp	2013-11-26 06:36:14 UTC (rev 7929)
@@ -184,12 +184,54 @@
     //for icon and label from the bottom up
     y -= legendSpacing * convertUnits;
 
+    // Compile the necessary information needed to avoid repeated linear searches for this information
+    LayerGroupChildMap groupChildren;
+    VisibleLayerCountMap visibleLayers;
+    CompileInformation(map, visibleLayers, groupChildren);
+
     // Add legend entries for layers that do not belong to a group
-    ProcessLayersForLegend(map, scale, NULL, x, y, textDef, dr, legendSpec, legendOffsetY, convertUnits);
+    ProcessLayersForLegend(map, scale, NULL, x, y, textDef, dr, legendSpec, legendOffsetY, convertUnits, visibleLayers, groupChildren);
 }
 
+void MgLegendPlotUtil::CompileInformation(MgMap* map, VisibleLayerCountMap& visibleLayers, LayerGroupChildMap& groupChildren)
+{
+    Ptr<MgLayerCollection> layers = map->GetLayers();
+    Ptr<MgLayerGroupCollection> groups = map->GetLayerGroups();
 
-void MgLegendPlotUtil::ProcessLayersForLegend(MgMap* map, double mapScale, MgLayerGroup* mggroup, double startX, double& startY, RS_TextDef textDef, Renderer& dr, MgPlotSpecification* legendSpec, double legendOffsetY, double convertUnits)
+    for (INT32 i = 0; i < layers->GetCount(); i++)
+    {
+        Ptr<MgLayerBase> layer = layers->GetItem(i);
+        if (!layer->IsVisible()) //Not visible
+            continue;
+
+        Ptr<MgLayerGroup> parentGroup = layer->GetGroup();
+        if (NULL == parentGroup.p) //No parent
+            continue;
+
+        STRING parentGroupName = parentGroup->GetName();
+        VisibleLayerCountMap::iterator vit = visibleLayers.find(parentGroupName);
+        if (vit == visibleLayers.end())
+            visibleLayers[parentGroupName] = 0;
+        visibleLayers[parentGroupName]++;
+    }
+
+    for (INT32 i = 0; i < groups->GetCount(); i++)
+    {
+        Ptr<MgLayerGroup> group = groups->GetItem(i);
+        Ptr<MgLayerGroup> parentGroup = group->GetGroup();
+        if (NULL != parentGroup.p)
+        {
+            STRING groupName = group->GetName();
+            STRING parentGroupName = parentGroup->GetName();
+            LayerGroupChildMap::iterator cit = groupChildren.find(parentGroupName);
+            if (cit == groupChildren.end())
+                groupChildren[parentGroupName] = LayerGroupList();
+            groupChildren[parentGroupName].push_back(groupName);
+        }
+    }
+}
+
+void MgLegendPlotUtil::ProcessLayersForLegend(MgMap* map, double mapScale, MgLayerGroup* mggroup, double startX, double& startY, RS_TextDef textDef, Renderer& dr, MgPlotSpecification* legendSpec, double legendOffsetY, double convertUnits, VisibleLayerCountMap& visibleLayers, LayerGroupChildMap& groupChildren)
 {
     double x;
     double &y = startY;
@@ -464,7 +506,11 @@
         Ptr<MgLayerGroup> groupParent = group->GetGroup();
         if (groupParent.p == mggroup)
         {
-            ProcessLayersForLegend(map, mapScale, group, startX + initialMarginX, y, textDef, dr, legendSpec, legendOffsetY, convertUnits);
+            //If this group has no visible layers, skip it
+            if (!HasVisibleLayers(group->GetName(), visibleLayers, groupChildren))
+                continue;
+
+            ProcessLayersForLegend(map, mapScale, group, startX + initialMarginX, y, textDef, dr, legendSpec, legendOffsetY, convertUnits, visibleLayers, groupChildren);
             if (y < bottomLimit)
             {
                 break;
@@ -473,7 +519,28 @@
     }
 }
 
+bool MgLegendPlotUtil::HasVisibleLayers(CREFSTRING groupName, VisibleLayerCountMap& visibleLayers, LayerGroupChildMap& groupChildren)
+{
+    INT32 total = 0;
+    VisibleLayerCountMap::iterator vit = visibleLayers.find(groupName);
+    if (vit != visibleLayers.end())
+    {
+        if (vit->second > 0)
+            return true;
+    }
 
+    LayerGroupChildMap::iterator cit = groupChildren.find(groupName);
+    if (cit != groupChildren.end())
+    {
+        for (LayerGroupList::iterator lit = cit->second.begin(); lit != cit->second.end(); lit++)
+        {
+            if (HasVisibleLayers(*lit, visibleLayers, groupChildren))
+                return true;
+        }
+    }
+    return false;
+}
+
 //
 //  Compute the legend size and the offset position on the page
 //

Modified: trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.h
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.h	2013-11-25 14:41:19 UTC (rev 7928)
+++ trunk/MgDev/Server/src/Services/Mapping/LegendPlotUtil.h	2013-11-26 06:36:14 UTC (rev 7929)
@@ -20,6 +20,10 @@
 
 class EPlotRenderer;
 
+typedef std::vector<STRING> LayerGroupList;
+typedef std::map<STRING, LayerGroupList> LayerGroupChildMap;
+typedef std::map<STRING, int> VisibleLayerCountMap;
+
 class MG_SERVER_MAPPING_API MgLegendPlotUtil
 {
 public:
@@ -42,12 +46,14 @@
     //Eventually the scale bar and north arrow ones need to be cleaned up also in order
     //to use them in the AJAX viewer
     void AddLegendElement(double dMapScale, Renderer& dr, MgMap* map, MgPlotSpecification* plotSpec, double legendOffsetX, double legendOffsetY);
-    void ProcessLayersForLegend(MgMap* map, double mapScale, MgLayerGroup* mggroup, double startX, double& startY, RS_TextDef textDef, Renderer& dr, MgPlotSpecification* plotSpec, double legendOffsetY, double convertUnits);
+    void ProcessLayersForLegend(MgMap* map, double mapScale, MgLayerGroup* mggroup, double startX, double& startY, RS_TextDef textDef, Renderer& dr, MgPlotSpecification* plotSpec, double legendOffsetY, double convertUnits, VisibleLayerCountMap& visibleLayers, LayerGroupChildMap& groupChildren);
     void BuildLegendContent(MgMap* map, double scale, MgPlotSpecification* legendSpec, double legendOffsetX, double legendOffsetY, Renderer& dr, double convertUnits);
 
     void ExtentFromMapCenter(MgMap* map, double metersPerUnit, RS_Bounds& b);
+    void CompileInformation(MgMap* map, VisibleLayerCountMap& visibleLayers, LayerGroupChildMap& groupChildren);
 
 private:
+    static bool HasVisibleLayers(CREFSTRING groupName, VisibleLayerCountMap& visibleLayers, LayerGroupChildMap& groupChildren);
 
     MgResourceService* m_svcResource;
     RS_String m_legendFontName;

Modified: trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp	2013-11-25 14:41:19 UTC (rev 7928)
+++ trunk/MgDev/Server/src/UnitTesting/TestRenderingService.cpp	2013-11-26 06:36:14 UTC (rev 7929)
@@ -814,6 +814,58 @@
     }
 }
 
+void TestRenderingService::TestCase_RenderLegendEmptyGroups(CREFSTRING imageFormat, CREFSTRING extension)
+{
+    try
+    {
+        // make a runtime map
+        Ptr<MgMap> map = CreateTestMap();
+        map->SetViewScale(75000.0);
+        Ptr<MgColor> bgc = new MgColor(255, 255, 255, 255);
+
+        // Set up the following structure
+        //
+        // EmptyGroup1
+        // EmptyGroup2
+        //    EmptyGroup3
+        //
+        // None of these should be visible when we render the legend
+
+        Ptr<MgLayerGroupCollection> groups = map->GetLayerGroups();
+        Ptr<MgLayerGroup> group1 = new MgLayerGroup(L"EmptyGroup1");
+        group1->SetLegendLabel(L"EmptyGroup1");
+        Ptr<MgLayerGroup> group2 = new MgLayerGroup(L"EmptyGroup2");
+        group2->SetLegendLabel(L"EmptyGroup2");
+        Ptr<MgLayerGroup> group3 = new MgLayerGroup(L"EmptyGroup3");
+        group3->SetLegendLabel(L"EmptyGroup3");
+
+        group1->SetDisplayInLegend(true);
+        group2->SetDisplayInLegend(true);
+        group3->SetDisplayInLegend(true);
+
+        groups->Add(group1);
+        groups->Add(group2);
+        groups->Add(group3);
+        group3->SetGroup(group2);
+
+        map->Save();
+
+        // Call the API
+        Ptr<MgByteReader> rdr3 = m_svcRendering->RenderMapLegend(map, 200, 400, bgc, imageFormat);
+        rdr3->ToFile(GetPath(L"../UnitTestFiles/RenderLegendEmptyGroups", imageFormat, extension));
+    }
+    catch (MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch (...)
+    {
+        throw;
+    }
+}
+
 void TestRenderingService::TestCase_StylizationFunctions(CREFSTRING imageFormat, CREFSTRING extension)
 {
     try

Modified: trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h	2013-11-25 14:41:19 UTC (rev 7928)
+++ trunk/MgDev/Server/src/UnitTesting/TestRenderingService.h	2013-11-26 06:36:14 UTC (rev 7929)
@@ -42,6 +42,7 @@
     CPPUNIT_TEST(TestCase_RenderMapPNG);
     CPPUNIT_TEST(TestCase_RenderMapWithWatermarkPNG);
     CPPUNIT_TEST(TestCase_RenderLegendPNG);
+    CPPUNIT_TEST(TestCase_RenderLegendEmptyGroupsPNG);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSPNG);
     CPPUNIT_TEST(TestCase_RenderLegendMultiCTSPNG);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSWithThemePNG);
@@ -51,7 +52,7 @@
 
     CPPUNIT_TEST(TestCase_StylizationFunctionsPNG8);
 
-	CPPUNIT_TEST(TestCase_SymbologyPointsPNG8);
+    CPPUNIT_TEST(TestCase_SymbologyPointsPNG8);
     CPPUNIT_TEST(TestCase_SymbologyPointsParamPNG8);
     CPPUNIT_TEST(TestCase_SymbologyLinesPNG8);
     CPPUNIT_TEST(TestCase_SymbologyLinesCrossTickPNG8);
@@ -66,6 +67,7 @@
     CPPUNIT_TEST(TestCase_RenderMapPNG8);
     CPPUNIT_TEST(TestCase_RenderMapWithWatermarkPNG8);
     CPPUNIT_TEST(TestCase_RenderLegendPNG8);
+    CPPUNIT_TEST(TestCase_RenderLegendEmptyGroupsPNG8);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSPNG8);
     CPPUNIT_TEST(TestCase_RenderLegendMultiCTSPNG8);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSWithThemePNG8);
@@ -75,7 +77,7 @@
 
     CPPUNIT_TEST(TestCase_StylizationFunctionsGIF);
 
-	CPPUNIT_TEST(TestCase_SymbologyPointsGIF);
+    CPPUNIT_TEST(TestCase_SymbologyPointsGIF);
     CPPUNIT_TEST(TestCase_SymbologyPointsParamGIF);
     CPPUNIT_TEST(TestCase_SymbologyLinesGIF);
     CPPUNIT_TEST(TestCase_SymbologyLinesCrossTickGIF);
@@ -90,6 +92,7 @@
     CPPUNIT_TEST(TestCase_RenderMapGIF);
     CPPUNIT_TEST(TestCase_RenderMapWithWatermarkGIF);
     CPPUNIT_TEST(TestCase_RenderLegendGIF);
+    CPPUNIT_TEST(TestCase_RenderLegendEmptyGroupsGIF);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSGIF);
     CPPUNIT_TEST(TestCase_RenderLegendMultiCTSGIF);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSWithThemeGIF);
@@ -99,7 +102,7 @@
 
     CPPUNIT_TEST(TestCase_StylizationFunctionsJPG);
 
-	CPPUNIT_TEST(TestCase_SymbologyPointsJPG);
+    CPPUNIT_TEST(TestCase_SymbologyPointsJPG);
     CPPUNIT_TEST(TestCase_SymbologyPointsParamJPG);
     CPPUNIT_TEST(TestCase_SymbologyLinesJPG);
     CPPUNIT_TEST(TestCase_SymbologyLinesCrossTickJPG);
@@ -114,6 +117,7 @@
     CPPUNIT_TEST(TestCase_RenderMapJPG);
     CPPUNIT_TEST(TestCase_RenderMapWithWatermarkJPG);
     CPPUNIT_TEST(TestCase_RenderLegendJPG);
+    CPPUNIT_TEST(TestCase_RenderLegendEmptyGroupsJPG);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSJPG);
     CPPUNIT_TEST(TestCase_RenderLegendMultiCTSJPG);
     CPPUNIT_TEST(TestCase_RenderLegendMultiFTSWithThemeJPG);
@@ -137,14 +141,15 @@
     void TestStart();
     void TestEnd();
 
-	void TestCase_QueryFeatures();
+    void TestCase_QueryFeatures();
 
-	//Parameterized versions that all format-specific tests call into
+    //Parameterized versions that all format-specific tests call into
     void TestCase_RenderDynamicOverlay(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderDynamicOverlayTiledMap(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderMap(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderMapWithWatermark(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderLegend(CREFSTRING imageFormat, CREFSTRING extension);
+    void TestCase_RenderLegendEmptyGroups(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderLegendMultiFTS(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderLegendMultiCTS(CREFSTRING imageFormat, CREFSTRING extension);
     void TestCase_RenderLegendMultiFTSWithTheme(CREFSTRING imageFormat, CREFSTRING extension);
@@ -164,12 +169,13 @@
 
     void TestCase_StylizationFunctions(CREFSTRING imageFormat, CREFSTRING extension);
 
-	//PNG output tests
-	void TestCase_RenderDynamicOverlayPNG() { TestCase_RenderDynamicOverlay(L"PNG", L"png"); }
+    //PNG output tests
+    void TestCase_RenderDynamicOverlayPNG() { TestCase_RenderDynamicOverlay(L"PNG", L"png"); }
     void TestCase_RenderDynamicOverlayTiledMapPNG() { TestCase_RenderDynamicOverlayTiledMap(L"PNG", L"png"); }
     void TestCase_RenderMapPNG() { TestCase_RenderMap(L"PNG", L"png"); }
     void TestCase_RenderMapWithWatermarkPNG() { TestCase_RenderMapWithWatermark(L"PNG", L"png"); }
     void TestCase_RenderLegendPNG() { TestCase_RenderLegend(L"PNG", L"png"); }
+    void TestCase_RenderLegendEmptyGroupsPNG() { TestCase_RenderLegendEmptyGroups(L"PNG", L"png"); }
     void TestCase_SymbologyPointsPNG() { TestCase_SymbologyPoints(L"PNG", L"png"); }
     void TestCase_SymbologyPointsParamPNG() { TestCase_SymbologyPointsParam(L"PNG", L"png"); }
     void TestCase_SymbologyLinesPNG() { TestCase_SymbologyLines(L"PNG", L"png"); }
@@ -186,12 +192,13 @@
     void TestCase_RenderLegendSingleFTSMultiCTSPNG() { TestCase_RenderLegendSingleFTSMultiCTS(L"PNG", L"png"); }
     void TestCase_StylizationFunctionsPNG() { TestCase_StylizationFunctions(L"PNG", L"png"); }
 
-	//PNG8 output tests
-	void TestCase_RenderDynamicOverlayPNG8() { TestCase_RenderDynamicOverlay(L"PNG8", L"png"); }
+    //PNG8 output tests
+    void TestCase_RenderDynamicOverlayPNG8() { TestCase_RenderDynamicOverlay(L"PNG8", L"png"); }
     void TestCase_RenderDynamicOverlayTiledMapPNG8() { TestCase_RenderDynamicOverlayTiledMap(L"PNG8", L"png"); }
     void TestCase_RenderMapPNG8() { TestCase_RenderMap(L"PNG8", L"png"); }
     void TestCase_RenderMapWithWatermarkPNG8() { TestCase_RenderMapWithWatermark(L"PNG8", L"png"); }
     void TestCase_RenderLegendPNG8() { TestCase_RenderLegend(L"PNG8", L"png"); }
+    void TestCase_RenderLegendEmptyGroupsPNG8() { TestCase_RenderLegendEmptyGroups(L"PNG8", L"png"); }
     void TestCase_SymbologyPointsPNG8() { TestCase_SymbologyPoints(L"PNG8", L"png"); }
     void TestCase_SymbologyPointsParamPNG8() { TestCase_SymbologyPointsParam(L"PNG8", L"png"); }
     void TestCase_SymbologyLinesPNG8() { TestCase_SymbologyLines(L"PNG8", L"png"); }
@@ -208,12 +215,13 @@
     void TestCase_RenderLegendSingleFTSMultiCTSPNG8() { TestCase_RenderLegendSingleFTSMultiCTS(L"PNG8", L"png"); }
     void TestCase_StylizationFunctionsPNG8() { TestCase_StylizationFunctions(L"PNG8", L"png"); }
 
-	//GIF output tests
-	void TestCase_RenderDynamicOverlayGIF() { TestCase_RenderDynamicOverlay(L"GIF", L"gif"); }
+    //GIF output tests
+    void TestCase_RenderDynamicOverlayGIF() { TestCase_RenderDynamicOverlay(L"GIF", L"gif"); }
     void TestCase_RenderDynamicOverlayTiledMapGIF() { TestCase_RenderDynamicOverlayTiledMap(L"GIF", L"gif"); }
     void TestCase_RenderMapGIF() { TestCase_RenderMap(L"GIF", L"gif"); }
     void TestCase_RenderMapWithWatermarkGIF() { TestCase_RenderMapWithWatermark(L"GIF", L"gif"); }
     void TestCase_RenderLegendGIF() { TestCase_RenderLegend(L"GIF", L"gif"); }
+    void TestCase_RenderLegendEmptyGroupsGIF() { TestCase_RenderLegendEmptyGroups(L"GIF", L"gif"); }
     void TestCase_SymbologyPointsGIF() { TestCase_SymbologyPoints(L"GIF", L"gif"); }
     void TestCase_SymbologyPointsParamGIF() { TestCase_SymbologyPointsParam(L"GIF", L"gif"); }
     void TestCase_SymbologyLinesGIF() { TestCase_SymbologyLines(L"GIF", L"gif"); }
@@ -230,12 +238,13 @@
     void TestCase_RenderLegendSingleFTSMultiCTSGIF() { TestCase_RenderLegendSingleFTSMultiCTS(L"GIF", L"gif"); }
     void TestCase_StylizationFunctionsGIF() { TestCase_StylizationFunctions(L"GIF", L"gif"); }
 
-	//JPG output tests
-	void TestCase_RenderDynamicOverlayJPG() { TestCase_RenderDynamicOverlay(L"JPG", L"jpg"); }
+    //JPG output tests
+    void TestCase_RenderDynamicOverlayJPG() { TestCase_RenderDynamicOverlay(L"JPG", L"jpg"); }
     void TestCase_RenderDynamicOverlayTiledMapJPG() { TestCase_RenderDynamicOverlayTiledMap(L"JPG", L"jpg"); }
     void TestCase_RenderMapJPG() { TestCase_RenderMap(L"JPG", L"jpg"); }
     void TestCase_RenderMapWithWatermarkJPG() { TestCase_RenderMapWithWatermark(L"JPG", L"jpg"); }
     void TestCase_RenderLegendJPG() { TestCase_RenderLegend(L"JPG", L"jpg"); }
+    void TestCase_RenderLegendEmptyGroupsJPG() { TestCase_RenderLegendEmptyGroups(L"JPG", L"jpg"); }
     void TestCase_SymbologyPointsJPG() { TestCase_SymbologyPoints(L"JPG", L"jpg"); }
     void TestCase_SymbologyPointsParamJPG() { TestCase_SymbologyPointsParam(L"JPG", L"jpg"); }
     void TestCase_SymbologyLinesJPG() { TestCase_SymbologyLines(L"JPG", L"jpg"); }
@@ -260,7 +269,7 @@
     MgMap* CreateTestStylizationFunctionMap();
     MgMap* CreateTestMapWithWatermark();
     MgPolygon* CreateSelectionPolygon(MgMap* map, double width, double height);
-	static STRING GetPath(CREFSTRING basePath, CREFSTRING imageFormat, CREFSTRING extension);
+    static STRING GetPath(CREFSTRING basePath, CREFSTRING imageFormat, CREFSTRING extension);
 
 private:
     Ptr<MgSiteConnection> m_siteConnection;



More information about the mapguide-commits mailing list