438 changes: 4 additions & 434 deletions src/core/qgsfeaturerequest.cpp

Large diffs are not rendered by default.

34 changes: 0 additions & 34 deletions src/core/qgsfeaturerequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,40 +164,6 @@ class CORE_EXPORT QgsFeatureRequest
const QgsMapToPixel* mMapToPixel;
//! Factor tolterance to apply in transformation between map coordinates and device coordinates
float mMapToPixelTol;

// Map2pixel simplification for fast rendering
public:
//! Default Threshold of map2pixel simplification between map coordinates and device coordinates for fast rendering
static float const MAPTOPIXEL_THRESHOLD_DEFAULT;

//! Returns whether the device-geometry can be replaced by its BBOX when is applied the specified map2pixel tolerance
static bool canbeGeneralizedByWndBoundingBox( const QgsRectangle& envelope, float mapToPixelTol = 1.0f );
//! Returns whether the device-geometry can be replaced by its BBOX when is applied the specified map2pixel tolerance
static bool canbeGeneralizedByWndBoundingBox( const QVector<QPointF>& points, float mapToPixelTol = 1.0f );

//! Returns whether the envelope can be replaced by its BBOX when is applied the map2pixel context
static bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope,
const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mtp, float mapToPixelTol = 1.0f );

//! Returns whether the envelope can be replaced by its BBOX when is applied the map2pixel context
inline bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope ) const { return canbeGeneralizedByMapBoundingBox( envelope, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }

//! Simplify the specified geometry (Removing duplicated points) when is applied the map2pixel context
static bool simplifyGeometry( const QgsFeatureRequest::Flags& requestFlags,
QgsGeometry* geometry,
const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mtp, float mapToPixelTol = 1.0f );

//! Simplify the specified geometry (Removing duplicated points) when is applied the map2pixel context
inline bool simplifyGeometry( QgsGeometry* geometry ) const { return simplifyGeometry( mFlags, geometry, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }

//! Simplify the specified point stream (Removing duplicated points) when is applied a map2pixel context
static bool simplifyGeometry( const QgsFeatureRequest::Flags& requestFlags,
QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount,
const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mtp, float mapToPixelTol = 1.0f );

//! Simplify the specified point stream (Removing duplicated points) when is applied the map2pixel context
inline bool simplifyGeometry( const QgsFeatureRequest::Flags& requestFlags,
QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount ) const { return simplifyGeometry( requestFlags, geometryType, envelope, xptr, xStride, yptr, yStride, pointCount, pointSimplifiedCount, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }
};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRequest::Flags )
Expand Down
80 changes: 80 additions & 0 deletions src/core/qgsgeometrysimplifier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/***************************************************************************
qgsgeometrysimplifier.cpp
---------------------
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include <limits>
#include "qgsgeometrysimplifier.h"

//! Returns whether the device-envelope can be replaced by its BBOX when is applied the specified tolerance
bool QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( const QgsRectangle& envelope, float mapToPixelTol )
{
return (envelope.xMaximum()-envelope.xMinimum()) < mapToPixelTol && (envelope.yMaximum()-envelope.yMinimum()) < mapToPixelTol;
}

//! Returns whether the device-geometry can be replaced by its BBOX when is applied the specified tolerance
bool QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( const QVector<QPointF>& points, float mapToPixelTol )
{
double xmin = std::numeric_limits<double>::max(), x,y;
double ymin = std::numeric_limits<double>::max();
double xmax = -std::numeric_limits<double>::max();
double ymax = -std::numeric_limits<double>::max();

for ( int i = 0, numPoints = points.size(); i < numPoints; ++i )
{
x = points[i].x();
y = points[i].y();

if (xmin>x) xmin = x;
if (ymin>y) ymin = y;
if (xmax<x) xmax = x;
if (ymax<y) ymax = y;
}
return canbeGeneralizedByDeviceBoundingBox( QgsRectangle( xmin, ymin, xmax, ymax ), mapToPixelTol );
}

/***************************************************************************/
/**
* Implementation of GeometrySimplifier using the Douglas-Peucker algorithm
*/
QgsTopologyPreservingSimplifier::QgsTopologyPreservingSimplifier( double tolerance ) : mTolerance( tolerance )
{
}
QgsTopologyPreservingSimplifier::~QgsTopologyPreservingSimplifier()
{
}

//! Returns a simplified version the specified geometry
QgsGeometry* QgsTopologyPreservingSimplifier::simplify( QgsGeometry* geometry )
{
return geometry->simplify( mTolerance );
}

//! Simplifies the specified geometry
bool QgsTopologyPreservingSimplifier::simplifyGeometry( QgsGeometry* geometry )
{
QgsGeometry* g = geometry->simplify( mTolerance );

if ( g )
{
size_t wkbSize = g->wkbSize();
unsigned char* wkb = (unsigned char*)malloc( wkbSize );
memcpy( wkb, g->asWkb(), wkbSize );
geometry->fromWkb( wkb, wkbSize );
delete g;

return true;
}
return false;
}
65 changes: 65 additions & 0 deletions src/core/qgsgeometrysimplifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/***************************************************************************
qgsgeometrysimplifier.h
---------------------
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSGEOMETRYSIMPLIFIER_H
#define QGSGEOMETRYSIMPLIFIER_H

#include "qgsgeometry.h"

/**
* Abstract base class for simplify geometries using a specific algorithm
*/
class CORE_EXPORT QgsAbstractGeometrySimplifier
{
public:
//! Returns a simplified version the specified geometry
virtual QgsGeometry* simplify( QgsGeometry* geometry ) = 0;
//! Simplifies the specified geometry
virtual bool simplifyGeometry( QgsGeometry* geometry ) = 0;

// MapToPixel simplification helper methods
public:
//! Returns whether the device-envelope can be replaced by its BBOX when is applied the specified tolerance
static bool canbeGeneralizedByDeviceBoundingBox( const QgsRectangle& envelope, float mapToPixelTol = 1.0f );
//! Returns whether the device-geometry can be replaced by its BBOX when is applied the specified tolerance
static bool canbeGeneralizedByDeviceBoundingBox( const QVector<QPointF>& points, float mapToPixelTol = 1.0f );
};

/***************************************************************************/
/**
* Implementation of GeometrySimplifier using the Douglas-Peucker algorithm
*
* Simplifies a geometry, ensuring that the result is a valid geometry having the same dimension and number of components as the input.
* The simplification uses a maximum distance difference algorithm similar to the one used in the Douglas-Peucker algorithm.
*/
class CORE_EXPORT QgsTopologyPreservingSimplifier : public QgsAbstractGeometrySimplifier
{
public:
QgsTopologyPreservingSimplifier( double tolerance );
virtual ~QgsTopologyPreservingSimplifier();

private:
//! Distance tolerance for the simplification
double mTolerance;

public:
//! Returns a simplified version the specified geometry
virtual QgsGeometry* simplify( QgsGeometry* geometry );
//! Simplifies the specified geometry
virtual bool simplifyGeometry( QgsGeometry* geometry );
};

#endif // QGSGEOMETRYSIMPLIFIER_H
401 changes: 401 additions & 0 deletions src/core/qgsmaptopixelgeometrysimplifier.cpp

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions src/core/qgsmaptopixelgeometrysimplifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/***************************************************************************
qgsmaptopixelgeometrysimplifier.h
---------------------
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMAPTOPIXELGEOMETRYSIMPLIFIER_H
#define QGSMAPTOPIXELGEOMETRYSIMPLIFIER_H

#include "qgsgeometry.h"
#include "qgscoordinatetransform.h"
#include "qgsmaptopixel.h"

#include "qgsgeometrysimplifier.h"

/**
* Implementation of GeometrySimplifier using the "MapToPixel" algorithm
*
* Simplifies a geometry removing points within of the maximum distance difference that defines the MapToPixel info of a RenderContext request.
* This class enables simplify the geometries to be rendered in a MapCanvas target to speed up the vector drawing.
*/
class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier
{
public:
QgsMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol );
virtual ~QgsMapToPixelSimplifier();

//! Applicable simplification flags
enum SimplifyFlag
{
NoFlags = 0, //!< No simplification can be applied
SimplifyGeometry = 1, //!< The geometries can be simplified using the current map2pixel context state
SimplifyEnvelope = 2, //!< The geometries can be fully simplified by its BoundingBox
};

private:
//! Simplify the WKB-geometry using the specified tolerance
static bool simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, unsigned char* sourceWkb, size_t sourceWkbSize, unsigned char* targetWkb, size_t& targetWkbSize, const QgsRectangle& envelope, float map2pixelTol, bool writeHeader = true, bool isaLinearRing = false );

protected:
//! Current simplification flags
int mSimplifyFlags;

//! For transformation between coordinate systems from current layer to map target. Can be 0 if on-the-fly reprojection is not used
const QgsCoordinateTransform* mMapCoordTransform;
//! For transformation between map coordinates and device coordinates
const QgsMapToPixel* mMapToPixel;
//! Factor tolterance to apply in transformation between map coordinates and device coordinates
float mMapToPixelTol;

//! Returns the squared 2D-distance of the vector defined by the two points specified
static float calculateLengthSquared2D( double x1, double y1, double x2, double y2 );
//! Returns the MapTolerance for transform between map coordinates and device coordinates
static float calculateViewPixelTolerance( const QgsRectangle& boundingRect, const QgsCoordinateTransform* ct, const QgsMapToPixel* mapToPixel );

public:
int simplifyFlags() const { return mSimplifyFlags; }
void setSimplifyFlags( int simplifyFlags ) { mSimplifyFlags = simplifyFlags; }

const QgsCoordinateTransform* coordinateTransform() const { return mMapCoordTransform; }
void setCoordinateTransform( const QgsCoordinateTransform* ct ) { mMapCoordTransform = ct; }

const QgsMapToPixel* mapToPixel() const { return mMapToPixel; }
void setMapToPixel( const QgsMapToPixel* mtp ) { mMapToPixel = mtp; }

float mapToPixelTol() const { return mMapToPixelTol; }
void setMapToPixelTol( float map2pixelTol ) { mMapToPixelTol = map2pixelTol; }

//! Returns a simplified version the specified geometry
virtual QgsGeometry* simplify( QgsGeometry* geometry );
//! Simplifies the specified geometry
virtual bool simplifyGeometry( QgsGeometry* geometry );

// MapToPixel simplification helper methods
public:

//! Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel context
static bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope,
const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol = 1.0f );

//! Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel context
inline bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope ) const { return canbeGeneralizedByMapBoundingBox( envelope, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }

//! Simplifies the geometry when is applied the specified map2pixel context
static bool simplifyGeometry( QgsGeometry* geometry,
int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol = 1.0f );

};

#endif // QGSMAPTOPIXELGEOMETRYSIMPLIFIER_H
39 changes: 26 additions & 13 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
#include "qgssymbologyv2conversion.h"
#include "qgspallabeling.h"

#include "qgsmaptopixelgeometrysimplifier.h"

#ifdef TESTPROVIDERLIB
#include <dlfcn.h>
#endif
Expand Down Expand Up @@ -135,8 +137,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mValidExtent( false )
, mSymbolFeatureCounted( false )
, mCurrentRendererContext( 0 )
, mSimplifyDrawingTol( QgsFeatureRequest::MAPTOPIXEL_THRESHOLD_DEFAULT )
, mSimplifyDrawingHints( QgsVectorLayer::FullSimplification )
, mSimplifyDrawingTol( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD )

{
mActions = new QgsAttributeAction( this );
Expand Down Expand Up @@ -699,23 +701,37 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
.setFilterRect( rendererContext.extent() )
.setSubsetOfAttributes( attributes );

QgsFeatureIterator fit = QgsFeatureIterator();

// Enable the simplification of the geometries (Using the current map2pixel context) before fetch the features.
if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification | QgsVectorLayer::EnvelopeSimplification ) && !(featureRequest.flags() & QgsFeatureRequest::NoGeometry) && !rendererContext.renderingPrintComposition() )
{
QgsFeatureRequest::Flags simplificationHints = QgsFeatureRequest::NoFlags;
if ( mSimplifyDrawingHints & QgsVectorLayer::GeometrySimplification ) simplificationHints |= QgsFeatureRequest::SimplifyGeometry;
if ( mSimplifyDrawingHints & QgsVectorLayer::EnvelopeSimplification ) simplificationHints |= QgsFeatureRequest::SimplifyEnvelope;

QPainter* p = rendererContext.painter();
float dpi = ( p->device()->logicalDpiX() + p->device()->logicalDpiY() ) / 2;
float map2pixelTol = mSimplifyDrawingTol * 96.0f/dpi;

featureRequest.setFlags( featureRequest.flags() | simplificationHints );
int simplifyFlags = QgsMapToPixelSimplifier::NoFlags;
if ( mSimplifyDrawingHints & QgsVectorLayer::GeometrySimplification ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyGeometry;
if ( mSimplifyDrawingHints & QgsVectorLayer::EnvelopeSimplification ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyEnvelope;

QgsFeatureRequest::Flags requestFlags = QgsFeatureRequest::NoFlags;
if ( mSimplifyDrawingHints & QgsVectorLayer::GeometrySimplification ) requestFlags |= QgsFeatureRequest::SimplifyGeometry;
if ( mSimplifyDrawingHints & QgsVectorLayer::EnvelopeSimplification ) requestFlags |= QgsFeatureRequest::SimplifyEnvelope;

featureRequest.setFlags( featureRequest.flags() | requestFlags );
featureRequest.setCoordinateTransform( rendererContext.coordinateTransform() );
featureRequest.setMapToPixel( &rendererContext.mapToPixel() );
featureRequest.setMapToPixelTol( mSimplifyDrawingTol * 96.0f/dpi );
}
featureRequest.setMapToPixelTol( map2pixelTol );

QgsFeatureIterator fit = getFeatures( featureRequest );
QgsMapToPixelSimplifier* simplifier =
new QgsMapToPixelSimplifier( simplifyFlags, rendererContext.coordinateTransform(), &rendererContext.mapToPixel(), map2pixelTol );

fit = QgsFeatureIterator( new QgsSimplifiedVectorLayerFeatureIterator( this, featureRequest, simplifier ) );
}
else
{
fit = getFeatures( featureRequest );
}

if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels ) && mRendererV2->usingSymbolLevels() )
drawRendererV2Levels( fit, rendererContext, labeling );
Expand Down Expand Up @@ -1233,17 +1249,14 @@ bool QgsVectorLayer::setSubsetString( QString subset )

bool QgsVectorLayer::simplifyDrawingCanbeApplied( int simplifyHint ) const
{
return ( mSimplifyDrawingHints & simplifyHint ) && !mEditBuffer && ( !mCurrentRendererContext || !mCurrentRendererContext->renderingPrintComposition() );
return mDataProvider && ( mSimplifyDrawingHints & simplifyHint ) && !mEditBuffer && ( !mCurrentRendererContext || !mCurrentRendererContext->renderingPrintComposition() );
}

QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request )
{
if ( !mDataProvider )
return QgsFeatureIterator();

if ( request.flags() & ( QgsFeatureRequest::SimplifyGeometry | QgsFeatureRequest::SimplifyEnvelope ) && !( request.flags() & QgsFeatureRequest::NoGeometry ) )
return QgsFeatureIterator( new QgsSimplifiedVectorLayerFeatureIterator( this, request ) );

return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, request ) );
}

Expand Down
16 changes: 10 additions & 6 deletions src/core/qgsvectorlayerfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ void QgsVectorLayerFeatureIterator::updateFeatureGeometry( QgsFeature &f )
}

/***************************************************************************
MapToPixel simplification classes
QgsSimplifiedVectorLayerFeatureIterator class
----------------------
begin : October 2013
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
Expand All @@ -606,13 +606,19 @@ void QgsVectorLayerFeatureIterator::updateFeatureGeometry( QgsFeature &f )
* *
***************************************************************************/

QgsSimplifiedVectorLayerFeatureIterator::QgsSimplifiedVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request )
QgsSimplifiedVectorLayerFeatureIterator::QgsSimplifiedVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request, QgsAbstractGeometrySimplifier* simplifier )
: QgsVectorLayerFeatureIterator( layer, request )
, mSimplifier( simplifier )
{
mSupportsPresimplify = layer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries;
}
QgsSimplifiedVectorLayerFeatureIterator::~QgsSimplifiedVectorLayerFeatureIterator()
{
if ( mSimplifier )
{
delete mSimplifier;
mSimplifier = NULL;
}
}

//! fetch next feature, return true on success
Expand All @@ -621,10 +627,8 @@ bool QgsSimplifiedVectorLayerFeatureIterator::fetchFeature( QgsFeature& feature
if (QgsVectorLayerFeatureIterator::fetchFeature( feature ))
{
const QgsMapToPixel* mtp = mRequest.mapToPixel();
if ( mtp && !mSupportsPresimplify ) mRequest.simplifyGeometry( feature.geometry() );
if ( mtp && !mSupportsPresimplify && mSimplifier ) mSimplifier->simplifyGeometry( feature.geometry() );
return true;
}
return false;
}

/***************************************************************************/
12 changes: 8 additions & 4 deletions src/core/qgsvectorlayerfeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera
};

/***************************************************************************
MapToPixel simplification classes
QgsSimplifiedVectorLayerFeatureIterator class
----------------------
begin : October 2013
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
Expand All @@ -132,18 +132,22 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera
* *
***************************************************************************/

//! Provides a specialized VectorLayerFeatureIterator for enable map2pixel simplification of the geometries
#include "qgsgeometrysimplifier.h"

//! Provides a specialized VectorLayerFeatureIterator for enable simplification of the geometries fetched
class CORE_EXPORT QgsSimplifiedVectorLayerFeatureIterator : public QgsVectorLayerFeatureIterator
{
public:
QgsSimplifiedVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request );
QgsSimplifiedVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request, QgsAbstractGeometrySimplifier* simplifier );
~QgsSimplifiedVectorLayerFeatureIterator( );

protected:
//! fetch next feature, return true on success
virtual bool fetchFeature( QgsFeature& feature );

private:
//! Related geometry simplifier
QgsAbstractGeometrySimplifier* mSimplifier;
//! Indicates the related vector provider supports simplify the geometries before fecth the feature
bool mSupportsPresimplify;
};
Expand Down
3 changes: 2 additions & 1 deletion src/core/symbology-ng/qgslinesymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "qgsrendercontext.h"
#include "qgslogger.h"
#include "qgsvectorlayer.h"
#include "qgsgeometrysimplifier.h"

#include <QPainter>
#include <QDomDocument>
Expand Down Expand Up @@ -181,7 +182,7 @@ void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
p->setPen( context.selected() ? mSelPen : mPen );

// Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #2 points).
if ( points.size()<=2 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsFeatureRequest::canbeGeneralizedByWndBoundingBox( points, context.layer()->simplifyDrawingTol() ) && p->renderHints() & QPainter::Antialiasing )
if ( points.size()<=2 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyDrawingTol() ) && (p->renderHints() & QPainter::Antialiasing) )
{
p->setRenderHint( QPainter::Antialiasing, false );
p->drawPolyline( points );
Expand Down
3 changes: 2 additions & 1 deletion src/core/symbology-ng/qgssymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "qgsrendercontext.h"
#include "qgsvectorlayer.h"
#include "qgsdxfexport.h"
#include "qgsgeometrysimplifier.h"

#include <QSize>
#include <QPainter>
Expand Down Expand Up @@ -358,7 +359,7 @@ void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points,
}

// Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #5 points).
if ( points.size()<=5 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsFeatureRequest::canbeGeneralizedByWndBoundingBox( points, context.layer()->simplifyDrawingTol() ) && p->renderHints() & QPainter::Antialiasing )
if ( points.size()<=5 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyDrawingTol() ) && (p->renderHints() & QPainter::Antialiasing) )
{
p->setRenderHint( QPainter::Antialiasing, false );
p->drawRect( points.boundingRect() );
Expand Down
2 changes: 1 addition & 1 deletion src/providers/ogr/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp)
SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp qgsogrmaptopixelgeometrysimplifier.cpp)

SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h)

Expand Down
168 changes: 25 additions & 143 deletions src/providers/ogr/qgsogrfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )

if ( geom )
{
notifyReadedFeature( fet, geom, feature );
fetchedFeature( fet, geom );

// get the wkb representation
int memorySize = OGR_G_WkbSize( geom );
Expand All @@ -242,8 +242,6 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )

QgsGeometry* geometry = feature.geometry();
if ( !geometry ) feature.setGeometryAndOwnership( wkb, memorySize ); else geometry->fromWkb( wkb, memorySize );

notifyLoadedFeature( fet, feature );
}
if (( useIntersect && ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) )
|| ( geometryTypeFilter && ( !feature.geometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry()->wkbType() ) != P->mOgrGeometryTypeFilter ) ) )
Expand Down Expand Up @@ -279,19 +277,15 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
return true;
}

//! notify the OGRFeatureH was readed of the data provider
void QgsOgrFeatureIterator::notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature )
{
}
//! notify the OGRFeatureH was loaded to the QgsFeature object
void QgsOgrFeatureIterator::notifyLoadedFeature( OGRFeatureH fet, QgsFeature& feature )
//! Notified a new OGRFeatureH fecthed from data provider
void QgsOgrFeatureIterator::fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry )
{
}

/***************************************************************************
MapToPixel simplification classes
QgsOgrSimplifiedFeatureIterator class
----------------------
begin : October 2013
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
Expand All @@ -304,149 +298,37 @@ void QgsOgrFeatureIterator::notifyLoadedFeature( OGRFeatureH fet, QgsFeature& fe
* *
***************************************************************************/

#include <ogr_geometry.h>

//! Provides a specialized FeatureIterator for enable map2pixel simplification of the geometries
QgsOgrSimplifiedFeatureIterator::QgsOgrSimplifiedFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request ) : QgsOgrFeatureIterator( p, request )
{
mPointBufferCount = 512;
mPointBufferPtr = (OGRRawPoint*)OGRMalloc( mPointBufferCount * sizeof(OGRRawPoint) );
}
QgsOgrSimplifiedFeatureIterator::~QgsOgrSimplifiedFeatureIterator( )
//! Provides a specialized FeatureIterator for enable simplification of the geometries
QgsOgrSimplifiedFeatureIterator::QgsOgrSimplifiedFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request )
: QgsOgrFeatureIterator( p, request )
, mSimplifier( NULL )
{
if ( mPointBufferPtr )
{
OGRFree( mPointBufferPtr );
mPointBufferPtr = NULL;
}
}
QgsFeatureRequest::Flags requestFlags = request.flags();

//! Returns a point buffer of the specified size
OGRRawPoint* QgsOgrSimplifiedFeatureIterator::mallocPoints( int numPoints )
{
if ( mPointBufferPtr && mPointBufferCount < numPoints )
{
OGRFree( mPointBufferPtr );
mPointBufferPtr = NULL;
}
if ( mPointBufferPtr==NULL )
int simplifyFlags = QgsMapToPixelSimplifier::NoFlags;
if ( requestFlags & QgsFeatureRequest::SimplifyGeometry ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyGeometry;
if ( requestFlags & QgsFeatureRequest::SimplifyEnvelope ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyEnvelope;

if ( simplifyFlags != QgsMapToPixelSimplifier::NoFlags )
{
mPointBufferCount = numPoints;
mPointBufferPtr = (OGRRawPoint*)OGRMalloc( mPointBufferCount * sizeof(OGRRawPoint) );
mSimplifier = new QgsOgrMapToPixelSimplifier( simplifyFlags, request.coordinateTransform(), request.mapToPixel(), request.mapToPixelTol() );
}
return mPointBufferPtr;
}

//! Simplify the OGR-geometry using the specified tolerance
bool QgsOgrSimplifiedFeatureIterator::simplifyOgrGeometry( const QgsFeatureRequest& request, OGRGeometry* geometry, bool isaLinearRing )
QgsOgrSimplifiedFeatureIterator::~QgsOgrSimplifiedFeatureIterator( )
{
OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() );

// Simplify the geometry rewriting temporally its WKB-stream for saving calloc's.
if ( wkbGeometryType == wkbLineString )
if ( mSimplifier )
{
OGRLineString* lineString = (OGRLineString*)geometry;

int numPoints = lineString->getNumPoints();
if ( (isaLinearRing && numPoints<=5) || (!isaLinearRing && numPoints<=2) ) return false;

OGREnvelope env;
geometry->getEnvelope( &env );
QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY );

// Can replace the geometry by its BBOX ?
if ( request.flags() & QgsFeatureRequest::SimplifyEnvelope && request.canbeGeneralizedByMapBoundingBox( envelope ) )
{
OGRRawPoint* points = NULL;
int numPoints = 0;

double x1 = envelope.xMinimum();
double y1 = envelope.yMinimum();
double x2 = envelope.xMaximum();
double y2 = envelope.yMaximum();

if ( isaLinearRing )
{
numPoints = 5;
points = mallocPoints( numPoints );
points[0].x = x1; points[0].y = y1;
points[1].x = x2; points[1].y = y1;
points[2].x = x2; points[2].y = y2;
points[3].x = x1; points[3].y = y2;
points[4].x = x1; points[4].y = y1;
}
else
{
numPoints = 2;
points = mallocPoints( numPoints );
points[0].x = x1; points[0].y = y1;
points[1].x = x2; points[1].y = y2;
}
lineString->setPoints( numPoints, points );
lineString->flattenTo2D();
return true;
}
else
if ( request.flags() & QgsFeatureRequest::SimplifyGeometry )
{
QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line;
int numSimplifiedPoints = 0;

OGRRawPoint* points = mallocPoints( numPoints );
double* xptr = (double*)points;
double* yptr = xptr+1;
lineString->getPoints( points );

if ( request.simplifyGeometry( request.flags(), geometryType, envelope, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) )
{
lineString->setPoints( numSimplifiedPoints, points );
lineString->flattenTo2D();
}
return numSimplifiedPoints!=numPoints;
}
delete mSimplifier;
mSimplifier = NULL;
}
else
if ( wkbGeometryType == wkbPolygon )
{
OGRPolygon* polygon = (OGRPolygon*)geometry;
bool result = simplifyOgrGeometry( request, polygon->getExteriorRing(), true );

for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i )
{
result |= simplifyOgrGeometry( request, polygon->getInteriorRing(i), true );
}
if ( result ) polygon->flattenTo2D();
return result;
}
else
if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon )
{
OGRGeometryCollection* collection = (OGRGeometryCollection*)geometry;
bool result = false;

for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i )
{
result |= simplifyOgrGeometry( request, collection->getGeometryRef(i), wkbGeometryType==wkbMultiPolygon );
}
if ( result ) collection->flattenTo2D();
return result;
}
return false;
}

//! notify the OGRFeatureH was readed of the data provider
void QgsOgrSimplifiedFeatureIterator::notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature )
//! Notified a new OGRFeatureH fecthed from data provider
void QgsOgrSimplifiedFeatureIterator::fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry )
{
if ( mRequest.flags() & ( QgsFeatureRequest::SimplifyGeometry | QgsFeatureRequest::SimplifyEnvelope ) )
if ( mSimplifier && (mSimplifier->simplifyFlags() & (QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope) ) )
{
OGRwkbGeometryType wkbType = QgsOgrProvider::ogrWkbSingleFlatten( OGR_G_GetGeometryType(geom) );

if ( wkbType == wkbLineString || wkbType == wkbPolygon )
{
simplifyOgrGeometry( mRequest, (OGRGeometry*)geom, wkbType==wkbPolygon );
}
mSimplifier->simplifyGeometry( (OGRGeometry*) geometry );
}
QgsOgrFeatureIterator::notifyReadedFeature( fet, geom, feature );
QgsOgrFeatureIterator::fetchedFeature( feature, geometry );
}

/***************************************************************************/
32 changes: 11 additions & 21 deletions src/providers/ogr/qgsogrfeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator
//! Get an attribute associated with a feature
void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex );

//! notify the OGRFeatureH was readed of the data provider
virtual void notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature );
//! notify the OGRFeatureH was loaded to the QgsFeature object
virtual void notifyLoadedFeature( OGRFeatureH fet, QgsFeature& feature );
//! Notified a new OGRFeatureH fecthed from data provider
virtual void fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry );

bool mFeatureFetched;

Expand All @@ -64,9 +62,9 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator
};

/***************************************************************************
MapToPixel simplification classes
QgsOgrSimplifiedFeatureIterator class
----------------------
begin : October 2013
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
Expand All @@ -79,33 +77,25 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator
* *
***************************************************************************/

#include "qgsogrmaptopixelgeometrysimplifier.h"

class OGRRawPoint;
class OGRGeometry;

//! Provides a specialized FeatureIterator for enable map2pixel simplification of the geometries
//! Provides a specialized FeatureIterator for enable simplification of the geometries fetched
class QgsOgrSimplifiedFeatureIterator : public QgsOgrFeatureIterator
{
public:
QgsOgrSimplifiedFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request );
~QgsOgrSimplifiedFeatureIterator( );

protected:
//! notify the OGRFeatureH was readed of the data provider
virtual void notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature );
//! Notified a new OGRFeatureH fecthed from data provider
virtual void fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry );

private:
//! Point memory buffer for optimize the simplification process
OGRRawPoint* mPointBufferPtr;
//! Current Point memory buffer size
int mPointBufferCount;

//! Simplify the OGR-geometry using the specified tolerance
bool simplifyOgrGeometry ( const QgsFeatureRequest& request, OGRGeometry* geometry, bool isaLinearRing );

//! Returns a point buffer of the specified size
OGRRawPoint* mallocPoints( int numPoints );
//! Related geometry simplifier
QgsOgrMapToPixelSimplifier* mSimplifier;
};

/***************************************************************************/

#endif // QGSOGRFEATUREITERATOR_H
201 changes: 201 additions & 0 deletions src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/***************************************************************************
qgsogrmaptopixelgeometrysimplifier.cpp
---------------------
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsogrmaptopixelgeometrysimplifier.h"
#include "qgsogrprovider.h"

QgsOgrMapToPixelSimplifier::QgsOgrMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapTolPixel, float mapToPixelTol ) : QgsMapToPixelSimplifier( simplifyFlags, coordinateTransform, mapTolPixel, mapToPixelTol )
{
mPointBufferCount = 512;
mPointBufferPtr = (OGRRawPoint*)OGRMalloc( mPointBufferCount * sizeof(OGRRawPoint) );
}
QgsOgrMapToPixelSimplifier::~QgsOgrMapToPixelSimplifier()
{
if ( mPointBufferPtr )
{
OGRFree( mPointBufferPtr );
mPointBufferPtr = NULL;
}
}

//! Returns a point buffer of the specified size
OGRRawPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints )
{
if ( mPointBufferPtr && mPointBufferCount < numPoints )
{
OGRFree( mPointBufferPtr );
mPointBufferPtr = NULL;
}
if ( mPointBufferPtr==NULL )
{
mPointBufferCount = numPoints;
mPointBufferPtr = (OGRRawPoint*)OGRMalloc( mPointBufferCount * sizeof(OGRRawPoint) );
}
return mPointBufferPtr;
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Helper simplification methods

//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount)
{
bool canbeGeneralizable = ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry );

pointSimplifiedCount = pointCount;
if ( geometryType == QGis::Point || geometryType == QGis::UnknownGeometry ) return false;
pointSimplifiedCount = 0;

double map2pixelTol = mMapToPixelTol * QgsMapToPixelSimplifier::calculateViewPixelTolerance( envelope, mMapCoordTransform, mMapToPixel );
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
double x,y, lastX=0, lastY=0;

char* xsourcePtr = (char*)xptr;
char* ysourcePtr = (char*)yptr;
char* xtargetPtr = (char*)xptr;
char* ytargetPtr = (char*)yptr;

for ( int i = 0, numPoints = geometryType==QGis::Polygon ? pointCount-1 : pointCount; i < numPoints; ++i )
{
memcpy( &x, xsourcePtr, sizeof( double ) ); xsourcePtr += xStride;
memcpy( &y, ysourcePtr, sizeof( double ) ); ysourcePtr += yStride;

if ( i==0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D(x,y,lastX,lastY)>map2pixelTol )
{
memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride;
memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride;
pointSimplifiedCount++;
}
}
if ( geometryType == QGis::Polygon )
{
memcpy( xtargetPtr, xptr, sizeof( double ) );
memcpy( ytargetPtr, yptr, sizeof( double ) );
pointSimplifiedCount++;
}
return pointSimplifiedCount!=pointCount;
}

//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing )
{
OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() );

// Simplify the geometry rewriting temporally its WKB-stream for saving calloc's.
if ( wkbGeometryType == wkbLineString )
{
OGRLineString* lineString = (OGRLineString*)geometry;

int numPoints = lineString->getNumPoints();
if ( (isaLinearRing && numPoints<=5) || (!isaLinearRing && numPoints<=2) ) return false;

OGREnvelope env;
geometry->getEnvelope( &env );
QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY );

// Can replace the geometry by its BBOX ?
if ( (mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope) && canbeGeneralizedByMapBoundingBox( envelope ) )
{
OGRRawPoint* points = NULL;
int numPoints = 0;

double x1 = envelope.xMinimum();
double y1 = envelope.yMinimum();
double x2 = envelope.xMaximum();
double y2 = envelope.yMaximum();

if ( isaLinearRing )
{
numPoints = 5;
points = mallocPoints( numPoints );
points[0].x = x1; points[0].y = y1;
points[1].x = x2; points[1].y = y1;
points[2].x = x2; points[2].y = y2;
points[3].x = x1; points[3].y = y2;
points[4].x = x1; points[4].y = y1;
}
else
{
numPoints = 2;
points = mallocPoints( numPoints );
points[0].x = x1; points[0].y = y1;
points[1].x = x2; points[1].y = y2;
}
lineString->setPoints( numPoints, points );
lineString->flattenTo2D();
return true;
}
else
if ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry )
{
QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line;
int numSimplifiedPoints = 0;

OGRRawPoint* points = mallocPoints( numPoints );
double* xptr = (double*)points;
double* yptr = xptr+1;
lineString->getPoints( points );

if ( simplifyOgrGeometry( geometryType, envelope, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) )
{
lineString->setPoints( numSimplifiedPoints, points );
lineString->flattenTo2D();
}
return numSimplifiedPoints!=numPoints;
}
}
else
if ( wkbGeometryType == wkbPolygon )
{
OGRPolygon* polygon = (OGRPolygon*)geometry;
bool result = simplifyOgrGeometry( polygon->getExteriorRing(), true );

for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i )
{
result |= simplifyOgrGeometry( polygon->getInteriorRing(i), true );
}
if ( result ) polygon->flattenTo2D();
return result;
}
else
if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon )
{
OGRGeometryCollection* collection = (OGRGeometryCollection*)geometry;
bool result = false;

for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i )
{
result |= simplifyOgrGeometry( collection->getGeometryRef(i), wkbGeometryType==wkbMultiPolygon );
}
if ( result ) collection->flattenTo2D();
return result;
}
return false;
}

//////////////////////////////////////////////////////////////////////////////////////////////

//! Simplifies the specified geometry
bool QgsOgrMapToPixelSimplifier::simplifyGeometry( OGRGeometry* geometry )
{
OGRwkbGeometryType wkbGeometryType = QgsOgrProvider::ogrWkbSingleFlatten( geometry->getGeometryType() );

if ( wkbGeometryType == wkbLineString || wkbGeometryType == wkbPolygon )
{
return simplifyOgrGeometry( geometry, wkbGeometryType==wkbPolygon );
}
return false;
}
54 changes: 54 additions & 0 deletions src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/***************************************************************************
qgsogrmaptopixelgeometrysimplifier.h
---------------------
begin : December 2013
copyright : (C) 2013 by Alvaro Huarte
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSOGRMAPTOPIXELGEOMETRYSIMPLIFIER_H
#define QGSOGRMAPTOPIXELGEOMETRYSIMPLIFIER_H

#include "qgsmaptopixelgeometrysimplifier.h"
#include <ogr_geometry.h>

/**
* OGR implementation of GeometrySimplifier using the "MapToPixel" algorithm
*
* Simplifies a geometry removing points within of the maximum distance difference that defines the MapToPixel info of a RenderContext request.
* This class enables simplify the geometries to be rendered in a MapCanvas target to speed up the vector drawing.
*/
class QgsOgrMapToPixelSimplifier : public QgsMapToPixelSimplifier
{
public:
QgsOgrMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol );
virtual ~QgsOgrMapToPixelSimplifier();

private:
//! Point memory buffer for optimize the simplification process
OGRRawPoint* mPointBufferPtr;
//! Current Point memory buffer size
int mPointBufferCount;

//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount);
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing );

//! Returns a point buffer of the specified size
OGRRawPoint* mallocPoints( int numPoints );

public:
//! Simplifies the specified geometry
bool simplifyGeometry( OGRGeometry* geometry );
};

#endif // QGSOGRMAPTOPIXELGEOMETRYSIMPLIFIER_H