31 : mSimplifyFlags( simplifyFlags )
32 , mSimplifyAlgorithm( simplifyAlgorithm )
33 , mTolerance( tolerance )
42 float vx =
static_cast< float >( x2 - x1 );
43 float vy =
static_cast< float >( y2 - y1 );
45 return ( vx * vx ) + ( vy * vy );
50 int grid_x1 = std::round( ( x1 - gridOriginX ) * gridInverseSizeXY );
51 int grid_x2 = std::round( ( x2 - gridOriginX ) * gridInverseSizeXY );
52 if ( grid_x1 != grid_x2 )
return false;
54 int grid_y1 = std::round( ( y1 - gridOriginY ) * gridInverseSizeXY );
55 int grid_y2 = std::round( ( y2 - gridOriginY ) * gridInverseSizeXY );
56 return grid_y1 == grid_y2;
66 #include "simplify/effectivearea.h"
71 static std::unique_ptr< QgsAbstractGeometry > generalizeWkbGeometryByBoundingBox(
84 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
87 const double x1 = envelope.
xMinimum();
88 const double y1 = envelope.
yMinimum();
89 const double x2 = envelope.
xMaximum();
90 const double y2 = envelope.
yMaximum();
95 return qgis::make_unique< QgsLineString >( QVector<double>() << x1 << x2, QVector<double>() << y1 << y2 );
99 std::unique_ptr< QgsLineString > ext = qgis::make_unique< QgsLineString >(
100 QVector< double >() << x1
105 QVector< double >() << y1
111 return std::move( ext );
114 std::unique_ptr< QgsPolygon > polygon = qgis::make_unique< QgsPolygon >();
115 polygon->setExteriorRing( ext.release() );
116 return std::move( polygon );
121 std::unique_ptr< QgsAbstractGeometry > QgsMapToPixelSimplifier::simplifyGeometry(
int simplifyFlags,
122 SimplifyAlgorithm simplifyAlgorithm,
126 bool isGeneralizable =
true;
134 return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope, isaLinearRing );
138 isGeneralizable =
false;
146 const int numPoints = srcCurve.
numPoints();
148 std::unique_ptr<QgsCurve> output;
150 QVector< double > lineStringX;
151 QVector< double > lineStringY;
156 lineStringX.reserve( numPoints );
157 lineStringY.reserve( numPoints );
164 double x = 0.0, y = 0.0, lastX = 0.0, lastY = 0.0;
166 if ( numPoints <= ( isaLinearRing ? 4 : 2 ) )
167 isGeneralizable =
false;
170 bool hasLongSegments =
false;
184 double gridOriginX = envelope.
xMinimum();
185 double gridOriginY = envelope.
yMinimum();
188 float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1.0f / ( 0.8 * map2pixelTol ) ) : 0.0f;
190 const double *xData =
nullptr;
191 const double *yData =
nullptr;
194 xData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->xData();
195 yData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->yData();
198 for (
int i = 0; i < numPoints; ++i )
200 if ( xData && yData )
207 x = srcCurve.
xAt( i );
208 y = srcCurve.
yAt( i );
213 !
equalSnapToGrid( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
214 ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
220 lineStringX.append( x );
221 lineStringY.append( y );
232 output.reset( qgsgeometry_cast< QgsCurve * >( srcCurve.
snappedToGrid( map2pixelTol, map2pixelTol ) ) );
238 map2pixelTol *= map2pixelTol;
240 EFFECTIVE_AREAS ea( srcCurve );
243 ptarray_calc_areas( &ea, isaLinearRing ? 4 : 2, set_area, map2pixelTol );
245 for (
int i = 0; i < numPoints; ++i )
247 if ( ea.res_arealist[ i ] > map2pixelTol )
250 output->insertVertex(
QgsVertexId( 0, 0, output->numPoints() ), ea.inpts.at( i ) );
253 lineStringX.append( ea.inpts.at( i ).x() );
254 lineStringY.append( ea.inpts.at( i ).y() );
263 map2pixelTol *= map2pixelTol;
265 const double *xData =
nullptr;
266 const double *yData =
nullptr;
269 xData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->xData();
270 yData = qgsgeometry_cast< const QgsLineString * >( &srcCurve )->yData();
273 for (
int i = 0; i < numPoints; ++i )
275 if ( xData && yData )
282 x = srcCurve.
xAt( i );
283 y = srcCurve.
yAt( i );
286 isLongSegment =
false;
291 ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
297 lineStringX.append( x );
298 lineStringY.append( y );
303 hasLongSegments |= isLongSegment;
311 output = qgis::make_unique< QgsLineString >( lineStringX, lineStringY );
313 if ( output->numPoints() < ( isaLinearRing ? 4 : 2 ) )
316 if ( !hasLongSegments )
320 return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope, isaLinearRing );
327 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
336 output->insertVertex(
QgsVertexId( 0, 0, output->numPoints() ),
QgsPoint( output->xAt( 0 ), output->yAt( 0 ) ) );
340 return std::move( output );
345 std::unique_ptr<QgsPolygon> polygon(
new QgsPolygon() );
347 polygon->setExteriorRing( qgsgeometry_cast<QgsCurve *>( extRing.release() ) );
352 polygon->addInteriorRing( qgsgeometry_cast<QgsCurve *>( ring.release() ) );
354 return std::move( polygon );
361 collection->reserve( numGeoms );
362 for (
int i = 0; i < numGeoms; ++i )
366 collection->addGeometry( part.release() );
368 return std::move( collection );
370 return std::unique_ptr< QgsAbstractGeometry >( geometry.
clone() );
378 return envelope.
width() < map2pixelTol && envelope.
height() < map2pixelTol;
403 if ( numPoints <= ( isaLinearRing ? 6 : 3 ) )