00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgsclipper.h"
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 const double QgsClipper::MAX_X = 16000;
00032 const double QgsClipper::MIN_X = -16000;
00033 const double QgsClipper::MAX_Y = 16000;
00034 const double QgsClipper::MIN_Y = -16000;
00035
00036 const double QgsClipper::SMALL_NUM = 1e-12;
00037
00038 unsigned char* QgsClipper::clippedLineWKB( unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line )
00039 {
00040 wkb++;
00041 unsigned int wkbType = *(( int* ) wkb );
00042 wkb += sizeof( unsigned int );
00043 unsigned int nPoints = *(( int* ) wkb );
00044 wkb += sizeof( unsigned int );
00045
00046 bool hasZValue = ( wkbType == QGis::WKBLineString25D );
00047
00048 double p0x, p0y, p1x, p1y;
00049 double p1x_c, p1y_c;
00050 double lastClipX, lastClipY;
00051
00052 line.reserve( nPoints + 1 );
00053 line.clear();
00054
00055 for ( unsigned int i = 0; i < nPoints; ++i )
00056 {
00057 if ( i == 0 )
00058 {
00059 memcpy( &p1x, wkb, sizeof( double ) );
00060 wkb += sizeof( double );
00061 memcpy( &p1y, wkb, sizeof( double ) );
00062 wkb += sizeof( double );
00063 if ( hasZValue )
00064 {
00065 wkb += sizeof( double );
00066 }
00067 continue;
00068 }
00069 else
00070 {
00071 p0x = p1x;
00072 p0y = p1y;
00073
00074 memcpy( &p1x, wkb, sizeof( double ) );
00075 wkb += sizeof( double );
00076 memcpy( &p1y, wkb, sizeof( double ) );
00077 wkb += sizeof( double );
00078 if ( hasZValue )
00079 {
00080 wkb += sizeof( double );
00081 }
00082
00083 p1x_c = p1x; p1y_c = p1y;
00084 if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(),
00085 p0x, p0y, p1x_c, p1y_c ) )
00086 {
00087 bool newLine = line.size() > 0 && ( p0x != lastClipX || p0y != lastClipY );
00088 if ( newLine )
00089 {
00090
00091 connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line );
00092 }
00093 if ( line.size() < 1 || newLine )
00094 {
00095
00096 line << QPointF( p0x, p0y );
00097 }
00098
00099
00100 lastClipX = p1x_c; lastClipY = p1y_c;
00101 line << QPointF( p1x_c, p1y_c );
00102 }
00103 }
00104 }
00105 return wkb;
00106 }
00107
00108 void QgsClipper::connectSeparatedLines( double x0, double y0, double x1, double y1,
00109 const QgsRectangle& clipRect, QPolygonF& pts )
00110 {
00111
00112 if ( doubleNear( x0, clipRect.xMinimum() ) )
00113 {
00114 if ( doubleNear( x1, clipRect.xMinimum() ) )
00115 {
00116 return;
00117 }
00118 else if ( doubleNear( y1, clipRect.yMaximum() ) )
00119 {
00120 pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
00121 return;
00122 }
00123 else if ( doubleNear( x1, clipRect.xMaximum() ) )
00124 {
00125 pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
00126 pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
00127 return;
00128 }
00129 else if ( doubleNear( y1, clipRect.yMinimum() ) )
00130 {
00131 pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
00132 return;
00133 }
00134 }
00135 else if ( doubleNear( y0, clipRect.yMaximum() ) )
00136 {
00137 if ( doubleNear( y1, clipRect.yMaximum() ) )
00138 {
00139 return;
00140 }
00141 else if ( doubleNear( x1, clipRect.xMaximum() ) )
00142 {
00143 pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
00144 return;
00145 }
00146 else if ( doubleNear( y1, clipRect.yMinimum() ) )
00147 {
00148 pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
00149 pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
00150 return;
00151 }
00152 else if ( doubleNear( x1, clipRect.xMinimum() ) )
00153 {
00154 pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
00155 return;
00156 }
00157 }
00158 else if ( doubleNear( x0, clipRect.xMaximum() ) )
00159 {
00160 if ( doubleNear( x1, clipRect.xMaximum() ) )
00161 {
00162 return;
00163 }
00164 else if ( doubleNear( y1, clipRect.yMinimum() ) )
00165 {
00166 pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
00167 return;
00168 }
00169 else if ( doubleNear( x1, clipRect.xMinimum() ) )
00170 {
00171 pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
00172 pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
00173 return;
00174 }
00175 else if ( doubleNear( y1, clipRect.yMaximum() ) )
00176 {
00177 pts << QPointF( clipRect.xMaximum(), clipRect.yMaximum() );
00178 return;
00179 }
00180 }
00181 else if ( doubleNear( y0, clipRect.yMinimum() ) )
00182 {
00183 if ( doubleNear( y1, clipRect.yMinimum() ) )
00184 {
00185 return;
00186 }
00187 else if ( doubleNear( x1, clipRect.xMinimum() ) )
00188 {
00189 pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
00190 return;
00191 }
00192 else if ( doubleNear( y1, clipRect.yMaximum() ) )
00193 {
00194 pts << QPointF( clipRect.xMinimum(), clipRect.yMinimum() );
00195 pts << QPointF( clipRect.xMinimum(), clipRect.yMaximum() );
00196 return;
00197 }
00198 else if ( doubleNear( x1, clipRect.xMaximum() ) )
00199 {
00200 pts << QPointF( clipRect.xMaximum(), clipRect.yMinimum() );
00201 return;
00202 }
00203 }
00204 }