[mapguide-commits] r4219 - in trunk/MgDev/Common: MapGuideCommon/Services Renderers

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Sep 11 00:46:40 EDT 2009


Author: waltweltonlair
Date: 2009-09-11 00:46:39 -0400 (Fri, 11 Sep 2009)
New Revision: 4219

Modified:
   trunk/MgDev/Common/MapGuideCommon/Services/PrintLayout.cpp
   trunk/MgDev/Common/Renderers/DWFRenderer.cpp
   trunk/MgDev/Common/Renderers/DWFRenderer.h
Log:
Fix #1089: Plot to DWF (eplot) - plot wrong -> islands/holes filled

For polygons containing holes DWFRenderer generates WT_ContourSets.  The DWF spec for WT_ContourSet requires that filled areas be specified by clockwise wound points, and holes be specified by counter-clockwise wound points.  The bug is that DWFRenderer was not enforcing this when it created WT_ContourSets.  It's possible for the feature geometry to have contours which are oriented opposite to the DWF spec, and then the contour set will not display correctly in DWF Viewer / ADR.

The fix is to verify that all contours are oriented per the DWF spec before creating the WT_ContourSet.  Note that the code I added assumes simple contours.

Two additional changes:
* removed some unnecessary code in MgPrintLayout::DetermineLayoutMapExtents
* in DWFRenderer::ProcessPolyline I moved the call to LineBuffer::Optimize further down to avoid allocating the new buffer before it's needed


Modified: trunk/MgDev/Common/MapGuideCommon/Services/PrintLayout.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/PrintLayout.cpp	2009-09-11 00:36:51 UTC (rev 4218)
+++ trunk/MgDev/Common/MapGuideCommon/Services/PrintLayout.cpp	2009-09-11 04:46:39 UTC (rev 4219)
@@ -692,11 +692,6 @@
 //
 MgEnvelope* MgPrintLayout::DetermineLayoutMapExtents(MgMap* map, double metersPerUnit, double mapWidth, double mapHeight)
 {
-    // Initialize the layout map extents with the full map extent
-    Ptr<MgEnvelope> env = map->GetDataExtent();
-    Ptr<MgCoordinate> ll = env->GetLowerLeftCoordinate();
-    Ptr<MgCoordinate> ur = env->GetUpperRightCoordinate();
-
     // Compute the aspect ratio of the available map area
     double pageAR = mapWidth / mapHeight;
 

Modified: trunk/MgDev/Common/Renderers/DWFRenderer.cpp
===================================================================
--- trunk/MgDev/Common/Renderers/DWFRenderer.cpp	2009-09-11 00:36:51 UTC (rev 4218)
+++ trunk/MgDev/Common/Renderers/DWFRenderer.cpp	2009-09-11 04:46:39 UTC (rev 4219)
@@ -585,7 +585,7 @@
 
         if (workbuffer->cntr_count() == 1)
         {
-            // just a polygon, no need for a contourset
+            // just a polygon, no need for a contour set
             WT_Polygon polygon(workbuffer->point_count(), m_wtPointBuffer, false);
             polygon.serialize(*m_w2dFile);
             IncrementDrawableCount();
@@ -593,6 +593,11 @@
         else
         {
             // otherwise make a contour set
+
+            // ensure the contours are oriented per the DWF spec
+            OrientContours(workbuffer->cntr_count(), workbuffer->cntrs(), m_wtPointBuffer);
+
+            // now create the contour set
             WT_Contour_Set cset(*m_w2dFile, workbuffer->cntr_count(), (WT_Integer32*)workbuffer->cntrs(), workbuffer->point_count(), m_wtPointBuffer, true);
             cset.serialize(*m_w2dFile);
             IncrementDrawableCount();
@@ -675,9 +680,6 @@
 
     WriteStroke(lsym);
 
-    LineBuffer* workbuffer = srclb->Optimize(m_drawingScale, m_pPool);
-    std::auto_ptr<LineBuffer> spLB(workbuffer);
-
     bool oldLinePatternActive = m_linePatternActive;
 
     //determine pattern to apply
@@ -721,6 +723,9 @@
         m_w2dFile->desired_rendition().dash_pattern() = dpat;
     }
 
+    LineBuffer* workbuffer = srclb->Optimize(m_drawingScale, m_pPool);
+    std::auto_ptr<LineBuffer> spLB(workbuffer);
+
     WritePolylines(workbuffer);
 
     if (m_obsMesh)
@@ -2139,6 +2144,79 @@
 }
 
 
+//----------------------------------------------------------------------------
+//
+// Used by ProcessPolygon and DrawScreenPolygon to ensure that contours in
+// contour sets are oriented according to the DWF spec.  The spec requires
+// that filled areas be specified by clockwise wound points, and holes be
+// specified by counter-clockwise wound points.  So in our context the first
+// contour needs to be CW, and the remaining ones CCW.  The implementation
+// assumes simple contours (no self-intersection).
+//
+//----------------------------------------------------------------------------
+void DWFRenderer::OrientContours(int numContours, int* contourCounts, WT_Logical_Point* wtPointBuffer)
+{
+    if (numContours == 1)
+        return;
+
+    int start_pt = 0;
+    int end_pt = 0;
+
+    // iterate over the contours
+    for (int j=0; j<numContours; ++j)
+    {
+        // get point range for current contour
+        start_pt = end_pt;
+        end_pt += contourCounts[j];
+
+        if (contourCounts[j] < 2)
+            continue;
+
+        // compute area of current contour
+        double x0;
+        double y0;
+        double x1 = wtPointBuffer[end_pt-1].m_x;
+        double y1 = wtPointBuffer[end_pt-1].m_y;
+        double area2 = 0.0;
+        for (int i=start_pt; i<end_pt; ++i)
+        {
+            x0 = x1;
+            y0 = y1;
+            x1 = wtPointBuffer[i].m_x;
+            y1 = wtPointBuffer[i].m_y;
+            area2 += x0*y1 - y0*x1;
+        }
+
+        // the first contour (outer ring) needs to be CW (area < 0), and the
+        // remaining ones CCW (area > 0)
+        bool flipContour = false;
+        if (j == 0)
+        {
+            if (area2 > 0.0)
+                flipContour = true;
+        }
+        else if (area2 < 0.0)
+            flipContour = true;
+
+        if (flipContour)
+        {
+            int halfCount = contourCounts[j] / 2;
+            for (int i=0; i<halfCount; ++i)
+            {
+                int pt0 = start_pt + i;
+                int pt1 = end_pt - i - 1;
+                WT_Integer32 xTmp = wtPointBuffer[pt0].m_x;
+                WT_Integer32 yTmp = wtPointBuffer[pt0].m_y;
+                wtPointBuffer[pt0].m_x = wtPointBuffer[pt1].m_x;
+                wtPointBuffer[pt0].m_y = wtPointBuffer[pt1].m_y;
+                wtPointBuffer[pt1].m_x = xTmp;
+                wtPointBuffer[pt1].m_y = yTmp;
+            }
+        }
+    }
+}
+
+
 void DWFRenderer::SetSymbolManager(RS_SymbolManager* manager)
 {
     m_symbolManager = manager;
@@ -2440,7 +2518,7 @@
 
     if (geom->cntr_count() == 1)
     {
-        // just a polygon, no need for a contourset
+        // just a polygon, no need for a contour set
         WT_Polygon polygon(geom->point_count(), m_wtPointBuffer, false);
         polygon.serialize(*file);
         IncrementDrawableCount();
@@ -2448,6 +2526,11 @@
     else
     {
         // otherwise make a contour set
+
+        // ensure the contours are oriented per the DWF spec
+        OrientContours(geom->cntr_count(), geom->cntrs(), m_wtPointBuffer);
+
+        // now create the contour set
         WT_Contour_Set cset(*file, geom->cntr_count(), (WT_Integer32*)geom->cntrs(), geom->point_count(), m_wtPointBuffer, true);
         cset.serialize(*file);
         IncrementDrawableCount();

Modified: trunk/MgDev/Common/Renderers/DWFRenderer.h
===================================================================
--- trunk/MgDev/Common/Renderers/DWFRenderer.h	2009-09-11 00:36:51 UTC (rev 4218)
+++ trunk/MgDev/Common/Renderers/DWFRenderer.h	2009-09-11 04:46:39 UTC (rev 4219)
@@ -311,6 +311,10 @@
                              WT_Dash_Pattern& dash,
                              WT_Line_Pattern& lpat);
 
+    // used by ProcessPolygon and DrawScreenPolygon to ensure that contours in
+    // contour sets are oriented according to the DWF spec
+    void OrientContours(int numContours, int* contourCounts, WT_Logical_Point* wtPointBuffer);
+
     unsigned int m_nObjectId;
     void* m_hObjNodes;
 



More information about the mapguide-commits mailing list