[mapguide-commits] r1367 - trunk/MgDev/Common/Stylization

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Sat Mar 24 15:00:44 EDT 2007


Author: traianstanev
Date: 2007-03-24 15:00:43 -0400 (Sat, 24 Mar 2007)
New Revision: 1367

Modified:
   trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp
   trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.h
Log:
Fixes to the highway shield positioning algorithm (fix by Martin).

Modified: trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp	2007-03-24 02:10:49 UTC (rev 1366)
+++ trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp	2007-03-24 19:00:43 UTC (rev 1367)
@@ -349,6 +349,78 @@
     if (shieldCount < 1)
         return;
 
+
+    SE_RenderLineStyle* rlStyle = (SE_RenderLineStyle* ) rstyle;
+    double startOffset = rlStyle->startOffset;
+    double increment = rlStyle->repeat;
+
+    // the endOffset is used in this context as the increment between multiple shields in one group
+ // double incrementS = 10 * mm2px;
+    double incrementS = rlStyle->endOffset;
+
+
+    // calc the overall length of this geometry
+
+    double totalLen = 0;
+    int pointIndex = 0;
+    for (int i = 0; i < geometry->cntr_count(); i++)
+    {
+        int ptcount = geometry->cntrs()[i];
+        double* pts = geometry->points() + 2*pointIndex;
+
+
+        for (int cur_seg = 0; cur_seg < ptcount - 1; cur_seg++)
+        {
+            double* seg = pts + cur_seg * 2;
+
+            // transform the point to screen space
+            double  cx1, cy1, cx2, cy2;
+            renderer->WorldToScreenPoint(seg[0], seg[1], cx1, cy1);
+            renderer->WorldToScreenPoint(seg[2], seg[3], cx2, cy2);
+
+            // calc length
+            double dx = cx2 - cx1;
+            double dy = cy2 - cy1;
+            totalLen += sqrt(dx*dx + dy*dy);
+        }
+
+        pointIndex += ptcount;
+    }
+
+
+    if (startOffset >= 0)
+    {
+        // calc optimal start offset (with rlStyle->startOffset taken as a minimum)
+        // to co-locate shield groups placed on two-line highways where the two
+        // parallel lines are processed from opposit ends.
+        // this avoids a problem with perceived irregular placement when overposting
+        // removes just some of the duplicate shields
+
+        double shieldGroupLen = (shieldCount - 1) * incrementS;
+
+        // length in excess of the required length to place one group with startOffset on each side
+        double availLen = totalLen - (shieldGroupLen + 2 * startOffset);
+
+        if (availLen < 0)
+        {
+            // there is no room to 'properly' place even one group, nothing to do but cry about it
+            return;
+        }
+
+        int numAdditionalGroups = (int) (availLen / (shieldGroupLen + increment));
+
+        double additionalOffset = (availLen - numAdditionalGroups * (shieldGroupLen + increment)) / 2;
+
+        startOffset += additionalOffset;
+    }
+    else
+    {
+        // negative startOffset value disables the optimization
+        // use absolute value as the offset
+        startOffset = startOffset * -1;
+    }
+
+
     SE_RenderPrimitiveList * symbolVectors = new SE_RenderPrimitiveList[shieldCount];
 
     std::wstring countryCode = highwayInfo.getFirstToken();
@@ -363,10 +435,25 @@
 
         SE_RenderRaster* rr = new SE_RenderRaster();
 
-        std::wstring imgPathName = HIGWAY_SHIELD_SYMBOLS_LOCATION + HIGWAY_SHIELD_SYMBOLS_PREFIX +
-                                   countryCode + L"_" + shieldType + L".png";
-        rr->pngPtr = symbolManager->GetImageData(L"", imgPathName.c_str(), rr->pngSize);
+        std::wstring imgName = HIGWAY_SHIELD_SYMBOLS_PREFIX + countryCode + L"_" + shieldType + L".png";
 
+        rr->pngPtr = symbolManager->GetImageData(HIGWAY_SHIELD_SYMBOLS_RESOURCE.c_str(), imgName.c_str(), rr->pngSize);
+
+        if (rr->pngSize == 0)
+        {
+            // could not find the image or resource
+
+            // we could fall back and try to pick up the image from a disk file like this:
+         // std::wstring imgPathName = HIGWAY_SHIELD_SYMBOLS_LOCATION + imgName;
+         // rr->pngPtr = symbolManager->GetImageData(L"", imgPathName.c_str(), rr->pngSize);
+            // but let's not do that unles really necessary
+
+            // cannot just leave this shield empty, that causes exceptions later, so bail out
+            // TODO: find a better way to handle this condition
+            return;
+        }
+
+
         rr->position[0] = 0;
         rr->position[1] = 0;
         rr->extent[0] = 20;
@@ -427,15 +514,13 @@
     }
 
 
-    SE_RenderLineStyle* style = (SE_RenderLineStyle* ) rstyle;
+    int ptindex = 0;
     SE_Matrix symxf;
-    int ptindex = 0;
-    double increment = style->repeat;
- // double incrementS = 10 * mm2px;          // the 'increment' used between multiple shields
-    double incrementS = style->endOffset;    // use endOffset as the increment between multiple shields
-
     shieldIndex = 0;
 
+    // init position along the whole geometry to the start offset
+    double drawpos = startOffset;
+
     for (int j=0; j<geometry->cntr_count(); j++)
     {
         // current polyline
@@ -443,7 +528,7 @@
         double* pts = geometry->points() + 2*ptindex;
 
         // init position along the current segment to the start offset
-        double drawpos = style->startOffset;
+     // double drawpos = startOffset;
 
         int cur_seg = 0;
 
@@ -484,16 +569,16 @@
                 // follow the segment and place the shield symbols alternated via shieldIndex
                 while (drawpos < len)
                 {
-                    if (style->drawLast)
+                    if (rlStyle->drawLast)
                     {
 
-                        style->symbol = symbolVectors[shieldIndex];
-                        memcpy(style->bounds, symbolVectors[shieldIndex].front()->bounds, sizeof(style->bounds));
-                        SE_RenderStyle* clonedStyle = renderer->CloneRenderStyle(style);
+                        rlStyle->symbol = symbolVectors[shieldIndex];
+                        memcpy(rlStyle->bounds, symbolVectors[shieldIndex].front()->bounds, sizeof(rlStyle->bounds));
+                        SE_RenderStyle* clonedStyle = renderer->CloneRenderStyle(rlStyle);
 
                         SE_LabelInfo info(symxf.x2, symxf.y2, 0.0, 0.0, RS_Units_Device, 0, clonedStyle);
 
-                        renderer->ProcessLabelGroup(&info, 1, RS_OverpostType_AllFit, style->addToExclusionRegions, geometry);
+                        renderer->ProcessLabelGroup(&info, 1, RS_OverpostType_AllFit, rlStyle->addToExclusionRegions, geometry);
 
                     }
                     else
@@ -501,7 +586,7 @@
                         renderer->DrawSymbol(symbolVectors[shieldIndex], symxf, 0);
 
                         // TODO: if this is ever needed ...
-                     // if (style->addToExclusionRegions)
+                     // if (rlStyle->addToExclusionRegions)
                      //     renderer->AddExclusionRegion(style, symxf, 0);
                     }
 
@@ -531,6 +616,30 @@
         ptindex += ptcount;
     }
 
+    // cleanup time
+
+    // the rlStyle->symbol has been assigned various values from the 'symbolVectors',
+    // 'un-assign' it, so that we can clean them up
+    rlStyle->symbol.clear();
+
+    for (shieldIndex = 0; shieldIndex < shieldCount; shieldIndex++)
+    {
+        for (SE_RenderPrimitiveList::iterator iter = symbolVectors[shieldIndex].begin();
+             iter != symbolVectors[shieldIndex].end();
+             iter++)
+        {
+            // necessary since destructor of SE_RenderPrimitive is not virtual
+            switch ((*iter)->type)
+            {
+                case SE_RenderPolylinePrimitive: delete (SE_RenderPolyline*)(*iter);break;
+                case SE_RenderPolygonPrimitive: delete (SE_RenderPolygon*)(*iter);break;
+                case SE_RenderRasterPrimitive: delete (SE_RenderRaster*)(*iter);break;
+                case SE_RenderTextPrimitive: delete (SE_RenderText*)(*iter);break;
+                default: throw; //means there is a bug
+            }
+        }
+    }
+
     delete [] symbolVectors;
 
 }

Modified: trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.h	2007-03-24 02:10:49 UTC (rev 1366)
+++ trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.h	2007-03-24 19:00:43 UTC (rev 1367)
@@ -20,8 +20,8 @@
 
 #include "SE_RenderProxies.h"
 
-//const std::wstring HIGWAY_SHIELD_SYMBOLS_LOCATION = L"Library://Symbology/HighwaySymbols/";
 const std::wstring HIGWAY_SHIELD_SYMBOLS_LOCATION = L"C:/";
+const std::wstring HIGWAY_SHIELD_SYMBOLS_RESOURCE = L"Library://Symbology/HighwaySymbols/MultipleShields.SymbolDefinition";
 const std::wstring HIGWAY_SHIELD_SYMBOLS_PREFIX = L"shield_";
 
 class LineBuffer;



More information about the mapguide-commits mailing list