[QGIS Commit] r15547 - in trunk/qgis/src/core: . symbology-ng

svn_qgis at osgeo.org svn_qgis at osgeo.org
Mon Mar 21 04:08:43 EDT 2011


Author: mhugent
Date: 2011-03-21 01:08:43 -0700 (Mon, 21 Mar 2011)
New Revision: 15547

Modified:
   trunk/qgis/src/core/qgsclipper.h
   trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp
   trunk/qgis/src/core/symbology-ng/qgssymbollayerv2.cpp
Log:
Modify polygon clipping to clip close to the drawing rectangle. Should now solve the clipping for print composer too 

Modified: trunk/qgis/src/core/qgsclipper.h
===================================================================
--- trunk/qgis/src/core/qgsclipper.h	2011-03-20 22:47:02 UTC (rev 15546)
+++ trunk/qgis/src/core/qgsclipper.h	2011-03-21 08:08:43 UTC (rev 15547)
@@ -79,7 +79,7 @@
                              std::vector<double>& y,
                              bool shapeOpen );
 
-    static void trimFeature( QPolygonF& pts, bool shapeOpen );
+    static void trimPolygon( QPolygonF& pts, const QgsRectangle& clipRect );
 
     /**Reads a polyline from WKB and clips it to clipExtent
       @param wkb pointer to the start of the line wkb
@@ -101,15 +101,12 @@
                                        Boundary b,
                                        bool shapeOpen );
 
-    static void trimFeatureToBoundary( const QPolygonF& inPts,
-                                       QPolygonF& outPts,
-                                       Boundary b,
-                                       bool shapeOpen );
+    static void trimPolygonToBoundary( const QPolygonF& inPts, QPolygonF& outPts, const QgsRectangle& rect, Boundary b, double boundaryValue );
 
     // Determines if a point is inside or outside the given boundary
     static bool inside( const double x, const double y, Boundary b );
 
-    static bool inside( const QPointF& pt, Boundary b );
+    static bool inside( const QPointF& pt, Boundary b, double val );
 
     // Calculates the intersection point between a line defined by a
     // (x1, y1), and (x2, y2) and the given boundary
@@ -117,9 +114,9 @@
                                const double x2, const double y2,
                                Boundary b );
 
-    static QPointF intersect( const QPointF& pt1,
-                              const QPointF& pt2,
-                              Boundary b );
+    static QPointF intersectRect( const QPointF& pt1,
+                                  const QPointF& pt2,
+                                  Boundary b, const QgsRectangle& rect );
 
     //Implementation of 'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
     static bool clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 );
@@ -179,34 +176,18 @@
   trimFeatureToBoundary( tmpX, tmpY, x, y, YMin, shapeOpen );
 }
 
-inline void QgsClipper::trimFeature( QPolygonF& pts, bool shapeOpen )
+inline void QgsClipper::trimPolygon( QPolygonF& pts, const QgsRectangle& clipRect )
 {
-  bool needs_clipping = false;
-  const QPointF* ptsData = pts.constData();
-  for ( int i = 0; i < pts.count(); i++, ptsData++ )
-  {
-    if ( ptsData->x() < MIN_X || ptsData->x() > MAX_X
-         || ptsData->y() < MIN_Y || ptsData->y() > MAX_Y )
-    {
-      needs_clipping = true;
-      break;
-    }
-  }
-  if ( !needs_clipping )
-    return;
-
   QPolygonF tmpPts;
   tmpPts.reserve( pts.size() );
-  trimFeatureToBoundary( pts, tmpPts, XMax, shapeOpen );
 
+  trimPolygonToBoundary( pts, tmpPts, clipRect, XMax, clipRect.xMaximum() );
   pts.clear();
-  trimFeatureToBoundary( tmpPts, pts, YMax, shapeOpen );
-
+  trimPolygonToBoundary( tmpPts, pts, clipRect, YMax, clipRect.yMaximum() );
   tmpPts.clear();
-  trimFeatureToBoundary( pts, tmpPts, XMin, shapeOpen );
-
+  trimPolygonToBoundary( pts, tmpPts, clipRect, XMin, clipRect.xMinimum() );
   pts.clear();
-  trimFeatureToBoundary( tmpPts, pts, YMin, shapeOpen );
+  trimPolygonToBoundary( tmpPts, pts, clipRect, YMin, clipRect.yMinimum() );
 }
 
 // An auxilary function that is part of the polygon trimming
@@ -280,22 +261,16 @@
   }
 }
 
-inline void QgsClipper::trimFeatureToBoundary(
-  const QPolygonF& inPts, QPolygonF& outPts,
-  Boundary b, bool shapeOpen )
+inline void QgsClipper::trimPolygonToBoundary( const QPolygonF& inPts, QPolygonF& outPts, const QgsRectangle& rect, Boundary b, double boundaryValue )
 {
-  // The shapeOpen parameter selects whether this function treats the
-  // shape as open or closed. False is appropriate for polygons and
-  // true for polylines.
-
   unsigned int i1 = inPts.size() - 1; // start with last point
 
   // and compare to the first point initially.
   for ( int i2 = 0; i2 < inPts.size() ; ++i2 )
   { // look at each edge of the polygon in turn
-    if ( inside( inPts[i2], b ) ) // end point of edge is inside boundary
+    if ( inside( inPts[i2], b, boundaryValue ) ) // end point of edge is inside boundary
     {
-      if ( inside( inPts[i1], b ) )
+      if ( inside( inPts[i1], b, boundaryValue ) )
       {
         outPts.append( inPts[i2] );
       }
@@ -303,23 +278,16 @@
       {
         // edge crosses into the boundary, so trim back to the boundary, and
         // store both ends of the new edge
-        if ( !( i2 == 0 && shapeOpen ) )
-        {
-          outPts.append( intersect( inPts[i1], inPts[i2], b ) );
-        }
-
+        outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
         outPts.append( inPts[i2] );
       }
     }
     else // end point of edge is outside boundary
     {
       // start point is in boundary, so need to trim back
-      if ( inside( inPts[i1], b ) )
+      if ( inside( inPts[i1], b, boundaryValue ) )
       {
-        if ( !( i2 == 0 && shapeOpen ) )
-        {
-          outPts.append( intersect( inPts[i1], inPts[i2], b ) );
-        }
+        outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
       }
     }
     i1 = i2;
@@ -353,18 +321,18 @@
   return false;
 }
 
-inline bool QgsClipper::inside( const QPointF& pt, Boundary b )
+inline bool QgsClipper::inside( const QPointF& pt, Boundary b, double val )
 {
   switch ( b )
   {
     case XMax: // x < MAX_X is inside
-      return ( pt.x() < MAX_X );
+      return ( pt.x() < val );
     case XMin: // x > MIN_X is inside
-      return ( pt.x() > MIN_X );
+      return ( pt.x() > val );
     case YMax: // y < MAX_Y is inside
-      return ( pt.y() < MAX_Y );
+      return ( pt.y() < val );
     case YMin: // y > MIN_Y is inside
-      return ( pt.y() > MIN_Y );
+      return ( pt.y() > val );
   }
   return false;
 }
@@ -421,9 +389,9 @@
   return p;
 }
 
-inline QPointF QgsClipper::intersect( const QPointF& pt1,
-                                      const QPointF& pt2,
-                                      Boundary b )
+inline QPointF QgsClipper::intersectRect( const QPointF& pt1,
+    const QPointF& pt2,
+    Boundary b, const QgsRectangle& rect )
 {
   // This function assumes that the two given points (x1, y1), and
   // (x2, y2) cross the given boundary. Making this assumption allows
@@ -436,20 +404,20 @@
   switch ( b )
   {
     case XMax: // x = MAX_X boundary
-      r_n = -( x1 - MAX_X ) * ( MAX_Y - MIN_Y );
-      r_d = ( x2 - x1 )   * ( MAX_Y - MIN_Y );
+      r_n = -( x1 - rect.xMaximum() ) * ( rect.yMaximum() - rect.yMinimum() );
+      r_d = ( x2 - x1 )   * ( rect.yMaximum() - rect.yMinimum() );
       break;
     case XMin: // x = MIN_X boundary
-      r_n = -( x1 - MIN_X ) * ( MAX_Y - MIN_Y );
-      r_d = ( x2 - x1 )   * ( MAX_Y - MIN_Y );
+      r_n = -( x1 - rect.xMinimum() ) * ( rect.yMaximum() - rect.yMinimum() );
+      r_d = ( x2 - x1 )   * ( rect.yMaximum() - rect.yMinimum() );
       break;
     case YMax: // y = MAX_Y boundary
-      r_n = ( y1 - MAX_Y ) * ( MAX_X - MIN_X );
-      r_d = -( y2 - y1 )   * ( MAX_X - MIN_X );
+      r_n = ( y1 - rect.yMaximum() ) * ( rect.xMaximum() - rect.xMinimum() );
+      r_d = -( y2 - y1 )   * ( rect.xMaximum() - rect.xMinimum() );
       break;
     case YMin: // y = MIN_Y boundary
-      r_n = ( y1 - MIN_Y ) * ( MAX_X - MIN_X );
-      r_d = -( y2 - y1 )   * ( MAX_X - MIN_X );
+      r_n = ( y1 - rect.yMinimum() ) * ( rect.xMaximum() - rect.xMinimum() );
+      r_d = -( y2 - y1 )   * ( rect.xMaximum() - rect.xMinimum() );
       break;
   }
 

Modified: trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp	2011-03-20 22:47:02 UTC (rev 15546)
+++ trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp	2011-03-21 08:08:43 UTC (rev 15547)
@@ -118,6 +118,10 @@
   const QgsMapToPixel& mtp = context.mapToPixel();
   double z = 0; // dummy variable for coordiante transform
 
+  const QgsRectangle& e = context.extent();
+  double cw = e.width() / 10; double ch = e.height() / 10;
+  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
+
   for ( unsigned int idx = 0; idx < numRings; idx++ )
   {
     unsigned int nPoints = *(( int* )wkb );
@@ -131,14 +135,6 @@
       x = *(( double * ) wkb ); wkb += sizeof( double );
       y = *(( double * ) wkb ); wkb += sizeof( double );
 
-      // TODO: maybe to the transform at once (faster?)
-      if ( ct )
-      {
-        z = 0;
-        ct->transformInPlace( x, y, z );
-      }
-      mtp.transformInPlace( x, y );
-
       poly[jdx] = QPointF( x, y );
 
       if ( hasZValue )
@@ -148,6 +144,20 @@
     if ( nPoints < 1 )
       continue;
 
+    //clip close to view extent
+    QgsClipper::trimPolygon( poly, clipRect );
+
+    //transform the QPolygonF to screen coordinates
+    for ( int i = 0; i < poly.size(); ++i )
+    {
+      if ( ct )
+      {
+        z = 0;
+        ct->transformInPlace( poly[i].rx(), poly[i].ry(), z );
+      }
+      mtp.transformInPlace( poly[i].rx(), poly[i].ry() );
+    }
+
     if ( idx == 0 )
       pts = poly;
     else

Modified: trunk/qgis/src/core/symbology-ng/qgssymbollayerv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgssymbollayerv2.cpp	2011-03-20 22:47:02 UTC (rev 15546)
+++ trunk/qgis/src/core/symbology-ng/qgssymbollayerv2.cpp	2011-03-21 08:08:43 UTC (rev 15547)
@@ -74,27 +74,19 @@
   if ( rings == NULL )
   {
     // simple polygon without holes
-
-    // clip polygon rings! Qt (as of version 4.6) has a slow algorithm for
-    // clipping painter paths: we will clip the rings by ourselves, so
-    // the clipping in Qt will not be triggered.
-    QPolygonF ring = points;
-    QgsClipper::trimFeature( ring, false );
-    p->drawPolygon( ring );
+    p->drawPolygon( points );
   }
   else
   {
     // polygon with holes must be drawn using painter path
     QPainterPath path;
     QPolygonF outerRing = points;
-    QgsClipper::trimFeature( outerRing, false );
     path.addPolygon( outerRing );
 
     QList<QPolygonF>::const_iterator it = rings->constBegin();
     for ( ; it != rings->constEnd(); ++it )
     {
       QPolygonF ring = *it;
-      QgsClipper::trimFeature( ring, false );
       path.addPolygon( ring );
     }
 



More information about the QGIS-commit mailing list