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"
72 static 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 );
122 std::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;
157 lineStringX.reserve( numPoints );
158 lineStringY.reserve( numPoints );
165 double x = 0.0, y = 0.0, lastX = 0.0, lastY = 0.0;
167 if ( numPoints <= ( isaLinearRing ? 4 : 2 ) )
168 isGeneralizable =
false;
171 bool hasLongSegments =
false;
185 const double gridOriginX = envelope.
xMinimum();
186 const double gridOriginY = envelope.
yMinimum();
189 const float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1.0f / ( 0.8 * map2pixelTol ) ) : 0.0f;
191 const double *xData =
nullptr;
192 const double *yData =
nullptr;
195 xData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->xData();
196 yData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->yData();
199 for (
int i = 0; i < numPoints; ++i )
201 if ( xData && yData )
208 x = srcCurve.
xAt( i );
209 y = srcCurve.
yAt( i );
214 !
equalSnapToGrid( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
215 ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
221 lineStringX.append( x );
222 lineStringY.append( y );
233 output.reset( qgsgeometry_cast< QgsCurve * >( srcCurve.
snappedToGrid( map2pixelTol, map2pixelTol ) ) );
239 map2pixelTol *= map2pixelTol;
241 EFFECTIVE_AREAS ea( srcCurve );
243 const int set_area = 0;
244 ptarray_calc_areas( &ea, isaLinearRing ? 4 : 2, set_area, map2pixelTol );
246 for (
int i = 0; i < numPoints; ++i )
248 if ( ea.res_arealist[ i ] > map2pixelTol )
251 output->insertVertex(
QgsVertexId( 0, 0, output->numPoints() ), ea.inpts.at( i ) );
254 lineStringX.append( ea.inpts.at( i ).x() );
255 lineStringY.append( ea.inpts.at( i ).y() );
264 map2pixelTol *= map2pixelTol;
266 const double *xData =
nullptr;
267 const double *yData =
nullptr;
270 xData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->xData();
271 yData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->yData();
274 for (
int i = 0; i < numPoints; ++i )
276 if ( xData && yData )
283 x = srcCurve.
xAt( i );
284 y = srcCurve.
yAt( i );
287 isLongSegment =
false;
292 ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
298 lineStringX.append( x );
299 lineStringY.append( y );
304 hasLongSegments |= isLongSegment;
312 output = std::make_unique< QgsLineString >( lineStringX, lineStringY );
314 if ( output->numPoints() < ( isaLinearRing ? 4 : 2 ) )
317 if ( !hasLongSegments )
321 return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope, isaLinearRing );
328 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
337 output->insertVertex(
QgsVertexId( 0, 0, output->numPoints() ),
QgsPoint( output->xAt( 0 ), output->yAt( 0 ) ) );
341 return std::move( output );
346 std::unique_ptr<QgsPolygon> polygon(
new QgsPolygon() );
348 polygon->setExteriorRing( qgsgeometry_cast<QgsCurve *>( extRing.release() ) );
353 polygon->addInteriorRing( qgsgeometry_cast<QgsCurve *>( ring.release() ) );
355 return std::move( polygon );
362 collection->reserve( numGeoms );
363 for (
int i = 0; i < numGeoms; ++i )
367 collection->addGeometry( part.release() );
369 return std::move( collection );
371 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
379 return envelope.
width() < map2pixelTol && envelope.
height() < map2pixelTol;
404 if ( numPoints <= ( isaLinearRing ? 6 : 3 ) )
448 if ( numPoints <= ( isaLinearRing ? 6 : 3 ) )