port more WKB parsing to Qgs(Const)WkbPtr including bounds checking

This commit is contained in:
Juergen E. Fischer 2016-01-31 18:09:13 +01:00
parent ded1ebb33b
commit 2ea3d7744d
65 changed files with 632 additions and 888 deletions

View File

@ -324,3 +324,4 @@
%Include geometry/qgspolygonv2.sip
%Include geometry/qgssurfacev2.sip
%Include geometry/qgswkbtypes.sip
%Include geometry/qgswkbptr.sip

View File

@ -127,7 +127,7 @@ class QgsAbstractGeometryV2
/** Sets the geometry from a WKB string.
* @see fromWkt
*/
virtual bool fromWkb( const unsigned char * wkb ) = 0;
virtual bool fromWkb( QgsConstWkbPtr wkb ) = 0;
/** Sets the geometry from a WKT string.
* @see fromWkb
@ -368,15 +368,4 @@ class QgsAbstractGeometryV2
/** Updates the geometry type based on whether sub geometries contain z or m values.
*/
void setZMTypeFromSubGeometry( const QgsAbstractGeometryV2* subggeom, QgsWKBTypes::Type baseGeomType );
/** Reads a WKB header and tests its validity.
* @param wkbPtr
* @param wkbType destination for WKB type from header
* @param endianSwap will be set to true if endian from WKB must be swapped to match QGIS platform endianness
* @param expectedType expected WKB type
* @returns true if header is valid and matches expected type
* @note not available in Python bindings
*/
//static bool readWkbHeader( QgsConstWkbPtr& wkbPtr, QgsWKBTypes::Type& wkbType, bool& endianSwap, QgsWKBTypes::Type expectedType );
};

View File

@ -18,7 +18,7 @@ class QgsCircularStringV2: public QgsCurveV2
virtual QgsRectangle calculateBoundingBox() const;
virtual bool fromWkb( const unsigned char * wkb );
virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );
int wkbSize() const;

View File

@ -20,7 +20,7 @@ class QgsCompoundCurveV2: public QgsCurveV2
virtual QgsRectangle calculateBoundingBox() const;
virtual bool fromWkb( const unsigned char* wkb );
virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );
int wkbSize() const;

View File

@ -17,7 +17,7 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
virtual QgsRectangle calculateBoundingBox() const;
virtual bool fromWkb( const unsigned char* wkb );
virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );
int wkbSize() const;

View File

@ -57,7 +57,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
virtual void draw( QPainter& p ) const;
bool fromWkb( const unsigned char * wkb );
bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );
int wkbSize() const;
unsigned char* asWkb( int& binarySize ) const;

View File

@ -112,7 +112,8 @@ class QgsLineStringV2: public QgsCurveV2
virtual int dimension() const;
virtual QgsLineStringV2* clone() const /Factory/;
virtual bool fromWkb( const unsigned char* wkb );
virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );
int wkbSize() const;

View File

@ -143,7 +143,7 @@ class QgsPointV2: public QgsAbstractGeometryV2
virtual int dimension() const;
virtual QgsPointV2* clone() const /Factory/;
void clear();
virtual bool fromWkb( const unsigned char* wkb );
virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );
int wkbSize() const;
unsigned char* asWkb( int& binarySize ) const;

View File

@ -13,7 +13,7 @@ class QgsPolygonV2: public QgsCurvePolygonV2
virtual QString geometryType() const;
virtual QgsPolygonV2* clone() const;
virtual bool fromWkb( const unsigned char* wkb );
virtual bool fromWkb( QgsConstWkbPtr wkb );
// inherited: bool fromWkt( const QString &wkt );

View File

@ -0,0 +1,21 @@
class QgsWkbPtr
{
%TypeHeaderCode
#include <qgswkbptr.h>
%End
public:
QgsWkbPtr( unsigned char *wkb /Array/, int size /ArraySize/ );
};
class QgsConstWkbPtr
{
%TypeHeaderCode
#include <qgswkbptr.h>
%End
public:
QgsConstWkbPtr( unsigned char *wkb /Array/, int size /ArraySize/ );
};

View File

@ -56,5 +56,5 @@ class QgsClipper
@param wkb pointer to the start of the line wkb
@param clipExtent clipping bounds
@param line out: clipped line coordinates*/
static const unsigned char* clippedLineWKB( const unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line );
static QgsConstWkbPtr clippedLineWKB( QgsConstWkbPtr wkb, const QgsRectangle& clipExtent, QPolygonF& line );
};

View File

@ -374,9 +374,9 @@ class QgsFeatureRendererV2
//! render editing vertex marker for a polygon
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
static const unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb );
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkb );
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );

View File

@ -226,13 +226,13 @@ class QgsSymbolV2
* Creates a line string in screen coordinates from a wkb string in map
* coordinates
*/
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
/**
* Creates a polygon in screen coordinates from a wkb string in map
* coordinates
*/
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
/**
* Retrieve a cloned list of all layers that make up this symbol.

View File

@ -108,7 +108,8 @@ int QgsInterpolator::addVerticesToCache( const QgsGeometry *geom, bool zCoord, d
return 1;
bool hasZValue = false;
QgsConstWkbPtr currentWkbPtr( geom->asWkb() + 1 + sizeof( int ) );
QgsConstWkbPtr currentWkbPtr( geom->asWkb(), geom->wkbSize() );
currentWkbPtr.readHeader();
vertexData theVertex; //the current vertex
QGis::WkbType wkbType = geom->wkbType();

View File

@ -199,7 +199,8 @@ int QgsTINInterpolator::insertData( QgsFeature* f, bool zCoord, int attr, InputT
//parse WKB. It is ugly, but we cannot use the methods with QgsPoint because they don't contain z-values for 25D types
bool hasZValue = false;
double x, y, z;
QgsConstWkbPtr currentWkbPtr( g->asWkb() + 1 + sizeof( int ) );
QgsConstWkbPtr currentWkbPtr( g->asWkb(), g->wkbSize() );
currentWkbPtr.readHeader();
//maybe a structure or break line
Line3D* line = nullptr;
@ -236,7 +237,7 @@ int QgsTINInterpolator::insertData( QgsFeature* f, bool zCoord, int attr, InputT
currentWkbPtr >> nPoints;
for ( int index = 0; index < nPoints; ++index )
{
currentWkbPtr += 1 + sizeof( int );
currentWkbPtr.readHeader();
currentWkbPtr >> x >> y;
if ( hasZValue ) //skip z-coordinate for 25D geometries
{
@ -388,7 +389,7 @@ int QgsTINInterpolator::insertData( QgsFeature* f, bool zCoord, int attr, InputT
currentWkbPtr >> nPolys;
for ( int index = 0; index < nPolys; ++index )
{
currentWkbPtr += 1 + sizeof( int );
currentWkbPtr.readHeader();
int nRings;
currentWkbPtr >> nRings;
for ( int index2 = 0; index2 < nRings; ++index2 )

View File

@ -25,6 +25,8 @@
#include "qgsvectorfilewriter.h"
#include "qgsvectordataprovider.h"
#include "qgsdistancearea.h"
#include "qgis.h"
#include <QProgressDialog>
bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer,
@ -1178,13 +1180,10 @@ QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, dou
QgsMultiPolyline resultGeom;
//need to go with WKB and z coordinate until QgsGeometry supports M values
const unsigned char* lineWkb = lineGeom->asWkb();
const unsigned char* ptr = lineWkb + 1;
QGis::WkbType wkbType;
memcpy( &wkbType, ptr, sizeof( wkbType ) );
ptr += sizeof( wkbType );
QgsConstWkbPtr wkbPtr( lineGeom->asWkb(), lineGeom->wkbSize() );
wkbPtr.readHeader();
QGis::WkbType wkbType = lineGeom->wkbType();
if ( wkbType != QGis::WKBLineString25D && wkbType != QGis::WKBMultiLineString25D )
{
return nullptr;
@ -1192,16 +1191,16 @@ QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, dou
if ( wkbType == QGis::WKBLineString25D )
{
locateBetweenWkbString( ptr, resultGeom, fromMeasure, toMeasure );
locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
}
else if ( wkbType == QGis::WKBMultiLineString25D )
{
int* nLines = ( int* )ptr;
ptr += sizeof( int );
for ( int i = 0; i < *nLines; ++i )
int nLines;
wkbPtr >> nLines;
for ( int i = 0; i < nLines; ++i )
{
ptr += ( 1 + sizeof( wkbType ) );
ptr = locateBetweenWkbString( ptr, resultGeom, fromMeasure, toMeasure );
wkbPtr.readHeader();
wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
}
}
@ -1222,12 +1221,8 @@ QgsGeometry* QgsGeometryAnalyzer::locateAlongMeasure( double measure, const QgsG
QgsMultiPoint resultGeom;
//need to go with WKB and z coordinate until QgsGeometry supports M values
const unsigned char* lineWkb = lineGeom->asWkb();
const unsigned char* ptr = lineWkb + 1;
QGis::WkbType wkbType;
memcpy( &wkbType, ptr, sizeof( wkbType ) );
ptr += sizeof( wkbType );
QgsConstWkbPtr wkbPtr( lineGeom->asWkb(), lineGeom->wkbSize() );
QGis::WkbType wkbType = lineGeom->wkbType();
if ( wkbType != QGis::WKBLineString25D && wkbType != QGis::WKBMultiLineString25D )
{
@ -1236,16 +1231,16 @@ QgsGeometry* QgsGeometryAnalyzer::locateAlongMeasure( double measure, const QgsG
if ( wkbType == QGis::WKBLineString25D )
{
locateAlongWkbString( ptr, resultGeom, measure );
locateAlongWkbString( wkbPtr, resultGeom, measure );
}
else if ( wkbType == QGis::WKBMultiLineString25D )
{
int* nLines = ( int* )ptr;
ptr += sizeof( int );
for ( int i = 0; i < *nLines; ++i )
int nLines;
wkbPtr >> nLines;
for ( int i = 0; i < nLines; ++i )
{
ptr += ( 1 + sizeof( wkbType ) );
ptr = locateAlongWkbString( ptr, resultGeom, measure );
wkbPtr.readHeader();
wkbPtr = locateAlongWkbString( wkbPtr, resultGeom, measure );
}
}
@ -1253,34 +1248,27 @@ QgsGeometry* QgsGeometryAnalyzer::locateAlongMeasure( double measure, const QgsG
{
return nullptr;
}
return QgsGeometry::fromMultiPoint( resultGeom );
}
const unsigned char* QgsGeometryAnalyzer::locateBetweenWkbString( const unsigned char* ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure )
QgsConstWkbPtr QgsGeometryAnalyzer::locateBetweenWkbString( QgsConstWkbPtr wkbPtr, QgsMultiPolyline& result, double fromMeasure, double toMeasure )
{
int* nPoints = ( int* ) ptr;
ptr += sizeof( int );
double prevx = 0.0, prevy = 0.0, prevz = 0.0;
double *x, *y, *z;
int nPoints;
wkbPtr >> nPoints;
QgsPolyline currentLine;
QgsPoint pt1, pt2;
bool measureInSegment; //true if measure is contained in the segment
bool secondPointClipped; //true if second point is != segment endpoint
for ( int i = 0; i < *nPoints; ++i )
double prevx = 0.0, prevy = 0.0, prevz = 0.0;
for ( int i = 0; i < nPoints; ++i )
{
x = ( double* )ptr;
ptr += sizeof( double );
y = ( double* )ptr;
ptr += sizeof( double );
z = ( double* ) ptr;
ptr += sizeof( double );
double x, y, z;
wkbPtr >> x >> y >> z;
if ( i > 0 )
{
measureInSegment = clipSegmentByRange( prevx, prevy, prevz, *x, *y, *z, fromMeasure, toMeasure, pt1, pt2, secondPointClipped );
QgsPoint pt1, pt2;
bool secondPointClipped; //true if second point is != segment endpoint
bool measureInSegment = clipSegmentByRange( prevx, prevy, prevz, x, y, z, fromMeasure, toMeasure, pt1, pt2, secondPointClipped );
if ( measureInSegment )
{
if ( currentLine.size() < 1 ) //no points collected yet, so the first point needs to be added to the line
@ -1293,7 +1281,7 @@ const unsigned char* QgsGeometryAnalyzer::locateBetweenWkbString( const unsigned
currentLine.append( pt2 );
}
if ( secondPointClipped || i == *nPoints - 1 ) //close current segment
if ( secondPointClipped || i == nPoints - 1 ) //close current segment
{
if ( currentLine.size() > 1 )
{
@ -1303,49 +1291,45 @@ const unsigned char* QgsGeometryAnalyzer::locateBetweenWkbString( const unsigned
}
}
}
prevx = *x;
prevy = *y;
prevz = *z;
prevx = x;
prevy = y;
prevz = z;
}
return ptr;
return wkbPtr;
}
const unsigned char* QgsGeometryAnalyzer::locateAlongWkbString( const unsigned char* ptr, QgsMultiPoint& result, double measure )
QgsConstWkbPtr QgsGeometryAnalyzer::locateAlongWkbString( QgsConstWkbPtr wkbPtr, QgsMultiPoint& result, double measure )
{
int* nPoints = ( int* ) ptr;
ptr += sizeof( int );
int nPoints;
wkbPtr >> nPoints;
double x, y, z;
double prevx = 0.0, prevy = 0.0, prevz = 0.0;
double *x, *y, *z;
QgsPoint pt1, pt2;
bool pt1Ok, pt2Ok;
for ( int i = 0; i < *nPoints; ++i )
for ( int i = 0; i < nPoints; ++i )
{
x = ( double* )ptr;
ptr += sizeof( double );
y = ( double* )ptr;
ptr += sizeof( double );
z = ( double* ) ptr;
ptr += sizeof( double );
wkbPtr >> x >> y >> z;
if ( i > 0 )
{
locateAlongSegment( prevx, prevy, prevz, *x, *y, *z, measure, pt1Ok, pt1, pt2Ok, pt2 );
QgsPoint pt1, pt2;
bool pt1Ok, pt2Ok;
locateAlongSegment( prevx, prevy, prevz, x, y, z, measure, pt1Ok, pt1, pt2Ok, pt2 );
if ( pt1Ok )
{
result.append( pt1 );
}
if ( pt2Ok && ( i == ( *nPoints - 1 ) ) )
if ( pt2Ok && i == nPoints - 1 )
{
result.append( pt2 );
}
}
prevx = *x;
prevy = *y;
prevz = *z;
prevx = x;
prevy = y;
prevz = z;
}
return ptr;
return wkbPtr;
}
bool QgsGeometryAnalyzer::clipSegmentByRange( double x1, double y1, double m1, double x2, double y2, double m2, double range1, double range2, QgsPoint& pt1,

View File

@ -151,8 +151,8 @@ class ANALYSIS_EXPORT QgsGeometryAnalyzer
@param offset the offset value in layer unit. Negative values mean offset towards left, positive values offset to the right side*/
bool createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset );
QgsPoint createPointOffset( double x, double y, double dist, QgsGeometry* lineGeom ) const;
const unsigned char* locateBetweenWkbString( const unsigned char* ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure );
const unsigned char* locateAlongWkbString( const unsigned char* ptr, QgsMultiPoint& result, double measure );
QgsConstWkbPtr locateBetweenWkbString( QgsConstWkbPtr ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure );
QgsConstWkbPtr locateAlongWkbString( QgsConstWkbPtr ptr, QgsMultiPoint& result, double measure );
static bool clipSegmentByRange( double x1, double y1, double m1, double x2, double y2, double m2, double range1, double range2, QgsPoint& pt1, QgsPoint& pt2, bool& secondPointClipped );
static void locateAlongSegment( double x1, double y1, double m1, double x2, double y2, double m2, double measure, bool& pt1Ok, QgsPoint& pt1, bool& pt2Ok, QgsPoint& pt2 );
};

View File

@ -35,6 +35,7 @@
#include "qgsrubberband.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgswkbptr.h"
// QWT Charting widget
@ -817,8 +818,6 @@ void QgsGPSInformationWidget::on_mBtnCloseFeature_clicked()
QgsFeature* f = new QgsFeature( 0 );
int size = 0;
char end = QgsApplication::endian();
unsigned char *wkb = nullptr;
int wkbtype = 0;
QgsCoordinateTransform t( mWgs84CRS, vlayer->crs() );
@ -827,15 +826,13 @@ void QgsGPSInformationWidget::on_mBtnCloseFeature_clicked()
double y = myPoint.y();
size = 1 + sizeof( int ) + 2 * sizeof( double );
wkb = new unsigned char[size];
wkbtype = QGis::WKBPoint;
memcpy( &wkb[0], &end, 1 );
memcpy( &wkb[1], &wkbtype, sizeof( int ) );
memcpy( &wkb[5], &x, sizeof( double ) );
memcpy( &wkb[5] + sizeof( double ), &y, sizeof( double ) );
unsigned char *buf = new unsigned char[size];
QgsWkbPtr wkbPtr( buf, size );
wkbPtr << ( char ) QgsApplication::endian() << wkbtype << x << y;
QgsGeometry *g = new QgsGeometry();
g->fromWkb( &wkb[0], size );
g->fromWkb( buf, size );
f->setGeometry( g );
QgsFeatureAction action( tr( "Feature added" ), *f, vlayer, -1, -1, this );
@ -865,54 +862,37 @@ void QgsGPSInformationWidget::on_mBtnCloseFeature_clicked()
//create QgsFeature with wkb representation
QgsFeature* f = new QgsFeature( 0 );
unsigned char* wkb;
int size;
char end = QgsApplication::endian();
if ( layerWKBType == QGis::WKBLineString )
{
size = 1 + 2 * sizeof( int ) + 2 * mCaptureList.size() * sizeof( double );
wkb = new unsigned char[size];
int wkbtype = QGis::WKBLineString;
int length = mCaptureList.size();
memcpy( &wkb[0], &end, 1 );
memcpy( &wkb[1], &wkbtype, sizeof( int ) );
memcpy( &wkb[1+sizeof( int )], &length, sizeof( int ) );
int position = 1 + 2 * sizeof( int );
double x, y;
int size = 1 + 2 * sizeof( int ) + 2 * mCaptureList.size() * sizeof( double );
unsigned char *buf = new unsigned char[size];
QgsWkbPtr wkbPtr( buf, size );
wkbPtr << ( char ) QgsApplication::endian() << QGis::WKBLineString << mCaptureList.size();
for ( QList<QgsPoint>::const_iterator it = mCaptureList.constBegin(); it != mCaptureList.constEnd(); ++it )
{
QgsPoint savePoint = *it;
// transform the gps point into the layer crs
QgsCoordinateTransform t( mWgs84CRS, vlayer->crs() );
QgsPoint myPoint = t.transform( savePoint );
x = myPoint.x();
y = myPoint.y();
memcpy( &wkb[position], &x, sizeof( double ) );
position += sizeof( double );
memcpy( &wkb[position], &y, sizeof( double ) );
position += sizeof( double );
wkbPtr << myPoint.x() << myPoint.y();
}
QgsGeometry *g = new QgsGeometry();
g->fromWkb( &wkb[0], size );
g->fromWkb( buf, size );
f->setGeometry( g );
}
else if ( layerWKBType == QGis::WKBPolygon )
{
size = 1 + 3 * sizeof( int ) + 2 * ( mCaptureList.size() + 1 ) * sizeof( double );
wkb = new unsigned char[size];
int wkbtype = QGis::WKBPolygon;
int length = mCaptureList.size() + 1;//+1 because the first point is needed twice
int numrings = 1;
memcpy( &wkb[0], &end, 1 );
memcpy( &wkb[1], &wkbtype, sizeof( int ) );
memcpy( &wkb[1+sizeof( int )], &numrings, sizeof( int ) );
memcpy( &wkb[1+2*sizeof( int )], &length, sizeof( int ) );
int position = 1 + 3 * sizeof( int );
double x, y;
int size = 1 + 3 * sizeof( int ) + 2 * ( mCaptureList.size() + 1 ) * sizeof( double );
unsigned char *buf = new unsigned char[size];
QgsWkbPtr wkbPtr( buf, size );
wkbPtr << ( char ) QgsApplication::endian() << QGis::WKBPolygon << 1 << mCaptureList.size() + 1;
QList<QgsPoint>::iterator it;
for ( it = mCaptureList.begin(); it != mCaptureList.end(); ++it )
{
@ -920,28 +900,16 @@ void QgsGPSInformationWidget::on_mBtnCloseFeature_clicked()
// transform the gps point into the layer crs
QgsCoordinateTransform t( mWgs84CRS, vlayer->crs() );
QgsPoint myPoint = t.transform( savePoint );
x = myPoint.x();
y = myPoint.y();
memcpy( &wkb[position], &x, sizeof( double ) );
position += sizeof( double );
memcpy( &wkb[position], &y, sizeof( double ) );
position += sizeof( double );
wkbPtr << myPoint.x() << myPoint.y();
}
// close the polygon
it = mCaptureList.begin();
QgsPoint savePoint = *it;
x = savePoint.x();
y = savePoint.y();
memcpy( &wkb[position], &x, sizeof( double ) );
position += sizeof( double );
memcpy( &wkb[position], &y, sizeof( double ) );
wkbPtr << savePoint.x() << savePoint.y();
QgsGeometry *g = new QgsGeometry();
g->fromWkb( &wkb[0], size );
g->fromWkb( buf, size );
f->setGeometry( g );
int avoidIntersectionsReturn = f->geometry()->avoidIntersections();

View File

@ -18,6 +18,7 @@ email : marco.hugentobler at sourcepole dot com
#include "qgswkbptr.h"
#include "qgsgeos.h"
#include "qgsmaptopixel.h"
#include <limits>
#include <QTransform>
@ -173,29 +174,6 @@ QString QgsAbstractGeometryV2::wktTypeStr() const
return wkt;
}
bool QgsAbstractGeometryV2::readWkbHeader( QgsConstWkbPtr& wkbPtr, QgsWKBTypes::Type& wkbType, bool& endianSwap, QgsWKBTypes::Type expectedType )
{
if ( !static_cast<const unsigned char*>( wkbPtr ) )
{
return false;
}
char wkbEndian;
wkbPtr >> wkbEndian;
endianSwap = wkbEndian != QgsApplication::endian();
wkbPtr >> wkbType;
if ( endianSwap )
QgsApplication::endian_swap( wkbType );
if ( QgsWKBTypes::flatType( wkbType ) != expectedType )
{
wkbType = QgsWKBTypes::Unknown;
return false;
}
return true;
}
QgsPointV2 QgsAbstractGeometryV2::centroid() const
{
// http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon

View File

@ -19,6 +19,8 @@ email : marco.hugentobler at sourcepole dot com
#include "qgscoordinatetransform.h"
#include "qgsrectangle.h"
#include "qgswkbtypes.h"
#include "qgswkbptr.h"
#include <QString>
class QgsCoordinateTransform;
@ -27,9 +29,7 @@ class QgsCurveV2;
class QgsMultiCurveV2;
class QgsMultiPointV2;
class QgsPointV2;
class QgsConstWkbPtr;
struct QgsVertexId;
class QgsWkbPtr;
class QPainter;
@ -114,7 +114,7 @@ class CORE_EXPORT QgsAbstractGeometryV2
/** Sets the geometry from a WKB string.
* @see fromWkt
*/
virtual bool fromWkb( const unsigned char * wkb ) = 0;
virtual bool fromWkb( QgsConstWkbPtr wkb ) = 0;
/** Sets the geometry from a WKT string.
* @see fromWkb
@ -205,7 +205,7 @@ class CORE_EXPORT QgsAbstractGeometryV2
* in this variable if found.
* @param vertex container for found node
* @return false if at end
*/
*/
virtual bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const = 0;
/** Retrieves the sequence of geometries, rings and nodes.
@ -358,17 +358,6 @@ class CORE_EXPORT QgsAbstractGeometryV2
/** Updates the geometry type based on whether sub geometries contain z or m values.
*/
void setZMTypeFromSubGeometry( const QgsAbstractGeometryV2* subggeom, QgsWKBTypes::Type baseGeomType );
/** Reads a WKB header and tests its validity.
* @param wkbPtr
* @param wkbType destination for WKB type from header
* @param endianSwap will be set to true if endian from WKB must be swapped to match QGIS platform endianness
* @param expectedType expected WKB type
* @returns true if header is valid and matches expected type
* @note not available in Python bindings
*/
static bool readWkbHeader( QgsConstWkbPtr& wkbPtr, QgsWKBTypes::Type& wkbType, bool& endianSwap, QgsWKBTypes::Type expectedType );
};

View File

@ -206,14 +206,11 @@ QList<QgsPointV2> QgsCircularStringV2::compassPointsOnSegment( double p1Angle, d
return pointList;
}
bool QgsCircularStringV2::fromWkb( const unsigned char* wkb )
bool QgsCircularStringV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
if ( !wkb )
{
if ( !wkbPtr )
return false;
}
QgsConstWkbPtr wkbPtr( wkb );
QgsWKBTypes::Type type = wkbPtr.readHeader();
if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::CircularString )
{
@ -272,7 +269,7 @@ unsigned char* QgsCircularStringV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, binarySize );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
QList<QgsPointV2> pts;

View File

@ -43,7 +43,7 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
virtual QgsRectangle calculateBoundingBox() const override;
virtual bool fromWkb( const unsigned char * wkb ) override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;
int wkbSize() const override;
@ -87,6 +87,7 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
virtual QgsLineStringV2* curveToLine() const override;
void draw( QPainter& p ) const override;
/** Transforms the geometry using a coordinate transform
* @param ct coordinate transform
* @param d transformation direction

View File

@ -98,15 +98,14 @@ QgsRectangle QgsCompoundCurveV2::calculateBoundingBox() const
return bbox;
}
bool QgsCompoundCurveV2::fromWkb( const unsigned char* wkb )
bool QgsCompoundCurveV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
clear();
if ( !wkb )
if ( !wkbPtr )
{
return false;
}
QgsConstWkbPtr wkbPtr( wkb );
QgsWKBTypes::Type type = wkbPtr.readHeader();
if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::CompoundCurve )
{
@ -120,10 +119,8 @@ bool QgsCompoundCurveV2::fromWkb( const unsigned char* wkb )
int currentCurveSize = 0;
for ( int i = 0; i < nCurves; ++i )
{
wkbPtr += 1; //skip endian
QgsWKBTypes::Type curveType;
wkbPtr >> curveType;
wkbPtr -= ( 1 + sizeof( int ) );
QgsWKBTypes::Type curveType = wkbPtr.readHeader();
wkbPtr -= 1 + sizeof( int );
if ( QgsWKBTypes::flatType( curveType ) == QgsWKBTypes::LineString )
{
currentCurve = new QgsLineStringV2();
@ -209,7 +206,7 @@ unsigned char* QgsCompoundCurveV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, binarySize );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
wkb << static_cast<quint32>( mCurves.size() );

View File

@ -44,7 +44,7 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
virtual QgsRectangle calculateBoundingBox() const override;
virtual bool fromWkb( const unsigned char* wkb ) override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;
int wkbSize() const override;

View File

@ -82,14 +82,14 @@ void QgsCurvePolygonV2::clear()
}
bool QgsCurvePolygonV2::fromWkb( const unsigned char* wkb )
bool QgsCurvePolygonV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
clear();
if ( !wkb )
if ( !wkbPtr )
{
return false;
}
QgsConstWkbPtr wkbPtr( wkb );
QgsWKBTypes::Type type = wkbPtr.readHeader();
if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::CurvePolygon )
{
@ -103,10 +103,8 @@ bool QgsCurvePolygonV2::fromWkb( const unsigned char* wkb )
int currentCurveSize = 0;
for ( int i = 0; i < nRings; ++i )
{
wkbPtr += 1; //skip endian
QgsWKBTypes::Type curveType;
wkbPtr >> curveType;
wkbPtr -= ( 1 + sizeof( int ) );
QgsWKBTypes::Type curveType = wkbPtr.readHeader();
wkbPtr -= 1 + sizeof( int );
if ( curveType == QgsWKBTypes::LineString || curveType == QgsWKBTypes::LineStringZ || curveType == QgsWKBTypes::LineStringM ||
curveType == QgsWKBTypes::LineStringZM || curveType == QgsWKBTypes::LineString25D )
{
@ -149,6 +147,7 @@ bool QgsCurvePolygonV2::fromWkt( const QString& wkt )
if ( QgsWKBTypes::flatType( parts.first ) != QgsWKBTypes::parseType( geometryType() ) )
return false;
mWkbType = parts.first;
QString defaultChildWkbType = QString( "LineString%1%2" ).arg( is3D() ? "Z" : "", isMeasure() ? "M" : "" );
@ -233,23 +232,23 @@ unsigned char* QgsCurvePolygonV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
wkb << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
QgsWkbPtr wkbPtr( geomPtr, binarySize );
wkbPtr << static_cast<char>( QgsApplication::endian() );
wkbPtr << static_cast<quint32>( wkbType() );
wkbPtr << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
if ( mExteriorRing )
{
int curveWkbLen = 0;
unsigned char* ringWkb = mExteriorRing->asWkb( curveWkbLen );
memcpy( wkb, ringWkb, curveWkbLen );
wkb += curveWkbLen;
unsigned char *ringWkb = mExteriorRing->asWkb( curveWkbLen );
memcpy( wkbPtr, ringWkb, curveWkbLen );
wkbPtr += curveWkbLen;
}
Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
{
int curveWkbLen = 0;
unsigned char* ringWkb = curve->asWkb( curveWkbLen );
memcpy( wkb, ringWkb, curveWkbLen );
wkb += curveWkbLen;
unsigned char *ringWkb = curve->asWkb( curveWkbLen );
memcpy( wkbPtr, ringWkb, curveWkbLen );
wkbPtr += curveWkbLen;
}
return geomPtr;
}

View File

@ -43,7 +43,7 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
virtual QgsRectangle calculateBoundingBox() const override;
virtual bool fromWkb( const unsigned char* wkb ) override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;
int wkbSize() const override;

View File

@ -244,7 +244,7 @@ void QgsGeometry::fromWkb( unsigned char *wkb, int length )
delete d->geometry;
removeWkbGeos();
}
d->geometry = QgsGeometryFactory::geomFromWkb( wkb );
d->geometry = QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr( wkb, length ) );
d->mWkb = wkb;
d->mWkbSize = length;
}

View File

@ -138,11 +138,12 @@ class CORE_EXPORT QgsGeometry
@note not available in python bindings
*/
void fromGeos( GEOSGeometry* geos );
/**
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
This class will take ownership of the buffer.
*/
void fromWkb( unsigned char * wkb, int length );
void fromWkb( unsigned char *wkb, int length );
/**
Returns the buffer containing this geometry in WKB format.

View File

@ -179,15 +179,15 @@ void QgsGeometryCollectionV2::draw( QPainter& p ) const
}
}
bool QgsGeometryCollectionV2::fromWkb( const unsigned char * wkb )
bool QgsGeometryCollectionV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
if ( !wkb )
if ( !wkbPtr )
{
return false;
}
QgsConstWkbPtr wkbPtr( wkb + 1 );
//type
wkbPtr >> mWkbType;
mWkbType = wkbPtr.readHeader();
int nGeometries = 0;
wkbPtr >> nGeometries;
@ -237,7 +237,7 @@ unsigned char* QgsGeometryCollectionV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, binarySize );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
wkb << static_cast<quint32>( mGeometries.size() );

View File

@ -81,7 +81,7 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
#endif
virtual void draw( QPainter& p ) const override;
bool fromWkb( const unsigned char * wkb ) override;
bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;
int wkbSize() const override;
unsigned char* asWkb( int& binarySize ) const override;

View File

@ -29,24 +29,22 @@
#include "qgsmultisurfacev2.h"
#include "qgswkbtypes.h"
QgsAbstractGeometryV2* QgsGeometryFactory::geomFromWkb( const unsigned char* wkb )
QgsAbstractGeometryV2* QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr wkbPtr )
{
if ( !wkb )
{
if ( !wkbPtr )
return nullptr;
}
//find out type (bytes 2-5)
int type;
memcpy( &type, wkb + 1, sizeof( int ) );
QgsWKBTypes::Type type = wkbPtr.readHeader();
wkbPtr -= 1 + sizeof( int );
QgsAbstractGeometryV2* geom = nullptr;
geom = geomFromWkbType( QgsWKBTypes::Type( type ) );
geom = geomFromWkbType( type );
if ( geom )
{
geom->fromWkb( wkb );
}
geom->fromWkb( wkbPtr );
return geom;
}

View File

@ -20,6 +20,8 @@
#include "qgsrectangle.h"
#include "qgswkbtypes.h"
#include "qgswkbptr.h"
#include <QString>
class QgsAbstractGeometryV2;
@ -45,7 +47,7 @@ class CORE_EXPORT QgsGeometryFactory
public:
/** Construct geometry from a WKB string.
*/
static QgsAbstractGeometryV2* geomFromWkb( const unsigned char* wkb );
static QgsAbstractGeometryV2* geomFromWkb( QgsConstWkbPtr wkb );
/** Construct geometry from a WKT string.
*/

View File

@ -21,6 +21,7 @@
#include "qgsgeometryutils.h"
#include "qgsmaptopixel.h"
#include "qgswkbptr.h"
#include <QPainter>
#include <limits>
#include <QDomDocument>
@ -89,13 +90,13 @@ void QgsLineStringV2::clear()
mBoundingBox = QgsRectangle();
}
bool QgsLineStringV2::fromWkb( const unsigned char* wkb )
bool QgsLineStringV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
if ( !wkb )
if ( !wkbPtr )
{
return false;
}
QgsConstWkbPtr wkbPtr( wkb );
QgsWKBTypes::Type type = wkbPtr.readHeader();
if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::LineString )
{
@ -143,7 +144,7 @@ unsigned char* QgsLineStringV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, binarySize );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
QList<QgsPointV2> pts;

View File

@ -139,7 +139,7 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
virtual QgsLineStringV2* clone() const override;
virtual void clear() override;
virtual bool fromWkb( const unsigned char* wkb ) override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;
int wkbSize() const override;

View File

@ -96,9 +96,8 @@ QgsPointV2 *QgsPointV2::clone() const
return new QgsPointV2( *this );
}
bool QgsPointV2::fromWkb( const unsigned char* wkb )
bool QgsPointV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
QgsConstWkbPtr wkbPtr( wkb );
QgsWKBTypes::Type type = wkbPtr.readHeader();
if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::Point )
{
@ -183,7 +182,7 @@ unsigned char* QgsPointV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, binarySize );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
wkb << mX << mY;

View File

@ -155,7 +155,7 @@ class CORE_EXPORT QgsPointV2: public QgsAbstractGeometryV2
virtual int dimension() const override { return 0; }
virtual QgsPointV2* clone() const override;
void clear() override;
virtual bool fromWkb( const unsigned char* wkb ) override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;
int wkbSize() const override;
unsigned char* asWkb( int& binarySize ) const override;

View File

@ -52,7 +52,8 @@ bool QgsPolygonV2::operator==( const QgsPolygonV2& other ) const
( mInteriorRings.at( i ) && !other.mInteriorRings.at( i ) ) )
return false;
if ( mInteriorRings.at( i ) && other.mInteriorRings.at( i ) && *mInteriorRings.at( i ) != *other.mInteriorRings.at( i ) )
if ( mInteriorRings.at( i ) && other.mInteriorRings.at( i ) &&
*mInteriorRings.at( i ) != *other.mInteriorRings.at( i ) )
return false;
}
@ -69,15 +70,14 @@ QgsPolygonV2* QgsPolygonV2::clone() const
return new QgsPolygonV2( *this );
}
bool QgsPolygonV2::fromWkb( const unsigned char* wkb )
bool QgsPolygonV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
clear();
if ( !wkb )
if ( !wkbPtr )
{
return false;
}
QgsConstWkbPtr wkbPtr( wkb );
QgsWKBTypes::Type type = wkbPtr.readHeader();
if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::Polygon )
{
@ -149,7 +149,7 @@ unsigned char* QgsPolygonV2::asWkb( int& binarySize ) const
{
binarySize = wkbSize();
unsigned char* geomPtr = new unsigned char[binarySize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, binarySize );
wkb << static_cast<char>( QgsApplication::endian() );
wkb << static_cast<quint32>( wkbType() );
wkb << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );

View File

@ -37,7 +37,7 @@ class CORE_EXPORT QgsPolygonV2: public QgsCurvePolygonV2
virtual QString geometryType() const override { return "Polygon"; }
virtual QgsPolygonV2* clone() const override;
virtual bool fromWkb( const unsigned char* wkb ) override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
int wkbSize() const override;
unsigned char* asWkb( int& binarySize ) const override;

View File

@ -14,27 +14,33 @@
***************************************************************************/
#include "qgswkbptr.h"
QgsConstWkbPtr::QgsConstWkbPtr( const unsigned char *p ): mEndianSwap( false )
QgsWkbPtr::QgsWkbPtr( unsigned char *p, int size )
{
mP = p;
mStart = mP;
mEnd = mP + size;
}
QgsConstWkbPtr::QgsConstWkbPtr( const unsigned char *p, int size )
{
mP = const_cast< unsigned char * >( p );
mEnd = mP + size;
mEndianSwap = false;
}
QgsWKBTypes::Type QgsConstWkbPtr::readHeader() const
{
if ( !mP )
{
return QgsWKBTypes::Unknown;
}
char wkbEndian;
( *this ) >> wkbEndian;
*this >> wkbEndian;
mEndianSwap = ( wkbEndian != QgsApplication::endian() );
QgsWKBTypes::Type wkbType;
( *this ) >> wkbType;
int wkbType;
*this >> wkbType;
if ( mEndianSwap )
{
QgsApplication::endian_swap( wkbType );
}
return wkbType;
return static_cast<QgsWKBTypes::Type>( wkbType );
}

View File

@ -18,6 +18,17 @@
#include "qgswkbtypes.h"
#include "qgsapplication.h"
#include "qgis.h"
#include "qgsexception.h"
/** \ingroup core
* * Custom exception class for Wkb related exceptions.
* */
class CORE_EXPORT QgsWkbException : public QgsException
{
public:
QgsWkbException( QString const &what ) : QgsException( what ) {}
};
/** \class QgsWkbPtr
* \note not available in Python bindings
@ -26,33 +37,50 @@
class CORE_EXPORT QgsWkbPtr
{
mutable unsigned char *mP;
unsigned char *mStart;
unsigned char *mEnd;
void verify( int size ) const { Q_ASSERT( mP && mP + size <= mEnd ); if ( !mP || mP + size > mEnd ) throw QgsWkbException( "wkb access out of bounds" ); }
template<typename T> void read( T& v ) const
{
verify( sizeof v );
memcpy( &v, mP, sizeof v );
mP += sizeof v;
}
template<typename T> void write( T& v ) const
{
verify( sizeof v );
memcpy( mP, &v, sizeof v );
mP += sizeof v;
}
public:
QgsWkbPtr( unsigned char *p ): mP( p ) {}
QgsWkbPtr( unsigned char *p, int size );
inline const QgsWkbPtr &operator>>( double &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsWkbPtr &operator>>( int &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsWkbPtr &operator>>( unsigned int &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsWkbPtr &operator>>( char &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsWkbPtr &operator>>( QgsWKBTypes::Type &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsWkbPtr &operator>>( QGis::WkbType &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
#ifdef QT_ARCH_ARM
inline const QgsWkbPtr &operator>>( qreal &r ) const { double v; memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); r = v; return *this; }
#endif
inline const QgsWkbPtr &operator>>( double &v ) const { read( v ); return *this; }
inline const QgsWkbPtr &operator>>( float &r ) const { double v; read( v ); r = v; return *this; }
inline const QgsWkbPtr &operator>>( int &v ) const { read( v ); return *this; }
inline const QgsWkbPtr &operator>>( unsigned int &v ) const { read( v ); return *this; }
inline const QgsWkbPtr &operator>>( char &v ) const { read( v ); return *this; }
inline const QgsWkbPtr &operator>>( QgsWKBTypes::Type &v ) const { read( v ); return *this; }
inline const QgsWkbPtr &operator>>( QGis::WkbType &v ) const { read( v ); return *this; }
inline QgsWkbPtr &operator<<( const double &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline QgsWkbPtr &operator<<( const int &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline QgsWkbPtr &operator<<( const unsigned int &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline QgsWkbPtr &operator<<( const char &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline QgsWkbPtr &operator<<( const QgsWKBTypes::Type &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline QgsWkbPtr &operator<<( const QGis::WkbType &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
#ifdef QT_ARCH_ARM
inline QgsWkbPtr &operator<<( const qreal &r ) { double v = r; memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
#endif
inline QgsWkbPtr &operator<<( const double &v ) { write( v ); return *this; }
inline QgsWkbPtr &operator<<( const float &r ) { double v = r; write( v ); return *this; }
inline QgsWkbPtr &operator<<( const int &v ) { write( v ); return *this; }
inline QgsWkbPtr &operator<<( const unsigned int &v ) { write( v ); return *this; }
inline QgsWkbPtr &operator<<( const char &v ) { write( v ); return *this; }
inline QgsWkbPtr &operator<<( const QgsWKBTypes::Type &v ) { write( v ); return *this; }
inline QgsWkbPtr &operator<<( const QGis::WkbType &v ) { write( v ); return *this; }
inline void operator+=( int n ) { mP += n; }
inline void operator+=( int n ) { verify( n ); mP += n; }
inline operator unsigned char *() const { return mP; }
inline int size() const { return mEnd -mStart; }
inline int remaining() const { return mEnd -mP; }
inline int writtenSize() const { return mP -mStart; }
};
/** \class QgsConstWkbPtr
@ -62,10 +90,22 @@ class CORE_EXPORT QgsWkbPtr
class CORE_EXPORT QgsConstWkbPtr
{
mutable unsigned char *mP;
unsigned char *mEnd;
mutable bool mEndianSwap;
void verify( int size ) const { Q_ASSERT( mP && mP + size <= mEnd ); if ( !mP || mP + size > mEnd ) throw QgsWkbException( "wkb access out of bounds" ); }
template<typename T> void read( T& v ) const
{
verify( sizeof v );
memcpy( &v, mP, sizeof( v ) );
mP += sizeof( v );
if ( mEndianSwap )
QgsApplication::endian_swap( v );
}
public:
QgsConstWkbPtr( const unsigned char *p );
QgsConstWkbPtr( const unsigned char *p, int size );
QgsWKBTypes::Type readHeader() const;
inline const QgsConstWkbPtr &operator>>( double &v ) const { read( v ); return *this; }
@ -73,23 +113,12 @@ class CORE_EXPORT QgsConstWkbPtr
inline const QgsConstWkbPtr &operator>>( int &v ) const { read( v ); return *this; }
inline const QgsConstWkbPtr &operator>>( unsigned int &v ) const { read( v ); return *this; }
inline const QgsConstWkbPtr &operator>>( char &v ) const { read( v ); return *this; }
inline const QgsConstWkbPtr &operator>>( QGis::WkbType &v ) const { read( v ); return *this; }
inline const QgsConstWkbPtr &operator>>( QgsWKBTypes::Type &v ) const { read( v ); return *this; }
inline void operator+=( int n ) { mP += n; }
inline void operator+=( int n ) { verify( n ); mP += n; }
inline void operator-=( int n ) { mP -= n; }
inline operator const unsigned char *() const { return mP; }
template<typename T> void read( T& v ) const
{
memcpy( &v, mP, sizeof( v ) );
mP += sizeof( v );
if ( mEndianSwap )
{
QgsApplication::endian_swap( v );
}
}
inline int remaining() const { return mEnd -mP; }
};
#endif // QGSWKBPTR_H

View File

@ -98,14 +98,14 @@ class CORE_EXPORT QGis
static bool isMultiType( WkbType type );
// get dimension of points
// @deprecated use QgsWKBTypes::hasZ() and QgsWKBTypes::hasM()
// @deprecated use QgsWKBTypes::coordDimensions()
/* Q_DECL_DEPRECATED */
static int wkbDimensions( WkbType type );
//! Converts from old (pre 2.10) WKB type to new WKB type
//! Converts from old (pre 2.10) WKB type (OGR) to new WKB type
static QgsWKBTypes::Type fromOldWkbType( QGis::WkbType type );
//! Converts from new (post 2.10) WKB type to old WKB type
//! Converts from new (post 2.10) WKB type (OGC) to old WKB type
static QGis::WkbType fromNewWkbType( QgsWKBTypes::Type type );
enum GeometryType

View File

@ -37,17 +37,14 @@ const double QgsClipper::MIN_Y = -16000;
const double QgsClipper::SMALL_NUM = 1e-12;
const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line )
QgsConstWkbPtr QgsClipper::clippedLineWKB( QgsConstWkbPtr wkbPtr, const QgsRectangle& clipExtent, QPolygonF& line )
{
QgsConstWkbPtr wkbPtr( wkb + 1 );
QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
unsigned int wkbType, nPoints;
wkbPtr >> wkbType >> nPoints;
bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
int nPoints;
wkbPtr >> nPoints;
int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates
double p1x_c, p1y_c; //clipped end coordinates
@ -56,16 +53,12 @@ const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const
line.clear();
line.reserve( nPoints + 1 );
for ( unsigned int i = 0; i < nPoints; ++i )
for ( int i = 0; i < nPoints; ++i )
{
if ( i == 0 )
{
wkbPtr >> p1x >> p1y;
if ( hasZValue )
wkbPtr += sizeof( double );
if ( hasMValue )
wkbPtr += sizeof( double );
wkbPtr += skipZM;
continue;
}
else
@ -74,10 +67,7 @@ const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const
p0y = p1y;
wkbPtr >> p1x >> p1y;
if ( hasZValue )
wkbPtr += sizeof( double );
if ( hasMValue )
wkbPtr += sizeof( double );
wkbPtr += skipZM;
p1x_c = p1x;
p1y_c = p1y;

View File

@ -22,6 +22,7 @@
#include "qgis.h"
#include "qgspoint.h"
#include "qgsrectangle.h"
#include "qgswkbptr.h"
#include <QVector>
#include <QPolygonF>
@ -86,7 +87,7 @@ class CORE_EXPORT QgsClipper
@param wkb pointer to the start of the line wkb
@param clipExtent clipping bounds
@param line out: clipped line coordinates*/
static const unsigned char* clippedLineWKB( const unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line );
static QgsConstWkbPtr clippedLineWKB( QgsConstWkbPtr wkb, const QgsRectangle& clipExtent, QPolygonF& line );
private:

View File

@ -539,15 +539,15 @@ QGis::UnitType QgsDistanceArea::lengthUnits() const
return willUseEllipsoid() ? QGis::Meters : mCoordTransform->sourceCrs().mapUnits();
}
const unsigned char *QgsDistanceArea::measurePolygon( const unsigned char* feature, double* area, double* perimeter, bool hasZptr ) const
QgsConstWkbPtr QgsDistanceArea::measurePolygon( QgsConstWkbPtr wkbPtr, double* area, double* perimeter, bool hasZptr ) const
{
if ( !feature )
if ( !wkbPtr )
{
QgsDebugMsg( "no feature to measure" );
return nullptr;
return wkbPtr;
}
QgsConstWkbPtr wkbPtr( feature + 1 + sizeof( int ) );
wkbPtr.readHeader();
// get number of rings in the polygon
int numRings;
@ -556,7 +556,7 @@ const unsigned char *QgsDistanceArea::measurePolygon( const unsigned char* featu
if ( numRings == 0 )
{
QgsDebugMsg( "no rings to measure" );
return nullptr;
return QgsConstWkbPtr( nullptr, 0 );
}
// Set pointer to the first ring

View File

@ -18,6 +18,7 @@
#include <QList>
#include "qgscoordinatetransform.h"
#include "qgswkbptr.h"
class QgsGeometry;
class QgsAbstractGeometryV2;
@ -220,7 +221,7 @@ class CORE_EXPORT QgsDistanceArea
protected:
//! measures polygon area and perimeter, vertices are extracted from WKB
// @note not available in python bindings
const unsigned char* measurePolygon( const unsigned char* feature, double* area, double* perimeter, bool hasZptr = false ) const;
QgsConstWkbPtr measurePolygon( QgsConstWkbPtr feature, double* area, double* perimeter, bool hasZptr = false ) const;
/**
calculates distance from two points on ellipsoid

View File

@ -20,6 +20,8 @@
#include "qgslogger.h"
#include "qgsmessagelog.h"
#include "qgsnetworkaccessmanager.h"
#include "qgswkbptr.h"
#include <QBuffer>
#include <QList>
#include <QNetworkRequest>
@ -45,8 +47,7 @@ QgsGml::QgsGml(
, mFinished( false )
, mCurrentFeature( nullptr )
, mFeatureCount( 0 )
, mCurrentWKB( nullptr )
, mCurrentWKBSize( 0 )
, mCurrentWKB( nullptr, 0 )
, mDimension( 2 )
, mCoorMode( QgsGml::coordinate )
, mEpsg( 0 )
@ -286,22 +287,19 @@ void QgsGml::startElement( const XML_Char* el, const XML_Char** attr )
}
else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "Polygon" )
{
mCurrentWKBFragments.push_back( QList<unsigned char*>() );
mCurrentWKBFragmentSizes.push_back( QList<int>() );
mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
}
else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiPoint" )
{
mParseModeStack.push( QgsGml::multiPoint );
//we need one nested list for intermediate WKB
mCurrentWKBFragments.push_back( QList<unsigned char*>() );
mCurrentWKBFragmentSizes.push_back( QList<int>() );
mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
}
else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiLineString" )
{
mParseModeStack.push( QgsGml::multiLine );
//we need one nested list for intermediate WKB
mCurrentWKBFragments.push_back( QList<unsigned char*>() );
mCurrentWKBFragmentSizes.push_back( QList<int>() );
mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
}
else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiPolygon" )
{
@ -384,7 +382,7 @@ void QgsGml::endElement( const XML_Char* el )
QgsGeometry *g = new QgsGeometry();
g->fromWkb( mCurrentWKB, mCurrentWKBSize );
mCurrentFeature->setGeometry( g );
mCurrentWKB = nullptr;
mCurrentWKB = QgsWkbPtr( nullptr, 0 );
}
else if ( !mCurrentExtent.isEmpty() )
{
@ -419,7 +417,7 @@ void QgsGml::endElement( const XML_Char* el )
if ( theParseMode == QgsGml::geometry )
{
//directly add WKB point to the feature
if ( getPointWKB( &mCurrentWKB, &mCurrentWKBSize, *( pointList.begin() ) ) != 0 )
if ( getPointWKB( mCurrentWKB, *( pointList.begin() ) ) != 0 )
{
//error
}
@ -431,23 +429,19 @@ void QgsGml::endElement( const XML_Char* el )
}
else //multipoint, add WKB as fragment
{
unsigned char* wkb = nullptr;
int wkbSize = 0;
QList<unsigned char*> wkbList;
QList<int> wkbSizeList;
if ( getPointWKB( &wkb, &wkbSize, *( pointList.begin() ) ) != 0 )
QgsWkbPtr wkbPtr( nullptr, 0 );
if ( getPointWKB( wkbPtr, *( pointList.begin() ) ) != 0 )
{
//error
}
if ( !mCurrentWKBFragments.isEmpty() )
{
mCurrentWKBFragments.last().push_back( wkb );
mCurrentWKBFragmentSizes.last().push_back( wkbSize );
mCurrentWKBFragments.last().push_back( wkbPtr );
}
else
{
QgsDebugMsg( "No wkb fragments" );
delete [] wkb;
delete [] wkbPtr;
}
}
}
@ -462,7 +456,7 @@ void QgsGml::endElement( const XML_Char* el )
}
if ( theParseMode == QgsGml::geometry )
{
if ( getLineWKB( &mCurrentWKB, &mCurrentWKBSize, pointList ) != 0 )
if ( getLineWKB( mCurrentWKB, pointList ) != 0 )
{
//error
}
@ -474,23 +468,19 @@ void QgsGml::endElement( const XML_Char* el )
}
else //multiline, add WKB as fragment
{
unsigned char* wkb = nullptr;
int wkbSize = 0;
QList<unsigned char*> wkbList;
QList<int> wkbSizeList;
if ( getLineWKB( &wkb, &wkbSize, pointList ) != 0 )
QgsWkbPtr wkbPtr( nullptr, 0 );
if ( getLineWKB( wkbPtr, pointList ) != 0 )
{
//error
}
if ( !mCurrentWKBFragments.isEmpty() )
{
mCurrentWKBFragments.last().push_back( wkb );
mCurrentWKBFragmentSizes.last().push_back( wkbSize );
mCurrentWKBFragments.last().push_back( wkbPtr );
}
else
{
QgsDebugMsg( "no wkb fragments" );
delete [] wkb;
delete [] wkbPtr;
}
}
}
@ -501,20 +491,20 @@ void QgsGml::endElement( const XML_Char* el )
{
//error
}
unsigned char* wkb = nullptr;
int wkbSize = 0;
if ( getRingWKB( &wkb, &wkbSize, pointList ) != 0 )
QgsWkbPtr wkbPtr( nullptr, 0 );
if ( getRingWKB( wkbPtr, pointList ) != 0 )
{
//error
}
if ( !mCurrentWKBFragments.isEmpty() )
{
mCurrentWKBFragments.last().push_back( wkb );
mCurrentWKBFragmentSizes.last().push_back( wkbSize );
mCurrentWKBFragments.last().push_back( wkbPtr );
}
else
{
delete[] wkb;
delete[] wkbPtr;
QgsDebugMsg( "no wkb fragments" );
}
}
@ -728,145 +718,94 @@ int QgsGml::pointsFromString( QList<QgsPoint>& points, const QString& coordStrin
return 1;
}
int QgsGml::getPointWKB( unsigned char** wkb, int* size, const QgsPoint& point ) const
int QgsGml::getPointWKB( QgsWkbPtr &wkbPtr, const QgsPoint& point ) const
{
int wkbSize = 1 + sizeof( int ) + 2 * sizeof( double );
*size = wkbSize;
*wkb = new unsigned char[wkbSize];
QGis::WkbType type = QGis::WKBPoint;
double x = point.x();
double y = point.y();
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
wkbPtr = QgsWkbPtr( new unsigned char[wkbSize], wkbSize );
QgsWkbPtr fillPtr( wkbPtr );
fillPtr << mEndian << QGis::WKBPoint << point.x() << point.y();
memcpy( &( *wkb )[wkbPosition], &mEndian, 1 );
wkbPosition += 1;
memcpy( &( *wkb )[wkbPosition], &type, sizeof( int ) );
wkbPosition += sizeof( int );
memcpy( &( *wkb )[wkbPosition], &x, sizeof( double ) );
wkbPosition += sizeof( double );
memcpy( &( *wkb )[wkbPosition], &y, sizeof( double ) );
return 0;
}
int QgsGml::getLineWKB( unsigned char** wkb, int* size, const QList<QgsPoint>& lineCoordinates ) const
int QgsGml::getLineWKB( QgsWkbPtr &wkbPtr, const QList<QgsPoint>& lineCoordinates ) const
{
int wkbSize = 1 + 2 * sizeof( int ) + lineCoordinates.size() * 2 * sizeof( double );
*size = wkbSize;
*wkb = new unsigned char[wkbSize];
QGis::WkbType type = QGis::WKBLineString;
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
double x, y;
int nPoints = lineCoordinates.size();
wkbPtr = QgsWkbPtr( new unsigned char[wkbSize], wkbSize );
//fill the contents into *wkb
memcpy( &( *wkb )[wkbPosition], &mEndian, 1 );
wkbPosition += 1;
memcpy( &( *wkb )[wkbPosition], &type, sizeof( int ) );
wkbPosition += sizeof( int );
memcpy( &( *wkb )[wkbPosition], &nPoints, sizeof( int ) );
wkbPosition += sizeof( int );
QgsWkbPtr fillPtr( wkbPtr );
fillPtr << mEndian << QGis::WKBLineString << lineCoordinates.size();
QList<QgsPoint>::const_iterator iter;
for ( iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter )
{
x = iter->x();
y = iter->y();
memcpy( &( *wkb )[wkbPosition], &x, sizeof( double ) );
wkbPosition += sizeof( double );
memcpy( &( *wkb )[wkbPosition], &y, sizeof( double ) );
wkbPosition += sizeof( double );
fillPtr << iter->x() << iter->y();
}
return 0;
}
int QgsGml::getRingWKB( unsigned char** wkb, int* size, const QList<QgsPoint>& ringCoordinates ) const
int QgsGml::getRingWKB( QgsWkbPtr &wkbPtr, const QList<QgsPoint>& ringCoordinates ) const
{
int wkbSize = sizeof( int ) + ringCoordinates.size() * 2 * sizeof( double );
*size = wkbSize;
*wkb = new unsigned char[wkbSize];
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
double x, y;
int nPoints = ringCoordinates.size();
memcpy( &( *wkb )[wkbPosition], &nPoints, sizeof( int ) );
wkbPosition += sizeof( int );
wkbPtr = QgsWkbPtr( new unsigned char[wkbSize], wkbSize );
QgsWkbPtr fillPtr( wkbPtr );
fillPtr << ringCoordinates.size();
QList<QgsPoint>::const_iterator iter;
for ( iter = ringCoordinates.begin(); iter != ringCoordinates.end(); ++iter )
{
x = iter->x();
y = iter->y();
memcpy( &( *wkb )[wkbPosition], &x, sizeof( double ) );
wkbPosition += sizeof( double );
memcpy( &( *wkb )[wkbPosition], &y, sizeof( double ) );
wkbPosition += sizeof( double );
fillPtr << iter->x() << iter->y();
}
return 0;
}
int QgsGml::createMultiLineFromFragments()
{
mCurrentWKBSize = 0;
mCurrentWKBSize += 1 + 2 * sizeof( int );
mCurrentWKBSize += totalWKBFragmentSize();
mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );
mCurrentWKB = new unsigned char[mCurrentWKBSize];
int pos = 0;
QGis::WkbType type = QGis::WKBMultiLineString;
int numLines = mCurrentWKBFragments.begin()->size();
//add endian
memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
pos += 1;
memcpy( &( mCurrentWKB[pos] ), &type, sizeof( int ) );
pos += sizeof( int );
memcpy( &( mCurrentWKB[pos] ), &numLines, sizeof( int ) );
pos += sizeof( int );
QList<unsigned char*>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
QList<int>::iterator sizeIt = mCurrentWKBFragmentSizes.begin()->begin();
QgsWkbPtr wkbPtr( mCurrentWKB, mCurrentWKBSize );
wkbPtr << mEndian << QGis::WKBMultiLineString << mCurrentWKBFragments.begin()->size();
QList<QgsWkbPtr>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
//copy (and delete) all the wkb fragments
for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt, ++sizeIt )
for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt )
{
memcpy( &( mCurrentWKB[pos] ), *wkbIt, *sizeIt );
pos += *sizeIt;
memcpy( wkbPtr, *wkbIt, wkbIt->size() );
wkbPtr += wkbIt->size();
delete[] *wkbIt;
}
mCurrentWKBFragments.clear();
mCurrentWKBFragmentSizes.clear();
*mWkbType = QGis::WKBMultiLineString;
return 0;
}
int QgsGml::createMultiPointFromFragments()
{
mCurrentWKBSize = 0;
mCurrentWKBSize += 1 + 2 * sizeof( int );
mCurrentWKBSize += totalWKBFragmentSize();
mCurrentWKB = new unsigned char[mCurrentWKBSize];
mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );
int pos = 0;
QGis::WkbType type = QGis::WKBMultiPoint;
int numPoints = mCurrentWKBFragments.begin()->size();
QgsWkbPtr wkbPtr( mCurrentWKB );
wkbPtr << mEndian << QGis::WKBMultiPoint << mCurrentWKBFragments.begin()->size();
memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
pos += 1;
memcpy( &( mCurrentWKB[pos] ), &type, sizeof( int ) );
pos += sizeof( int );
memcpy( &( mCurrentWKB[pos] ), &numPoints, sizeof( int ) );
pos += sizeof( int );
QList<unsigned char*>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
QList<int>::iterator sizeIt = mCurrentWKBFragmentSizes.begin()->begin();
for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt, ++sizeIt )
QList<QgsWkbPtr>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt )
{
memcpy( &( mCurrentWKB[pos] ), *wkbIt, *sizeIt );
pos += *sizeIt;
memcpy( wkbPtr, *wkbIt, wkbIt->size() );
wkbPtr += wkbIt->size();
delete[] *wkbIt;
}
mCurrentWKBFragments.clear();
mCurrentWKBFragmentSizes.clear();
*mWkbType = QGis::WKBMultiPoint;
return 0;
}
@ -874,32 +813,21 @@ int QgsGml::createMultiPointFromFragments()
int QgsGml::createPolygonFromFragments()
{
mCurrentWKBSize = 0;
mCurrentWKBSize += 1 + 2 * sizeof( int );
mCurrentWKBSize += totalWKBFragmentSize();
mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );
mCurrentWKB = new unsigned char[mCurrentWKBSize];
int pos = 0;
QGis::WkbType type = QGis::WKBPolygon;
int numRings = mCurrentWKBFragments.begin()->size();
memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
pos += 1;
memcpy( &( mCurrentWKB[pos] ), &type, sizeof( int ) );
pos += sizeof( int );
memcpy( &( mCurrentWKB[pos] ), &numRings, sizeof( int ) );
pos += sizeof( int );
QgsWkbPtr wkbPtr( mCurrentWKB );
wkbPtr << mEndian << QGis::WKBPolygon << mCurrentWKBFragments.begin()->size();
QList<unsigned char*>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
QList<int>::iterator sizeIt = mCurrentWKBFragmentSizes.begin()->begin();
for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt, ++sizeIt )
QList<QgsWkbPtr>::iterator wkbIt = mCurrentWKBFragments.begin()->begin();
for ( ; wkbIt != mCurrentWKBFragments.begin()->end(); ++wkbIt )
{
memcpy( &( mCurrentWKB[pos] ), *wkbIt, *sizeIt );
pos += *sizeIt;
memcpy( wkbPtr, *wkbIt, wkbIt->size() );
wkbPtr += wkbIt->size();
delete[] *wkbIt;
}
mCurrentWKBFragments.clear();
mCurrentWKBFragmentSizes.clear();
*mWkbType = QGis::WKBPolygon;
return 0;
}
@ -911,51 +839,29 @@ int QgsGml::createMultiPolygonFromFragments()
mCurrentWKBSize += totalWKBFragmentSize();
mCurrentWKBSize += mCurrentWKBFragments.size() * ( 1 + 2 * sizeof( int ) ); //fragments are just the rings
mCurrentWKB = new unsigned char[mCurrentWKBSize];
int pos = 0;
QGis::WkbType type = QGis::WKBMultiPolygon;
QGis::WkbType polygonType = QGis::WKBPolygon;
int numPolys = mCurrentWKBFragments.size();
int numRings;
memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
pos += 1;
memcpy( &( mCurrentWKB[pos] ), &type, sizeof( int ) );
pos += sizeof( int );
memcpy( &( mCurrentWKB[pos] ), &numPolys, sizeof( int ) );
pos += sizeof( int );
mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );
QgsWkbPtr wkbPtr( mCurrentWKB );
wkbPtr << ( char ) mEndian << QGis::WKBMultiPolygon << mCurrentWKBFragments.size();
//have outer and inner iterators
QList< QList<unsigned char*> >::iterator outerWkbIt;
QList< QList<int> >::iterator outerSizeIt;
QList< unsigned char* >::iterator innerWkbIt;
QList< int >::iterator innerSizeIt;
QList< QList<QgsWkbPtr> >::iterator outerWkbIt = mCurrentWKBFragments.begin();
outerWkbIt = mCurrentWKBFragments.begin();
outerSizeIt = mCurrentWKBFragmentSizes.begin();
for ( ; outerWkbIt != mCurrentWKBFragments.end(); ++outerWkbIt, ++outerSizeIt )
for ( ; outerWkbIt != mCurrentWKBFragments.end(); ++outerWkbIt )
{
//new polygon
memcpy( &( mCurrentWKB[pos] ), &mEndian, 1 );
pos += 1;
memcpy( &( mCurrentWKB[pos] ), &polygonType, sizeof( int ) );
pos += sizeof( int );
numRings = outerWkbIt->size();
memcpy( &( mCurrentWKB[pos] ), &numRings, sizeof( int ) );
pos += sizeof( int );
wkbPtr << ( char ) mEndian << QGis::WKBPolygon << outerWkbIt->size();
innerWkbIt = outerWkbIt->begin();
innerSizeIt = outerSizeIt->begin();
for ( ; innerWkbIt != outerWkbIt->end(); ++innerWkbIt, ++innerSizeIt )
QList<QgsWkbPtr>::iterator innerWkbIt = outerWkbIt->begin();
for ( ; innerWkbIt != outerWkbIt->end(); ++innerWkbIt )
{
memcpy( &( mCurrentWKB[pos] ), *innerWkbIt, *innerSizeIt );
pos += *innerSizeIt;
memcpy( wkbPtr, *innerWkbIt, innerWkbIt->size() );
wkbPtr += innerWkbIt->size();
delete[] *innerWkbIt;
}
}
mCurrentWKBFragments.clear();
mCurrentWKBFragmentSizes.clear();
*mWkbType = QGis::WKBMultiPolygon;
return 0;
}
@ -963,11 +869,11 @@ int QgsGml::createMultiPolygonFromFragments()
int QgsGml::totalWKBFragmentSize() const
{
int result = 0;
Q_FOREACH ( const QList<int> &list, mCurrentWKBFragmentSizes )
Q_FOREACH ( const QList<QgsWkbPtr> &list, mCurrentWKBFragments )
{
Q_FOREACH ( int i, list )
Q_FOREACH ( const QgsWkbPtr &i, list )
{
result += i;
result += i.size();
}
}
return result;

View File

@ -25,6 +25,7 @@
#include "qgslogger.h"
#include "qgspoint.h"
#include "qgsrectangle.h"
#include "qgswkbptr.h"
#include <QPair>
#include <QByteArray>
@ -164,9 +165,9 @@ class CORE_EXPORT QgsGml : public QObject
int pointsFromPosListString( QList<QgsPoint>& points, const QString& coordString, int dimension ) const;
int pointsFromString( QList<QgsPoint>& points, const QString& coordString ) const;
int getPointWKB( unsigned char** wkb, int* size, const QgsPoint& ) const;
int getLineWKB( unsigned char** wkb, int* size, const QList<QgsPoint>& lineCoordinates ) const;
int getRingWKB( unsigned char** wkb, int* size, const QList<QgsPoint>& ringCoordinates ) const;
int getPointWKB( QgsWkbPtr &wkbPtr, const QgsPoint& ) const;
int getLineWKB( QgsWkbPtr &wkbPtr, const QList<QgsPoint>& lineCoordinates ) const;
int getRingWKB( QgsWkbPtr &wkbPtr, const QList<QgsPoint>& ringCoordinates ) const;
/** Creates a multiline from the information in mCurrentWKBFragments and
* mCurrentWKBFragmentSizes. Assign the result. The multiline is in
* mCurrentWKB and mCurrentWKBSize. The function deletes the memory in
@ -224,7 +225,7 @@ class CORE_EXPORT QgsGml : public QObject
QString mCurrentFeatureId;
int mFeatureCount;
/** The total WKB for a feature*/
unsigned char* mCurrentWKB;
QgsWkbPtr mCurrentWKB;
/** The total WKB size for a feature*/
int mCurrentWKBSize;
QgsRectangle mCurrentExtent;
@ -232,9 +233,7 @@ class CORE_EXPORT QgsGml : public QObject
* intermediate WKB is stored at all. For multipoints and multilines and
* polygons, only one nested list is used. For multipolygons, both nested lists
* are used*/
QList< QList<unsigned char*> > mCurrentWKBFragments;
/** Similar to mCurrentWKB, but only the size*/
QList< QList<int> > mCurrentWKBFragmentSizes;
QList< QList<QgsWkbPtr> > mCurrentWKBFragments;
QString mAttributeName;
QgsApplication::endian_t mEndian;
/** Coordinate separator for coordinate strings. Usually "," */

View File

@ -15,26 +15,11 @@
***************************************************************************/
#include <limits>
#include <stdexcept>
#include "qgsmaptopixelgeometrysimplifier.h"
#include "qgsapplication.h"
#include "qgslogger.h"
class QgsParserException: public std::runtime_error
{
public:
QgsParserException( const QString &msg )
: std::runtime_error( msg.toStdString() )
{}
};
class QgsShortWkbException: public QgsParserException
{
public:
QgsShortWkbException( const QString &msg )
: QgsParserException( QString( "Premature end of WKB: " ) + msg )
{}
};
QgsMapToPixelSimplifier::QgsMapToPixelSimplifier( int simplifyFlags, double tolerance )
: mSimplifyFlags( simplifyFlags )
@ -59,21 +44,19 @@ float QgsMapToPixelSimplifier::calculateLengthSquared2D( double x1, double y1, d
}
//! Returns the BBOX of the specified WKB-point stream
inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, const unsigned char* wkb, int numPoints )
inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, QgsConstWkbPtr wkbPtr, int numPoints )
{
double x, y;
QgsRectangle r;
r.setMinimal();
int sizeOfDoubleX = sizeof( double );
int sizeOfDoubleY = ( QGis::wkbDimensions( wkbType ) - 1 ) * sizeof( double );
int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
Q_ASSERT( skipZM >= 0 );
for ( int i = 0; i < numPoints; ++i )
{
memcpy( &x, wkb, sizeof( double ) );
wkb += sizeOfDoubleX;
memcpy( &y, wkb, sizeof( double ) );
wkb += sizeOfDoubleY;
double x, y;
wkbPtr >> x >> y;
wkbPtr += skipZM;
r.combineExtentWith( x, y );
}
@ -83,24 +66,24 @@ inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, const un
//! Generalize the WKB-geometry using the BBOX of the original geometry
static bool generalizeWkbGeometryByBoundingBox(
QGis::WkbType wkbType,
const unsigned char *sourceWkb, int sourceWkbSize,
unsigned char *targetWkb, int &targetWkbSize,
QgsConstWkbPtr sourceWkbPtr,
QgsWkbPtr targetWkbPtr,
int &targetWkbSize,
const QgsRectangle &envelope, bool writeHeader )
{
Q_UNUSED( sourceWkb );
unsigned char* wkb2 = targetWkb;
QgsWkbPtr savedTargetWkb( targetWkbPtr );
unsigned int geometryType = QGis::singleType( QGis::flatType( wkbType ) );
int sizeOfDoubleX = sizeof( double );
int sizeOfDoubleY = sizeof( double ) * ( QGis::wkbDimensions( wkbType ) - 1 );
int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
Q_ASSERT( skipZM >= 0 );
// If the geometry is already minimal skip the generalization
int minimumSize = geometryType == QGis::WKBLineString ? 4 + 2 * ( sizeOfDoubleX + sizeOfDoubleY ) : 8 + 5 * ( sizeOfDoubleX + sizeOfDoubleY );
int minimumSize = geometryType == QGis::WKBLineString ? 4 + 2 * ( 2 * sizeof( double ) + skipZM ) : 8 + 5 * ( 2 * sizeof( double ) + skipZM );
if ( writeHeader )
minimumSize += 5;
if ( sourceWkbSize <= minimumSize )
if ( sourceWkbPtr.remaining() <= minimumSize )
{
targetWkbSize = 0;
return false;
@ -114,70 +97,25 @@ static bool generalizeWkbGeometryByBoundingBox(
// Write the main header of the geometry
if ( writeHeader )
{
char byteOrder = QgsApplication::endian(); // byteOrder
memcpy( targetWkb, &byteOrder, 1 );
targetWkb += 1;
memcpy( targetWkb, &geometryType, 4 ); // type
targetWkb += 4;
targetWkbPtr << ( char ) QgsApplication::endian() << geometryType;
if ( geometryType == QGis::WKBPolygon ) // numRings
{
int numRings = 1;
memcpy( targetWkb, &numRings, 4 );
targetWkb += 4;
targetWkbPtr << 1;
}
}
// Write the generalized geometry
if ( geometryType == QGis::WKBLineString )
{
int numPoints = 2;
memcpy( targetWkb, &numPoints, 4 ); // numPoints;
targetWkb += 4;
memcpy( targetWkb, &x1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &x2, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y2, sizeof( double ) );
targetWkb += sizeof( double );
targetWkbPtr << 2 << x1 << y1 << x2 << y2;
}
else
{
int numPoints = 5;
memcpy( targetWkb, &numPoints, 4 ); // numPoints;
targetWkb += 4;
memcpy( targetWkb, &x1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &x2, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &x2, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y2, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &x1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y2, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &x1, sizeof( double ) );
targetWkb += sizeof( double );
memcpy( targetWkb, &y1, sizeof( double ) );
targetWkb += sizeof( double );
targetWkbPtr << 5 << x1 << y1 << x2 << y1 << x2 << y2 << x1 << y2 << x1 << y1;
}
targetWkbSize += targetWkb - wkb2;
targetWkbSize += targetWkbPtr - savedTargetWkb;
return true;
}
@ -185,8 +123,9 @@ static bool generalizeWkbGeometryByBoundingBox(
//! Simplify the WKB-geometry using the specified tolerance
bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
int simplifyFlags, QGis::WkbType wkbType,
const unsigned char *sourceWkb, int sourceWkbSize,
unsigned char *targetWkb, int &targetWkbSize,
QgsConstWkbPtr sourceWkbPtr,
QgsWkbPtr targetWkbPtr,
int &targetWkbSize,
const QgsRectangle &envelope, double map2pixelTol,
bool writeHeader, bool isaLinearRing )
{
@ -194,17 +133,15 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
bool result = false;
// Save initial WKB settings to use when the simplification creates invalid geometries
const unsigned char* sourcePrevWkb = sourceWkb;
unsigned char* targetPrevWkb = targetWkb;
QgsConstWkbPtr sourcePrevWkbPtr( sourceWkbPtr );
QgsWkbPtr targetPrevWkbPtr( targetWkbPtr );
int targetWkbPrevSize = targetWkbSize;
const unsigned char* endOfSourceWkb = sourceWkb + sourceWkbSize;
// Can replace the geometry by its BBOX ?
if (( simplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) &&
isGeneralizableByMapBoundingBox( envelope, map2pixelTol ) )
{
isGeneralizable = generalizeWkbGeometryByBoundingBox( wkbType, sourceWkb, sourceWkbSize, targetWkb, targetWkbSize, envelope, writeHeader );
isGeneralizable = generalizeWkbGeometryByBoundingBox( wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, writeHeader );
if ( isGeneralizable )
return true;
}
@ -215,52 +152,38 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
// Write the main header of the geometry
if ( writeHeader )
{
if ( sourceWkbSize < 5 )
throw QgsParserException( QString( "Premature end of WKB reading header " ) );
QgsWKBTypes::Type geometryType = sourceWkbPtr.readHeader();
targetWkb[0] = sourceWkb[0]; // byteOrder
sourceWkb += 1;
targetWkb += 1;
targetWkbPtr << ( char ) QgsApplication::endian() << QgsWKBTypes::flatType( geometryType );
int geometryType;
memcpy( &geometryType, sourceWkb, 4 );
int flatType = QGis::flatType( static_cast< QGis::WkbType >( geometryType ) );
memcpy( targetWkb, &flatType, 4 ); // type
sourceWkb += 4;
targetWkb += 4;
targetWkbSize += 5;
targetWkbSize += targetWkbPtr - targetPrevWkbPtr;
}
const unsigned char* wkb1 = sourceWkb;
unsigned char* wkb2 = targetWkb;
unsigned int flatType = QGis::flatType( wkbType );
// Write the geometry
if ( flatType == QGis::WKBLineString || isaLinearRing )
{
QgsWkbPtr savedTargetWkbPtr( targetWkbPtr );
double x, y, lastX = 0, lastY = 0;
QgsRectangle r;
r.setMinimal();
int sizeOfDoubleX = sizeof( double );
int sizeOfDoubleY = ( QGis::wkbDimensions( wkbType ) - 1 ) * sizeof( double );
if ( sourceWkb + 4 >= endOfSourceWkb )
throw QgsShortWkbException( "reading numPoints" );
int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
Q_ASSERT( skipZM >= 0 );
int numPoints;
memcpy( &numPoints, sourceWkb, 4 );
sourceWkb += 4;
sourceWkbPtr >> numPoints;
if ( numPoints <= ( isaLinearRing ? 5 : 2 ) )
isGeneralizable = false;
QgsWkbPtr numPtr( targetWkbPtr );
int numTargetPoints = 0;
memcpy( targetWkb, &numTargetPoints, 4 );
targetWkb += 4;
targetWkbPtr << numTargetPoints;
targetWkbSize += 4;
double* ptr = reinterpret_cast< double* >( targetWkb );
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
bool isLongSegment;
@ -269,21 +192,13 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
// Check whether the LinearRing is really closed.
if ( isaLinearRing )
{
QgsConstWkbPtr checkPtr( sourceWkbPtr );
double x1, y1, x2, y2;
const unsigned char* startWkbX = sourceWkb;
const unsigned char* startWkbY = startWkbX + sizeOfDoubleX;
const unsigned char* finalWkbX = sourceWkb + ( numPoints - 1 ) * ( sizeOfDoubleX + sizeOfDoubleY );
const unsigned char* finalWkbY = finalWkbX + sizeOfDoubleX;
if ( finalWkbY + sizeof( double ) > endOfSourceWkb )
throw QgsShortWkbException( "reading last point" );
memcpy( &x1, startWkbX, sizeof( double ) );
memcpy( &y1, startWkbY, sizeof( double ) );
memcpy( &x2, finalWkbX, sizeof( double ) );
memcpy( &y2, finalWkbY, sizeof( double ) );
checkPtr >> x1 >> y1;
checkPtr += skipZM + ( numPoints - 1 ) * ( 2 * sizeof( double ) + skipZM );
checkPtr >> x2 >> y2;
isaLinearRing = qgsDoubleNear( x1, x2 ) && qgsDoubleNear( y1, y2 );
}
@ -291,15 +206,8 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
// Process each vertex...
for ( int i = 0; i < numPoints; ++i )
{
if ( sourceWkb + sizeOfDoubleX + sizeOfDoubleY > endOfSourceWkb )
{
throw QgsParserException( QString( "Premature end of WKB reading point %1/%2" ) .arg( i + 1 ) .arg( numPoints ) );
}
memcpy( &x, sourceWkb, sizeof( double ) );
sourceWkb += sizeOfDoubleX;
memcpy( &y, sourceWkb, sizeof( double ) );
sourceWkb += sizeOfDoubleY;
sourceWkbPtr >> x >> y;
sourceWkbPtr += skipZM;
isLongSegment = false;
@ -308,12 +216,9 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
( isLongSegment = ( calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) ) ||
( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
{
memcpy( ptr, &x, sizeof( double ) );
targetWkbPtr << x << y;
lastX = x;
ptr++;
memcpy( ptr, &y, sizeof( double ) );
lastY = y;
ptr++;
numTargetPoints++;
hasLongSegments |= isLongSegment;
@ -321,7 +226,11 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
r.combineExtentWith( x, y );
}
targetWkb = wkb2 + 4;
QgsWkbPtr nextPointPtr( targetWkbPtr );
targetWkbPtr = savedTargetWkbPtr;
targetWkbPtr += sizeof( int );
if ( numTargetPoints < ( isaLinearRing ? 4 : 2 ) )
{
@ -330,16 +239,16 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
{
// approximate the geometry's shape by its bounding box
// (rect for linear ring / one segment for line string)
unsigned char* targetTempWkb = targetWkb;
QgsWkbPtr tempWkbPtr( targetWkbPtr );
int targetWkbTempSize = targetWkbSize;
sourceWkb = sourcePrevWkb;
targetWkb = targetPrevWkb;
sourceWkbPtr = sourcePrevWkbPtr;
targetWkbPtr = targetPrevWkbPtr;
targetWkbSize = targetWkbPrevSize;
if ( generalizeWkbGeometryByBoundingBox( wkbType, sourceWkb, sourceWkbSize, targetWkb, targetWkbSize, r, writeHeader ) )
if ( generalizeWkbGeometryByBoundingBox( wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize, r, writeHeader ) )
return true;
targetWkb = targetTempWkb;
targetWkbPtr = tempWkbPtr;
targetWkbSize = targetWkbTempSize;
}
else
@ -351,48 +260,45 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
// other pieces of QGIS will survive that :-/
}
}
if ( isaLinearRing )
{
// make sure we keep the linear ring closed
memcpy( &x, targetWkb + 0, sizeof( double ) );
memcpy( &y, targetWkb + sizeof( double ), sizeof( double ) );
targetWkbPtr << x << y;
if ( !qgsDoubleNear( lastX, x ) || !qgsDoubleNear( lastY, y ) )
{
memcpy( ptr, &x, sizeof( double ) );
ptr++;
memcpy( ptr, &y, sizeof( double ) );
ptr++;
nextPointPtr << x << y;
numTargetPoints++;
}
}
targetWkbSize += numTargetPoints * sizeof( double ) * 2;
targetWkb = wkb2;
memcpy( targetWkb, &numTargetPoints, 4 );
numPtr << numTargetPoints;
targetWkbSize += numTargetPoints * sizeof( double ) * 2;
result = numPoints != numTargetPoints;
}
else if ( flatType == QGis::WKBPolygon )
{
int numRings;
memcpy( &numRings, sourceWkb, 4 );
sourceWkb += 4;
memcpy( targetWkb, &numRings, 4 );
targetWkb += 4;
sourceWkbPtr >> numRings;
targetWkbPtr << numRings;
targetWkbSize += 4;
for ( int i = 0; i < numRings; ++i )
{
int numPoints_i;
memcpy( &numPoints_i, sourceWkb, 4 );
QgsRectangle envelope_i = numRings == 1 ? envelope : calculateBoundingBox( wkbType, sourceWkb + 4, numPoints_i );
sourceWkbPtr >> numPoints_i;
int sourceWkbSize_i = 4 + numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
QgsRectangle envelope_i = numRings == 1 ? envelope : calculateBoundingBox( wkbType, sourceWkbPtr, numPoints_i );
sourceWkbPtr -= sizeof( int );
int sourceWkbSize_i = sizeof( int ) + numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
int targetWkbSize_i = 0;
result |= simplifyWkbGeometry( simplifyFlags, wkbType, sourceWkb, sourceWkbSize_i, targetWkb, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
sourceWkb += sourceWkbSize_i;
targetWkb += targetWkbSize_i;
result |= simplifyWkbGeometry( simplifyFlags, wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
sourceWkbPtr += sourceWkbSize_i;
targetWkbPtr += targetWkbSize_i;
targetWkbSize += targetWkbSize_i;
}
@ -400,53 +306,55 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
else if ( flatType == QGis::WKBMultiLineString || flatType == QGis::WKBMultiPolygon )
{
int numGeoms;
memcpy( &numGeoms, sourceWkb, 4 );
sourceWkb += 4;
wkb1 += 4;
memcpy( targetWkb, &numGeoms, 4 );
targetWkb += 4;
sourceWkbPtr >> numGeoms;
targetWkbPtr << numGeoms;
targetWkbSize += 4;
QgsConstWkbPtr sourceWkbPtr2( sourceWkbPtr );
for ( int i = 0; i < numGeoms; ++i )
{
int sourceWkbSize_i = 0;
int targetWkbSize_i = 0;
sourceWkbPtr2.readHeader();
// ... calculate the wkb-size of the current child complex geometry
if ( flatType == QGis::WKBMultiLineString )
{
int numPoints_i;
memcpy( &numPoints_i, wkb1 + 5, 4 );
int wkbSize_i = 4 + numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
sourceWkbPtr2 >> numPoints_i;
sourceWkbSize_i += 5 + wkbSize_i;
wkb1 += 5 + wkbSize_i;
int wkbSize_i = numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
sourceWkbSize_i += 9 + wkbSize_i;
sourceWkbPtr2 += wkbSize_i;
}
else
{
int numPrings_i;
memcpy( &numPrings_i, wkb1 + 5, 4 );
sourceWkbSize_i = 9;
wkb1 += 9;
sourceWkbPtr2 >> numPrings_i;
sourceWkbSize_i = 1 + 2 * sizeof( int );
for ( int j = 0; j < numPrings_i; ++j )
{
int numPoints_i;
memcpy( &numPoints_i, wkb1, 4 );
int wkbSize_i = 4 + numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
sourceWkbPtr2 >> numPoints_i;
sourceWkbSize_i += wkbSize_i;
wkb1 += wkbSize_i;
int wkbSize_i = numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
sourceWkbSize_i += 4 + wkbSize_i;
sourceWkbPtr2 += wkbSize_i;
}
}
result |= simplifyWkbGeometry( simplifyFlags, QGis::singleType( wkbType ), sourceWkb, endOfSourceWkb - sourceWkb, targetWkb, targetWkbSize_i, envelope, map2pixelTol, true, false );
sourceWkb += sourceWkbSize_i;
targetWkb += targetWkbSize_i;
result |= simplifyWkbGeometry( simplifyFlags, QGis::singleType( wkbType ), sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope, map2pixelTol, true, false );
sourceWkbPtr += sourceWkbSize_i;
targetWkbPtr += targetWkbSize_i;
targetWkbSize += targetWkbSize_i;
}
}
return result;
}
@ -465,7 +373,7 @@ QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) const
QgsGeometry* g = new QgsGeometry();
int wkbSize = geometry->wkbSize();
unsigned char* wkb = reinterpret_cast< unsigned char* >( malloc( wkbSize ) );
unsigned char* wkb = new unsigned char[ wkbSize ];
memcpy( wkb, geometry->asWkb(), wkbSize );
g->fromWkb( wkb, wkbSize );
simplifyGeometry( g, mSimplifyFlags, mTolerance );
@ -474,7 +382,7 @@ QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) const
}
//! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context
bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance )
bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simplifyFlags, double tolerance )
{
int finalWkbSize = 0;
@ -486,24 +394,24 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simpl
QgsRectangle envelope = geometry->boundingBox();
QGis::WkbType wkbType = geometry->wkbType();
const unsigned char* wkb = geometry->asWkb();
int wkbSize = geometry->wkbSize();
QgsConstWkbPtr wkbPtr( geometry->asWkb(), geometry->wkbSize() );
unsigned char* targetWkb = new unsigned char[wkbSize];
memcpy( targetWkb, wkb, wkbSize );
unsigned char* targetWkb = new unsigned char[wkbPtr.remaining()];
memcpy( targetWkb, wkbPtr, wkbPtr.remaining() );
QgsWkbPtr targetWkbPtr( targetWkb, wkbPtr.remaining() );
try
{
if ( simplifyWkbGeometry( simplifyFlags, wkbType, wkb, wkbSize, targetWkb, finalWkbSize, envelope, tolerance ) )
if ( simplifyWkbGeometry( simplifyFlags, wkbType, wkbPtr, targetWkbPtr, finalWkbSize, envelope, tolerance ) )
{
unsigned char* finalWkb = new unsigned char[finalWkbSize];
unsigned char *finalWkb = new unsigned char[finalWkbSize];
memcpy( finalWkb, targetWkb, finalWkbSize );
geometry->fromWkb( finalWkb, finalWkbSize );
delete [] targetWkb;
return true;
}
}
catch ( const QgsParserException &e )
catch ( const QgsWkbException &e )
{
QgsDebugMsg( QString( "Exception thrown by simplifier: %1" ) .arg( e.what() ) );
}

View File

@ -45,7 +45,7 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier
private:
//! Simplify the WKB-geometry using the specified tolerance
static bool simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, const unsigned char* sourceWkb, int sourceWkbSize, unsigned char* targetWkb, int &targetWkbSize, const QgsRectangle& envelope, double map2pixelTol, bool writeHeader = true, bool isaLinearRing = false );
static bool simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, QgsConstWkbPtr sourceWkbPtr, QgsWkbPtr targetWkbPtr, int &targetWkbSize, const QgsRectangle& envelope, double map2pixelTol, bool writeHeader = true, bool isaLinearRing = false );
protected:
//! Current simplification flags

View File

@ -1080,7 +1080,8 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry* geometry, QDomDocumen
bool hasZValue = false;
QgsConstWkbPtr wkbPtr( geometry->asWkb() + 1 + sizeof( int ) );
QgsConstWkbPtr wkbPtr( geometry->asWkb(), geometry->wkbSize() );
wkbPtr.readHeader();
if ( format == "GML3" )
{
@ -1135,11 +1136,12 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry* geometry, QDomDocumen
for ( int idx = 0; idx < nPoints; ++idx )
{
wkbPtr += 1 + sizeof( int );
QDomElement pointMemberElem = doc.createElement( "gml:pointMember" );
QDomElement pointElem = doc.createElement( "gml:Point" );
QDomElement coordElem = baseCoordElem.cloneNode().toElement();
wkbPtr.readHeader();
double x, y;
wkbPtr >> x >> y;
QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) );
@ -1206,7 +1208,8 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry* geometry, QDomDocumen
{
QDomElement lineStringMemberElem = doc.createElement( "gml:lineStringMember" );
QDomElement lineStringElem = doc.createElement( "gml:LineString" );
wkbPtr += 1 + sizeof( int ); // skip type since we know its 2
wkbPtr.readHeader();
int nPoints;
wkbPtr >> nPoints;
@ -1312,7 +1315,7 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry* geometry, QDomDocumen
QDomElement polygonMemberElem = doc.createElement( "gml:polygonMember" );
QDomElement polygonElem = doc.createElement( "gml:Polygon" );
wkbPtr += 1 + sizeof( int );
wkbPtr.readHeader();
int numRings;
wkbPtr >> numRings;

View File

@ -18,6 +18,7 @@
#include "qgsgeometry.h"
#include "qgsvectorlayer.h"
#include "qgswkbptr.h"
#include "qgis.h"
#include <spatialindex/SpatialIndex.h>
@ -301,7 +302,7 @@ struct _CohenSutherland
};
static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry* geom, const QgsRectangle& rect, QgsVectorLayer* vl, QgsFeatureId fid )
static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry *geom, const QgsRectangle& rect, QgsVectorLayer *vl, QgsFeatureId fid )
{
// this code is stupidly based on QgsGeometry::closestSegmentWithContext
// we need iterator for segments...
@ -313,9 +314,10 @@ static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry* geom, co
_CohenSutherland cs( rect );
QgsWkbPtr wkbPtr( wkb + 1 );
QGis::WkbType wkbType;
wkbPtr >> wkbType;
QgsConstWkbPtr wkbPtr( wkb, geom->wkbSize() );
wkbPtr.readHeader();
QGis::WkbType wkbType = geom->wkbType();
bool hasZValue = false;
switch ( wkbType )
@ -373,7 +375,7 @@ static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry* geom, co
wkbPtr >> nLines;
for ( int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
{
wkbPtr += 1 + sizeof( int );
wkbPtr.readHeader();
int nPoints;
wkbPtr >> nPoints;
@ -455,7 +457,7 @@ static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry* geom, co
wkbPtr >> nPolygons;
for ( int polynr = 0, pointIndex = 0; polynr < nPolygons; ++polynr )
{
wkbPtr += 1 + sizeof( int );
wkbPtr.readHeader();
int nRings;
wkbPtr >> nRings;
for ( int ringnr = 0; ringnr < nRings; ++ringnr )

View File

@ -242,14 +242,14 @@ QgsSpatialIndex& QgsSpatialIndex::operator=( const QgsSpatialIndex & other )
return *this;
}
Region QgsSpatialIndex::rectToRegion( const QgsRectangle& rect )
SpatialIndex::Region QgsSpatialIndex::rectToRegion( const QgsRectangle& rect )
{
double pt1[2], pt2[2];
pt1[0] = rect.xMinimum();
pt1[1] = rect.yMinimum();
pt2[0] = rect.xMaximum();
pt2[1] = rect.yMaximum();
return Region( pt1, pt2, 2 );
return SpatialIndex::Region( pt1, pt2, 2 );
}
bool QgsSpatialIndex::featureInfo( const QgsFeature& f, SpatialIndex::Region& r, QgsFeatureId &id )
@ -267,7 +267,7 @@ bool QgsSpatialIndex::featureInfo( const QgsFeature& f, SpatialIndex::Region& r,
bool QgsSpatialIndex::insertFeature( const QgsFeature& f )
{
Region r;
SpatialIndex::Region r;
QgsFeatureId id;
if ( !featureInfo( f, r, id ) )
return false;
@ -298,7 +298,7 @@ bool QgsSpatialIndex::insertFeature( const QgsFeature& f )
bool QgsSpatialIndex::deleteFeature( const QgsFeature& f )
{
Region r;
SpatialIndex::Region r;
QgsFeatureId id;
if ( !featureInfo( f, r, id ) )
return false;
@ -312,7 +312,7 @@ QList<QgsFeatureId> QgsSpatialIndex::intersects( const QgsRectangle& rect ) cons
QList<QgsFeatureId> list;
QgisVisitor visitor( list );
Region r = rectToRegion( rect );
SpatialIndex::Region r = rectToRegion( rect );
d->mRTree->intersectsWithQuery( r, visitor );

View File

@ -70,7 +70,7 @@ Qgs25DRenderer::Qgs25DRenderer()
QgsStringMap wallProperties;
wallProperties.insert( "geometryModifier", WALL_EXPRESSION );
wallProperties.insert( "symbolType", "Fill" );
QgsSymbolLayerV2* walls = QgsGeometryGeneratorSymbolLayerV2::create( wallProperties );;
QgsSymbolLayerV2* walls = QgsGeometryGeneratorSymbolLayerV2::create( wallProperties );
QgsStringMap roofProperties;
roofProperties.insert( "geometryModifier", ROOF_EXPRESSION );

View File

@ -29,6 +29,7 @@
#include "qgsmultipointv2.h"
#include "qgspointv2.h"
#include "qgsunittypes.h"
#include "qgswkbptr.h"
#include <QDomElement>
#include <QPainter>
@ -169,7 +170,7 @@ void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, Qg
QgsGeometry groupGeom( groupMultiPoint );
QgsGeometry* centroid = groupGeom.centroid();
QPointF pt;
_getPoint( pt, context, centroid->asWkb() );
_getPoint( pt, context, QgsConstWkbPtr( centroid->asWkb(), centroid->wkbSize() ) );
delete centroid;
//calculate max diagonal size from all symbols in group

View File

@ -42,14 +42,12 @@
const unsigned char* QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb )
QgsConstWkbPtr QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkbPtr )
{
QgsConstWkbPtr wkbPtr( wkb + 1 );
unsigned int wkbType;
wkbPtr >> wkbType >> pt.rx() >> pt.ry();
if ( static_cast< QgsWKBTypes::Type >( wkbType ) == QgsWKBTypes::Point25D || static_cast< QgsWKBTypes::Type >( wkbType ) == QgsWKBTypes::PointZ )
wkbPtr += sizeof( double );
QgsDebugCall;
QgsWKBTypes::Type type = wkbPtr.readHeader();
wkbPtr >> pt.rx() >> pt.ry();
wkbPtr += ( QgsWKBTypes::coordDimensions( type ) - 2 ) * sizeof( double );
if ( context.coordinateTransform() )
{
@ -62,17 +60,13 @@ const unsigned char* QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderCont
return wkbPtr;
}
const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
QgsConstWkbPtr QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
QgsConstWkbPtr wkbPtr( wkb + 1 );
unsigned int wkbType, nPoints;
wkbPtr >> wkbType >> nPoints;
QgsDebugCall;
QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
unsigned int nPoints;
wkbPtr >> nPoints;
bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
double x = 0.0;
double y = 0.0;
const QgsCoordinateTransform* ct = context.coordinateTransform();
const QgsMapToPixel& mtp = context.mapToPixel();
@ -83,22 +77,20 @@ const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRe
double cw = e.width() / 10;
double ch = e.height() / 10;
QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
wkbPtr = QgsConstWkbPtr( QgsClipper::clippedLineWKB( wkb, clipRect, pts ) );
wkbPtr -= 1 + 2 * sizeof( int );
wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts );
}
else
{
pts.resize( nPoints );
int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
QPointF* ptr = pts.data();
for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
{
wkbPtr >> x >> y;
if ( hasZValue )
wkbPtr += sizeof( double );
if ( hasMValue )
wkbPtr += sizeof( double );
*ptr = QPointF( x, y );
wkbPtr >> ptr->rx() >> ptr->ry();
wkbPtr += skipZM;
}
}
@ -117,20 +109,16 @@ const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRe
return wkbPtr;
}
const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
QgsConstWkbPtr QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
QgsConstWkbPtr wkbPtr( wkb + 1 );
unsigned int wkbType, numRings;
wkbPtr >> wkbType >> numRings;
QgsDebugCall;
QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
unsigned int numRings;
wkbPtr >> numRings;
if ( numRings == 0 ) // sanity check for zero rings in polygon
return wkbPtr;
bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
double x, y;
holes.clear();
const QgsCoordinateTransform* ct = context.coordinateTransform();
@ -140,6 +128,8 @@ const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QP
double ch = e.height() / 10;
QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
for ( unsigned int idx = 0; idx < numRings; idx++ )
{
unsigned int nPoints;
@ -151,13 +141,8 @@ const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QP
QPointF* ptr = poly.data();
for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
{
wkbPtr >> x >> y;
if ( hasZValue )
wkbPtr += sizeof( double );
if ( hasMValue )
wkbPtr += sizeof( double );
*ptr = QPointF( x, y );
wkbPtr >> ptr->rx() >> ptr->ry();
wkbPtr += skipZM;
}
if ( nPoints < 1 )
@ -173,7 +158,6 @@ const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QP
ct->transformPolygon( poly );
}
ptr = poly.data();
for ( int i = 0; i < poly.size(); ++i, ++ptr )
{

View File

@ -401,9 +401,9 @@ class CORE_EXPORT QgsFeatureRendererV2
//! render editing vertex marker for a polygon
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
static const unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb );
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkb );
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );

View File

@ -107,17 +107,12 @@ QgsSymbolV2::QgsSymbolV2( SymbolType type, const QgsSymbolLayerV2List& layers )
}
const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
QgsConstWkbPtr QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
QgsConstWkbPtr wkbPtr( wkb + 1 );
unsigned int wkbType, nPoints;
wkbPtr >> wkbType >> nPoints;
QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
unsigned int nPoints;
wkbPtr >> nPoints;
bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
double x = 0.0;
double y = 0.0;
const QgsCoordinateTransform* ct = context.coordinateTransform();
const QgsMapToPixel& mtp = context.mapToPixel();
@ -128,22 +123,21 @@ const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderConte
double cw = e.width() / 10;
double ch = e.height() / 10;
QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
wkbPtr = QgsConstWkbPtr( QgsClipper::clippedLineWKB( wkb, clipRect, pts ) );
wkbPtr -= 1 + 2 * sizeof( int );
wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts );
}
else
{
pts.resize( nPoints );
QPointF* ptr = pts.data();
int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
Q_ASSERT( skipZM >= 0 );
QPointF *ptr = pts.data();
for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
{
wkbPtr >> x >> y;
if ( hasZValue )
wkbPtr += sizeof( double );
if ( hasMValue )
wkbPtr += sizeof( double );
*ptr = QPointF( x, y );
wkbPtr >> ptr->rx() >> ptr->ry();
wkbPtr += skipZM;
}
}
@ -153,7 +147,7 @@ const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderConte
ct->transformPolygon( pts );
}
QPointF* ptr = pts.data();
QPointF *ptr = pts.data();
for ( int i = 0; i < pts.size(); ++i, ++ptr )
{
mtp.transformInPlace( ptr->rx(), ptr->ry() );
@ -162,20 +156,16 @@ const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderConte
return wkbPtr;
}
const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
QgsConstWkbPtr QgsSymbolV2::_getPolygon( QPolygonF &pts, QList<QPolygonF> &holes, QgsRenderContext &context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
QgsConstWkbPtr wkbPtr( wkb + 1 );
unsigned int wkbType, numRings;
wkbPtr >> wkbType >> numRings;
QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
QgsDebugMsg( QString( "wkbType=%1" ).arg( wkbType ) );
unsigned int numRings;
wkbPtr >> numRings;
if ( numRings == 0 ) // sanity check for zero rings in polygon
return wkbPtr;
bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
double x, y;
holes.clear();
const QgsCoordinateTransform* ct = context.coordinateTransform();
@ -185,6 +175,9 @@ const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>&
double ch = e.height() / 10;
QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
Q_ASSERT( skipZM >= 0 );
for ( unsigned int idx = 0; idx < numRings; idx++ )
{
unsigned int nPoints;
@ -192,17 +185,11 @@ const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>&
QPolygonF poly( nPoints );
// Extract the points from the WKB and store in a pair of vectors.
QPointF* ptr = poly.data();
QPointF *ptr = poly.data();
for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
{
wkbPtr >> x >> y;
if ( hasZValue )
wkbPtr += sizeof( double );
if ( hasMValue )
wkbPtr += sizeof( double );
*ptr = QPointF( x, y );
wkbPtr >> ptr->rx() >> ptr->ry();
wkbPtr += skipZM;
}
if ( nPoints < 1 )
@ -210,7 +197,10 @@ const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>&
//clip close to view extent, if needed
QRectF ptsRect = poly.boundingRect();
if ( clipToExtent && !context.extent().contains( ptsRect ) ) QgsClipper::trimPolygon( poly, clipRect );
if ( clipToExtent && !context.extent().contains( ptsRect ) )
{
QgsClipper::trimPolygon( poly, clipRect );
}
//transform the QPolygonF to screen coordinates
if ( ct )
@ -218,7 +208,6 @@ const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>&
ct->transformPolygon( poly );
}
ptr = poly.data();
for ( int i = 0; i < poly.size(); ++i, ++ptr )
{
@ -695,7 +684,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
return;
}
const QgsGeometry* segmentizedGeometry = geom;
const QgsGeometry *segmentizedGeometry = geom;
bool deleteSegmentizedGeometry = false;
context.setGeometry( geom->geometry() );
@ -704,7 +693,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
//convert curve types to normal point/line/polygon ones
if ( QgsWKBTypes::isCurvedType( geom->geometry()->wkbType() ) )
{
QgsAbstractGeometryV2* g = geom->geometry()->segmentize();
QgsAbstractGeometryV2 *g = geom->geometry()->segmentize();
if ( !g )
{
return;
@ -733,7 +722,6 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
}
const QgsPointV2* point = static_cast< const QgsPointV2* >( segmentizedGeometry->geometry() );
_getPoint( pt, context, point );
( static_cast<QgsMarkerSymbolV2*>( this ) )->renderPoint( pt, &feature, context, layer, selected );
@ -754,7 +742,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
QgsDebugMsg( "linestring can be drawn only with line symbol!" );
break;
}
_getLineString( pts, context, segmentizedGeometry->asWkb(), !tileMapRendering && clipFeaturesToExtent() );
_getLineString( pts, context, QgsConstWkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() ), !tileMapRendering && clipFeaturesToExtent() );
static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
}
break;
@ -767,7 +755,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
break;
}
_getPolygon( pts, holes, context, segmentizedGeometry->asWkb(), !tileMapRendering && clipFeaturesToExtent() );
_getPolygon( pts, holes, context, QgsConstWkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() ), !tileMapRendering && clipFeaturesToExtent() );
static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
}
break;
@ -806,10 +794,11 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
break;
}
QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() );
wkbPtr.readHeader();
unsigned int num;
wkbPtr >> num;
const unsigned char* ptr = wkbPtr;
const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
@ -821,7 +810,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
{
context.setGeometry( geomCollection->geometryN( i ) );
}
ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr, !tileMapRendering && clipFeaturesToExtent() ) );
wkbPtr = _getLineString( pts, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() );
static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
}
}
@ -836,10 +825,11 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
break;
}
QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() );
wkbPtr.readHeader();
unsigned int num;
wkbPtr >> num;
const unsigned char* ptr = wkbPtr;
QPolygonF pts;
QList<QPolygonF> holes;
@ -854,7 +844,8 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
{
context.setGeometry( geomCollection->geometryN( i ) );
}
ptr = _getPolygon( pts, holes, context, ptr, !tileMapRendering && clipFeaturesToExtent() );
wkbPtr = _getPolygon( pts, holes, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() );
static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
}
break;

View File

@ -276,13 +276,13 @@ class CORE_EXPORT QgsSymbolV2
* Creates a line string in screen coordinates from a wkb string in map
* coordinates
*/
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
/**
* Creates a polygon in screen coordinates from a wkb string in map
* coordinates
*/
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
/**
* Retrieve a cloned list of all layers that make up this symbol.

View File

@ -168,21 +168,21 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! Set how often map preview should be updated while it is being rendered (in milliseconds)
//! @note added in 2.4
void setMapUpdateInterval( int timeMiliseconds );
void setMapUpdateInterval( int timeMilliseconds );
//! Find out how often map preview should be updated while it is being rendered (in milliseconds)
//! @note added in 2.4
int mapUpdateInterval() const;
//! @deprecated since 2.4 - there could be more than just one "map" items
Q_DECL_DEPRECATED QgsMapCanvasMap* map();
Q_DECL_DEPRECATED QgsMapCanvasMap *map();
//! @deprecated since 2.4 - use mapSettings() for anything related to current renderer settings
//// SIP: removed /Transfer/ because it crashes after few calls to iface.mapCanvas().mapRenderer().hasCrsTransformEnabled()
//// and in fact there is no transfer of ownership from c++ to python!
//// Actually the problem comes from the fact that "hasCrsTransformEnabled" is both a signal and a normal method
//// /KeepReference/ is necessary because otherwise mapRenderer().hasCrsTransformEnabled() was crashing
Q_DECL_DEPRECATED QgsMapRenderer* mapRenderer();
Q_DECL_DEPRECATED QgsMapRenderer *mapRenderer();
//! Accessor for the canvas paint device
//! @deprecated since 2.4

View File

@ -385,51 +385,47 @@ void QgsGPXFeatureIterator::readAttributes( QgsFeature& feature, const QgsTrack&
break;
}
}
}
QgsGeometry* QgsGPXFeatureIterator::readWaypointGeometry( const QgsWaypoint& wpt )
QgsGeometry *QgsGPXFeatureIterator::readWaypointGeometry( const QgsWaypoint& wpt )
{
char* geo = new char[21];
std::memset( geo, 0, 21 );
geo[0] = QgsApplication::endian();
geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBPoint;
std::memcpy( geo + 5, &wpt.lon, sizeof( double ) );
std::memcpy( geo + 13, &wpt.lat, sizeof( double ) );
int size = 1 + sizeof( int ) + 2 * sizeof( double );
unsigned char *geo = new unsigned char[size];
QgsWkbPtr wkbPtr( geo, size );
wkbPtr << ( char ) QgsApplication::endian() << QGis::WKBPoint << wpt.lon << wpt.lat;
QgsGeometry *g = new QgsGeometry();
g->fromWkb(( unsigned char * )geo, 21 );
g->fromWkb( geo, size );
return g;
}
QgsGeometry* QgsGPXFeatureIterator::readRouteGeometry( const QgsRoute& rte )
QgsGeometry *QgsGPXFeatureIterator::readRouteGeometry( const QgsRoute& rte )
{
// some wkb voodoo
int nPoints = rte.points.size();
char* geo = new char[9 + 16 * nPoints];
std::memset( geo, 0, 9 + 16 * nPoints );
geo[0] = QgsApplication::endian();
geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBLineString;
std::memcpy( geo + 5, &nPoints, 4 );
int size = 1 + 2 * sizeof( int ) + 2 * sizeof( double ) * rte.points.size();
unsigned char *geo = new unsigned char[size];
QgsWkbPtr wkbPtr( geo, size );
wkbPtr << ( char ) QgsApplication::endian() << QGis::WKBLineString << rte.points.size();
for ( int i = 0; i < rte.points.size(); ++i )
{
std::memcpy( geo + 9 + 16 * i, &rte.points[i].lon, sizeof( double ) );
std::memcpy( geo + 9 + 16 * i + 8, &rte.points[i].lat, sizeof( double ) );
wkbPtr << rte.points[i].lon << rte.points[i].lat;
}
//create QgsGeometry and use it for intersection test
//if geometry is to be fetched, it is attached to the feature, otherwise we delete it
QgsGeometry* theGeometry = new QgsGeometry();
theGeometry->fromWkb(( unsigned char * )geo, 9 + 16 * nPoints );
return theGeometry;
QgsGeometry *g = new QgsGeometry();
g->fromWkb( geo, size );
return g;
}
QgsGeometry* QgsGPXFeatureIterator::readTrackGeometry( const QgsTrack& trk )
QgsGeometry *QgsGPXFeatureIterator::readTrackGeometry( const QgsTrack& trk )
{
// TODO: support multi line string for segments
if ( trk.segments.isEmpty() )
return nullptr;
@ -439,39 +435,38 @@ QgsGeometry* QgsGPXFeatureIterator::readTrackGeometry( const QgsTrack& trk )
{
totalPoints += trk.segments[i].points.size();
}
if ( totalPoints == 0 )
return nullptr;
//QgsDebugMsg( "GPX feature track total points: " + QString::number( totalPoints ) );
// some wkb voodoo
char* geo = new char[9 + 16 * totalPoints];
int size = 1 + 2 * sizeof( int ) + 2 * sizeof( double ) * totalPoints;
unsigned char *geo = new unsigned char[size];
if ( !geo )
{
QgsDebugMsg( "Too large track!!!" );
QgsDebugMsg( "Track too large!" );
return nullptr;
}
std::memset( geo, 0, 9 + 16 * totalPoints );
geo[0] = QgsApplication::endian();
geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBLineString;
std::memcpy( geo + 5, &totalPoints, 4 );
int thisPoint = 0;
QgsWkbPtr wkbPtr( geo, size );
wkbPtr << ( char ) QgsApplication::endian() << QGis::WKBLineString << totalPoints;
for ( int k = 0; k < trk.segments.size(); k++ )
{
int nPoints = trk.segments[k].points.size();
for ( int i = 0; i < nPoints; ++i )
{
std::memcpy( geo + 9 + 16 * thisPoint, &trk.segments[k].points[i].lon, sizeof( double ) );
std::memcpy( geo + 9 + 16 * thisPoint + 8, &trk.segments[k].points[i].lat, sizeof( double ) );
thisPoint++;
wkbPtr << trk.segments[k].points[i].lon << trk.segments[k].points[i].lat;
}
}
//create QgsGeometry and use it for intersection test
//if geometry is to be fetched, it is attached to the feature, otherwise we delete it
QgsGeometry* theGeometry = new QgsGeometry();
theGeometry->fromWkb(( unsigned char * )geo, 9 + 16 * totalPoints );
return theGeometry;
QgsGeometry *g = new QgsGeometry();
g->fromWkb( geo, size );
return g;
}

View File

@ -529,7 +529,7 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
{
feature.setAttribute( 1, QgsGrass::vectorTypeName( type ) );
int node1, node2;;
int node1, node2;
Vect_get_line_nodes( mSource->map(), lid, &node1, &node2 );
feature.setAttribute( 2, node1 );
if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE )

View File

@ -657,7 +657,7 @@ QString QgsHttpRequestHandler::readPostBody() const
QgsMessageLog::logMessage( "length is: " + lengthQString );
if ( conversionSuccess )
{
input = ( char* )malloc( length + 1 );
input = new char[length + 1];
memset( input, 0, length + 1 );
for ( int i = 0; i < length; ++i )
{
@ -672,7 +672,7 @@ QString QgsHttpRequestHandler::readPostBody() const
{
QgsMessageLog::logMessage( "input is NULL " );
}
free( input );
delete [] input;
}
else
{

View File

@ -1189,7 +1189,7 @@ void QgsServerProjectParser::layerFromLegendLayer( const QDomElement& legendLaye
QList<QDomElement> QgsServerProjectParser::findLegendGroupElements() const
{
QList<QDomElement> LegendGroupElemList;
QgsLayerTreeGroup* rootLayerTreeGroup = new QgsLayerTreeGroup;;
QgsLayerTreeGroup* rootLayerTreeGroup = new QgsLayerTreeGroup;
QDomElement layerTreeElem = mXMLDoc->documentElement().firstChildElement( "layer-tree-group" );
if ( !layerTreeElem.isNull() )

View File

@ -503,19 +503,19 @@ void TestQgsGeometry::pointV2()
unsigned char* wkb = p12.asWkb( size );
QCOMPARE( size, p12.wkbSize() );
QgsPointV2 p13;
p13.fromWkb( wkb );
p13.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QVERIFY( p13 == p12 );
//bad WKB - check for no crash
p13 = QgsPointV2( 1, 2 );
QVERIFY( !p13.fromWkb( 0 ) );
QVERIFY( !p13.fromWkb( QgsConstWkbPtr( nullptr, 0 ) ) );
QCOMPARE( p13.wkbType(), QgsWKBTypes::Unknown );
QgsLineStringV2 line;
p13 = QgsPointV2( 1, 2 );
wkb = line.asWkb( size );
QVERIFY( !p13.fromWkb( wkb ) );
QVERIFY( !p13.fromWkb( QgsConstWkbPtr( wkb, size ) ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p13.wkbType(), QgsWKBTypes::Unknown );
@ -1310,7 +1310,7 @@ void TestQgsGeometry::lineStringV2()
unsigned char* wkb = l15.asWkb( size );
QCOMPARE( size, l15.wkbSize() );
QgsLineStringV2 l16;
l16.fromWkb( wkb );
l16.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( l16.numPoints(), 4 );
@ -1328,11 +1328,11 @@ void TestQgsGeometry::lineStringV2()
//bad WKB - check for no crash
l16.clear();
QVERIFY( !l16.fromWkb( 0 ) );
QVERIFY( !l16.fromWkb( QgsConstWkbPtr( nullptr, 0 ) ) );
QCOMPARE( l16.wkbType(), QgsWKBTypes::Unknown );
QgsPointV2 point( 1, 2 );
wkb = point.asWkb( size ) ;
QVERIFY( !l16.fromWkb( wkb ) );
QVERIFY( !l16.fromWkb( QgsConstWkbPtr( wkb, size ) ) );
delete[] wkb;
wkb = 0;
QCOMPARE( l16.wkbType(), QgsWKBTypes::Unknown );
@ -2058,7 +2058,7 @@ void TestQgsGeometry::lineStringV2()
QVERIFY( l37.boundingBox().isNull() );
l37.setPoints( QList< QgsPointV2 >() << QgsPointV2( 5, 10 ) << QgsPointV2( 10, 15 ) );
wkb = toAppend->asWkb( size );
l37.fromWkb( wkb );
l37.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( l37.boundingBox(), QgsRectangle( 1, 0, 4, 2 ) );
@ -2658,7 +2658,7 @@ void TestQgsGeometry::polygonV2()
unsigned char* wkb = p16.asWkb( size );
QCOMPARE( size, p16.wkbSize() );
QgsPolygonV2 p17;
p17.fromWkb( wkb );
p17.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p16, p17 );
@ -2678,7 +2678,7 @@ void TestQgsGeometry::polygonV2()
size = 0;
wkb = p16.asWkb( size );
QCOMPARE( size, p16.wkbSize() );
p17.fromWkb( wkb );
p17.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p16, p17 );
@ -2698,7 +2698,7 @@ void TestQgsGeometry::polygonV2()
size = 0;
wkb = p16.asWkb( size );
QCOMPARE( size, p16.wkbSize() );
p17.fromWkb( wkb );
p17.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p16, p17 );
@ -2718,7 +2718,7 @@ void TestQgsGeometry::polygonV2()
size = 0;
wkb = p16.asWkb( size );
QCOMPARE( size, p16.wkbSize() );
p17.fromWkb( wkb );
p17.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p16, p17 );
@ -2738,19 +2738,19 @@ void TestQgsGeometry::polygonV2()
size = 0;
wkb = p16.asWkb( size );
QCOMPARE( size, p16.wkbSize() );
p17.clear();;
p17.fromWkb( wkb );
p17.clear();
p17.fromWkb( QgsConstWkbPtr( wkb, size ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p16, p17 );
//bad WKB - check for no crash
p17.clear();
QVERIFY( !p17.fromWkb( 0 ) );
QVERIFY( !p17.fromWkb( QgsConstWkbPtr( nullptr, 0 ) ) );
QCOMPARE( p17.wkbType(), QgsWKBTypes::Unknown );
QgsPointV2 point( 1, 2 );
wkb = point.asWkb( size ) ;
QVERIFY( !p17.fromWkb( wkb ) );
QVERIFY( !p17.fromWkb( QgsConstWkbPtr( wkb, size ) ) );
delete[] wkb;
wkb = 0;
QCOMPARE( p17.wkbType(), QgsWKBTypes::Unknown );

View File

@ -99,7 +99,7 @@ void TestQgsGeometryImport::pointWkb()
//create wkb
char byteOrder = QgsApplication::endian();
unsigned char* geomPtr = new unsigned char[21];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, 21 );
wkb << byteOrder << QGis::WKBPoint << x << y;
QgsGeometry geom;
@ -178,7 +178,7 @@ void TestQgsGeometryImport::linestringWkb()
char byteOrder = QgsApplication::endian();
int wkbSize = 1 + 2 * sizeof( int ) + line.size() * 2 * sizeof( double );
unsigned char* geomPtr = new unsigned char[wkbSize];
QgsWkbPtr wkb( geomPtr );
QgsWkbPtr wkb( geomPtr, wkbSize );
wkb << byteOrder << QGis::WKBLineString << line.size();
for ( int i = 0; i < line.size(); ++i )