Skip to content

Commit d4f69b3

Browse files
author
mhugent
committed
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@15090 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 406ce0d commit d4f69b3

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+
}

0 commit comments

Comments
 (0)