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

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Aug 12 12:42:37 EDT 2010


Author: waltweltonlair
Date: 2010-08-12 16:42:37 +0000 (Thu, 12 Aug 2010)
New Revision: 5088

Modified:
   trunk/MgDev/Common/Stylization/SE_LineRenderer.cpp
   trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp
   trunk/MgDev/Common/Stylization/SE_Renderer.cpp
   trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp
   trunk/MgDev/Common/Stylization/StylizationUtil.cpp
Log:
Fix #1422 (Add enhanced stylization support for UnitsControl)

This submission adds UnitsControl support to the enhanced stylization engine.  All line style
rendering code paths have been updated to the check the UnitsControl setting and to adjust
the repeat / startOffset / endOffset values accordingly.

A small change to the code which draws style previews (for use in legends) was also made
to better display line styles that use parametric UnitsControl.


Modified: trunk/MgDev/Common/Stylization/SE_LineRenderer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_LineRenderer.cpp	2010-08-12 04:50:01 UTC (rev 5087)
+++ trunk/MgDev/Common/Stylization/SE_LineRenderer.cpp	2010-08-12 16:42:37 UTC (rev 5088)
@@ -212,12 +212,16 @@
 
 void SE_LineRenderer::ProcessLineOverlapWrap(SE_Renderer* renderer, LineBuffer* geometry, SE_RenderLineStyle* style)
 {
+    _ASSERT(style->repeat > 0.0);
+
     SE_BufferPool* lbp = renderer->GetBufferPool();
 
     SE_RenderPrimitiveList& rs = style->symbol;
 
     RS_FontEngine* fe = renderer->GetRSFontEngine();
 
+    double px2su = renderer->GetScreenUnitsPerPixel();
+
     RS_Bounds styleBounds(DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX);
     styleBounds.add_point(style->bounds[0]);
     styleBounds.add_point(style->bounds[1]);
@@ -227,12 +231,6 @@
     double affected_height = rs_max(fabs(styleBounds.miny), fabs(styleBounds.maxy));
     double affected_height_inv = (affected_height > 0.0)? 1.0 / affected_height : 0.0;
 
-    double increment = style->repeat;
-    _ASSERT(increment > 0.0);
-
-    double startOffsetMax = rs_max(style->startOffset, 0.0);
-    double endOffsetMax   = rs_max(style->endOffset, 0.0);
-
     bool roundJoin = (style->vertexJoin == SE_LineJoin_Round);
 
     // get the size of the largest contour so we can pre-allocate hotspots for it
@@ -337,6 +335,31 @@
             int ptCount = SE_LineRenderer::ConfigureHotSpots(renderer, geometry, cur_contour, style, styleBounds, hotspots);
             double total_length = hotspots[ptCount-1].mid;
 
+            // get the distribution for the current contour
+            double repeat = style->repeat;
+            double startOffset = style->startOffset;
+            double endOffset = style->endOffset;
+            if (style->unitsControl == SE_UnitsControl_Parametric)
+            {
+                repeat *= total_length;
+                startOffset *= total_length;
+                endOffset *= total_length;
+
+                // It makes no sense to distribute symbols using a repeat value
+                // which is much less than one pixel.  We'll scale up any value
+                // less than 0.25 to 0.5.
+                if (repeat > 0.0 && repeat < 0.25*px2su)
+                {
+                    // just increase it by an integer multiple so the overall
+                    // distribution isn't affected
+                    int factor = (int)(0.5*px2su / repeat);
+                    repeat *= factor;
+                }
+            }
+
+            double startOffsetMax = rs_max(startOffset, 0.0);
+            double endOffsetMax   = rs_max(endOffset, 0.0);
+
             // check if:
             // - the start offset goes beyond the end of the contour
             // - the end offset goes beyond the beginning of the contour
@@ -353,22 +376,22 @@
             // calculate the initial draw position
             double drawpos  = startpos;
 
-            if (style->startOffset < 0.0 && style->endOffset >= 0.0)
+            if (startOffset < 0.0 && endOffset >= 0.0)
             {
                 // only end offset is specified - adjust the draw position so we
-                // have: endpos = drawpos + i*increment
-                drawpos = fmod(endpos, increment);
+                // have: endpos = drawpos + i*repeat
+                drawpos = fmod(endpos, repeat);
 
-                // reduce the draw position by one increment if the initial style would
+                // reduce the draw position by one repeat if the initial style would
                 // still display
-                if (drawpos - increment + styleBounds.maxx >= 0.0)
-                    drawpos -= increment;
+                if (drawpos - repeat + styleBounds.maxx >= 0.0)
+                    drawpos -= repeat;
 
                 // Roundoff error can lead to the final symbol position being slightly
                 // greater than endpos, which could lead to additional undesireable
                 // clipping of the final symbol.  Prevent this by reducing drawpos
-                // slightly (a fraction of the increment).
-                drawpos -= 1.0e-10 * increment;
+                // slightly (a fraction of the repeat).
+                drawpos -= 1.0e-10 * repeat;
             }
 
             // cache these for later use
@@ -413,7 +436,7 @@
                     // Just put the pedal to the metal and draw an unwarped symbol.
                     renderer->DrawSymbol(rs, xformStart, next_hotspot->angle_start);
 
-                    drawpos += increment;
+                    drawpos += repeat;
                     sym_minx = drawpos + styleBounds.minx;
                     sym_maxx = drawpos + styleBounds.maxx;
                 }
@@ -942,7 +965,7 @@
                     }
 
                     // we're finally done with the symbol draw, so move forward by the repeat amount
-                    drawpos += increment;
+                    drawpos += repeat;
                     sym_minx = drawpos + styleBounds.minx;
                     sym_maxx = drawpos + styleBounds.maxx;
 

Modified: trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp	2010-08-12 04:50:01 UTC (rev 5087)
+++ trunk/MgDev/Common/Stylization/SE_PositioningAlgorithms.cpp	2010-08-12 16:42:37 UTC (rev 5088)
@@ -499,6 +499,12 @@
     if (rstyle->type != SE_RenderStyle_Line)
         return;
 
+    SE_RenderLineStyle* rlStyle = (SE_RenderLineStyle*)rstyle;
+
+    // ... and the units control must be absolute
+    if (rlStyle->unitsControl != SE_UnitsControl_Absolute)
+        return;
+
     // highway info format:  countryCode|type1|num1|type2|num2|type3|num3|...
     // example:              US|2|101|3|1
     StringOfTokens highwayInfo(featureReader->GetString(L"Url"), L"|");
@@ -507,7 +513,6 @@
     if (shieldCount < 1)
         return;
 
-    SE_RenderLineStyle* rlStyle = (SE_RenderLineStyle*)rstyle;
     double startOffset = rlStyle->startOffset;
     double increment = rlStyle->repeat;
 

Modified: trunk/MgDev/Common/Stylization/SE_Renderer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_Renderer.cpp	2010-08-12 04:50:01 UTC (rev 5087)
+++ trunk/MgDev/Common/Stylization/SE_Renderer.cpp	2010-08-12 16:42:37 UTC (rev 5088)
@@ -959,6 +959,7 @@
 
     SE_Matrix symxf;
     bool yUp = YPointsUp();
+    double px2su = GetScreenUnitsPerPixel();
 
     double baseAngleRad = style->angleRad;
 
@@ -987,7 +988,6 @@
     double segX0, segY0, segX1, segY1;
 
     // this is the same for all contours / groups
-    double repeat = style->repeat;
     double leftEdge = style->bounds[0].x;
     double rightEdge = style->bounds[1].x;
 
@@ -1022,11 +1022,33 @@
         if (segLens[start_seg_contour] == 0.0)
             continue;
 
+        // get the distribution for the current contour
+        double repeat = style->repeat;
+        double startOffset = style->startOffset;
+        double endOffset = style->endOffset;
+        if (style->unitsControl == SE_UnitsControl_Parametric)
+        {
+            repeat *= segLens[start_seg_contour];
+            startOffset *= segLens[start_seg_contour];
+            endOffset *= segLens[start_seg_contour];
+
+            // It makes no sense to distribute symbols using a repeat value
+            // which is much less than one pixel.  We'll scale up any value
+            // less than 0.25 to 0.5.
+            if (repeat > 0.0 && repeat < 0.25*px2su)
+            {
+                // just increase it by an integer multiple so the overall
+                // distribution isn't affected
+                int factor = (int)(0.5*px2su / repeat);
+                repeat *= factor;
+            }
+        }
+
         // check if:
         // - the start offset goes beyond the end of the contour
         // - the end offset goes beyond the beginning of the contour
         // - the start offset goes beyond the end offset
-        double offsetSum = rs_max(style->startOffset, 0.0) + rs_max(style->endOffset, 0.0);
+        double offsetSum = rs_max(startOffset, 0.0) + rs_max(endOffset, 0.0);
         if (offsetSum > segLens[start_seg_contour])
             continue;
 
@@ -1039,8 +1061,8 @@
         ComputeGroupLengths(segLens, numGroups, segGroups, groupLens);
 
         // for this vertex control option we set the offsets to zero if they're unspecified
-        double startOffset = rs_max(style->startOffset, 0.0);
-        double endOffset = rs_max(style->endOffset, 0.0);
+        startOffset = rs_max(startOffset, 0.0);
+        endOffset = rs_max(endOffset, 0.0);
 
         // compute the starting group based on the style's start offset
         int start_group = 0;
@@ -1431,6 +1453,7 @@
 
     SE_Matrix symxf;
     bool yUp = YPointsUp();
+    double px2su = GetScreenUnitsPerPixel();
 
     double baseAngleRad = style->angleRad;
 
@@ -1458,9 +1481,6 @@
     // screen coordinates of current line segment
     double segX0, segY0, segX1, segY1;
 
-    // this is the same for all contours / groups
-    double repeat = style->repeat;
-
     // get segment lengths
     double* segLens = (double*)alloca(sizeof(double)*geometry->point_count());
     ComputeSegmentLengths(geometry, segLens);
@@ -1479,11 +1499,33 @@
         if (segLens[start_seg_contour] == 0.0)
             continue;
 
+        // get the distribution for the current contour
+        double repeat = style->repeat;
+        double startOffset = style->startOffset;
+        double endOffset = style->endOffset;
+        if (style->unitsControl == SE_UnitsControl_Parametric)
+        {
+            repeat *= segLens[start_seg_contour];
+            startOffset *= segLens[start_seg_contour];
+            endOffset *= segLens[start_seg_contour];
+
+            // It makes no sense to distribute symbols using a repeat value
+            // which is much less than one pixel.  We'll scale up any value
+            // less than 0.25 to 0.5.
+            if (repeat > 0.0 && repeat < 0.25*px2su)
+            {
+                // just increase it by an integer multiple so the overall
+                // distribution isn't affected
+                int factor = (int)(0.5*px2su / repeat);
+                repeat *= factor;
+            }
+        }
+
         // check if:
         // - the start offset goes beyond the end of the contour
         // - the end offset goes beyond the beginning of the contour
         // - the start offset goes beyond the end offset
-        double offsetSum = rs_max(style->startOffset, 0.0) + rs_max(style->endOffset, 0.0);
+        double offsetSum = rs_max(startOffset, 0.0) + rs_max(endOffset, 0.0);
         if (offsetSum > segLens[start_seg_contour])
             continue;
 
@@ -1497,7 +1539,6 @@
 
         // compute the starting group based on the style's start offset
         int start_group = 0;
-        double startOffset = style->startOffset;
         if (startOffset > 0.0)
         {
             for (int k=0; k<numGroups; ++k)
@@ -1515,7 +1556,6 @@
 
         // compute the ending group based on the style's end offset
         int end_group = numGroups-1;
-        double endOffset = style->endOffset;
         if (endOffset > 0.0)
         {
             for (int k=numGroups-1; k>=0; --k)

Modified: trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp	2010-08-12 04:50:01 UTC (rev 5087)
+++ trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp	2010-08-12 16:42:37 UTC (rev 5088)
@@ -804,21 +804,33 @@
 
     style->angleRad = fmod(angleDeg.evaluate(ctx->exec), 360.0) * M_PI180;
 
-    // scale by xform->x0 and xform->y1 instead of mm2su, because these encompass
-    // mm2su as well as scaleX and scaleY
-    style->startOffset = startOffset.evaluate(ctx->exec) * fabs(ctx->xform->x0);
-    style->endOffset   = endOffset.evaluate(ctx->exec)   * fabs(ctx->xform->x0);
-    style->repeat      = repeat.evaluate(ctx->exec)      * fabs(ctx->xform->x0);
-    double origRepeat  = style->repeat;
+    style->startOffset = startOffset.evaluate(ctx->exec);
+    style->endOffset   = endOffset.evaluate(ctx->exec);
+    style->repeat      = repeat.evaluate(ctx->exec);
 
-    // It makes no sense to distribute symbols using a repeat value which is much
-    // less than one pixel.  We'll scale up any value less than 0.25 to 0.5.
-    if (style->repeat > 0.0 && style->repeat < 0.25*ctx->px2su)
+    // with parametric units control the repeat / offsets will be scaled
+    // later on by each contour length, which includes the transform
+    double origRepeat = -1.0;
+    if (style->unitsControl == SE_UnitsControl_Absolute)
     {
-        // just increase it by an integer multiple so the overall distribution
-        // isn't affected
-        int factor = (int)(0.5*ctx->px2su / style->repeat);
-        style->repeat *= factor;
+        // scale by xform->x0 and xform->y1 instead of mm2su, because
+        // these include mm2su as well as scaleX and scaleY
+        style->startOffset *= fabs(ctx->xform->x0);
+        style->endOffset   *= fabs(ctx->xform->x0);
+        style->repeat      *= fabs(ctx->xform->x0);
+
+        origRepeat = style->repeat;
+
+        // It makes no sense to distribute symbols using a repeat value
+        // which is much less than one pixel.  We'll scale up any value
+        // less than 0.25 to 0.5.
+        if (style->repeat > 0.0 && style->repeat < 0.25*ctx->px2su)
+        {
+            // just increase it by an integer multiple so the overall
+            // distribution isn't affected
+            int factor = (int)(0.5*ctx->px2su / style->repeat);
+            style->repeat *= factor;
+        }
     }
 
     double angleLimit = vertexAngleLimit.evaluate(ctx->exec);
@@ -982,16 +994,17 @@
     double origRepeatX = style->repeat[0];
     double origRepeatY = style->repeat[1];
 
-    // It makes no sense to distribute symbols using repeat values which are much
-    // less than one pixel.  We'll scale up any values less than 0.25 to 0.5.
+    // It makes no sense to distribute symbols using repeat values which
+    // are much less than one pixel.  We'll scale up any values less than
+    // 0.25 to 0.5.
     for (int i=0; i<=1; ++i)
     {
         // work with absolute value in case repeat is negative
         double repeat = fabs(style->repeat[i]);
         if (repeat > 0.0 && repeat < 0.25*ctx->px2su)
         {
-            // just increase it by an integer multiple so the overall distribution
-            // isn't affected
+            // just increase it by an integer multiple so the overall
+            // distribution isn't affected
             int factor = (int)(0.5*ctx->px2su / repeat);
             style->repeat[i] *= factor;
         }

Modified: trunk/MgDev/Common/Stylization/StylizationUtil.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/StylizationUtil.cpp	2010-08-12 04:50:01 UTC (rev 5087)
+++ trunk/MgDev/Common/Stylization/StylizationUtil.cpp	2010-08-12 16:42:37 UTC (rev 5088)
@@ -659,7 +659,7 @@
                     // don't call style->apply() since we do some special processing
                     // to make the point symbol fill the preview image
 
-                    SE_RenderPointStyle* ptStyle = (SE_RenderPointStyle*)(rStyle);
+                    SE_RenderPointStyle* ptStyle = (SE_RenderPointStyle*)rStyle;
 
                     // get the center of the scaled point symbol
                     double symCtrX = 0.5*(symBounds.minx + symBounds.maxx) * scale;
@@ -723,6 +723,18 @@
                         }
                     }
 
+                    // if the the line style uses parametric units control reconfigure
+                    // it so you just get one symbol at the middle
+                    SE_RenderLineStyle* lnStyle = (SE_RenderLineStyle*)rStyle;
+                    if (lnStyle->unitsControl == SE_UnitsControl_Parametric)
+                    {
+                        if (lnStyle->repeat > 0.0)
+                            lnStyle->repeat = 0.5;
+
+                        lnStyle->startOffset = rs_min(lnStyle->startOffset, 0.0);
+                        lnStyle->endOffset = rs_min(lnStyle->endOffset, 0.0);
+                    }
+
                     // just apply the style to the preview geometry
                     applyCtx.geometry = &lb;
                     style->apply(&applyCtx);
@@ -829,6 +841,9 @@
             // look the same when scaled.  We therefore don't want these to be a contributing
             // factor in the scaling, and therefore don't add their bounds to the returned
             // bounds.
+            //
+            // Another example is line styles which have parametric-based units control
+            // enabled.
             bool addBounds = true;
 
             SE_RenderStyle* rStyle = style->rstyle;
@@ -836,7 +851,7 @@
             {
                 case SE_RenderStyle_Point:
                 {
-                    SE_RenderPointStyle* ptStyle = (SE_RenderPointStyle*)(rStyle);
+                    SE_RenderPointStyle* ptStyle = (SE_RenderPointStyle*)rStyle;
 
                     // point usage offset (already scaled)
                     xformStyle.translate(ptStyle->offset[0], ptStyle->offset[1]);
@@ -853,10 +868,10 @@
 
                 case SE_RenderStyle_Line:
                 {
-                    SE_RenderLineStyle* lnStyle = (SE_RenderLineStyle*)(rStyle);
+                    SE_RenderLineStyle* lnStyle = (SE_RenderLineStyle*)rStyle;
 
                     // see comment above the addBounds declaration
-                    if (lnStyle->solidLine)
+                    if (lnStyle->solidLine || lnStyle->unitsControl == SE_UnitsControl_Parametric)
                         addBounds = false;
 
                     // make the preview bounds width include two repetitions of the symbol
@@ -874,7 +889,7 @@
 
                 case SE_RenderStyle_Area:
                 {
-                    SE_RenderAreaStyle* arStyle = (SE_RenderAreaStyle*)(rStyle);
+                    SE_RenderAreaStyle* arStyle = (SE_RenderAreaStyle*)rStyle;
 
                     // see comment above the addBounds declaration
                     if (arStyle->solidFill)
@@ -1019,7 +1034,7 @@
             {
                 case SE_RenderStyle_Point:
                 {
-                    SE_RenderPointStyle* ptStyle = (SE_RenderPointStyle*)(rStyle);
+                    SE_RenderPointStyle* ptStyle = (SE_RenderPointStyle*)rStyle;
 
                     // point usage offset (already scaled)
                     xformStyle.translate(ptStyle->offset[0], ptStyle->offset[1]);
@@ -1036,7 +1051,7 @@
 
                 case SE_RenderStyle_Line:
                 {
-                    SE_RenderLineStyle* lnStyle = (SE_RenderLineStyle*)(rStyle);
+                    SE_RenderLineStyle* lnStyle = (SE_RenderLineStyle*)rStyle;
 
                     // line usage rotation - assume geometry angle is zero
                     xformStyle.rotate(lnStyle->angleRad);
@@ -1046,7 +1061,7 @@
 
                 case SE_RenderStyle_Area:
                 {
-                    SE_RenderAreaStyle* arStyle = (SE_RenderAreaStyle*)(rStyle);
+                    SE_RenderAreaStyle* arStyle = (SE_RenderAreaStyle*)rStyle;
 
                     // area usage rotation - assume geometry angle is zero
                     xformStyle.rotate(arStyle->angleRad);



More information about the mapguide-commits mailing list