mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-10 00:05:25 -04:00
Feature #8725: Fast rendering of geom (v-OGR)
Implements fast rendering of LineStrings and Polygons pre-applying a view threshold filter to the geometries to render in qgis. Also disable 'Antialiasing' when it is possible. View Table of test results in 'http://hub.qgis.org/issues/8725' (This version of branch implements the improvement in vector-providers)
This commit is contained in:
parent
cecfff0408
commit
db8eaf0c20
@ -202,5 +202,5 @@ class QgsFillSymbolLayerV2 : 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 );
|
||||
};
|
||||
|
@ -81,6 +81,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgslabelattributes.cpp
|
||||
qgslabelsearchtree.cpp
|
||||
qgslogger.cpp
|
||||
qgsmaprequest.cpp
|
||||
qgsmaplayer.cpp
|
||||
qgsmaplayerregistry.cpp
|
||||
qgsmaprenderer.cpp
|
||||
|
@ -45,6 +45,9 @@ const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const
|
||||
|
||||
bool hasZValue = ( wkbType == QGis::WKBLineString25D );
|
||||
|
||||
int sizeOfDoubleX = sizeof(double);
|
||||
int sizeOfDoubleY = hasZValue ? 2*sizeof(double) : sizeof(double);
|
||||
|
||||
double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates
|
||||
double p1x_c, p1y_c; //clipped end coordinates
|
||||
double lastClipX = 0.0, lastClipY = 0.0; //last successfully clipped coords
|
||||
@ -56,14 +59,9 @@ const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const
|
||||
{
|
||||
if ( i == 0 )
|
||||
{
|
||||
memcpy( &p1x, wkb, sizeof( double ) );
|
||||
wkb += sizeof( double );
|
||||
memcpy( &p1y, wkb, sizeof( double ) );
|
||||
wkb += sizeof( double );
|
||||
if ( hasZValue ) // ignore Z value
|
||||
{
|
||||
wkb += sizeof( double );
|
||||
}
|
||||
memcpy( &p1x, wkb, sizeof( double ) ); wkb += sizeOfDoubleX;
|
||||
memcpy( &p1y, wkb, sizeof( double ) ); wkb += sizeOfDoubleY;
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@ -71,14 +69,8 @@ const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const
|
||||
p0x = p1x;
|
||||
p0y = p1y;
|
||||
|
||||
memcpy( &p1x, wkb, sizeof( double ) );
|
||||
wkb += sizeof( double );
|
||||
memcpy( &p1y, wkb, sizeof( double ) );
|
||||
wkb += sizeof( double );
|
||||
if ( hasZValue ) // ignore Z value
|
||||
{
|
||||
wkb += sizeof( double );
|
||||
}
|
||||
memcpy( &p1x, wkb, sizeof( double ) ); wkb += sizeOfDoubleX;
|
||||
memcpy( &p1y, wkb, sizeof( double ) ); wkb += sizeOfDoubleY;
|
||||
|
||||
p1x_c = p1x; p1y_c = p1y;
|
||||
if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(),
|
||||
|
@ -49,6 +49,8 @@ QgsFeatureRequest::QgsFeatureRequest( const QgsFeatureRequest &rh )
|
||||
|
||||
QgsFeatureRequest& QgsFeatureRequest::operator=( const QgsFeatureRequest & rh )
|
||||
{
|
||||
QgsMapRequest::operator=( rh );
|
||||
|
||||
mFlags = rh.mFlags;
|
||||
mFilter = rh.mFilter;
|
||||
mFilterRect = rh.mFilterRect;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <QFlags>
|
||||
|
||||
#include "qgsmaprequest.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgsexpression.h"
|
||||
@ -53,7 +54,7 @@ typedef QList<int> QgsAttributeList;
|
||||
* QgsFeatureRequest().setFilterFid(45)
|
||||
*
|
||||
*/
|
||||
class CORE_EXPORT QgsFeatureRequest
|
||||
class CORE_EXPORT QgsFeatureRequest : public QgsMapRequest
|
||||
{
|
||||
public:
|
||||
enum Flag
|
||||
@ -61,7 +62,8 @@ class CORE_EXPORT QgsFeatureRequest
|
||||
NoFlags = 0,
|
||||
NoGeometry = 1, //!< Geometry is not required. It may still be returned if e.g. required for a filter condition.
|
||||
SubsetOfAttributes = 2, //!< Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
|
||||
ExactIntersect = 4 //!< Use exact geometry intersection (slower) instead of bounding boxes
|
||||
ExactIntersect = 4, //!< Use exact geometry intersection (slower) instead of bounding boxes
|
||||
SimplifyGeometries = 8 //!< Simplify the geometry using the current map2pixel context
|
||||
};
|
||||
Q_DECLARE_FLAGS( Flags, Flag )
|
||||
|
||||
|
@ -278,6 +278,10 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
|
||||
//so must be false at every new render operation
|
||||
mRenderContext.setRenderingStopped( false );
|
||||
|
||||
// Gets the configured Tolerance for simplify transformations between map coordinates and device coordinates
|
||||
QSettings mySettings2;
|
||||
mRenderContext.setMapToPixelTol( mySettings2.value( "Map/map2pixelTol", 1.0f ).toFloat() );
|
||||
|
||||
// set selection color
|
||||
QgsProject* prj = QgsProject::instance();
|
||||
int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
|
||||
|
409
src/core/qgsmaprequest.cpp
Normal file
409
src/core/qgsmaprequest.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
/***************************************************************************
|
||||
qgsmaprequest.cpp
|
||||
----------------------
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaprequest.h"
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgsgeometry.h"
|
||||
|
||||
QgsMapRequest::QgsMapRequest( ) : mMapCoordTransform( NULL ), mMapToPixel( NULL ), mMapToPixelTol( 1.0f )
|
||||
{
|
||||
}
|
||||
QgsMapRequest::QgsMapRequest( const QgsMapRequest &rh )
|
||||
{
|
||||
operator=( rh );
|
||||
}
|
||||
QgsMapRequest& QgsMapRequest::operator=( const QgsMapRequest & rh )
|
||||
{
|
||||
mMapCoordTransform = rh.mMapCoordTransform;
|
||||
mMapToPixel = rh.mMapToPixel;
|
||||
mMapToPixelTol = rh.mMapToPixelTol;
|
||||
return *this;
|
||||
}
|
||||
QgsMapRequest::~QgsMapRequest()
|
||||
{
|
||||
}
|
||||
|
||||
QgsMapRequest& QgsMapRequest::setCoordinateTransform( const QgsCoordinateTransform* ct )
|
||||
{
|
||||
mMapCoordTransform = ct;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QgsMapRequest& QgsMapRequest::setMapToPixel( const QgsMapToPixel* mtp )
|
||||
{
|
||||
mMapToPixel = mtp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QgsMapRequest& QgsMapRequest::setMapToPixelTol( float map2pixelTol )
|
||||
{
|
||||
mMapToPixelTol = map2pixelTol;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper simplification methods
|
||||
|
||||
#include "qgsrendercontext.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsapplication.h"
|
||||
|
||||
//! Returns the squared 2D-distance of the vector defined by the two points specified
|
||||
inline static float calculateLengthSquared2D( double x1, double y1, double x2, double y2 )
|
||||
{
|
||||
float vx = (float)( x2 - x1 );
|
||||
float vy = (float)( y2 - y1 );
|
||||
|
||||
return vx*vx + vy*vy;
|
||||
}
|
||||
|
||||
//! Returns the MapTolerance for transform between map coordinates and device coordinates
|
||||
inline static float calculateViewPixelTolerance( const QgsRectangle& boundingRect, const QgsCoordinateTransform* ct, const QgsMapToPixel* mtp )
|
||||
{
|
||||
double mapUnitsPerPixel = mtp ? mtp->mapUnitsPerPixel() : 1.0;
|
||||
double mapUnitsFactor = 1;
|
||||
|
||||
// Calculate one aprox factor of the size of the BBOX from the source CoordinateSystem to the target CoordinateSystem.
|
||||
if (ct && !((QgsCoordinateTransform*)ct)->isShortCircuited())
|
||||
{
|
||||
QgsRectangle sourceRect = boundingRect;
|
||||
QgsRectangle targetRect = ct->transform(sourceRect);
|
||||
|
||||
QgsPoint minimumSrcPoint( sourceRect.xMinimum(), sourceRect.yMinimum() );
|
||||
QgsPoint maximumSrcPoint( sourceRect.xMaximum(), sourceRect.yMaximum() );
|
||||
QgsPoint minimumDstPoint( targetRect.xMinimum(), targetRect.yMinimum() );
|
||||
QgsPoint maximumDstPoint( targetRect.xMaximum(), targetRect.yMaximum() );
|
||||
|
||||
double sourceHypothenuse = sqrt( calculateLengthSquared2D( minimumSrcPoint.x(), minimumSrcPoint.y(), maximumSrcPoint.x(), maximumSrcPoint.y() ) );
|
||||
double targetHypothenuse = sqrt( calculateLengthSquared2D( minimumDstPoint.x(), minimumDstPoint.y(), maximumDstPoint.x(), maximumDstPoint.y() ) );
|
||||
|
||||
if (targetHypothenuse!=0)
|
||||
mapUnitsFactor = sourceHypothenuse/targetHypothenuse;
|
||||
}
|
||||
return (float)( mapUnitsPerPixel * mapUnitsFactor );
|
||||
}
|
||||
|
||||
//! Returns the BBOX of the specified Q-point stream
|
||||
inline static QgsRectangle calculateBoundingBox( const QVector<QPointF>& points )
|
||||
{
|
||||
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 QgsRectangle( xmin, ymin, xmax, ymax );
|
||||
}
|
||||
|
||||
//! Returns the BBOX of the specified WKB-point stream
|
||||
inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, unsigned char* wkb, size_t numPoints )
|
||||
{
|
||||
unsigned char* wkb2 = wkb;
|
||||
|
||||
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();
|
||||
|
||||
int sizeOfDoubleX = sizeof(double);
|
||||
int sizeOfDoubleY = QGis::wkbDimensions(wkbType)==3 /*hasZValue*/ ? 2*sizeof(double) : sizeof(double);
|
||||
|
||||
for (size_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
x = *(( double * ) wkb ); wkb += sizeOfDoubleX;
|
||||
y = *(( double * ) wkb ); wkb += sizeOfDoubleY;
|
||||
|
||||
if (xmin>x) xmin = x;
|
||||
if (ymin>y) ymin = y;
|
||||
if (xmax<x) xmax = x;
|
||||
if (ymax<y) ymax = y;
|
||||
}
|
||||
wkb = wkb2;
|
||||
|
||||
return QgsRectangle( xmin, ymin, xmax, ymax );
|
||||
}
|
||||
|
||||
//! Generalize the WKB-geometry using the BBOX of the original geometry
|
||||
inline static bool generalizeGeometry( QGis::WkbType wkbType, unsigned char* sourceWkb, size_t sourceWkbSize, unsigned char* targetWkb, size_t& targetWkbSize, const QgsRectangle& envelope, bool writeHeader )
|
||||
{
|
||||
unsigned char* wkb2 = targetWkb;
|
||||
unsigned int geometryType = QGis::singleType( QGis::flatType( wkbType ) );
|
||||
|
||||
int sizeOfDoubleX = sizeof(double);
|
||||
int sizeOfDoubleY = QGis::wkbDimensions(wkbType)==3 /*hasZValue*/ ? 2*sizeof(double) : sizeof(double);
|
||||
|
||||
// Skip the unnecesary generalization because of is a very single geometry
|
||||
size_t minimumSize = (geometryType==QGis::WKBLineString ? 4 + 2*(sizeOfDoubleX+sizeOfDoubleY) : 8 + 5*(sizeOfDoubleX+sizeOfDoubleY) );
|
||||
if ( writeHeader ) minimumSize += 5;
|
||||
if ( sourceWkbSize <= minimumSize )
|
||||
{
|
||||
targetWkbSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
double x1 = envelope.xMinimum();
|
||||
double y1 = envelope.yMinimum();
|
||||
double x2 = envelope.xMaximum();
|
||||
double y2 = envelope.yMaximum();
|
||||
|
||||
// Write the main header of the geometry
|
||||
if ( writeHeader )
|
||||
{
|
||||
char byteOrder = QgsApplication::endian(); // byteOrder
|
||||
*targetWkb = byteOrder;
|
||||
targetWkb += 1;
|
||||
|
||||
*((int*)targetWkb) = geometryType; // type
|
||||
targetWkb += 4;
|
||||
|
||||
if (geometryType==QGis::WKBPolygon) { *((int*)targetWkb) = 1; targetWkb += 4; } // numRings
|
||||
}
|
||||
|
||||
// Write the generalized geometry
|
||||
if (geometryType==QGis::WKBLineString)
|
||||
{
|
||||
*((int*)targetWkb) = 2; // numPoints;
|
||||
targetWkb += 4;
|
||||
|
||||
double* ptr = (double*)targetWkb;
|
||||
targetWkb += 32;
|
||||
|
||||
*ptr = x1; ptr++; *ptr = y1; ptr++;
|
||||
*ptr = x2; ptr++; *ptr = y2; ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((int*)targetWkb) = 5; // numPoints;
|
||||
targetWkb += 4;
|
||||
|
||||
double* ptr = (double*)targetWkb;
|
||||
targetWkb += 80;
|
||||
|
||||
*ptr = x1; ptr++; *ptr = y1; ptr++;
|
||||
*ptr = x2; ptr++; *ptr = y1; ptr++;
|
||||
*ptr = x2; ptr++; *ptr = y2; ptr++;
|
||||
*ptr = x1; ptr++; *ptr = y2; ptr++;
|
||||
*ptr = x1; ptr++; *ptr = y1; ptr++;
|
||||
}
|
||||
targetWkbSize += targetWkb - wkb2;
|
||||
targetWkb = wkb2;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Simplify the WKB-geometry using the specified tolerance
|
||||
inline static bool simplifyWkbGeometry( 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 )
|
||||
{
|
||||
bool canbeGeneralizable = true;
|
||||
bool hasZValue = QGis::wkbDimensions(wkbType)==3;
|
||||
bool result = false;
|
||||
|
||||
// Can replace the geometry by its BBOX ?
|
||||
if ( (envelope.xMaximum()-envelope.xMinimum()) < map2pixelTol && (envelope.yMaximum()-envelope.yMinimum()) < map2pixelTol )
|
||||
{
|
||||
canbeGeneralizable = generalizeGeometry( wkbType, sourceWkb, sourceWkbSize, targetWkb, targetWkbSize, envelope, writeHeader );
|
||||
if (canbeGeneralizable) return true;
|
||||
}
|
||||
|
||||
// Write the main header of the geometry
|
||||
if ( writeHeader )
|
||||
{
|
||||
*targetWkb = *sourceWkb; // byteOrder
|
||||
sourceWkb += 1;
|
||||
targetWkb += 1;
|
||||
|
||||
*((int*)targetWkb) = QGis::flatType( (QGis::WkbType) *((int*)sourceWkb) ); // type
|
||||
sourceWkb += 4;
|
||||
targetWkb += 4;
|
||||
|
||||
targetWkbSize += 5;
|
||||
}
|
||||
|
||||
unsigned char* wkb1 = sourceWkb;
|
||||
unsigned char* wkb2 = targetWkb;
|
||||
unsigned int flatType = QGis::flatType( wkbType );
|
||||
|
||||
// Write the geometry
|
||||
if (flatType==QGis::WKBLineString || isaLinearRing)
|
||||
{
|
||||
double x,y, lastX=0,lastY=0;
|
||||
|
||||
int sizeOfDoubleX = sizeof(double);
|
||||
int sizeOfDoubleY = QGis::wkbDimensions(wkbType)==3 /*hasZValue*/ ? 2*sizeof(double) : sizeof(double);
|
||||
|
||||
int numPoints = *((int*)sourceWkb);
|
||||
sourceWkb += 4;
|
||||
if (numPoints <= (isaLinearRing ? 5 : 2)) canbeGeneralizable = false;
|
||||
|
||||
int numTargetPoints = 0;
|
||||
*((int*)targetWkb) = numTargetPoints;
|
||||
targetWkb += 4;
|
||||
targetWkbSize += 4;
|
||||
|
||||
double* ptr = (double*)targetWkb;
|
||||
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
|
||||
|
||||
// Process each vertex...
|
||||
for (int i = 0, numPoints_i = (isaLinearRing ? numPoints-1 : numPoints); i < numPoints_i; ++i)
|
||||
{
|
||||
x = *((double*)sourceWkb); sourceWkb += sizeOfDoubleX;
|
||||
y = *((double*)sourceWkb); sourceWkb += sizeOfDoubleY;
|
||||
|
||||
if ( i==0 || !canbeGeneralizable || calculateLengthSquared2D(x,y,lastX,lastY)>map2pixelTol)
|
||||
{
|
||||
*ptr = lastX = x; ptr++;
|
||||
*ptr = lastY = y; ptr++;
|
||||
numTargetPoints++;
|
||||
}
|
||||
}
|
||||
targetWkb = wkb2+4;
|
||||
|
||||
// Fix the topology of the geometry
|
||||
if ( isaLinearRing )
|
||||
{
|
||||
*ptr = x = *((double*)(targetWkb+0)); ptr++;
|
||||
*ptr = y = *((double*)(targetWkb+8)); ptr++;
|
||||
numTargetPoints++;
|
||||
}
|
||||
targetWkbSize += numTargetPoints * 16;
|
||||
targetWkb = wkb2;
|
||||
|
||||
*((int*)targetWkb) = numTargetPoints;
|
||||
result = numPoints!=numTargetPoints;
|
||||
}
|
||||
else
|
||||
if (flatType==QGis::WKBPolygon)
|
||||
{
|
||||
int numRings = *((int*)sourceWkb);
|
||||
sourceWkb += 4;
|
||||
|
||||
*((int*)targetWkb) = numRings;
|
||||
targetWkb += 4;
|
||||
targetWkbSize += 4;
|
||||
|
||||
for (int i = 0; i < numRings; ++i)
|
||||
{
|
||||
int numPoints_i = *((int*)sourceWkb);
|
||||
QgsRectangle envelope_i = numRings==1 ? envelope : calculateBoundingBox( wkbType, sourceWkb+4, numPoints_i );
|
||||
|
||||
size_t sourceWkbSize_i = 4 + numPoints_i * (hasZValue ? 3 : 2) * sizeof(double);
|
||||
size_t targetWkbSize_i = 0;
|
||||
|
||||
result |= simplifyWkbGeometry( wkbType, sourceWkb, sourceWkbSize_i, targetWkb, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
|
||||
sourceWkb += sourceWkbSize_i;
|
||||
targetWkb += targetWkbSize_i;
|
||||
|
||||
targetWkbSize += targetWkbSize_i;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (flatType==QGis::WKBMultiLineString || flatType==QGis::WKBMultiPolygon)
|
||||
{
|
||||
int numGeoms = *((int*)sourceWkb);
|
||||
sourceWkb += 4;
|
||||
wkb1 += 4;
|
||||
|
||||
*((int*)targetWkb) = numGeoms;
|
||||
targetWkb += 4;
|
||||
targetWkbSize += 4;
|
||||
|
||||
for (int i = 0; i < numGeoms; ++i)
|
||||
{
|
||||
size_t sourceWkbSize_i = 0;
|
||||
size_t targetWkbSize_i = 0;
|
||||
|
||||
// ... calculate the wkb-size of the current child complex geometry
|
||||
if (flatType==QGis::WKBMultiLineString)
|
||||
{
|
||||
int numPoints_i = *((int*)(wkb1+5));
|
||||
int wkbSize_i = 4 + numPoints_i * (hasZValue ? 3 : 2) * sizeof(double);
|
||||
|
||||
sourceWkbSize_i += 5 + wkbSize_i;
|
||||
wkb1 += 5 + wkbSize_i;
|
||||
}
|
||||
else
|
||||
{
|
||||
int numPrings_i = *((int*)(wkb1+5));
|
||||
sourceWkbSize_i = 9;
|
||||
wkb1 += 9;
|
||||
|
||||
for (int j = 0; j < numPrings_i; ++j)
|
||||
{
|
||||
int numPoints_i = *((int*)(wkb1));
|
||||
int wkbSize_i = 4 + numPoints_i * (hasZValue ? 3 : 2) * sizeof(double);
|
||||
|
||||
sourceWkbSize_i += wkbSize_i;
|
||||
wkb1 += wkbSize_i;
|
||||
}
|
||||
}
|
||||
result |= simplifyWkbGeometry( QGis::singleType(wkbType), sourceWkb, sourceWkbSize_i, targetWkb, targetWkbSize_i, envelope, map2pixelTol, true, false );
|
||||
sourceWkb += sourceWkbSize_i;
|
||||
targetWkb += targetWkbSize_i;
|
||||
|
||||
targetWkbSize += targetWkbSize_i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Returns whether the devide-geometry can be replaced by its BBOX when is applied the specified the map2pixel context
|
||||
bool QgsMapRequest::canbeGeneralizedByWndBoundingBox( const QgsRectangle& envelope, float mapToPixelTol )
|
||||
{
|
||||
return (envelope.xMaximum()-envelope.xMinimum()) < mapToPixelTol && (envelope.yMaximum()-envelope.yMinimum()) < mapToPixelTol;
|
||||
}
|
||||
//! Returns whether the devide-geometry can be replaced by its BBOX when is applied the specified the map2pixel context
|
||||
bool QgsMapRequest::canbeGeneralizedByWndBoundingBox( const QVector<QPointF>& points, float mapToPixelTol )
|
||||
{
|
||||
QgsRectangle env = calculateBoundingBox( points );
|
||||
return canbeGeneralizedByWndBoundingBox( env, mapToPixelTol);
|
||||
}
|
||||
|
||||
//! Simplify the specified geometry (Removing duplicated points) when is applied the map2pixel context
|
||||
bool QgsMapRequest::simplifyGeometry( QgsGeometry* geometry, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mtp, float mapToPixelTol )
|
||||
{
|
||||
size_t targetWkbSize = 0;
|
||||
|
||||
// Check whether the geometry can be simplified using the map2pixel context
|
||||
QGis::GeometryType geometryType = geometry->type();
|
||||
if (!(geometryType==QGis::Line || geometryType==QGis::Polygon)) return false;
|
||||
|
||||
QgsRectangle envelope = geometry->boundingBox();
|
||||
QGis::WkbType wkbType = geometry->wkbType();
|
||||
double map2pixelTol = mapToPixelTol * calculateViewPixelTolerance( envelope, coordinateTransform, mtp );
|
||||
|
||||
unsigned char* wkb = (unsigned char*)geometry->asWkb( );
|
||||
size_t wkbSize = geometry->wkbSize( );
|
||||
|
||||
// Simplify the geometry rewriting temporally its WKB-stream for saving calloc's.
|
||||
if ( simplifyWkbGeometry( wkbType, wkb, wkbSize, wkb, targetWkbSize, envelope, map2pixelTol ) )
|
||||
{
|
||||
unsigned char* targetWkb = (unsigned char*)malloc( targetWkbSize );
|
||||
memcpy( targetWkb, wkb, targetWkbSize );
|
||||
geometry->fromWkb( targetWkb, targetWkbSize );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
75
src/core/qgsmaprequest.h
Normal file
75
src/core/qgsmaprequest.h
Normal file
@ -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
|
@ -28,7 +28,8 @@ QgsRenderContext::QgsRenderContext()
|
||||
mScaleFactor( 1.0 ),
|
||||
mRasterScaleFactor( 1.0 ),
|
||||
mRendererScale( 1.0 ),
|
||||
mLabelingEngine( NULL )
|
||||
mLabelingEngine( NULL ),
|
||||
mMapToPixelTol( 1.0f )
|
||||
{
|
||||
|
||||
}
|
||||
@ -42,3 +43,7 @@ void QgsRenderContext::setCoordinateTransform( const QgsCoordinateTransform* t )
|
||||
mCoordTransform = t;
|
||||
}
|
||||
|
||||
void QgsRenderContext::setMapToPixelTol( float map2pixelTol )
|
||||
{
|
||||
mMapToPixelTol = map2pixelTol;
|
||||
}
|
||||
|
@ -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*/
|
||||
@ -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;
|
||||
|
@ -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( ", " );
|
||||
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 );
|
||||
|
||||
if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels )
|
||||
&& mRendererV2->usingSymbolLevels() )
|
||||
// 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() );
|
||||
|
||||
QgsFeatureIterator fit = getFeatures( featureRequest );
|
||||
|
||||
if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels ) && mRendererV2->usingSymbolLevels() )
|
||||
drawRendererV2Levels( fit, rendererContext, labeling );
|
||||
else
|
||||
drawRendererV2( fit, rendererContext, labeling );
|
||||
@ -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 ) );
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -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
|
||||
|
@ -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() )
|
||||
{
|
||||
@ -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 ) )
|
||||
@ -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() );
|
||||
|
@ -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 );
|
||||
|
@ -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();
|
||||
@ -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 );
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 ) ) )
|
||||
@ -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 );
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -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;
|
||||
@ -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
|
||||
|
@ -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 ) );
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user