Skip to content
Permalink
Browse files

Use 'fast clip' line clipping algorithm for long lines. Huge improvem…

…ent for wms benchmark performance (long contour lines)

git-svn-id: http://svn.osgeo.org/qgis/trunk@15090 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent
mhugent committed Jan 27, 2011
1 parent 406ce0d commit d4f69b3724e95cd5699005b0c49ad46381f78040
Showing with 666 additions and 13 deletions.
  1. +168 −0 src/core/qgsclipper.cpp
  2. +470 −0 src/core/qgsclipper.h
  3. +28 −13 src/core/symbology-ng/qgsrendererv2.cpp
@@ -35,3 +35,171 @@ const double QgsClipper::MAX_Y = 16000;
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;
}
}
}

0 comments on commit d4f69b3

Please sign in to comment.
You can’t perform that action at this time.