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

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Mar 26 20:23:57 EDT 2007


Author: waltweltonlair
Date: 2007-03-26 20:23:56 -0400 (Mon, 26 Mar 2007)
New Revision: 1379

Modified:
   trunk/MgDev/Common/Stylization/SE_RenderProxies.h
   trunk/MgDev/Common/Stylization/SE_Renderer.cpp
   trunk/MgDev/Common/Stylization/SE_Renderer.h
   trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp
   trunk/MgDev/Common/Stylization/StylizationEngine.cpp
Log:
The PointUsage element has AngleControl, Angle, and OriginOffsetX /
OriginOffsetY sub-elements, and these were being handled incorrectly
by the symbolization engine.  To fix this I:

- added the necessary data members to SE_RenderPointStyle
- implemented SE_PointStyle::evaluate to properly initialize
  the SE_RenderPointStyle
- updated SE_Renderer::CloneRenderStyle to account for the changes

I also noticed that the Text.Angle and Image.Angle properties
were not being taken into account.  I updated the code to do so.

Also fixed some issues with the code.  In SE_PointStyle::evaluate
we were updating the transform based on some of the properties
above.  There were numerous "TODO" and "BAD" comments in the code
regarding this.  The code which applies these properties to the
transform is now in SE_Renderer::ProcessPoint where it belongs.
The only thing SE_PointStyle::evaluate now does is create the
SE_RenderPointStyle.  This is how the line and area styles are
also done.  This update also let me remove the associated hack
in StylizationEngine::Stylize in which a copy of the transform
was being made each time.

Finally, I renamed some method parameters from angle to anglerad
to make it very clear what angle units the methods expect.


Modified: trunk/MgDev/Common/Stylization/SE_RenderProxies.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_RenderProxies.h	2007-03-26 21:12:51 UTC (rev 1378)
+++ trunk/MgDev/Common/Stylization/SE_RenderProxies.h	2007-03-27 00:23:56 UTC (rev 1379)
@@ -153,6 +153,11 @@
 struct SE_RenderPointStyle : public SE_RenderStyle
 {
     SE_INLINE SE_RenderPointStyle() : SE_RenderStyle(SE_RenderPointStyleType) { }
+
+    const wchar_t* angleControl;
+
+    double angle;
+    double offset[2];
 };
 
 

Modified: trunk/MgDev/Common/Stylization/SE_Renderer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_Renderer.cpp	2007-03-26 21:12:51 UTC (rev 1378)
+++ trunk/MgDev/Common/Stylization/SE_Renderer.cpp	2007-03-27 00:23:56 UTC (rev 1379)
@@ -23,6 +23,7 @@
 
 using namespace MDFMODEL_NAMESPACE;
 
+
 //cloning of RenderSymbols. Unfortunate but necessary for delay-drawing labels
 SE_RenderStyle* SE_Renderer::CloneRenderStyle(SE_RenderStyle* symbol)
 {
@@ -34,8 +35,13 @@
     {
     case SE_RenderPointStyleType:
         {
-        SE_RenderPointStyle* dps = new SE_RenderPointStyle();
-        ret = dps;
+            SE_RenderPointStyle* dps = new SE_RenderPointStyle();
+            SE_RenderPointStyle* sps = (SE_RenderPointStyle*)symbol;
+            ret = dps;
+            dps->angle = sps->angle;
+            dps->angleControl = sps->angleControl;
+            dps->offset[0] = sps->offset[0];
+            dps->offset[1] = sps->offset[1];
         }
         break;
     case SE_RenderLineStyleType:
@@ -155,15 +161,18 @@
 {
 }
 
+
 SE_Renderer::~SE_Renderer()
 {
 }
 
+
 void SE_Renderer::SetLineBufferPool(SE_LineBufferPool* pool)
 {
     m_lbp = pool;
 }
 
+
 void SE_Renderer::SetRenderSelectionMode(bool mode)
 {
     m_bSelectionMode = mode;
@@ -179,9 +188,37 @@
     }
 }
 
+
 void SE_Renderer::ProcessPoint(LineBuffer* geometry, SE_RenderPointStyle* style)
 {
+    double anglerad;
+    if (wcscmp(L"FromAngle", style->angleControl) == 0)
+    {
+        anglerad = style->angle;
+    }
+    else
+    {
+        switch(geometry->geom_type())
+        {
+        case FdoGeometryType_LineString:
+        case FdoGeometryType_MultiLineString:
+        case FdoGeometryType_Polygon:
+        case FdoGeometryType_MultiPolygon:
+        {
+            double x0, y0;
+            geometry->Centroid(LineBuffer::ctLine, &x0, &y0, &anglerad);
+            break;
+        }
+        default:
+            anglerad = 0.0;
+            break;
+        }
+    }
+
     SE_Matrix xform;
+    SE_Matrix xformbase;
+    xformbase.translate(style->offset[0], style->offset[1]);
+    xformbase.rotate(anglerad);
 
     /* Render the points */
     for (int i = 0; i < geometry->point_count(); i++)
@@ -192,22 +229,22 @@
         //transform to screen space -- geometry is in [the original] mapping space
         WorldToScreenPoint(x, y, x, y);
 
-        xform.setIdentity();
+        xform = xformbase;
         xform.translate(x, y);
-        double angle = 0.0; //TODO: angle needs to be added to the RenderPointStyle
+
         if (style->drawLast)
-            AddLabel(geometry, style, xform, 0.0);
+            AddLabel(geometry, style, xform, anglerad);
         else
         {
-            DrawSymbol(style->symbol, xform, angle);
+            DrawSymbol(style->symbol, xform, anglerad);
 
-            double angle = 0.0;
             if (style->addToExclusionRegions)
-                AddExclusionRegion(style, xform, angle);
+                AddExclusionRegion(style, xform, anglerad);
         }
     }
 }
 
+
 void SE_Renderer::ProcessLine(LineBuffer* geometry, SE_RenderLineStyle* style)
 {
     //determine if the style is a simple straight solid line
@@ -293,11 +330,11 @@
                 double dx_incr = dx * invlen;
                 double dy_incr = dy * invlen;
 
-                double symrot = fromAngle? style->angle : atan2(dy, dx);
+                double anglerad = fromAngle? style->angle : atan2(dy, dx);
                 double tx = seg_screen[0] + dx_incr * drawpos;
                 double ty = seg_screen[1] + dy_incr * drawpos;
 
-                symxf.rotate(symrot);
+                symxf.rotate(anglerad);
                 symxf.translate(tx, ty);
                 dx_incr *= increment;
                 dy_incr *= increment;
@@ -307,13 +344,13 @@
                 while (drawpos < len)
                 {
                     if (style->drawLast)
-                        AddLabel(geometry, style, symxf, symrot);
+                        AddLabel(geometry, style, symxf, anglerad);
                     else
                     {
-                        DrawSymbol(style->symbol, symxf, symrot);
+                        DrawSymbol(style->symbol, symxf, anglerad);
 
                         if (style->addToExclusionRegions)
-                            AddExclusionRegion(style, symxf, symrot);
+                            AddExclusionRegion(style, symxf, anglerad);
                     }
 
                     symxf.translate(dx_incr, dy_incr);
@@ -329,10 +366,12 @@
     }
 }
 
+
 void SE_Renderer::ProcessArea(LineBuffer* /*geometry*/, SE_RenderAreaStyle* /*style*/)
 {
 }
 
+
 void SE_Renderer::DrawSymbol(SE_RenderPrimitiveList& symbol, const SE_Matrix& posxform, double anglerad)
 {
     for (unsigned i = 0; i < symbol.size(); i++)
@@ -369,25 +408,16 @@
             double x, y;
             posxform.transform(tp->position[0], tp->position[1], x, y);
 
+            RS_TextDef tdef = tp->tdef;
+            tdef.rotation() += anglerad / M_PI180;
+
             if (m_bSelectionMode)
             {
-                RS_TextDef tdef = tp->tdef;
                 tdef.color() = m_textForeColor;
                 tdef.bgcolor() = m_textBackColor;
-                if (anglerad != 0)
-                    tdef.rotation() = anglerad / M_PI180;
-                DrawScreenText(tp->text, tdef, x, y, NULL, 0, 0.0);
             }
-            else if (anglerad != 0.0)
-            {
-                RS_TextDef tdef = tp->tdef;
-                tdef.rotation() = anglerad / M_PI180;
-                DrawScreenText(tp->text, tdef, x, y, NULL, 0, 0.0);
-            }
-            else
-            {
-                DrawScreenText(tp->text, tp->tdef, x, y, NULL, 0, 0.0);
-            }
+
+            DrawScreenText(tp->text, tdef, x, y, NULL, 0, 0.0);
         }
         else if (primitive->type == SE_RenderRasterPrimitive)
         {
@@ -395,31 +425,31 @@
 
             double x, y;
             posxform.transform(rp->position[0], rp->position[1], x, y);
+            double angleDeg = (rp->angle + anglerad) / M_PI180;
 
-            DrawScreenRaster((unsigned char*)rp->pngPtr, rp->pngSize, RS_ImageFormat_PNG, -1, -1, x, y, rp->extent[0], rp->extent[1], anglerad / M_PI180);
+            DrawScreenRaster((unsigned char*)rp->pngPtr, rp->pngSize, RS_ImageFormat_PNG, -1, -1, x, y, rp->extent[0], rp->extent[1], angleDeg);
         }
     }
 }
 
 
-void SE_Renderer::AddLabel(LineBuffer* geom, SE_RenderStyle* style, SE_Matrix& xform, double angle)
+void SE_Renderer::AddLabel(LineBuffer* geom, SE_RenderStyle* style, SE_Matrix& xform, double anglerad)
 {
     //clone the SE_RenderStyle so that the label renderer can keep track of it until
     //the end of rendering when it draws all the labels
     //TODO: cloning is bad.
     SE_RenderStyle* copied_style = CloneRenderStyle(style);
 
-    SE_LabelInfo info(xform.x2, xform.y2, 0.0, 0.0, RS_Units_Device, angle, copied_style);
+    SE_LabelInfo info(xform.x2, xform.y2, 0.0, 0.0, RS_Units_Device, anglerad, copied_style);
 
-    RS_OverpostType type = RS_OverpostType_AllFit;
-
-    ProcessLabelGroup(&info, 1, type, style->addToExclusionRegions, geom);
+    ProcessLabelGroup(&info, 1, RS_OverpostType_AllFit, style->addToExclusionRegions, geom);
 }
 
-void SE_Renderer::AddExclusionRegion(SE_RenderStyle* rstyle, SE_Matrix& xform, double angle)
+
+void SE_Renderer::AddExclusionRegion(SE_RenderStyle* rstyle, SE_Matrix& xform, double anglerad)
 {
     SE_Matrix xform2;
-    xform2.rotate(angle);
+    xform2.rotate(anglerad);
     xform2.translate(xform.x2, xform.y2);
 
     RS_F_Point* fpts = m_lastExclusionRegion;

Modified: trunk/MgDev/Common/Stylization/SE_Renderer.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_Renderer.h	2007-03-26 21:12:51 UTC (rev 1378)
+++ trunk/MgDev/Common/Stylization/SE_Renderer.h	2007-03-27 00:23:56 UTC (rev 1379)
@@ -71,9 +71,9 @@
     void SetRenderSelectionMode(bool mode);
 
 private:
-    void AddLabel(LineBuffer* geom, SE_RenderStyle* style, SE_Matrix& xform, double angle);
+    void AddLabel(LineBuffer* geom, SE_RenderStyle* style, SE_Matrix& xform, double anglerad);
 
-    void AddExclusionRegion(SE_RenderStyle* rstyle, SE_Matrix& xform, double angle);
+    void AddExclusionRegion(SE_RenderStyle* rstyle, SE_Matrix& xform, double anglerad);
 
     RS_F_Point m_lastExclusionRegion[4];
 

Modified: trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp	2007-03-26 21:12:51 UTC (rev 1378)
+++ trunk/MgDev/Common/Stylization/SE_SymbolDefProxies.cpp	2007-03-27 00:23:56 UTC (rev 1379)
@@ -160,7 +160,7 @@
 
     cxt->xform->transform(ret->position[0], ret->position[1]);
 
-    ret->tdef.rotation() = angle.evaluate(cxt->exec);
+    ret->tdef.rotation() = angle.evaluate(cxt->exec);   // in degrees
 
     int style = RS_FontStyle_Regular;
     if (underlined.evaluate(cxt->exec)) style |= (int)RS_FontStyle_Underline;
@@ -424,69 +424,20 @@
 
 void SE_PointStyle::evaluate(SE_EvalContext* cxt)
 {
-    SE_RenderPointStyle* render;
-
+    //can skip out of evaluation if style is constant and has been evaluated once
     if (cacheable && rstyle)
-    {
-        //style is constant and has been evluated once -- we can skip out of evaluation
         return;
-    }
-    else
-    {
-        render = new SE_RenderPointStyle();
-        delete rstyle;
-        rstyle = render;
-    }
 
-    LineBuffer::GeomOperationType type;
-    switch(cxt->geometry->geom_type())
-    {
-    case FdoGeometryType_LineString:
-    case FdoGeometryType_MultiLineString:
-        type = LineBuffer::ctLine;
-        break;
-    case FdoGeometryType_Polygon:
-    case FdoGeometryType_MultiPolygon:
-        type = LineBuffer::ctArea;
-        break;
-    case FdoGeometryType_Point:
-    case FdoGeometryType_MultiPoint:
-        type = LineBuffer::ctPoint;
-        break;
-    default:
-        type = LineBuffer::ctNone;
-        break;
-    }
+    SE_RenderPointStyle* render = new SE_RenderPointStyle();
+    delete rstyle;
+    rstyle = render;
 
-    double angle = 0.0;
-    const wchar_t* sAngleControl = angleControl.evaluate(cxt->exec);
-    if (wcscmp(L"FromGeometry", sAngleControl) == 0)
-    {
-        if (type == LineBuffer::ctLine || type == LineBuffer::ctArea)
-        {
-            double x0, y0;
-            double slope_rad = 0.0;
-            cxt->geometry->Centroid(LineBuffer::ctLine, &x0, &y0, &slope_rad);
+    render->angleControl = angleControl.evaluate(cxt->exec);
 
-            angle = slope_rad;
+    render->angle = angle.evaluate(cxt->exec) * M_PI180;
+    render->offset[0] = originOffset[0].evaluate(cxt->exec)*cxt->mm2px;
+    render->offset[1] = originOffset[1].evaluate(cxt->exec)*cxt->mm2px;
 
-            //TODO: do we really need to invert this in case of y-down?
-            if (cxt->xform->y1 < 0)
-                angle = -angle;
-        }
-    }
-    else
-        angle = this->angle.evaluate(cxt->exec) * M_PI180;
-
-    double originOffsetX = originOffset[0].evaluate(cxt->exec)*cxt->mm2px;
-    double originOffsetY = originOffset[1].evaluate(cxt->exec)*cxt->mm2px;
-
-    SE_Matrix sxform;
-    sxform.translate(originOffsetX, originOffsetY);
-    sxform.rotate(angle);
-    sxform.premultiply(*cxt->xform);
-    *cxt->xform = sxform; //BAD here we modify the passed in transform -- figure out a way to avoid this
-
     //evaluate all the primitives too
     SE_Style::evaluate(cxt);
 }
@@ -494,20 +445,14 @@
 
 void SE_LineStyle::evaluate(SE_EvalContext* cxt)
 {
-    SE_RenderLineStyle* render;
-
+    //can skip out of evaluation if style is constant and has been evaluated once
     if (cacheable && rstyle)
-    {
-        //style is constant and has been evluated once -- we can skip out of evaluation
         return;
-    }
-    else
-    {
-        render = new SE_RenderLineStyle();
-        delete rstyle;
-        rstyle = render;
-    }
 
+    SE_RenderLineStyle* render = new SE_RenderLineStyle();
+    delete rstyle;
+    rstyle = render;
+
     render->angleControl = angleControl.evaluate(cxt->exec);
     render->unitsControl = unitsControl.evaluate(cxt->exec);
     render->vertexControl = vertexControl.evaluate(cxt->exec);
@@ -526,29 +471,24 @@
 
 void SE_AreaStyle::evaluate(SE_EvalContext* cxt)
 {
-    SE_RenderAreaStyle* render;
+    //can skip out of evaluation if style is constant and has been evaluated once
     if (cacheable && rstyle)
-    {
-        //style is constant and has been evluated once -- we can skip out of evaluation
         return;
-    }
-    else
-    {
-        render = new SE_RenderAreaStyle();
-        delete rstyle;
-        rstyle = render;
-    }
 
+    SE_RenderAreaStyle* render = new SE_RenderAreaStyle();
+    delete rstyle;
+    rstyle = render;
+
     render->angleControl = angleControl.evaluate(cxt->exec);
     render->originControl = originControl.evaluate(cxt->exec);
     render->clippingControl = clippingControl.evaluate(cxt->exec);
 
     render->angle = angle.evaluate(cxt->exec) * M_PI180;
-    render->origin[0] = origin[0].evaluate(cxt->exec);
-    render->origin[1] = origin[1].evaluate(cxt->exec);
-    render->repeat[0] = repeat[0].evaluate(cxt->exec);
-    render->repeat[1] = repeat[1].evaluate(cxt->exec);
-    render->bufferWidth = bufferWidth.evaluate(cxt->exec);
+    render->origin[0] = origin[0].evaluate(cxt->exec)*cxt->mm2px;
+    render->origin[1] = origin[1].evaluate(cxt->exec)*cxt->mm2px;
+    render->repeat[0] = repeat[0].evaluate(cxt->exec)*cxt->mm2px;
+    render->repeat[1] = repeat[1].evaluate(cxt->exec)*cxt->mm2px;
+    render->bufferWidth = bufferWidth.evaluate(cxt->exec)*cxt->mm2px;
 
     //evaluate all the primitives too
     SE_Style::evaluate(cxt);

Modified: trunk/MgDev/Common/Stylization/StylizationEngine.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/StylizationEngine.cpp	2007-03-26 21:12:51 UTC (rev 1378)
+++ trunk/MgDev/Common/Stylization/StylizationEngine.cpp	2007-03-27 00:23:56 UTC (rev 1379)
@@ -275,14 +275,14 @@
                             sym->scale[1].evaluate(executor),
                             sym->absOffset[0].evaluate(executor),
                             sym->absOffset[1].evaluate(executor) );
-        
+
         //??? symbol geometry needs to be inverted if the y coordinate in the renderer points down
         //This is so that in symbol definitions y points up consistently no matter what the underlying
         //renderer is doing. Normally we could just apply the world to screen transform to everything,
         //but in some cases we only apply it to the position of the symbol and then offset the symbol
         //geometry from there -- so the symbol geometry needs to be pre-inverted.
         //TODO: check if all rotations still work in the right direction
-        xform.scale(mm2px, w2s.y1 < 0 ? -mm2px : mm2px);  
+        xform.scale(mm2px, w2s.y1 < 0 ? -mm2px : mm2px);
 
         //initialize the style evaluation context
         SE_EvalContext cxt;
@@ -292,6 +292,7 @@
         cxt.mm2pxw = m_serenderer->GetPixelsPerMillimeterWorld();
         cxt.pool = m_pool;
         cxt.fonte = m_serenderer->GetFontEngine();
+        cxt.xform = &xform;
         cxt.geometry = geometry; //only used by point styles, I really want to get rid of this
 
         for (std::vector<SE_Style*>::const_iterator siter = sym->styles.begin(); siter != sym->styles.end(); siter++)
@@ -321,13 +322,6 @@
                 continue;
             }
 
-            SE_Matrix tmpxform(xform);  //TODO: this is lame, but necessary since the xform can be modified
-                                        //when we evalute the style, in the case of point style set on a
-                                        //non-point geometry
-
-            cxt.xform = &tmpxform; //EXTREMELY IMPORTANT: evaluating of point styles will modify this
-                                   //transform without you knowing -- beware!
-
             //evaluate the style (all expressions inside it) and convert to a constant screen space
             //render style
             style->evaluate(&cxt);
@@ -340,7 +334,7 @@
             const wchar_t* positioningAlgo = sym->positioningAlgorithm.evaluate(executor);
             if (wcslen(positioningAlgo) > 0 && wcscmp(positioningAlgo, L"Default") != 0)
             {
-                LayoutCustomLabel(positioningAlgo, geometry, tmpxform, style, style->rstyle, mm2px);
+                LayoutCustomLabel(positioningAlgo, geometry, xform, style, style->rstyle, mm2px);
             }
             else
             {
@@ -351,6 +345,7 @@
     }
 }
 
+
 void StylizationEngine::LayoutCustomLabel(const wchar_t* positioningAlgo, LineBuffer* geometry, SE_Matrix& xform, SE_Style* style, SE_RenderStyle* rstyle, double mm2px)
 {
     // call the appropriate positioning algorithm based on the name



More information about the mapguide-commits mailing list