Skip to content

Commit c0b6f68

Browse files
author
mhugent
committedJan 27, 2011
Use 'fast clip' line clipping algorithm for long lines. Huge improvement for wms benchmark performance (long contour lines)
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@15090 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

3 files changed

+666
-13
lines changed

3 files changed

+666
-13
lines changed
 

‎src/core/qgsclipper.cpp

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,171 @@ const double QgsClipper::MAX_Y = 16000;
3535
const double QgsClipper::MIN_Y = -16000;
3636

3737
const double QgsClipper::SMALL_NUM = 1e-12;
38+
39+
unsigned char* QgsClipper::clippedLineWKB( unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line )
40+
{
41+
wkb++; // jump over endian info
42+
unsigned int wkbType = *(( int* ) wkb );
43+
wkb += sizeof( unsigned int );
44+
unsigned int nPoints = *(( int* ) wkb );
45+
wkb += sizeof( unsigned int );
46+
47+
bool hasZValue = ( wkbType == QGis::WKBLineString25D );
48+
49+
double p0x, p0y, p1x, p1y; //original coordinates
50+
double p1x_c, p1y_c; //clipped end coordinates
51+
double lastClipX, lastClipY; //last successfully clipped coords
52+
53+
line.reserve( nPoints + 1 );
54+
line.clear();
55+
56+
for ( unsigned int i = 0; i < nPoints; ++i )
57+
{
58+
if ( i == 0 )
59+
{
60+
memcpy( &p1x, wkb, sizeof( double ) );
61+
wkb += sizeof( double );
62+
memcpy( &p1y, wkb, sizeof( double ) );
63+
wkb += sizeof( double );
64+
if ( hasZValue ) // ignore Z value
65+
{
66+
wkb += sizeof( double );
67+
}
68+
continue;
69+
}
70+
else
71+
{
72+
p0x = p1x;
73+
p0y = p1y;
74+
75+
memcpy( &p1x, wkb, sizeof( double ) );
76+
wkb += sizeof( double );
77+
memcpy( &p1y, wkb, sizeof( double ) );
78+
wkb += sizeof( double );
79+
if ( hasZValue ) // ignore Z value
80+
{
81+
wkb += sizeof( double );
82+
}
83+
84+
p1x_c = p1x; p1y_c = p1y;
85+
if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(),
86+
p0x, p0y, p1x_c, p1y_c ) )
87+
{
88+
bool newLine = line.size() > 0 && ( p1x_c != lastClipX || p1y_c != lastClipY );
89+
if ( newLine )
90+
{
91+
//add edge points to connect old and new line
92+
connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line );
93+
}
94+
if ( line.size() < 1 || newLine )
95+
{
96+
//add first point
97+
line << QPointF( p0x, p0y );
98+
}
99+
100+
//add second point
101+
lastClipX = p1x_c; lastClipY = p1y_c;
102+
line << QPointF( p1x_c, p1y_c );
103+
}
104+
}
105+
}
106+
return wkb;
107+
}
108+
109+
void QgsClipper::connectSeparatedLines( double x0, double y0, double x1, double y1,
110+
const QgsRectangle& clipRect, QPolygonF& pts )
111+
{
112+
//test the different edge combinations...
113+
if ( doubleNear( x0, clipRect.xMinimum() ) )
114+
{
115+
if ( doubleNear( x1, clipRect.xMinimum() ) )
116+
{
117+
return;
118+
}
119+
else if ( doubleNear( y1, clipRect.yMaximum() ) )
120+
{
121+
pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
122+
return;
123+
}
124+
else if ( doubleNear( x1, clipRect.xMaximum() ) )
125+
{
126+
pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
127+
pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
128+
return;
129+
}
130+
else if ( doubleNear( y1, clipRect.yMinimum() ) )
131+
{
132+
pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
133+
return;
134+
}
135+
}
136+
else if ( doubleNear( y0, clipRect.yMaximum() ) )
137+
{
138+
if ( doubleNear( y1, clipRect.yMaximum() ) )
139+
{
140+
return;
141+
}
142+
else if ( doubleNear( x1, clipRect.xMaximum() ) )
143+
{
144+
pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
145+
return;
146+
}
147+
else if ( doubleNear( y1, clipRect.yMinimum() ) )
148+
{
149+
pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
150+
pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
151+
return;
152+
}
153+
else if ( doubleNear( x1, clipRect.xMinimum() ) )
154+
{
155+
pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
156+
return;
157+
}
158+
}
159+
else if ( doubleNear( x0, clipRect.xMaximum() ) )
160+
{
161+
if ( doubleNear( x1, clipRect.xMaximum() ) )
162+
{
163+
return;
164+
}
165+
else if ( doubleNear( y1, clipRect.yMinimum() ) )
166+
{
167+
pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
168+
return;
169+
}
170+
else if ( doubleNear( x1, clipRect.xMinimum() ) )
171+
{
172+
pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
173+
pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
174+
return;
175+
}
176+
else if ( doubleNear( y1, clipRect.yMaximum() ) )
177+
{
178+
pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
179+
return;
180+
}
181+
}
182+
else if ( doubleNear( y0, clipRect.yMinimum() ) )
183+
{
184+
if ( doubleNear( y1, clipRect.yMinimum() ) )
185+
{
186+
return;
187+
}
188+
else if ( doubleNear( x1, clipRect.xMinimum() ) )
189+
{
190+
pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
191+
return;
192+
}
193+
else if ( doubleNear( y1, clipRect.yMaximum() ) )
194+
{
195+
pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
196+
pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
197+
return;
198+
}
199+
else if ( doubleNear( x1, clipRect.xMaximum() ) )
200+
{
201+
pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
202+
return;
203+
}
204+
}
205+
}

‎src/core/qgsclipper.h

Lines changed: 470 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222

2323
#include "qgis.h"
2424
#include "qgspoint.h"
25+
#include "qgsrectangle.h"
2526

2627
#include <vector>
2728
#include <utility>
2829

30+
#include <QPolygonF>
31+
2932
/** \ingroup core
3033
* A class to trim lines and polygons to within a rectangular region.
3134
* The functions in this class are likely to be called from within a
@@ -76,6 +79,12 @@ class CORE_EXPORT QgsClipper
7679
std::vector<double>& y,
7780
bool shapeOpen );
7881

82+
/**Reads a polyline from WKB and clips it to clipExtent
83+
@param wkb pointer to the start of the line wkb
84+
@param clipExtent clipping bounds
85+
@param line out: clipped line coordinates*/
86+
static unsigned char* clippedLineWKB( unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line );
87+
7988
private:
8089

8190
// Used when testing for equivalance to 0.0
@@ -98,6 +107,30 @@ class CORE_EXPORT QgsClipper
98107
static QgsPoint intersect( const double x1, const double y1,
99108
const double x2, const double y2,
100109
Boundary b );
110+
111+
//Implementation of 'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
112+
static bool clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 );
113+
114+
/**Connects two lines splitted by the clip (by inserting points on the clip border)
115+
@param x0 x-coordinate of the first line end
116+
@param y0 y-coordinate of the first line end
117+
@param x1 x-coordinate of the second line start
118+
@param y1 y-coordinate of the second line start
119+
@param clipRect clip rectangle
120+
@param pts: in/out array of clipped points
121+
@param writePtr in/out: writing poisiton in the wkb array*/
122+
static void connectSeparatedLines( double x0, double y0, double x1, double y1,
123+
const QgsRectangle& clipRect, QPolygonF& pts );
124+
125+
//low level clip methods for fast clip algorithm
126+
static void clipStartTop( double& x0, double& y0, const double& x1, const double& y1, double yMax );
127+
static void clipStartBottom( double& x0, double& y0, const double& x1, const double& y1, double yMin );
128+
static void clipStartRight( double& x0, double& y0, const double& x1, const double& y1, double xMax );
129+
static void clipStartLeft( double& x0, double& y0, const double& x1, const double& y1, double xMin );
130+
static void clipEndTop( const double& x0, const double& y0, double& x1, double& y1, double yMax );
131+
static void clipEndBottom( const double& x0, const double& y0, double& x1, double& y1, double yMin );
132+
static void clipEndRight( const double& x0, const double& y0, double& x1, double& y1, double xMax );
133+
static void clipEndLeft( const double& x0, const double& y0, double& x1, double& y1, double xMin );
101134
};
102135

103136
// The inline functions
@@ -283,5 +316,442 @@ inline QgsPoint QgsClipper::intersect( const double x1, const double y1,
283316
return p;
284317
}
285318

319+
inline void QgsClipper::clipStartTop( double& x0, double& y0, const double& x1, const double& y1, double yMax )
320+
{
321+
x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
322+
y0 = yMax;
323+
}
324+
325+
inline void QgsClipper::clipStartBottom( double& x0, double& y0, const double& x1, const double& y1, double yMin )
326+
{
327+
x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
328+
y0 = yMin;
329+
}
330+
331+
inline void QgsClipper::clipStartRight( double& x0, double& y0, const double& x1, const double& y1, double xMax )
332+
{
333+
y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
334+
x0 = xMax;
335+
}
336+
337+
inline void QgsClipper::clipStartLeft( double& x0, double& y0, const double& x1, const double& y1, double xMin )
338+
{
339+
y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
340+
x0 = xMin;
341+
}
342+
343+
inline void QgsClipper::clipEndTop( const double& x0, const double& y0, double& x1, double& y1, double yMax )
344+
{
345+
x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
346+
y1 = yMax;
347+
}
348+
349+
inline void QgsClipper::clipEndBottom( const double& x0, const double& y0, double& x1, double& y1, double yMin )
350+
{
351+
x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
352+
y1 = yMin;
353+
}
354+
355+
inline void QgsClipper::clipEndRight( const double& x0, const double& y0, double& x1, double& y1, double xMax )
356+
{
357+
y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
358+
x1 = xMax;
359+
}
360+
361+
inline void QgsClipper::clipEndLeft( const double& x0, const double& y0, double& x1, double& y1, double xMin )
362+
{
363+
y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
364+
x1 = xMin;
365+
}
366+
367+
//'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
368+
inline bool QgsClipper::clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 )
369+
{
370+
int lineCode = 0;
371+
372+
if ( y1 < yBottom )
373+
lineCode |= 4;
374+
else if ( y1 > yTop )
375+
lineCode |= 8;
376+
377+
if ( x1 > xRight )
378+
lineCode |= 2;
379+
else if ( x1 < xLeft )
380+
lineCode |= 1;
381+
382+
if ( y0 < yBottom )
383+
lineCode |= 64;
384+
else if ( y0 > yTop )
385+
lineCode |= 128;
386+
387+
if ( x0 > xRight )
388+
lineCode |= 32;
389+
else if ( x0 < xLeft )
390+
lineCode |= 16;
391+
392+
switch ( lineCode )
393+
{
394+
case 0: //completely inside
395+
return true;
396+
397+
case 1:
398+
clipEndLeft( x0, y0, x1, y1, xLeft );
399+
return true;
400+
401+
case 2:
402+
clipEndRight( x0, y0, x1, y1, xRight );
403+
return true;
404+
405+
case 4:
406+
clipEndBottom( x0, y0, x1, y1, yBottom );
407+
return true;
408+
409+
case 5:
410+
clipEndLeft( x0, y0, x1, y1, xLeft );
411+
if ( y1 < yBottom )
412+
clipEndBottom( x0, y0, x1, y1, yBottom );
413+
return true;
414+
415+
case 6:
416+
clipEndRight( x0, y0, x1, y1, xRight );
417+
if ( y1 < yBottom )
418+
clipEndBottom( x0, y0, x1, y1, yBottom );
419+
return true;
420+
421+
case 8:
422+
clipEndTop( x0, y0, x1, y1, yTop );
423+
return true;
424+
425+
case 9:
426+
clipEndLeft( x0, y0, x1, y1, xLeft );
427+
if ( y1 > yTop )
428+
clipEndTop( x0, y0, x1, y1, yTop );
429+
return true;
430+
431+
case 10:
432+
clipEndRight( x0, y0, x1, y1, xRight );
433+
if ( y1 > yTop )
434+
clipEndTop( x0, y0, x1, y1, yTop );
435+
return true;
436+
437+
case 16:
438+
clipStartLeft( x0, y0, x1, y1, xLeft );
439+
return true;
440+
441+
case 18:
442+
clipStartLeft( x0, y0, x1, y1, xLeft );
443+
clipEndRight( x0, y0, x1, y1, xRight );
444+
return true;
445+
446+
case 20:
447+
clipStartLeft( x0, y0, x1, y1, xLeft );
448+
if ( y0 < yBottom )
449+
return false;
450+
clipEndBottom( x0, y0, x1, y1, yBottom );
451+
return true;
452+
453+
case 22:
454+
clipStartLeft( x0, y0, x1, y1, xLeft );
455+
if ( y0 < yBottom )
456+
return false;
457+
clipEndBottom( x0, y0, x1, y1, yBottom );
458+
if ( x1 > xRight )
459+
clipEndRight( x0, y0, x1, y1, xRight );
460+
return true;
461+
462+
case 24:
463+
clipStartLeft( x0, y0, x1, y1, xLeft );
464+
if ( y0 > yTop )
465+
return false;
466+
clipEndTop( x0, y0, x1, y1, yTop );
467+
return true;
468+
469+
case 26:
470+
clipStartLeft( x0, y0, x1, y1, xLeft );
471+
if ( y0 > yTop )
472+
return false;
473+
clipEndTop( x0, y0, x1, y1, yTop );
474+
if ( x1 > xRight )
475+
clipEndRight( x0, y0, x1, y1, xRight );
476+
return true;
477+
478+
case 32:
479+
clipStartRight( x0, y0, x1, y1, xRight );
480+
return true;
481+
482+
case 33:
483+
clipStartRight( x0, y0, x1, y1, xRight );
484+
clipEndLeft( x0, y0, x1, y1, xLeft );
485+
return true;
486+
487+
case 36:
488+
clipStartRight( x0, y0, x1, y1, xRight );
489+
if ( y0 < yBottom )
490+
return false;
491+
clipEndBottom( x0, y0, x1, y1, yBottom );
492+
return true;
493+
494+
case 37:
495+
clipStartRight( x0, y0, x1, y1, xRight );
496+
if ( y0 < yBottom )
497+
return false;
498+
clipEndBottom( x0, y0, x1, y1, yBottom );
499+
if ( x1 < xLeft )
500+
clipEndLeft( x0, y0, x1, y1, xLeft );
501+
return true;
502+
503+
case 40:
504+
clipStartRight( x0, y0, x1, y1, xRight );
505+
if ( y0 > yTop )
506+
return false;
507+
clipEndTop( x0, y0, x1, y1, yTop );
508+
return true;
509+
510+
case 41:
511+
clipStartRight( x0, y0, x1, y1, xRight );
512+
if ( y0 > yTop )
513+
return false;
514+
clipEndTop( x0, y0, x1, y1, yTop );
515+
if ( x1 < xLeft )
516+
clipEndLeft( x0, y0, x1, y1, xLeft );
517+
return true;
518+
519+
case 64:
520+
clipStartBottom( x0, y0, x1, y1, yBottom );
521+
return true;
522+
523+
case 65:
524+
clipStartBottom( x0, y0, x1, y1, yBottom );
525+
if ( x0 < xLeft )
526+
return false;
527+
clipEndLeft( x0, y0, x1, y1, xLeft );
528+
if ( y1 < yBottom )
529+
clipEndBottom( x0, y0, x1, y1, yBottom );
530+
return true;
531+
532+
case 66:
533+
clipStartBottom( x0, y0, x1, y1, yBottom );
534+
if ( x0 > xRight )
535+
return false;
536+
clipEndRight( x0, y0, x1, y1, xRight );
537+
return true;
538+
539+
case 72:
540+
clipStartBottom( x0, y0, x1, y1, yBottom );
541+
clipEndTop( x0, y0, x1, y1, yTop );
542+
return true;
543+
544+
case 73:
545+
clipStartBottom( x0, y0, x1, y1, yBottom );
546+
if ( x0 < xLeft )
547+
return false;
548+
clipEndLeft( x0, y0, x1, y1, xLeft );
549+
if ( y1 > yTop )
550+
clipEndTop( x0, y0, x1, y1, yTop );
551+
return true;
552+
553+
case 74:
554+
clipStartBottom( x0, y0, x1, y1, yBottom );
555+
if ( x0 > xRight )
556+
return false;
557+
clipEndRight( x0, y0, x1, y1, xRight );
558+
if ( y1 > yTop )
559+
clipEndTop( x0, y0, x1, y1, yTop );
560+
return true;
561+
562+
case 80:
563+
clipStartLeft( x0, y0, x1, y1, xLeft );
564+
if ( y0 < yBottom )
565+
clipStartBottom( x0, y0, x1, y1, yBottom );
566+
return true;
567+
568+
case 82:
569+
clipEndRight( x0, y0, x1, y1, xRight );
570+
if ( y1 < yBottom )
571+
return false;
572+
clipStartBottom( x0, y0, x1, y1, yBottom );
573+
if ( x0 < xLeft )
574+
clipStartLeft( x0, y0, x1, y1, xLeft );
575+
return true;
576+
577+
case 88:
578+
clipEndTop( x0, y0, x1, y1, yTop );
579+
if ( x1 < xLeft )
580+
return false;
581+
clipStartBottom( x0, y0, x1, y1, yBottom );
582+
if ( x0 < xLeft )
583+
clipStartLeft( x0, y0, x1, y1, xLeft );
584+
return true;
585+
586+
case 90:
587+
clipStartLeft( x0, y0, x1, y1, xLeft );
588+
if ( y0 > yTop )
589+
return false;
590+
clipEndRight( x0, y0, x1, y1, xRight );
591+
if ( y1 < yBottom )
592+
return false;
593+
if ( y0 < yBottom )
594+
clipStartBottom( x0, y0, x1, y1, yBottom );
595+
if ( y1 > yTop )
596+
clipEndTop( x0, y0, x1, y1, yTop );
597+
return true;
598+
599+
case 96:
600+
clipStartRight( x0, y0, x1, y1, xRight );
601+
if ( y0 < yBottom )
602+
clipStartBottom( x0, y0, x1, y1, yBottom );
603+
return true;
604+
605+
case 97:
606+
clipEndLeft( x0, y0, x1, y1, xLeft );
607+
if ( y1 < yBottom )
608+
return false;
609+
clipStartBottom( x0, y0, x1, y1, yBottom );
610+
if ( x0 > xRight )
611+
clipStartRight( x0, y0, x1, y1, xRight );
612+
return true;
613+
614+
case 104:
615+
clipEndTop( x0, y0, x1, y1, yTop );
616+
if ( x1 > xRight )
617+
return false;
618+
clipStartRight( x0, y0, x1, y1, xRight );
619+
if ( y0 < yBottom )
620+
clipStartBottom( x0, y0, x1, y1, yBottom );
621+
return true;
622+
623+
case 105:
624+
clipEndLeft( x0, y0, x1, y1, xLeft );
625+
if ( y1 < yBottom )
626+
return false;
627+
clipStartRight( x0, y0, x1, y1, xRight );
628+
if ( y0 > yTop )
629+
return false;
630+
if ( y1 > yTop )
631+
clipEndTop( x0, y0, x1, y1, yTop );
632+
if ( y0 < yBottom )
633+
clipStartBottom( x0, y0, x1, y1, yBottom );
634+
return true;
635+
636+
case 128:
637+
clipStartTop( x0, y0, x1, y1, yTop );
638+
return true;
639+
640+
case 129:
641+
clipStartTop( x0, y0, x1, y1, yTop );
642+
if ( x0 < xLeft )
643+
return false;
644+
clipEndLeft( x0, y0, x1, y1, xLeft );
645+
return true;
646+
647+
case 130:
648+
clipStartTop( x0, y0, x1, y1, yTop );
649+
if ( x0 > xRight )
650+
return false;
651+
clipEndRight( x0, y0, x1, y1, xRight );
652+
return true;
653+
654+
case 132:
655+
clipStartTop( x0, y0, x1, y1, yTop );
656+
clipEndBottom( x0, y0, x1, y1, yBottom );
657+
return true;
658+
659+
case 133:
660+
clipStartTop( x0, y0, x1, y1, yTop );
661+
if ( x0 < xLeft )
662+
return false;
663+
clipEndLeft( x0, y0, x1, y1, xLeft );
664+
if ( y1 < yBottom )
665+
clipEndBottom( x0, y0, x1, y1, yBottom );
666+
return true;
667+
668+
case 134:
669+
clipStartTop( x0, y0, x1, y1, yTop );
670+
if ( x0 > xRight )
671+
return false;
672+
clipEndRight( x0, y0, x1, y1, xRight );
673+
if ( y1 < yBottom )
674+
clipEndBottom( x0, y0, x1, y1, yBottom );
675+
return true;
676+
677+
case 144:
678+
clipStartLeft( x0, y0, x1, y1, xLeft );
679+
if ( y0 > yTop )
680+
clipStartTop( x0, y0, x1, y1, yTop );
681+
return true;
682+
683+
case 146:
684+
clipEndRight( x0, y0, x1, y1, xRight );
685+
if ( y1 > yTop )
686+
return false;
687+
clipStartTop( x0, y0, x1, y1, yTop );
688+
if ( x0 < xLeft )
689+
clipStartLeft( x0, y0, x1, y1, xLeft );
690+
return true;
691+
692+
case 148:
693+
clipEndBottom( x0, y0, x1, y1, yBottom );
694+
if ( x1 < xLeft )
695+
return false;
696+
clipStartLeft( x0, y0, x1, y1, xLeft );
697+
if ( y0 > yTop )
698+
clipStartTop( x0, y0, x1, y1, yTop );
699+
return true;
700+
701+
case 150:
702+
clipStartLeft( x0, y0, x1, y1, xLeft );
703+
if ( y0 < yBottom )
704+
return false;
705+
clipEndRight( x0, y0, x1, y1, xRight );
706+
if ( y1 > yTop )
707+
return false;
708+
if ( y0 > yTop )
709+
clipStartTop( x0, y0, x1, y1, yTop );
710+
if ( y1 < yBottom )
711+
clipEndBottom( x0, y0, x1, y1, yBottom );
712+
return true;
713+
714+
case 160:
715+
clipStartRight( x0, y0, x1, y1, xRight );
716+
if ( y0 > yTop )
717+
clipStartTop( x0, y0, x1, y1, yTop );
718+
return true;
719+
720+
case 161:
721+
clipEndLeft( x0, y0, x1, y1, xLeft );
722+
if ( y1 > yTop )
723+
return false;
724+
clipStartTop( x0, y0, x1, y1, yTop );
725+
if ( x0 > xRight )
726+
clipStartRight( x0, y0, x1, y1, xRight );
727+
return true;
728+
729+
case 164:
730+
clipEndBottom( x0, y0, x1, y1, yBottom );
731+
if ( x1 > xRight )
732+
return false;
733+
clipStartRight( x0, y0, x1, y1, xRight );
734+
if ( y0 > yTop )
735+
clipStartTop( x0, y0, x1, y1, yTop );
736+
return true;
737+
738+
case 165:
739+
clipEndLeft( x0, y0, x1, y1, xLeft );
740+
if ( y1 > yTop )
741+
return false;
742+
clipStartRight( x0, y0, x1, y1, xRight );
743+
if ( y0 < yBottom )
744+
return false;
745+
if ( y1 < yBottom )
746+
clipEndBottom( x0, y0, x1, y1, yBottom );
747+
if ( y0 > yTop )
748+
clipStartTop( x0, y0, x1, y1, yTop );
749+
return true;
750+
}
751+
752+
return false;
753+
754+
}
755+
286756

287757
#endif

‎src/core/symbology-ng/qgsrendererv2.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "qgsrendererv2registry.h"
99

1010
#include "qgsrendercontext.h"
11+
#include "qgsclipper.h"
1112
#include "qgsgeometry.h"
1213
#include "qgsfeature.h"
1314
#include "qgslogger.h"
@@ -54,31 +55,45 @@ unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRenderCo
5455
bool hasZValue = ( wkbType == QGis::WKBLineString25D );
5556
double x, y;
5657

57-
pts.resize( nPoints );
58-
5958
const QgsCoordinateTransform* ct = context.coordinateTransform();
6059
const QgsMapToPixel& mtp = context.mapToPixel();
6160
double z = 0; // dummy variable for coordiante transform
6261

63-
for ( unsigned int i = 0; i < nPoints; ++i )
62+
//apply clipping for large lines to achieve a better rendering performance
63+
if ( nPoints > 100 )
6464
{
65-
x = *(( double * ) wkb );
66-
wkb += sizeof( double );
67-
y = *(( double * ) wkb );
68-
wkb += sizeof( double );
65+
const QgsRectangle& e = context.extent();
66+
double cw = e.width() / 10; double ch = e.height() / 10;
67+
QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
68+
wkb = QgsClipper::clippedLineWKB( wkb - ( 2 * sizeof( unsigned int ) + 1 ), clipRect, pts );
69+
}
70+
else
71+
{
72+
pts.resize( nPoints );
6973

70-
if ( hasZValue ) // ignore Z value
74+
for ( unsigned int i = 0; i < nPoints; ++i )
75+
{
76+
x = *(( double * ) wkb );
77+
wkb += sizeof( double );
78+
y = *(( double * ) wkb );
7179
wkb += sizeof( double );
7280

73-
// TODO: maybe to the transform at once (faster?)
74-
if ( ct )
75-
ct->transformInPlace( x, y, z );
76-
mtp.transformInPlace( x, y );
81+
if ( hasZValue ) // ignore Z value
82+
wkb += sizeof( double );
7783

78-
pts[i] = QPointF( x, y );
84+
pts[i] = QPointF( x, y );
85+
}
86+
}
7987

88+
//transform the QPolygonF to screen coordinates
89+
for ( unsigned int i = 0; i < pts.size(); ++i )
90+
{
91+
if ( ct )
92+
ct->transformInPlace( pts[i].rx(), pts[i].ry(), z );
93+
mtp.transformInPlace( pts[i].rx(), pts[i].ry() );
8094
}
8195

96+
8297
return wkb;
8398
}
8499

0 commit comments

Comments
 (0)
Please sign in to comment.