409 changes: 409 additions & 0 deletions src/core/qgsmaprequest.cpp

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions src/core/qgsmaprequest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/***************************************************************************
qgsmaprequest.h
----------------------
begin : October 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 QGSMAPREQUEST_H
#define QGSMAPREQUEST_H

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

class QgsRectangle;
class QgsGeometry;

/**
* This class wraps a generic request for a map layer (or directly its data provider).
* The request may apply a simplification using the map2pixel render state to fetch
* only a particular subset of information.
*/
class CORE_EXPORT QgsMapRequest
{
public:
//! construct a default request
QgsMapRequest();
//! copy constructor
QgsMapRequest( const QgsMapRequest& rh );

QgsMapRequest& operator=( const QgsMapRequest& rh );

~QgsMapRequest();

public:
const QgsCoordinateTransform* coordinateTransform() const { return mMapCoordTransform; }
QgsMapRequest& setCoordinateTransform( const QgsCoordinateTransform* ct );

const QgsMapToPixel* mapToPixel() const { return mMapToPixel; }
QgsMapRequest& setMapToPixel( const QgsMapToPixel* mtp );

float mapToPixelTol() const { return mMapToPixelTol; }
QgsMapRequest& setMapToPixelTol( float map2pixelTol );

protected:
//! 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;

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

//! Simplify the specified geometry (Removing duplicated points) when is applied the map2pixel context
static bool simplifyGeometry( 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 ) { return simplifyGeometry( geometry, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }
};

#endif // QGSMAPREQUEST_H
7 changes: 6 additions & 1 deletion src/core/qgsrendercontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ QgsRenderContext::QgsRenderContext()
mScaleFactor( 1.0 ),
mRasterScaleFactor( 1.0 ),
mRendererScale( 1.0 ),
mLabelingEngine( NULL )
mLabelingEngine( NULL ),
mMapToPixelTol( 1.0f )
{

}
Expand All @@ -42,3 +43,7 @@ void QgsRenderContext::setCoordinateTransform( const QgsCoordinateTransform* t )
mCoordTransform = t;
}

void QgsRenderContext::setMapToPixelTol( float map2pixelTol )
{
mMapToPixelTol = map2pixelTol;
}
5 changes: 5 additions & 0 deletions src/core/qgsrendercontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ class CORE_EXPORT QgsRenderContext
//! Added in QGIS v2.0
void setSelectionColor( const QColor& color ) { mSelectionColor = color; }

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

private:

/**Painter for rendering operations*/
Expand All @@ -115,6 +118,8 @@ class CORE_EXPORT QgsRenderContext
bool mUseAdvancedEffects;

QgsMapToPixel mMapToPixel;
/** Tolerance for simplify transformations between map coordinates and device coordinates*/
float mMapToPixelTol;

/**True if the rendering has been canceled*/
bool mRenderingStopped;
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsvectordataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ QString QgsVectorDataProvider::capabilitiesString() const
QgsDebugMsg( "Capability: Change Geometries" );
}

if ( abilities & QgsVectorDataProvider::SimplifyGeometries )
{
abilitiesList += tr( "Simplify Geometries" );
QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature" );
}

return abilitiesList.join( ", " );

}
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsvectordataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
CreateAttributeIndex = 1 << 12,
/** allows user to select encoding */
SelectEncoding = 1 << 13,
/** supports simplification of geometries before fetch the feature */
SimplifyGeometries = 1 << 14,
};

/** bitmask of all provider's editing capabilities */
Expand Down
20 changes: 15 additions & 5 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,12 +687,19 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
//do startRender before getFeatures to give renderers the possibility of querying features in the startRender method
mRendererV2->startRender( rendererContext, this );

QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
.setFilterRect( rendererContext.extent() )
.setSubsetOfAttributes( attributes ) );
QgsFeatureRequest& featureRequest = QgsFeatureRequest()
.setFilterRect( rendererContext.extent() )
.setSubsetOfAttributes( attributes );

// Enable the simplification of the geometries before fetch the features using the current map2pixel context.
featureRequest.setFlags( featureRequest.flags() | QgsFeatureRequest::SimplifyGeometries );
featureRequest.setCoordinateTransform( rendererContext.coordinateTransform() );
featureRequest.setMapToPixel( &rendererContext.mapToPixel() );
featureRequest.setMapToPixelTol( rendererContext.mapToPixelTol() );

if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels )
&& mRendererV2->usingSymbolLevels() )
QgsFeatureIterator fit = getFeatures( featureRequest );

if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels ) && mRendererV2->usingSymbolLevels() )
drawRendererV2Levels( fit, rendererContext, labeling );
else
drawRendererV2( fit, rendererContext, labeling );
Expand Down Expand Up @@ -1209,6 +1216,9 @@ QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request
if ( !mDataProvider )
return QgsFeatureIterator();

if ( request.flags() & QgsFeatureRequest::SimplifyGeometries )
return QgsFeatureIterator( new QgsSimplifiedVectorLayerFeatureIterator( this, request ) );

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

Expand Down
39 changes: 39 additions & 0 deletions src/core/qgsvectorlayerfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,42 @@ void QgsVectorLayerFeatureIterator::updateFeatureGeometry( QgsFeature &f )
if ( mChangedGeometries.contains( f.id() ) )
f.setGeometry( mChangedGeometries[f.id()] );
}

/***************************************************************************
MapToPixel simplification classes
----------------------
begin : October 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. *
* *
***************************************************************************/

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

//! fetch next feature, return true on success
bool QgsSimplifiedVectorLayerFeatureIterator::fetchFeature( QgsFeature& feature )
{
if (QgsVectorLayerFeatureIterator::fetchFeature( feature ))
{
const QgsMapToPixel* mtp = mRequest.mapToPixel();
if ( mtp && !mSupportsPresimplify ) mRequest.simplifyGeometry( feature.geometry() );
return true;
}
return false;
}

/***************************************************************************/
34 changes: 34 additions & 0 deletions src/core/qgsvectorlayerfeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,38 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera
QMap<QgsVectorLayer*, FetchJoinInfo> mFetchJoinInfo;
};

/***************************************************************************
MapToPixel simplification classes
----------------------
begin : October 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. *
* *
***************************************************************************/

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

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

private:
//! Indicates the related vector provider supports simplify the geometries before fecth the feature
bool mSupportsPresimplify;
};

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

#endif // QGSVECTORLAYERFEATUREITERATOR_H
6 changes: 3 additions & 3 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void QgsSimpleFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<Q
p->translate( offset );
}

_renderPolygon( p, points, rings );
_renderPolygon( p, points, rings, context );

if ( !mOffset.isNull() )
{
Expand Down Expand Up @@ -313,7 +313,7 @@ void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPol
//if ( ! selectionIsOpaque )
// selColor.setAlphaF( context.alpha() );
p->setBrush( QBrush( selColor ) );
_renderPolygon( p, points, rings );
_renderPolygon( p, points, rings, context );
}

if ( qgsDoubleNear( mNextAngle, 0.0 ) )
Expand All @@ -328,7 +328,7 @@ void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPol
rotatedBrush.setTransform( t );
p->setBrush( rotatedBrush );
}
_renderPolygon( p, points, rings );
_renderPolygon( p, points, rings, context );
if ( mOutline )
{
mOutline->renderPolyline( points, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() );
Expand Down
9 changes: 9 additions & 0 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ 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 && QgsMapRequest::canbeGeneralizedByWndBoundingBox( points, context.renderContext().mapToPixelTol() ) && p->renderHints() & QPainter::Antialiasing )
{
p->setRenderHint( QPainter::Antialiasing, false );
p->drawPolyline ( points );
p->setRenderHint( QPainter::Antialiasing, true );
return;
}

if ( offset == 0 )
{
p->drawPolyline( points );
Expand Down
29 changes: 15 additions & 14 deletions src/core/symbology-ng/qgsrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRe
wkb += sizeof( unsigned int );

bool hasZValue = ( wkbType == QGis::WKBLineString25D );

int sizeOfDoubleX = sizeof(double);
int sizeOfDoubleY = hasZValue ? 2*sizeof(double) : sizeof(double);

double x, y;
const QgsCoordinateTransform* ct = context.coordinateTransform();
const QgsMapToPixel& mtp = context.mapToPixel();
Expand All @@ -86,13 +90,8 @@ const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRe
QPointF* ptr = pts.data();
for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
{
x = *(( double * ) wkb );
wkb += sizeof( double );
y = *(( double * ) wkb );
wkb += sizeof( double );

if ( hasZValue ) // ignore Z value
wkb += sizeof( double );
x = *(( double * ) wkb ); wkb += sizeOfDoubleX;
y = *(( double * ) wkb ); wkb += sizeOfDoubleY;

*ptr = QPointF( x, y );
}
Expand Down Expand Up @@ -126,6 +125,10 @@ const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QP
return wkb;

bool hasZValue = ( wkbType == QGis::WKBPolygon25D );

int sizeOfDoubleX = sizeof(double);
int sizeOfDoubleY = hasZValue ? 2*sizeof(double) : sizeof(double);

double x, y;
holes.clear();

Expand All @@ -146,20 +149,18 @@ const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QP
QPointF* ptr = poly.data();
for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
{
x = *(( double * ) wkb ); wkb += sizeof( double );
y = *(( double * ) wkb ); wkb += sizeof( double );
x = *(( double * ) wkb ); wkb += sizeOfDoubleX;
y = *(( double * ) wkb ); wkb += sizeOfDoubleY;

*ptr = QPointF( x, y );

if ( hasZValue )
wkb += sizeof( double );
}

if ( nPoints < 1 )
continue;

//clip close to view extent
QgsClipper::trimPolygon( poly, clipRect );
//clip close to view extent, if needed
QRectF ptsRect = poly.boundingRect();
if (!context.extent().contains( ptsRect )) QgsClipper::trimPolygon( poly, clipRect );

//transform the QPolygonF to screen coordinates
if ( ct )
Expand Down
11 changes: 10 additions & 1 deletion src/core/symbology-ng/qgssymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,22 @@ void QgsFillSymbolLayerV2::drawPreviewIcon( QgsSymbolV2RenderContext& context, Q
stopRender( context );
}

void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings )
void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
if ( !p )
{
return;
}

// Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #5 points).
if ( points.size()<=5 && QgsMapRequest::canbeGeneralizedByWndBoundingBox( points, context.renderContext().mapToPixelTol() ) && p->renderHints() & QPainter::Antialiasing )
{
p->setRenderHint( QPainter::Antialiasing, false );
p->drawPolygon( points );
p->setRenderHint( QPainter::Antialiasing, true );
return;
}

if ( rings == NULL )
{
// simple polygon without holes
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgssymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class CORE_EXPORT QgsFillSymbolLayerV2 : public QgsSymbolLayerV2
protected:
QgsFillSymbolLayerV2( bool locked = false );
/**Default method to render polygon*/
void _renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings );
void _renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );

double mAngle;
};
Expand Down
55 changes: 55 additions & 0 deletions src/providers/ogr/qgsogrfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,15 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )

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

// get the wkb representation
unsigned char *wkb = new unsigned char[OGR_G_WkbSize( geom )];
OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb );

feature.setGeometryAndOwnership( wkb, OGR_G_WkbSize( geom ) );

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 @@ -272,3 +276,54 @@ 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 )
{
}

/***************************************************************************
MapToPixel simplification classes
----------------------
begin : October 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. *
* *
***************************************************************************/

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

//! notify the OGRFeatureH was readed of the data provider
void QgsOgrSimplifiedFeatureIterator::notifyReadedFeature( OGRFeatureH fet, OGRGeometryH geom, QgsFeature& feature )
{
/* TODO: ### ahuarte47!
if ( mRequest.flags() & QgsFeatureRequest::SimplifyGeometries )
{
OGRwkbGeometryType wkbType = OGR_G_GetGeometryType( geom );
OGRwkbGeometryType wkbGeometryType = QgsOgrProvider::ogrWkbSingleFlatten( wkbType );
if (wkbGeometryType==wkbLineString || wkbGeometryType==wkbPolygon)
{
}
}*/
QgsOgrFeatureIterator::notifyReadedFeature( fet, geom, feature );
}

/***************************************************************************/
34 changes: 34 additions & 0 deletions src/providers/ogr/qgsogrfeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ 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 );

bool mFeatureFetched;

OGRDataSourceH ogrDataSource;
Expand All @@ -58,5 +63,34 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator
bool mFetchGeometry;
};

/***************************************************************************
MapToPixel simplification classes
----------------------
begin : October 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. *
* *
***************************************************************************/

//! Provides a specialized FeatureIterator for enable map2pixel simplification of the geometries
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 );
};

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

#endif // QGSOGRFEATUREITERATOR_H
8 changes: 8 additions & 0 deletions src/providers/ogr/qgsogrprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,10 @@ void QgsOgrProvider::setRelevantFields( bool fetchGeometry, const QgsAttributeLi

QgsFeatureIterator QgsOgrProvider::getFeatures( const QgsFeatureRequest& request )
{
/* TODO: ### ahuarte47!
if ( request.flags() & QgsFeatureRequest::SimplifyGeometries )
return QgsFeatureIterator( new QgsOgrSimplifiedFeatureIterator( this, request ) );
*/
return QgsFeatureIterator( new QgsOgrFeatureIterator( this, request ) );
}

Expand Down Expand Up @@ -1484,6 +1488,10 @@ int QgsOgrProvider::capabilities() const
ability &= ~( AddAttributes | DeleteFeatures );
}
}

// TODO: ### ahuarte47!
// By default, supports simplification of geometries before fetch the OGR-feature.
// ability |= SimplifyGeometries;
}

return ability;
Expand Down