32 : mSimplifyFlags( simplifyFlags )
33 , mSimplifyAlgorithm( simplifyAlgorithm )
34 , mTolerance( tolerance )
43 const float vx =
static_cast< float >( x2 - x1 );
44 const float vy =
static_cast< float >( y2 - y1 );
46 return ( vx * vx ) + ( vy * vy );
51 const int grid_x1 = std::round( ( x1 - gridOriginX ) * gridInverseSizeXY );
52 const int grid_x2 = std::round( ( x2 - gridOriginX ) * gridInverseSizeXY );
53 if ( grid_x1 != grid_x2 )
return false;
55 const int grid_y1 = std::round( ( y1 - gridOriginY ) * gridInverseSizeXY );
56 const int grid_y2 = std::round( ( y2 - gridOriginY ) * gridInverseSizeXY );
57 return grid_y1 == grid_y2;
67#include "simplify/effectivearea.h"
72static std::unique_ptr< QgsAbstractGeometry > generalizeWkbGeometryByBoundingBox(
85 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
88 const double x1 = envelope.
xMinimum();
89 const double y1 = envelope.
yMinimum();
90 const double x2 = envelope.
xMaximum();
91 const double y2 = envelope.
yMaximum();
96 return std::make_unique< QgsLineString >( QVector<double>() << x1 << x2, QVector<double>() << y1 << y2 );
100 std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString >(
101 QVector< double >() << x1
106 QVector< double >() << y1
112 return std::move( ext );
115 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
116 polygon->setExteriorRing( ext.release() );
117 return std::move( polygon );
122std::unique_ptr< QgsAbstractGeometry > QgsMapToPixelSimplifier::simplifyGeometry(
int simplifyFlags,
123 SimplifyAlgorithm simplifyAlgorithm,
127 bool isGeneralizable =
true;
135 return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope, isaLinearRing );
139 isGeneralizable =
false;
147 const int numPoints = srcCurve.
numPoints();
149 std::unique_ptr<QgsCurve> output;
151 QVector< double > lineStringX;
152 QVector< double > lineStringY;
153 QVector< double > lineStringZ;
154 QVector< double > lineStringM;
159 lineStringX.reserve( numPoints );
160 lineStringY.reserve( numPoints );
162 if ( geometry.
is3D() )
163 lineStringZ.reserve( numPoints );
166 lineStringM.reserve( numPoints );
173 double x = 0.0, y = 0.0, z = 0.0, m = 0.0, lastX = 0.0, lastY = 0.0;
175 if ( numPoints <= ( isaLinearRing ? 4 : 2 ) )
176 isGeneralizable = false;
179 bool hasLongSegments =
false;
180 const bool is3D = geometry.
is3D();
181 const bool isMeasure = geometry.
isMeasure();
195 const double gridOriginX = envelope.
xMinimum();
196 const double gridOriginY = envelope.
yMinimum();
199 const float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1.0f / ( 0.8 * map2pixelTol ) ) : 0.0f;
201 const double *xData =
nullptr;
202 const double *yData =
nullptr;
203 const double *zData =
nullptr;
204 const double *mData =
nullptr;
207 xData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->xData();
208 yData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->yData();
211 zData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->zData();
214 mData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->mData();
217 for (
int i = 0; i < numPoints; ++i )
219 if ( xData && yData )
226 x = srcCurve.
xAt( i );
227 y = srcCurve.
yAt( i );
231 z = zData ? *zData++ : srcCurve.
zAt( i );
234 m = mData ? *mData++ : srcCurve.
mAt( i );
238 !
equalSnapToGrid( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
239 ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
245 lineStringX.append( x );
246 lineStringY.append( y );
249 lineStringZ.append( z );
252 lineStringM.append( m );
263 output.reset( qgsgeometry_cast< QgsCurve * >( srcCurve.
snappedToGrid( map2pixelTol, map2pixelTol ) ) );
269 map2pixelTol *= map2pixelTol;
271 EFFECTIVE_AREAS ea( srcCurve );
273 const int set_area = 0;
274 ptarray_calc_areas( &ea, isaLinearRing ? 4 : 2, set_area, map2pixelTol );
276 for (
int i = 0; i < numPoints; ++i )
278 if ( ea.res_arealist[ i ] > map2pixelTol )
281 output->insertVertex(
QgsVertexId( 0, 0, output->numPoints() ), ea.inpts.at( i ) );
284 lineStringX.append( ea.inpts.at( i ).x() );
285 lineStringY.append( ea.inpts.at( i ).y() );
288 lineStringZ.append( ea.inpts.at( i ).z() );
291 lineStringM.append( ea.inpts.at( i ).m() );
300 map2pixelTol *= map2pixelTol;
302 const double *xData =
nullptr;
303 const double *yData =
nullptr;
306 xData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->xData();
307 yData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->yData();
310 for (
int i = 0; i < numPoints; ++i )
312 if ( xData && yData )
319 x = srcCurve.
xAt( i );
320 y = srcCurve.
yAt( i );
323 isLongSegment =
false;
328 ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
334 lineStringX.append( x );
335 lineStringY.append( y );
340 hasLongSegments |= isLongSegment;
348 output = std::make_unique< QgsLineString >( lineStringX, lineStringY, lineStringZ, lineStringM );
350 if ( output->numPoints() < ( isaLinearRing ? 4 : 2 ) )
353 if ( !hasLongSegments )
357 return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope, isaLinearRing );
364 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
373 output->insertVertex(
QgsVertexId( 0, 0, output->numPoints() ),
QgsPoint( output->xAt( 0 ), output->yAt( 0 ) ) );
377 return std::move( output );
382 std::unique_ptr<QgsPolygon> polygon(
new QgsPolygon() );
384 polygon->setExteriorRing( qgsgeometry_cast<QgsCurve *>( extRing.release() ) );
389 polygon->addInteriorRing( qgsgeometry_cast<QgsCurve *>( ring.release() ) );
391 return std::move( polygon );
398 collection->reserve( numGeoms );
399 for (
int i = 0; i < numGeoms; ++i )
403 collection->addGeometry( part.release() );
405 return std::move( collection );
407 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
415 return envelope.
width() < map2pixelTol && envelope.
height() < map2pixelTol;
440 if ( numPoints <= ( isaLinearRing ? 6 : 3 ) )
484 if ( numPoints <= ( isaLinearRing ? 6 : 3 ) )
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CircularString
CircularString.
Abstract base class for all geometries.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual QgsAbstractGeometry * createEmptyWithSameType() const =0
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
virtual QgsAbstractGeometry * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const =0
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual int numPoints() const =0
Returns the number of points in the curve.
virtual double xAt(int index) const =0
Returns the x-coordinate of the specified node in the line string.
virtual double zAt(int index) const =0
Returns the z-coordinate of the specified node in the line string.
virtual double mAt(int index) const =0
Returns the m-coordinate of the specified node in the line string.
virtual double yAt(int index) const =0
Returns the y-coordinate of the specified node in the line string.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
double mTolerance
Distance tolerance for the simplification.
static float calculateLengthSquared2D(double x1, double y1, double x2, double y2)
Returns the squared 2D-distance of the vector defined by the two points specified.
SimplifyAlgorithm
Types of simplification algorithms that can be used.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ SnapToGrid
The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points.
@ Distance
The simplification uses the distance between points to remove duplicate points.
@ SnappedToGridGlobal
Snap to a global grid based on the tolerance. Good for consistent results for incoming vertices,...
static bool isGeneralizableByMapBoundingBox(const QgsRectangle &envelope, double map2pixelTol)
Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel cont...
int simplifyFlags() const
Gets the simplification hints of the vector layer managed.
QgsMapToPixelSimplifier(int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm=Distance)
Constructor.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
@ NoFlags
No simplification can be applied.
@ SimplifyEnvelope
The geometries can be fully simplified by its BoundingBox.
@ SimplifyGeometry
The geometries can be simplified using the current map2pixel context state.
int mSimplifyFlags
Current simplification flags.
static bool equalSnapToGrid(double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY)
Returns whether the points belong to the same grid.
QgsGeometry simplify(const QgsGeometry &geometry) const override
Returns a simplified version the specified geometry.
SimplifyAlgorithm mSimplifyAlgorithm
Current algorithm.
Point geometry type, with support for z-dimension and m-values.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
double height() const
Returns the height of the rectangle.
static bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Utility class for identifying a unique vertex within a geometry.