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

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Jan 27 12:25:50 EST 2011


Author: mhugent
Date: 2011-01-27 09:25:50 -0800 (Thu, 27 Jan 2011)
New Revision: 15090

Modified:
   trunk/qgis/src/core/qgsclipper.cpp
   trunk/qgis/src/core/qgsclipper.h
   trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp
Log:
Use 'fast clip' line clipping algorithm for long lines. Huge improvement for wms benchmark performance (long contour lines)

Modified: trunk/qgis/src/core/qgsclipper.cpp
===================================================================
--- trunk/qgis/src/core/qgsclipper.cpp	2011-01-27 14:18:02 UTC (rev 15089)
+++ trunk/qgis/src/core/qgsclipper.cpp	2011-01-27 17:25:50 UTC (rev 15090)
@@ -35,3 +35,171 @@
 const double QgsClipper::MIN_Y = -16000;
 
 const double QgsClipper::SMALL_NUM = 1e-12;
+
+unsigned char* QgsClipper::clippedLineWKB( unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line )
+{
+  wkb++; // jump over endian info
+  unsigned int wkbType = *(( int* ) wkb );
+  wkb += sizeof( unsigned int );
+  unsigned int nPoints = *(( int* ) wkb );
+  wkb += sizeof( unsigned int );
+
+  bool hasZValue = ( wkbType == QGis::WKBLineString25D );
+
+  double p0x, p0y, p1x, p1y; //original coordinates
+  double p1x_c, p1y_c; //clipped end coordinates
+  double lastClipX, lastClipY; //last successfully clipped coords
+
+  line.reserve( nPoints + 1 );
+  line.clear();
+
+  for ( unsigned int i = 0; i < nPoints; ++i )
+  {
+    if ( i == 0 )
+    {
+      memcpy( &p1x, wkb, sizeof( double ) );
+      wkb += sizeof( double );
+      memcpy( &p1y, wkb, sizeof( double ) );
+      wkb += sizeof( double );
+      if ( hasZValue ) // ignore Z value
+      {
+        wkb += sizeof( double );
+      }
+      continue;
+    }
+    else
+    {
+      p0x = p1x;
+      p0y = p1y;
+
+      memcpy( &p1x, wkb, sizeof( double ) );
+      wkb += sizeof( double );
+      memcpy( &p1y, wkb, sizeof( double ) );
+      wkb += sizeof( double );
+      if ( hasZValue ) // ignore Z value
+      {
+        wkb += sizeof( double );
+      }
+
+      p1x_c = p1x; p1y_c = p1y;
+      if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(),
+                            p0x, p0y, p1x_c,  p1y_c ) )
+      {
+        bool newLine = line.size() > 0 && ( p1x_c != lastClipX || p1y_c != lastClipY );
+        if ( newLine )
+        {
+          //add edge points to connect old and new line
+          connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line );
+        }
+        if ( line.size() < 1 || newLine )
+        {
+          //add first point
+          line << QPointF( p0x, p0y );
+        }
+
+        //add second point
+        lastClipX = p1x_c; lastClipY = p1y_c;
+        line << QPointF( p1x_c,  p1y_c );
+      }
+    }
+  }
+  return wkb;
+}
+
+void QgsClipper::connectSeparatedLines( double x0, double y0, double x1, double y1,
+                                        const QgsRectangle& clipRect, QPolygonF& pts )
+{
+  //test the different edge combinations...
+  if ( doubleNear( x0, clipRect.xMinimum() ) )
+  {
+    if ( doubleNear( x1, clipRect.xMinimum() ) )
+    {
+      return;
+    }
+    else if ( doubleNear( y1, clipRect.yMaximum() ) )
+    {
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
+      return;
+    }
+    else if ( doubleNear( x1, clipRect.xMaximum() ) )
+    {
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
+      return;
+    }
+    else if ( doubleNear( y1, clipRect.yMinimum() ) )
+    {
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
+      return;
+    }
+  }
+  else if ( doubleNear( y0, clipRect.yMaximum() ) )
+  {
+    if ( doubleNear( y1, clipRect.yMaximum() ) )
+    {
+      return;
+    }
+    else if ( doubleNear( x1, clipRect.xMaximum() ) )
+    {
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
+      return;
+    }
+    else if ( doubleNear( y1, clipRect.yMinimum() ) )
+    {
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
+      return;
+    }
+    else if ( doubleNear( x1, clipRect.xMinimum() ) )
+    {
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
+      return;
+    }
+  }
+  else if ( doubleNear( x0, clipRect.xMaximum() ) )
+  {
+    if ( doubleNear( x1, clipRect.xMaximum() ) )
+    {
+      return;
+    }
+    else if ( doubleNear( y1, clipRect.yMinimum() ) )
+    {
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
+      return;
+    }
+    else if ( doubleNear( x1, clipRect.xMinimum() ) )
+    {
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
+      return;
+    }
+    else if ( doubleNear( y1, clipRect.yMaximum() ) )
+    {
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
+      return;
+    }
+  }
+  else if ( doubleNear( y0, clipRect.yMinimum() ) )
+  {
+    if ( doubleNear( y1, clipRect.yMinimum() ) )
+    {
+      return;
+    }
+    else if ( doubleNear( x1, clipRect.xMinimum() ) )
+    {
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
+      return;
+    }
+    else if ( doubleNear( y1, clipRect.yMaximum() ) )
+    {
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
+      pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
+      return;
+    }
+    else if ( doubleNear( x1, clipRect.xMaximum() ) )
+    {
+      pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
+      return;
+    }
+  }
+}

Modified: trunk/qgis/src/core/qgsclipper.h
===================================================================
--- trunk/qgis/src/core/qgsclipper.h	2011-01-27 14:18:02 UTC (rev 15089)
+++ trunk/qgis/src/core/qgsclipper.h	2011-01-27 17:25:50 UTC (rev 15090)
@@ -22,10 +22,13 @@
 
 #include "qgis.h"
 #include "qgspoint.h"
+#include "qgsrectangle.h"
 
 #include <vector>
 #include <utility>
 
+#include <QPolygonF>
+
 /** \ingroup core
  * A class to trim lines and polygons to within a rectangular region.
  * The functions in this class are likely to be called from within a
@@ -76,6 +79,12 @@
                              std::vector<double>& y,
                              bool shapeOpen );
 
+    /**Reads a polyline from WKB and clips it to clipExtent
+      @param wkb pointer to the start of the line wkb
+      @param clipExtent clipping bounds
+      @param line out: clipped line coordinates*/
+    static unsigned char* clippedLineWKB( unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line );
+
   private:
 
     // Used when testing for equivalance to 0.0
@@ -98,6 +107,30 @@
     static QgsPoint intersect( const double x1, const double y1,
                                const double x2, const double y2,
                                Boundary b );
+
+    //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 );
+
+    /**Connects two lines splitted by the clip (by inserting points on the clip border)
+      @param x0 x-coordinate of the first line end
+      @param y0 y-coordinate of the first line end
+      @param x1 x-coordinate of the second line start
+      @param y1 y-coordinate of the second line start
+      @param clipRect clip rectangle
+      @param pts: in/out array of clipped points
+      @param writePtr in/out: writing poisiton in the wkb array*/
+    static void connectSeparatedLines( double x0, double y0, double x1, double y1,
+                                       const QgsRectangle& clipRect, QPolygonF& pts );
+
+    //low level clip methods for fast clip algorithm
+    static void clipStartTop( double& x0, double& y0, const double& x1, const double& y1, double yMax );
+    static void clipStartBottom( double& x0, double& y0, const double& x1, const double& y1, double yMin );
+    static void clipStartRight( double& x0, double& y0, const double& x1, const double& y1, double xMax );
+    static void clipStartLeft( double& x0, double& y0, const double& x1, const double& y1, double xMin );
+    static void clipEndTop( const double& x0, const double& y0, double& x1, double& y1, double yMax );
+    static void clipEndBottom( const double& x0, const double& y0, double& x1, double& y1, double yMin );
+    static void clipEndRight( const double& x0, const double& y0, double& x1, double& y1, double xMax );
+    static void clipEndLeft( const double& x0, const double& y0, double& x1, double& y1, double xMin );
 };
 
 // The inline functions
@@ -283,5 +316,442 @@
   return p;
 }
 
+inline void QgsClipper::clipStartTop( double& x0, double& y0, const double& x1, const double& y1, double yMax )
+{
+  x0 += ( x1 - x0 )  * ( yMax - y0 ) / ( y1 - y0 );
+  y0 = yMax;
+}
 
+inline void QgsClipper::clipStartBottom( double& x0, double& y0, const double& x1, const double& y1, double yMin )
+{
+  x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
+  y0 = yMin;
+}
+
+inline void QgsClipper::clipStartRight( double& x0, double& y0, const double& x1, const double& y1, double xMax )
+{
+  y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
+  x0 = xMax;
+}
+
+inline void QgsClipper::clipStartLeft( double& x0, double& y0, const double& x1, const double& y1, double xMin )
+{
+  y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
+  x0 = xMin;
+}
+
+inline void QgsClipper::clipEndTop( const double& x0, const double& y0, double& x1, double& y1, double yMax )
+{
+  x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
+  y1 = yMax;
+}
+
+inline void QgsClipper::clipEndBottom( const double& x0, const double& y0, double& x1, double& y1, double yMin )
+{
+  x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
+  y1 = yMin;
+}
+
+inline void QgsClipper::clipEndRight( const double& x0, const double& y0, double& x1, double& y1, double xMax )
+{
+  y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
+  x1 = xMax;
+}
+
+inline void QgsClipper::clipEndLeft( const double& x0, const double& y0, double& x1, double& y1, double xMin )
+{
+  y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
+  x1 = xMin;
+}
+
+//'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
+inline bool QgsClipper::clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 )
+{
+  int lineCode = 0;
+
+  if ( y1 < yBottom )
+    lineCode |= 4;
+  else if ( y1 > yTop )
+    lineCode |= 8;
+
+  if ( x1 > xRight )
+    lineCode |= 2;
+  else if ( x1 < xLeft )
+    lineCode |= 1;
+
+  if ( y0 < yBottom )
+    lineCode |= 64;
+  else if ( y0 > yTop )
+    lineCode |= 128;
+
+  if ( x0 > xRight )
+    lineCode |= 32;
+  else if ( x0 < xLeft )
+    lineCode |= 16;
+
+  switch ( lineCode )
+  {
+    case 0: //completely inside
+      return true;
+
+    case 1:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 2:
+      clipEndRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 4:
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 5:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 6:
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 8:
+      clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 9:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 > yTop )
+        clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 10:
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 > yTop )
+        clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 16:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 18:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      clipEndRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 20:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 < yBottom )
+        return false;
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 22:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 < yBottom )
+        return false;
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      if ( x1 > xRight )
+        clipEndRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 24:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 > yTop )
+        return false;
+      clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 26:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 > yTop )
+        return false;
+      clipEndTop( x0, y0, x1, y1, yTop );
+      if ( x1 > xRight )
+        clipEndRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 32:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 33:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 36:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 < yBottom )
+        return false;
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 37:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 < yBottom )
+        return false;
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      if ( x1 < xLeft )
+        clipEndLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 40:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 > yTop )
+        return false;
+      clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 41:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 > yTop )
+        return false;
+      clipEndTop( x0, y0, x1, y1, yTop );
+      if ( x1 < xLeft )
+        clipEndLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 64:
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 65:
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 < xLeft )
+        return false;
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 66:
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 > xRight )
+        return false;
+      clipEndRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 72:
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 73:
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 < xLeft )
+        return false;
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 > yTop )
+        clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 74:
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 > xRight )
+        return false;
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 > yTop )
+        clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 80:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 < yBottom )
+        clipStartBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 82:
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 < yBottom )
+        return false;
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 < xLeft )
+        clipStartLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 88:
+      clipEndTop( x0, y0, x1, y1, yTop );
+      if ( x1 < xLeft )
+        return false;
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 < xLeft )
+        clipStartLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 90:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 > yTop )
+        return false;
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 < yBottom )
+        return false;
+      if ( y0 < yBottom )
+        clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( y1 > yTop )
+        clipEndTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 96:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 < yBottom )
+        clipStartBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 97:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 < yBottom )
+        return false;
+      clipStartBottom( x0, y0, x1, y1, yBottom );
+      if ( x0 > xRight )
+        clipStartRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 104:
+      clipEndTop( x0, y0, x1, y1, yTop );
+      if ( x1 > xRight )
+        return false;
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 < yBottom )
+        clipStartBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 105:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 < yBottom )
+        return false;
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 > yTop )
+        return false;
+      if ( y1 > yTop )
+        clipEndTop( x0, y0, x1, y1, yTop );
+      if ( y0 < yBottom )
+        clipStartBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 128:
+      clipStartTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 129:
+      clipStartTop( x0, y0, x1, y1, yTop );
+      if ( x0 < xLeft )
+        return false;
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 130:
+      clipStartTop( x0, y0, x1, y1, yTop );
+      if ( x0 > xRight )
+        return false;
+      clipEndRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 132:
+      clipStartTop( x0, y0, x1, y1, yTop );
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 133:
+      clipStartTop( x0, y0, x1, y1, yTop );
+      if ( x0 < xLeft )
+        return false;
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 134:
+      clipStartTop( x0, y0, x1, y1, yTop );
+      if ( x0 > xRight )
+        return false;
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 144:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 > yTop )
+        clipStartTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 146:
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 > yTop )
+        return false;
+      clipStartTop( x0, y0, x1, y1, yTop );
+      if ( x0 < xLeft )
+        clipStartLeft( x0, y0, x1, y1, xLeft );
+      return true;
+
+    case 148:
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      if ( x1 < xLeft )
+        return false;
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 > yTop )
+        clipStartTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 150:
+      clipStartLeft( x0, y0, x1, y1, xLeft );
+      if ( y0 < yBottom )
+        return false;
+      clipEndRight( x0, y0, x1, y1, xRight );
+      if ( y1 > yTop )
+        return false;
+      if ( y0 > yTop )
+        clipStartTop( x0, y0, x1, y1, yTop );
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      return true;
+
+    case 160:
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 > yTop )
+        clipStartTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 161:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 > yTop )
+        return false;
+      clipStartTop( x0, y0, x1, y1, yTop );
+      if ( x0 > xRight )
+        clipStartRight( x0, y0, x1, y1, xRight );
+      return true;
+
+    case 164:
+      clipEndBottom( x0, y0, x1, y1, yBottom );
+      if ( x1 > xRight )
+        return false;
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 > yTop )
+        clipStartTop( x0, y0, x1, y1, yTop );
+      return true;
+
+    case 165:
+      clipEndLeft( x0, y0, x1, y1, xLeft );
+      if ( y1 > yTop )
+        return false;
+      clipStartRight( x0, y0, x1, y1, xRight );
+      if ( y0 < yBottom )
+        return false;
+      if ( y1 < yBottom )
+        clipEndBottom( x0, y0, x1, y1, yBottom );
+      if ( y0 > yTop )
+        clipStartTop( x0, y0, x1, y1, yTop );
+      return true;
+  }
+
+  return false;
+
+}
+
+
 #endif

Modified: trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp	2011-01-27 14:18:02 UTC (rev 15089)
+++ trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp	2011-01-27 17:25:50 UTC (rev 15090)
@@ -8,6 +8,7 @@
 #include "qgsrendererv2registry.h"
 
 #include "qgsrendercontext.h"
+#include "qgsclipper.h"
 #include "qgsgeometry.h"
 #include "qgsfeature.h"
 #include "qgslogger.h"
@@ -54,31 +55,45 @@
   bool hasZValue = ( wkbType == QGis::WKBLineString25D );
   double x, y;
 
-  pts.resize( nPoints );
-
   const QgsCoordinateTransform* ct = context.coordinateTransform();
   const QgsMapToPixel& mtp = context.mapToPixel();
   double z = 0; // dummy variable for coordiante transform
 
-  for ( unsigned int i = 0; i < nPoints; ++i )
+  //apply clipping for large lines to achieve a better rendering performance
+  if ( nPoints > 100 )
   {
-    x = *(( double * ) wkb );
-    wkb += sizeof( double );
-    y = *(( double * ) wkb );
-    wkb += sizeof( double );
+    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 );
+    wkb = QgsClipper::clippedLineWKB( wkb - ( 2 * sizeof( unsigned int ) + 1 ), clipRect, pts );
+  }
+  else
+  {
+    pts.resize( nPoints );
 
-    if ( hasZValue ) // ignore Z value
+    for ( unsigned int i = 0; i < nPoints; ++i )
+    {
+      x = *(( double * ) wkb );
       wkb += sizeof( double );
+      y = *(( double * ) wkb );
+      wkb += sizeof( double );
 
-    // TODO: maybe to the transform at once (faster?)
-    if ( ct )
-      ct->transformInPlace( x, y, z );
-    mtp.transformInPlace( x, y );
+      if ( hasZValue ) // ignore Z value
+        wkb += sizeof( double );
 
-    pts[i] = QPointF( x, y );
+      pts[i] = QPointF( x, y );
+    }
+  }
 
+  //transform the QPolygonF to screen coordinates
+  for ( unsigned int i = 0; i < pts.size(); ++i )
+  {
+    if ( ct )
+      ct->transformInPlace( pts[i].rx(), pts[i].ry(), z );
+    mtp.transformInPlace( pts[i].rx(), pts[i].ry() );
   }
 
+
   return wkb;
 }
 



More information about the QGIS-commit mailing list