Add SimplifyAlgorithm enum for local simplification

It implements the SimplifyAlgorithm enum for local simplification of
geometries.
Also the SnapToGrid algorithm is added.
This commit is contained in:
Alvaro Huarte 2016-03-23 09:28:20 +01:00
parent 01ece90f51
commit 734b8b4c62
14 changed files with 200 additions and 44 deletions

View File

@ -4,6 +4,13 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
#include "qgsmaptopixelgeometrysimplifier.h"
%End
public:
//! Types of simplification algorithms that can be used
enum SimplifyAlgorithm
{
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
};
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance );
virtual ~QgsMapToPixelSimplifier();
@ -20,10 +27,16 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
//! Returns the squared 2D-distance of the vector defined by the two points specified
static float calculateLengthSquared2D( double x1, double y1, double x2, double y2 );
//! Returns whether the points belong to the same grid
static bool equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY );
public:
int simplifyFlags() const;
void setSimplifyFlags( int simplifyFlags );
SimplifyAlgorithm simplifyAlgorithm() const;
void setSimplifyAlgorithm( SimplifyAlgorithm simplifyAlgorithm );
//! Returns a simplified version the specified geometry
virtual QgsGeometry* simplify( QgsGeometry* geometry ) const;
//! Simplifies the specified geometry
@ -42,9 +55,9 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
bool isGeneralizableByMapBoundingBox( const QgsRectangle& envelope ) const;
//! Simplifies the geometry when is applied the specified map2pixel context
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance );
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
//! Simplifies the WKB-point array when is applied the specified map2pixel context
static bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance );
static bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
};

View File

@ -29,6 +29,18 @@ class QgsVectorSimplifyMethod
/** Gets the simplification hints of the vector layer managed */
QFlags<QgsVectorSimplifyMethod::SimplifyHint> simplifyHints() const;
/** Types of local simplification algorithms that can be used */
enum SimplifyAlgorithm
{
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
};
/** Sets the local simplification algorithm of the vector layer managed */
void setSimplifyAlgorithm( const SimplifyAlgorithm& simplifyAlgorithm );
/** Gets the local simplification algorithm of the vector layer managed */
SimplifyAlgorithm simplifyAlgorithm() const;
/** Sets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
void setTolerance( double tolerance );
/** Gets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */

View File

@ -613,6 +613,11 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
doubleSpinBoxMagnifierDefault->setSuffix( "%" );
doubleSpinBoxMagnifierDefault->setValue( mSettings->value( "/qgis/magnifier_level", 100 ).toInt() );
// Default local simplification algorithm
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( mSettings->value( "/qgis/simplifyAlgorithm", 0 ).toInt() ) );
// Slightly awkard here at the settings value is true to use QImage,
// but the checkbox is true to use QPixmap
chkAddedVisibility->setChecked( mSettings->value( "/qgis/new_layers_visible", true ).toBool() );
@ -1212,6 +1217,7 @@ void QgsOptions::saveOptions()
if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorSimplifyMethod::AntialiasingSimplification;
}
mSettings->setValue( "/qgis/simplifyDrawingHints", ( int ) simplifyHints );
mSettings->setValue( "/qgis/simplifyAlgorithm", mSimplifyAlgorithmComboBox->itemData( mSimplifyAlgorithmComboBox->currentIndex() ).toInt() );
mSettings->setValue( "/qgis/simplifyDrawingTol", mSimplifyDrawingSpinBox->value() );
mSettings->setValue( "/qgis/simplifyLocal", !mSimplifyDrawingAtProvider->isChecked() );
mSettings->setValue( "/qgis/simplifyMaxScale", 1.0 / mSimplifyMaximumScaleComboBox->scale() );

View File

@ -439,6 +439,11 @@ void QgsVectorLayerProperties::syncToLayer()
mSimplifyDrawingGroupBox->setEnabled( false );
}
// Default local simplification algorithm
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData(( int )simplifyMethod.simplifyAlgorithm() ) );
QStringList myScalesList = PROJECT_SCALES.split( ',' );
myScalesList.append( "1:1" );
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
@ -625,6 +630,7 @@ void QgsVectorLayerProperties::apply()
}
QgsVectorSimplifyMethod simplifyMethod = mLayer->simplifyMethod();
simplifyMethod.setSimplifyHints( simplifyHints );
simplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( mSimplifyAlgorithmComboBox->itemData( mSimplifyAlgorithmComboBox->currentIndex() ).toInt() ) );
simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() );
simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() );
simplifyMethod.setMaximumScale( 1.0 / mSimplifyMaximumScaleComboBox->scale() );

View File

@ -33,10 +33,11 @@ const QgsConstWkbPtr &QgsConstWkbSimplifierPtr::operator>>( QPolygonF &points )
if ( mSimplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification && mSimplifyMethod.forceLocalOptimization() )
{
int simplifyHints = mSimplifyMethod.simplifyHints() | QgsMapToPixelSimplifier::SimplifyEnvelope;
QgsMapToPixelSimplifier::SimplifyAlgorithm simplifyAlgorithm = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( mSimplifyMethod.simplifyAlgorithm() );
QgsConstWkbPtr wkbPtr = *this;
if ( QgsMapToPixelSimplifier::simplifyPoints( mWkbType, wkbPtr, points, simplifyHints, mSimplifyMethod.tolerance() ) )
if ( QgsMapToPixelSimplifier::simplifyPoints( mWkbType, wkbPtr, points, simplifyHints, mSimplifyMethod.tolerance(), simplifyAlgorithm ) )
{
mP = const_cast< unsigned char * >(( const unsigned char * ) wkbPtr );
return *this;

View File

@ -21,9 +21,10 @@
#include "qgslogger.h"
QgsMapToPixelSimplifier::QgsMapToPixelSimplifier( int simplifyFlags, double tolerance )
QgsMapToPixelSimplifier::QgsMapToPixelSimplifier( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
: mSimplifyFlags( simplifyFlags )
, mTolerance( tolerance )
, mSimplifyAlgorithm( simplifyAlgorithm )
{
}
@ -40,7 +41,22 @@ float QgsMapToPixelSimplifier::calculateLengthSquared2D( double x1, double y1, d
float vx = static_cast< float >( x2 - x1 );
float vy = static_cast< float >( y2 - y1 );
return vx*vx + vy*vy;
return ( vx * vx ) + ( vy * vy );
}
//! Returns whether the points belong to the same grid
bool QgsMapToPixelSimplifier::equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY )
{
int grid_x1 = qRound(( x1 - gridOriginX ) * gridInverseSizeXY );
int grid_x2 = qRound(( x2 - gridOriginX ) * gridInverseSizeXY );
if ( grid_x1 != grid_x2 ) return false;
int grid_y1 = qRound(( y1 - gridOriginY ) * gridInverseSizeXY );
int grid_y2 = qRound(( y2 - gridOriginY ) * gridInverseSizeXY );
if ( grid_y1 != grid_y2 ) return false;
return true;
}
//! Returns the BBOX of the specified WKB-point stream
@ -122,7 +138,9 @@ static bool generalizeWkbGeometryByBoundingBox(
//! Simplify the WKB-geometry using the specified tolerance
bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
int simplifyFlags, QGis::WkbType wkbType,
int simplifyFlags,
SimplifyAlgorithm simplifyAlgorithm,
QGis::WkbType wkbType,
QgsConstWkbPtr sourceWkbPtr,
QgsWkbPtr targetWkbPtr,
int &targetWkbSize,
@ -184,8 +202,6 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
targetWkbPtr << numTargetPoints;
targetWkbSize += 4;
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
bool isLongSegment;
bool hasLongSegments = false; //-> To avoid replace the simplified geometry by its BBOX when there are 'long' segments.
bool badLuck = false;
@ -205,27 +221,59 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
}
// Process each vertex...
for ( int i = 0; i < numPoints; ++i )
if ( simplifyAlgorithm == SnapToGrid )
{
sourceWkbPtr >> x >> y;
sourceWkbPtr += skipZM;
double gridOriginX = envelope.xMinimum();
double gridOriginY = envelope.yMinimum();
isLongSegment = false;
// Use a factor for the maximum displacement distance for simplification, similar as GeoServer does
float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1.0f / ( 0.8 * map2pixelTol ) ) : 0.0f;
if ( i == 0 ||
!isGeneralizable ||
( isLongSegment = ( calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) ) ||
( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
for ( int i = 0; i < numPoints; ++i )
{
targetWkbPtr << x << y;
lastX = x;
lastY = y;
numTargetPoints++;
sourceWkbPtr >> x >> y;
sourceWkbPtr += skipZM;
hasLongSegments |= isLongSegment;
if ( i == 0 ||
!isGeneralizable ||
!equalSnapToGrid( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
{
targetWkbPtr << x << y;
lastX = x;
lastY = y;
numTargetPoints++;
}
r.combineExtentWith( x, y );
}
}
else
{
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
r.combineExtentWith( x, y );
for ( int i = 0; i < numPoints; ++i )
{
sourceWkbPtr >> x >> y;
sourceWkbPtr += skipZM;
isLongSegment = false;
if ( i == 0 ||
!isGeneralizable ||
( isLongSegment = ( calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) ) ||
( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
{
targetWkbPtr << x << y;
lastX = x;
lastY = y;
numTargetPoints++;
hasLongSegments |= isLongSegment;
}
r.combineExtentWith( x, y );
}
}
QgsWkbPtr nextPointPtr( targetWkbPtr );
@ -296,7 +344,7 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
int sourceWkbSize_i = sizeof( int ) + numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
int targetWkbSize_i = 0;
result |= simplifyWkbGeometry( simplifyFlags, wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
result |= simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
sourceWkbPtr += sourceWkbSize_i;
targetWkbPtr += targetWkbSize_i;
@ -347,7 +395,7 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
sourceWkbPtr2 += wkbSize_i;
}
}
result |= simplifyWkbGeometry( simplifyFlags, QGis::singleType( wkbType ), sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope, map2pixelTol, true, false );
result |= simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, QGis::singleType( wkbType ), sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope, map2pixelTol, true, false );
sourceWkbPtr += sourceWkbSize_i;
targetWkbPtr += targetWkbSize_i;
@ -376,13 +424,13 @@ QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) const
unsigned char* wkb = new unsigned char[ wkbSize ];
memcpy( wkb, geometry->asWkb(), wkbSize );
g->fromWkb( wkb, wkbSize );
simplifyGeometry( g, mSimplifyFlags, mTolerance );
simplifyGeometry( g, mSimplifyFlags, mTolerance, mSimplifyAlgorithm );
return g;
}
//! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context
bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simplifyFlags, double tolerance )
bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
{
int finalWkbSize = 0;
@ -402,7 +450,7 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simpl
try
{
if ( simplifyWkbGeometry( simplifyFlags, wkbType, wkbPtr, targetWkbPtr, finalWkbSize, envelope, tolerance ) )
if ( simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, wkbType, wkbPtr, targetWkbPtr, finalWkbSize, envelope, tolerance ) )
{
unsigned char *finalWkb = new unsigned char[finalWkbSize];
memcpy( finalWkb, targetWkb, finalWkbSize );
@ -423,11 +471,11 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simpl
//! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context
bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry ) const
{
return simplifyGeometry( geometry, mSimplifyFlags, mTolerance );
return simplifyGeometry( geometry, mSimplifyFlags, mTolerance, mSimplifyAlgorithm );
}
//! Simplifies the WKB-point array (Removing duplicated points) when is applied the specified map2pixel context
bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance )
bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
{
QgsWKBTypes::Type singleType = QgsWKBTypes::singleType( wkbType );
QgsWKBTypes::Type flatType = QgsWKBTypes::flatType( singleType );
@ -457,7 +505,7 @@ bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsCons
targetWkbPtr << ( char ) QgsApplication::endian() << flatType;
targetWkbSize = 5;
if ( simplifyWkbGeometry( simplifyFlags, QGis::fromNewWkbType( singleType ), sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, tolerance, false, isaLinearRing ) )
if ( simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, QGis::fromNewWkbType( singleType ), sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, tolerance, false, isaLinearRing ) )
{
QgsConstWkbPtr finalWkbPtr( targetWkb, targetWkbSize );
finalWkbPtr.readHeader();
@ -481,5 +529,5 @@ bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsCons
//! Simplifies the specified WKB-point array
bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints ) const
{
return simplifyPoints( wkbType, sourceWkbPtr, targetPoints, mSimplifyFlags, mTolerance );
return simplifyPoints( wkbType, sourceWkbPtr, targetPoints, mSimplifyFlags, mTolerance, mSimplifyAlgorithm );
}

View File

@ -32,7 +32,14 @@
class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier
{
public:
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance );
//! Types of simplification algorithms that can be used
enum SimplifyAlgorithm
{
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
};
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
virtual ~QgsMapToPixelSimplifier();
//! Applicable simplification flags
@ -45,22 +52,31 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier
private:
//! Simplify the WKB-geometry using the specified tolerance
static bool simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, QgsConstWkbPtr sourceWkbPtr, QgsWkbPtr targetWkbPtr, int &targetWkbSize, const QgsRectangle& envelope, double map2pixelTol, bool writeHeader = true, bool isaLinearRing = false );
static bool simplifyWkbGeometry( int simplifyFlags, SimplifyAlgorithm simplifyAlgorithm, QGis::WkbType wkbType, QgsConstWkbPtr sourceWkbPtr, QgsWkbPtr targetWkbPtr, int &targetWkbSize, const QgsRectangle& envelope, double map2pixelTol, bool writeHeader = true, bool isaLinearRing = false );
protected:
//! Current simplification flags
int mSimplifyFlags;
//! Current algorithm
SimplifyAlgorithm mSimplifyAlgorithm;
//! Distance tolerance for the simplification
double mTolerance;
//! Returns the squared 2D-distance of the vector defined by the two points specified
static float calculateLengthSquared2D( double x1, double y1, double x2, double y2 );
//! Returns whether the points belong to the same grid
static bool equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY );
public:
int simplifyFlags() const { return mSimplifyFlags; }
void setSimplifyFlags( int simplifyFlags ) { mSimplifyFlags = simplifyFlags; }
SimplifyAlgorithm simplifyAlgorithm() const { return mSimplifyAlgorithm; }
void setSimplifyAlgorithm( SimplifyAlgorithm simplifyAlgorithm ) { mSimplifyAlgorithm = simplifyAlgorithm; }
//! Returns a simplified version the specified geometry
virtual QgsGeometry* simplify( QgsGeometry* geometry ) const override;
//! Simplifies the specified geometry
@ -82,10 +98,10 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier
}
//! Simplifies the geometry when is applied the specified map2pixel context
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance );
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
//! Simplifies the WKB-point array when is applied the specified map2pixel context
static bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance );
static bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
};
#endif // QGSMAPTOPIXELGEOMETRYSIMPLIFIER_H

View File

@ -2429,9 +2429,10 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
if ( simplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() )
{
int simplifyHints = simplifyMethod.simplifyHints() | QgsMapToPixelSimplifier::SimplifyEnvelope;
QgsMapToPixelSimplifier::SimplifyAlgorithm simplifyAlgorithm = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( simplifyMethod.simplifyAlgorithm() );
QgsGeometry* g = new QgsGeometry( *geom );
if ( QgsMapToPixelSimplifier::simplifyGeometry( g, simplifyHints, simplifyMethod.tolerance() ) )
if ( QgsMapToPixelSimplifier::simplifyGeometry( g, simplifyHints, simplifyMethod.tolerance(), simplifyAlgorithm ) )
{
geom = g;
scopedClonedGeom.reset( g );
@ -3008,9 +3009,10 @@ void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderConte
if ( simplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() )
{
int simplifyHints = simplifyMethod.simplifyHints() | QgsMapToPixelSimplifier::SimplifyEnvelope;
QgsMapToPixelSimplifier::SimplifyAlgorithm simplifyAlgorithm = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( simplifyMethod.simplifyAlgorithm() );
QgsGeometry* g = new QgsGeometry( *geom );
if ( QgsMapToPixelSimplifier::simplifyGeometry( g, simplifyHints, simplifyMethod.tolerance() ) )
if ( QgsMapToPixelSimplifier::simplifyGeometry( g, simplifyHints, simplifyMethod.tolerance(), simplifyAlgorithm ) )
{
geom = g;
scopedClonedGeom.reset( g );

View File

@ -49,7 +49,7 @@ QgsAbstractGeometrySimplifier* QgsSimplifyMethod::createGeometrySimplifier( cons
if ( methodType == QgsSimplifyMethod::OptimizeForRendering )
{
int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope;
return new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() );
return new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance(), QgsMapToPixelSimplifier::Distance );
}
else if ( methodType == QgsSimplifyMethod::PreserveTopology )
{

View File

@ -165,6 +165,7 @@ QgsVectorLayer::QgsVectorLayer( const QString& vectorLayerPath,
// Default simplify drawing settings
QSettings settings;
mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( settings.value( "/qgis/simplifyDrawingHints", static_cast< int>( mSimplifyMethod.simplifyHints() ) ).toInt() ) );
mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( settings.value( "/qgis/simplifyAlgorithm", static_cast< int>( mSimplifyMethod.simplifyAlgorithm() ) ).toInt() ) );
mSimplifyMethod.setThreshold( settings.value( "/qgis/simplifyDrawingTol", mSimplifyMethod.threshold() ).toFloat() );
mSimplifyMethod.setForceLocalOptimization( settings.value( "/qgis/simplifyLocal", mSimplifyMethod.forceLocalOptimization() ).toBool() );
mSimplifyMethod.setMaximumScale( settings.value( "/qgis/simplifyMaxScale", mSimplifyMethod.maximumScale() ).toFloat() );
@ -2033,6 +2034,7 @@ bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage )
// get the simplification drawing settings
mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( "simplifyDrawingHints", "1" ).toInt() ) );
mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( "simplifyAlgorithm", "0" ).toInt() ) );
mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() );
mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() );
mSimplifyMethod.setMaximumScale( e.attribute( "simplifyMaxScale", "1" ).toFloat() );
@ -2189,6 +2191,7 @@ bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &err
// save the simplification drawing settings
mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) );
mapLayerNode.setAttribute( "simplifyAlgorithm", QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) );
mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
mapLayerNode.setAttribute( "simplifyMaxScale", QString::number( mSimplifyMethod.maximumScale() ) );

View File

@ -19,6 +19,7 @@
QgsVectorSimplifyMethod::QgsVectorSimplifyMethod()
: mSimplifyHints( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD > 1 ? QgsVectorSimplifyMethod::FullSimplification : QgsVectorSimplifyMethod::GeometrySimplification )
, mSimplifyAlgorithm( QgsVectorSimplifyMethod::Distance )
, mThreshold( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD )
, mTolerance( 1 )
, mLocalOptimization( true )

View File

@ -42,6 +42,18 @@ class CORE_EXPORT QgsVectorSimplifyMethod
/** Gets the simplification hints of the vector layer managed */
inline SimplifyHints simplifyHints() const { return mSimplifyHints; }
/** Types of local simplification algorithms that can be used */
enum SimplifyAlgorithm
{
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
};
/** Sets the local simplification algorithm of the vector layer managed */
void setSimplifyAlgorithm( const SimplifyAlgorithm& simplifyAlgorithm ) { mSimplifyAlgorithm = simplifyAlgorithm; }
/** Gets the local simplification algorithm of the vector layer managed */
inline SimplifyAlgorithm simplifyAlgorithm() const { return mSimplifyAlgorithm; }
/** Sets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
void setTolerance( double tolerance ) { mTolerance = tolerance; }
/** Gets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
@ -65,6 +77,8 @@ class CORE_EXPORT QgsVectorSimplifyMethod
private:
/** Simplification hints for fast rendering of features of the vector layer managed */
SimplifyHints mSimplifyHints;
/** Simplification algorithm */
SimplifyAlgorithm mSimplifyAlgorithm;
/** Simplification tolerance, it represents the maximum distance between two coordinates which can be considered equal */
double mTolerance;
/** Simplification threshold */

View File

@ -1961,14 +1961,30 @@
</property>
</spacer>
</item>
<item row="2" column="1" colspan="4">
<item row="2" column="1">
<widget class="QLabel" name="mSimplifyAlgorithmLabel">
<property name="text">
<string>Simplification algorithm: </string>
</property>
<property name="toolTip">
<string>This algorithm only is applied to simplify on local side</string>
</property>
<property name="margin">
<number>2</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="mSimplifyAlgorithmComboBox"/>
</item>
<item row="3" column="1" colspan="4">
<widget class="QCheckBox" name="mSimplifyDrawingAtProvider">
<property name="text">
<string>Simplify on provider side if possible</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QLabel" name="mSimplifyMaxScaleLabel">
<property name="text">
<string>Maximum scale at which the layer should be simplified (1:1 always simplifies): </string>
@ -1978,7 +1994,7 @@
</property>
</widget>
</item>
<item row="3" column="2">
<item row="4" column="2">
<widget class="QgsScaleComboBox" name="mSimplifyMaximumScaleComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -5296,6 +5312,7 @@
<tabstop>spinMapUpdateInterval</tabstop>
<tabstop>mSimplifyDrawingGroupBox</tabstop>
<tabstop>mSimplifyDrawingSpinBox</tabstop>
<tabstop>mSimplifyAlgorithmComboBox</tabstop>
<tabstop>mSimplifyDrawingAtProvider</tabstop>
<tabstop>mSimplifyMaximumScaleComboBox</tabstop>
<tabstop>chkAntiAliasing</tabstop>

View File

@ -802,14 +802,30 @@
</property>
</spacer>
</item>
<item row="2" column="1" colspan="4">
<item row="2" column="1">
<widget class="QLabel" name="mSimplifyAlgorithmLabel">
<property name="text">
<string>Simplification algorithm: </string>
</property>
<property name="toolTip">
<string>This algorithm only is applied to simplify on local side</string>
</property>
<property name="margin">
<number>2</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="mSimplifyAlgorithmComboBox"/>
</item>
<item row="3" column="1" colspan="4">
<widget class="QCheckBox" name="mSimplifyDrawingAtProvider">
<property name="text">
<string>Simplify on provider side if possible</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QLabel" name="mSimplifyMaxScaleLabel">
<property name="text">
<string>Maximum scale at which the layer should be simplified (1:1 always simplifies): </string>
@ -819,7 +835,7 @@
</property>
</widget>
</item>
<item row="3" column="2">
<item row="4" column="2">
<widget class="QgsScaleComboBox" name="mSimplifyMaximumScaleComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -1745,6 +1761,7 @@
<tabstop>scrollArea_19</tabstop>
<tabstop>mSimplifyDrawingGroupBox</tabstop>
<tabstop>mSimplifyDrawingSpinBox</tabstop>
<tabstop>mSimplifyAlgorithmComboBox</tabstop>
<tabstop>mSimplifyDrawingAtProvider</tabstop>
<tabstop>mSimplifyMaximumScaleComboBox</tabstop>
<tabstop>mForceRasterCheckBox</tabstop>