Skip to content

Commit

Permalink
Feature #8725: Simplification is assigned by flag
Browse files Browse the repository at this point in the history
The drawing simplification can be configured using flags that indicates
what simplification type can be executed (Point, BBOX and AA)
  • Loading branch information
ahuarte47 committed Nov 5, 2013
1 parent 40ed4bb commit e63e92e
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -393,7 +393,7 @@ void QgsVectorLayerProperties::syncToLayer( void )
cbMaximumScale->setScale( 1.0 / layer->maximumScale() );

// get simplify drawing configuration
mSimplifyDrawingGroupBox->setChecked( layer->simplifyDrawing() );
mSimplifyDrawingGroupBox->setChecked( layer->simplifyDrawingHints() != QgsVectorLayer::NoSimplification );
mSimplifyDrawingSlider->setValue( (int)(5.0f * (layer->simplifyDrawingTol()-1)) );

// load appropriate symbology page (V1 or V2)
Expand Down Expand Up @@ -534,7 +534,7 @@ void QgsVectorLayerProperties::apply()
layer->setMetadataUrlFormat( mLayerMetadataUrlFormatComboBox->currentText() );

//layer simplify drawing configuration
layer->setSimplifyDrawing( mSimplifyDrawingGroupBox->isChecked() );
layer->setSimplifyDrawingHints( mSimplifyDrawingGroupBox->isChecked() ? QgsVectorLayer::FullSimplification : QgsVectorLayer::NoSimplification );
layer->setSimplifyDrawingTol( 1.0f + 0.2f*mSimplifyDrawingSlider->value() );

// update symbology
Expand Down
19 changes: 11 additions & 8 deletions src/core/qgsfeaturerequest.cpp
Expand Up @@ -379,18 +379,19 @@ inline static bool generalizeGeometry( QGis::WkbType wkbType, unsigned char* sou
}

//! 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 )
inline static bool simplifyWkbGeometry( const QgsFeatureRequest::Flags& requestFlags, 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 )
if ( ( requestFlags & QgsFeatureRequest::SimplifyEnvelope ) && (envelope.xMaximum()-envelope.xMinimum()) < map2pixelTol && (envelope.yMaximum()-envelope.yMinimum()) < map2pixelTol )
{
canbeGeneralizable = generalizeGeometry( wkbType, sourceWkb, sourceWkbSize, targetWkb, targetWkbSize, envelope, writeHeader );
if (canbeGeneralizable) return true;
}
if (!( requestFlags & QgsFeatureRequest::SimplifyGeometry ) ) canbeGeneralizable = false;

// Write the main header of the geometry
if ( writeHeader )
Expand Down Expand Up @@ -484,7 +485,7 @@ inline static bool simplifyWkbGeometry( QGis::WkbType wkbType, unsigned char* so
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 );
result |= simplifyWkbGeometry( requestFlags, wkbType, sourceWkb, sourceWkbSize_i, targetWkb, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
sourceWkb += sourceWkbSize_i;
targetWkb += targetWkbSize_i;

Expand Down Expand Up @@ -535,7 +536,7 @@ inline static bool simplifyWkbGeometry( QGis::WkbType wkbType, unsigned char* so
wkb1 += wkbSize_i;
}
}
result |= simplifyWkbGeometry( QGis::singleType(wkbType), sourceWkb, sourceWkbSize_i, targetWkb, targetWkbSize_i, envelope, map2pixelTol, true, false );
result |= simplifyWkbGeometry( requestFlags, QGis::singleType(wkbType), sourceWkb, sourceWkbSize_i, targetWkb, targetWkbSize_i, envelope, map2pixelTol, true, false );
sourceWkb += sourceWkbSize_i;
targetWkb += targetWkbSize_i;

Expand Down Expand Up @@ -573,7 +574,7 @@ bool QgsFeatureRequest::canbeGeneralizedByMapBoundingBox( const QgsRectangle& en
}

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

Expand All @@ -589,7 +590,7 @@ bool QgsFeatureRequest::simplifyGeometry( QgsGeometry* geometry, const QgsCoordi
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 ) )
if ( simplifyWkbGeometry( requestFlags, wkbType, wkb, wkbSize, wkb, targetWkbSize, envelope, map2pixelTol ) )
{
unsigned char* targetWkb = (unsigned char*)malloc( targetWkbSize );
memcpy( targetWkb, wkb, targetWkbSize );
Expand All @@ -600,8 +601,10 @@ bool QgsFeatureRequest::simplifyGeometry( QgsGeometry* geometry, const QgsCoordi
}

//! Simplify the specified point stream (Removing duplicated points) when is applied the map2pixel context
bool QgsFeatureRequest::simplifyGeometry( 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 )
bool QgsFeatureRequest::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 )
{
bool canbeGeneralizable = ( requestFlags & QgsFeatureRequest::SimplifyGeometry );

pointSimplifiedCount = pointCount;
if ( geometryType == QGis::Point || geometryType == QGis::UnknownGeometry ) return false;
pointSimplifiedCount = 0;
Expand All @@ -620,7 +623,7 @@ bool QgsFeatureRequest::simplifyGeometry( QGis::GeometryType geometryType, const
memcpy( &x, xsourcePtr, sizeof( double ) ); xsourcePtr += xStride;
memcpy( &y, ysourcePtr, sizeof( double ) ); ysourcePtr += yStride;

if ( i==0 || calculateLengthSquared2D(x,y,lastX,lastY)>map2pixelTol )
if ( i==0 || !canbeGeneralizable || calculateLengthSquared2D(x,y,lastX,lastY)>map2pixelTol )
{
memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride;
memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride;
Expand Down
14 changes: 9 additions & 5 deletions src/core/qgsfeaturerequest.h
Expand Up @@ -65,7 +65,8 @@ class CORE_EXPORT QgsFeatureRequest
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
SimplifyGeometries = 8 //!< Simplify the geometry using the current map2pixel context (e.g. for fast rendering...)
SimplifyGeometry = 8, //!< The geometries can be simplified using the current map2pixel context state (e.g. for fast rendering...)
SimplifyEnvelope = 16 //!< The geometries can be fully simplified by its BoundingBox (e.g. for fast rendering...)
};
Q_DECLARE_FLAGS( Flags, Flag )

Expand Down Expand Up @@ -182,18 +183,21 @@ class CORE_EXPORT QgsFeatureRequest
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( QgsGeometry* geometry,
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( geometry, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }
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( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount,
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( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount ) const { return simplifyGeometry( geometryType, envelope, xptr, xStride, yptr, yStride, pointCount, pointSimplifiedCount, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); }
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
22 changes: 15 additions & 7 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -136,7 +136,7 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mSymbolFeatureCounted( false )
, mCurrentRendererContext( 0 )
, mSimplifyDrawingTol( QgsFeatureRequest::MAPTOPIXEL_THRESHOLD_DEFAULT )
, mSimplifyDrawing( true )
, mSimplifyDrawingHints( QgsVectorLayer::FullSimplification )

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

// Enable the simplification of the geometries before fetch the features using the current map2pixel context.
if ( simplifyDrawingCanbeApplied() && !(featureRequest.flags() & QgsFeatureRequest::NoGeometry) && !rendererContext.renderingPrintComposition() )
// 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;

featureRequest.setFlags( featureRequest.flags() | QgsFeatureRequest::SimplifyGeometries );
featureRequest.setFlags( featureRequest.flags() | simplificationHints );
featureRequest.setCoordinateTransform( rendererContext.coordinateTransform() );
featureRequest.setMapToPixel( &rendererContext.mapToPixel() );
featureRequest.setMapToPixelTol( mSimplifyDrawingTol * 96.0f/dpi );
Expand Down Expand Up @@ -1221,13 +1225,17 @@ bool QgsVectorLayer::setSubsetString( QString subset )
return res;
}

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

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

if ( mSimplifyDrawing && (request.flags() & QgsFeatureRequest::SimplifyGeometries) && !(request.flags() & QgsFeatureRequest::NoGeometry) )
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 Expand Up @@ -1834,7 +1842,7 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() );

// get the simplification drawing configuration
setSimplifyDrawing( e.attribute( "simplifyDrawingFlag", "1" ) == "1" );
setSimplifyDrawingHints( e.attribute( "simplifyDrawingHints", "7" ).toInt() );
setSimplifyDrawingTol( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );

//also restore custom properties (for labeling-ng)
Expand Down Expand Up @@ -2171,7 +2179,7 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) );

// save the simplification drawing configuration
mapLayerNode.setAttribute( "simplifyDrawingFlag", mSimplifyDrawing ? 1 : 0 );
mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyDrawingHints ) );
mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyDrawingTol ) );

//save customproperties (for labeling ng)
Expand Down
27 changes: 18 additions & 9 deletions src/core/qgsvectorlayer.h
Expand Up @@ -1367,13 +1367,22 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Returns the Map2pixel simplification threshold for fast rendering of features */
float simplifyDrawingTol() const { return mSimplifyDrawingTol; }

/** Enable the Map2pixel simplification for fast rendering of features */
void setSimplifyDrawing( bool simplifyDrawing ) { mSimplifyDrawing = simplifyDrawing; }
/** Returns whether is enabled the map2pixel simplification of geometries for fast rendering of features */
bool simplifyDrawing() const { return mSimplifyDrawing; }
/** Simplification flags for fast rendering of features */
enum SimplifyHint
{
NoSimplification = 0, //!< No simplification can be applied
GeometrySimplification = 1, //!< The geometries can be simplified using the current map2pixel context state
EnvelopeSimplification = 2, //!< The geometries can be fully simplified by its BoundingBox using the current map2pixel context state
AntialiasingSimplification = 4, //!< The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'
FullSimplification = 7, //!< All simplification hints can be applied
};
/** Set the Map2pixel simplification hints for fast rendering of features */
void setSimplifyDrawingHints( int simplifyDrawingHints ) { mSimplifyDrawingHints = simplifyDrawingHints; }
/** Returns the Map2pixel simplification hints for fast rendering of features */
int simplifyDrawingHints() const { return mSimplifyDrawingHints; }

/** Returns whether the VectorLayer can apply geometry simplification in FeatureRequests */
bool simplifyDrawingCanbeApplied() const { return mSimplifyDrawing && !mEditBuffer && ( !mCurrentRendererContext || !mCurrentRendererContext->renderingPrintComposition() ); }
/** Returns whether the VectorLayer can apply the specified simplification hint */
bool simplifyDrawingCanbeApplied( int simplifyHint ) const;

public slots:
/**
Expand Down Expand Up @@ -1644,10 +1653,10 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Renderer object which holds the information about how to display the features */
QgsFeatureRendererV2 *mRendererV2;

/** Map2pixel simplification threshold for fast rendering of features */
/** Map2pixel geometry simplification threshold for fast rendering of features */
float mSimplifyDrawingTol;
/** Enable map2pixel simplification of geometries for fast rendering of features */
bool mSimplifyDrawing;
/** Map2pixel geometry simplification hints for fast rendering of features */
int mSimplifyDrawingHints;

/** Label */
QgsLabel *mLabel;
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgslinesymbollayerv2.cpp
Expand Up @@ -181,7 +181,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() && QgsFeatureRequest::canbeGeneralizedByWndBoundingBox( points, context.layer()->simplifyDrawingTol() ) && p->renderHints() & QPainter::Antialiasing )
if ( points.size()<=2 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsFeatureRequest::canbeGeneralizedByWndBoundingBox( points, context.layer()->simplifyDrawingTol() ) && p->renderHints() & QPainter::Antialiasing )
{
p->setRenderHint( QPainter::Antialiasing, false );
p->drawPolyline( points );
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgssymbollayerv2.cpp
Expand Up @@ -332,7 +332,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() && QgsFeatureRequest::canbeGeneralizedByWndBoundingBox( points, context.layer()->simplifyDrawingTol() ) && p->renderHints() & QPainter::Antialiasing )
if ( points.size()<=5 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsFeatureRequest::canbeGeneralizedByWndBoundingBox( points, context.layer()->simplifyDrawingTol() ) && p->renderHints() & QPainter::Antialiasing )
{
p->setRenderHint( QPainter::Antialiasing, false );
p->drawConvexPolygon( points );
Expand Down

0 comments on commit e63e92e

Please sign in to comment.