24QString QgsRandomExtractAlgorithm::name()
const
26 return QStringLiteral(
"randomextract" );
29QString QgsRandomExtractAlgorithm::displayName()
const
31 return QObject::tr(
"Random extract" );
34QStringList QgsRandomExtractAlgorithm::tags()
const
36 return QObject::tr(
"extract,filter,random,number,percentage" ).split(
',' );
39QString QgsRandomExtractAlgorithm::group()
const
41 return QObject::tr(
"Vector selection" );
44QString QgsRandomExtractAlgorithm::groupId()
const
46 return QStringLiteral(
"vectorselection" );
49QString QgsRandomExtractAlgorithm::shortHelpString()
const
51 return QObject::tr(
"This algorithm takes a vector layer and generates a new one that contains only a subset "
52 "of the features in the input layer.\n\n"
53 "The subset is defined randomly, using a percentage or count value to define the total number "
54 "of features in the subset." );
57QgsRandomExtractAlgorithm *QgsRandomExtractAlgorithm::createInstance()
const
59 return new QgsRandomExtractAlgorithm();
62void QgsRandomExtractAlgorithm::initAlgorithm(
const QVariantMap & )
66 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"METHOD" ), QObject::tr(
"Method" ), QStringList() << QObject::tr(
"Number of features" ) << QObject::tr(
"Percentage of features" ),
false, 0 ) );
75 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral(
"INPUT" ), context ) );
80 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, dest, source->fields(),
85 const int method = parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context );
86 int number = parameterAsInt( parameters, QStringLiteral(
"NUMBER" ), context );
87 const long count = source->featureCount();
93 throw QgsProcessingException( QObject::tr(
"Selected number is greater than feature count. Choose a lower value and try again." ) );
99 throw QgsProcessingException( QObject::tr(
"Percentage can't be greater than 100. Choose a lower value and try again." ) );
101 number =
static_cast< int >( std::ceil( number * count / 100 ) );
108 std::vector< QgsFeatureId > allFeats;
109 allFeats.reserve( count );
111 feedback->
pushInfo( QObject::tr(
"Building list of all features..." ) );
115 return QVariantMap();
116 allFeats.push_back( f.
id() );
118 feedback->
pushInfo( QObject::tr(
"Done." ) );
121 std::random_device randomDevice;
122 std::mt19937 mersenneTwister( randomDevice() );
123 std::uniform_int_distribution<size_t> fidsDistribution;
127 size_t actualFeatureCount = allFeats.size();
128 size_t shuffledFeatureCount = number;
129 bool invertSelection =
static_cast< size_t>( number ) > actualFeatureCount / 2;
130 if ( invertSelection )
131 shuffledFeatureCount = actualFeatureCount - number;
133 size_t nb = actualFeatureCount;
136 feedback->
pushInfo( QObject::tr(
"Randomly select %1 features" ).arg( number ) );
137 auto cursor = allFeats.begin();
138 using difference_type = std::vector<QgsFeatureId>::difference_type;
139 while ( shuffledFeatureCount-- )
142 return QVariantMap();
145 fidsDistribution.param( std::uniform_int_distribution<size_t>::param_type( 0, nb - 1 ) );
147 std::swap( *cursor, *( cursor +
static_cast<difference_type
>( fidsDistribution( mersenneTwister ) ) ) );
157 if ( invertSelection )
158 for (
auto it = cursor; it != allFeats.end(); ++it )
159 selected.insert( *it );
161 for (
auto it = allFeats.begin(); it != cursor; ++it )
162 selected.insert( *it );
164 feedback->
pushInfo( QObject::tr(
"Adding selected features" ) );
169 return QVariantMap();
176 outputs.insert( QStringLiteral(
"OUTPUT" ), dest );
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isCanceled() const
Tells whether the operation has been canceled already.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A numeric parameter for processing algorithms.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
QSet< QgsFeatureId > QgsFeatureIds