Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Feature #8725: Simplification is assigned by flag
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 Dec 17, 2013
1 parent b2d9ebb commit c30202f
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 @@ -1369,13 +1369,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 @@ -1646,10 +1655,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 @@ -358,7 +358,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 c30202f

Please sign in to comment.