mirror of
https://github.com/qgis/QGIS.git
synced 2025-07-03 00:03:10 -04:00
Compare commits
8 Commits
05d38b9bcb
...
db9b117f37
Author | SHA1 | Date | |
---|---|---|---|
|
db9b117f37 | ||
|
b927df884f | ||
|
6fd32d92fd | ||
|
296f0c1939 | ||
|
795bea680b | ||
|
6e53077db0 | ||
|
3f082b1688 | ||
|
43e1e61a1c |
@ -658,6 +658,9 @@ class Repositories(QObject):
|
||||
.text()
|
||||
.strip()
|
||||
)
|
||||
supports_qt6 = pluginNodes.item(i).firstChildElement(
|
||||
"supports_qt6"
|
||||
).text().strip().upper() in ["TRUE", "YES"]
|
||||
if not qgisMaximumVersion:
|
||||
if qgisMinimumVersion[0] == "3" and supports_qt6:
|
||||
qgisMaximumVersion = "4.99"
|
||||
|
@ -23,6 +23,113 @@
|
||||
|
||||
constexpr uint KMEANS_MAX_ITERATIONS = 1000;
|
||||
|
||||
//
|
||||
// QgsKmeansClusteringAlgorithmBase
|
||||
//
|
||||
|
||||
QStringList QgsKMeansClusteringAlgorithmBase::tags() const
|
||||
{
|
||||
return QObject::tr( "clustering,clusters,kmeans,points" ).split( ',' );
|
||||
}
|
||||
|
||||
QString QgsKMeansClusteringAlgorithmBase::group() const
|
||||
{
|
||||
return QObject::tr( "Vector analysis" );
|
||||
}
|
||||
|
||||
QString QgsKMeansClusteringAlgorithmBase::groupId() const
|
||||
{
|
||||
return QStringLiteral( "vectoranalysis" );
|
||||
}
|
||||
|
||||
// ported from https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/lwkmeans.c
|
||||
|
||||
void QgsKMeansClusteringAlgorithmBase::updateMeans( const std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, std::vector<uint> &weights, const int k )
|
||||
{
|
||||
const uint n = points.size();
|
||||
std::fill( weights.begin(), weights.end(), 0 );
|
||||
for ( int i = 0; i < k; i++ )
|
||||
{
|
||||
centers[i].setX( 0.0 );
|
||||
centers[i].setY( 0.0 );
|
||||
}
|
||||
for ( uint i = 0; i < n; i++ )
|
||||
{
|
||||
const int cluster = points[i].cluster;
|
||||
centers[cluster] += QgsVector( points[i].point.x(), points[i].point.y() );
|
||||
weights[cluster] += 1;
|
||||
}
|
||||
for ( int i = 0; i < k; i++ )
|
||||
{
|
||||
centers[i] /= weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ported from https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/lwkmeans.c
|
||||
|
||||
void QgsKMeansClusteringAlgorithmBase::findNearest( std::vector<QgsKMeansClusteringAlgorithm::Feature> &points, const std::vector<QgsPointXY> ¢ers, const int k, bool &changed )
|
||||
{
|
||||
changed = false;
|
||||
const std::size_t n = points.size();
|
||||
for ( std::size_t i = 0; i < n; i++ )
|
||||
{
|
||||
Feature &point = points[i];
|
||||
|
||||
// Initialize with distance to first cluster
|
||||
double currentDistance = point.point.sqrDist( centers[0] );
|
||||
int currentCluster = 0;
|
||||
|
||||
// Check all other cluster centers and find the nearest
|
||||
for ( int cluster = 1; cluster < k; cluster++ )
|
||||
{
|
||||
const double distance = point.point.sqrDist( centers[cluster] );
|
||||
if ( distance < currentDistance )
|
||||
{
|
||||
currentDistance = distance;
|
||||
currentCluster = cluster;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the nearest cluster this object is in
|
||||
if ( point.cluster != currentCluster )
|
||||
{
|
||||
changed = true;
|
||||
point.cluster = currentCluster;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ported from https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/lwkmeans.c
|
||||
|
||||
void QgsKMeansClusteringAlgorithmBase::calculateKMeans( std::vector<QgsKMeansClusteringAlgorithm::Feature> &objs, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
int converged = false;
|
||||
bool changed = false;
|
||||
|
||||
// avoid reallocating weights array for every iteration
|
||||
std::vector<uint> weights( k );
|
||||
|
||||
uint i = 0;
|
||||
for ( i = 0; i < KMEANS_MAX_ITERATIONS && !converged; i++ )
|
||||
{
|
||||
if ( feedback && feedback->isCanceled() )
|
||||
break;
|
||||
|
||||
findNearest( objs, centers, k, changed );
|
||||
updateMeans( objs, centers, weights, k );
|
||||
converged = !changed;
|
||||
}
|
||||
|
||||
if ( !converged && feedback )
|
||||
feedback->reportError( QObject::tr( "Clustering did not converge after %n iteration(s)", nullptr, static_cast<int>( i ) ) );
|
||||
else if ( feedback )
|
||||
feedback->pushInfo( QObject::tr( "Clustering converged after %n iteration(s)", nullptr, static_cast<int>( i ) ) );
|
||||
}
|
||||
|
||||
//
|
||||
// QgsKmeansClusteringAlgorithm
|
||||
//
|
||||
|
||||
QString QgsKMeansClusteringAlgorithm::name() const
|
||||
{
|
||||
return QStringLiteral( "kmeansclustering" );
|
||||
@ -33,21 +140,6 @@ QString QgsKMeansClusteringAlgorithm::displayName() const
|
||||
return QObject::tr( "K-means clustering" );
|
||||
}
|
||||
|
||||
QStringList QgsKMeansClusteringAlgorithm::tags() const
|
||||
{
|
||||
return QObject::tr( "clustering,clusters,kmeans,points" ).split( ',' );
|
||||
}
|
||||
|
||||
QString QgsKMeansClusteringAlgorithm::group() const
|
||||
{
|
||||
return QObject::tr( "Vector analysis" );
|
||||
}
|
||||
|
||||
QString QgsKMeansClusteringAlgorithm::groupId() const
|
||||
{
|
||||
return QStringLiteral( "vectoranalysis" );
|
||||
}
|
||||
|
||||
void QgsKMeansClusteringAlgorithm::initAlgorithm( const QVariantMap & )
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
|
||||
@ -459,89 +551,193 @@ void QgsKMeansClusteringAlgorithm::initClustersPlusPlus( std::vector<Feature> &p
|
||||
}
|
||||
}
|
||||
|
||||
// ported from https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/lwkmeans.c
|
||||
//
|
||||
// QgsKMeansClusteringFromSeedLayerAlgorithm
|
||||
//
|
||||
|
||||
void QgsKMeansClusteringAlgorithm::calculateKMeans( std::vector<QgsKMeansClusteringAlgorithm::Feature> &objs, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback )
|
||||
QString QgsKMeansClusteringFromSeedLayerAlgorithm::name() const
|
||||
{
|
||||
int converged = false;
|
||||
bool changed = false;
|
||||
return QStringLiteral( "kmeansclusteringfromseedlayer" );
|
||||
}
|
||||
|
||||
// avoid reallocating weights array for every iteration
|
||||
std::vector<uint> weights( k );
|
||||
QString QgsKMeansClusteringFromSeedLayerAlgorithm::displayName() const
|
||||
{
|
||||
return QObject::tr( "K-means clustering (from seed layer)" );
|
||||
}
|
||||
|
||||
uint i = 0;
|
||||
for ( i = 0; i < KMEANS_MAX_ITERATIONS && !converged; i++ )
|
||||
void QgsKMeansClusteringFromSeedLayerAlgorithm::initAlgorithm( const QVariantMap & )
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "SEED" ), QObject::tr( "Seed layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPoint ) ) );
|
||||
|
||||
auto fieldNameParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral( "FIELD_NAME" ), QObject::tr( "Cluster field name" ), QStringLiteral( "CLUSTER_ID" ) );
|
||||
fieldNameParam->setFlags( fieldNameParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
|
||||
addParameter( fieldNameParam.release() );
|
||||
auto sizeFieldNameParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral( "SIZE_FIELD_NAME" ), QObject::tr( "Cluster size field name" ), QStringLiteral( "CLUSTER_SIZE" ) );
|
||||
sizeFieldNameParam->setFlags( sizeFieldNameParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
|
||||
addParameter( sizeFieldNameParam.release() );
|
||||
|
||||
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Clusters" ), Qgis::ProcessingSourceType::VectorAnyGeometry ) );
|
||||
}
|
||||
|
||||
QString QgsKMeansClusteringFromSeedLayerAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm calculates the 2D distance based k-means cluster number for each input feature.\n\n"
|
||||
"If input geometries are lines or polygons, the clustering is based on the centroid of the feature.\n\n" );
|
||||
}
|
||||
|
||||
QString QgsKMeansClusteringFromSeedLayerAlgorithm::shortDescription() const
|
||||
{
|
||||
return QObject::tr( "Calculates the 2D distance based k-means cluster number for each input feature.\n"
|
||||
"Uses the provided seed layer for starting centers." );
|
||||
}
|
||||
|
||||
QgsKMeansClusteringFromSeedLayerAlgorithm *QgsKMeansClusteringFromSeedLayerAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsKMeansClusteringFromSeedLayerAlgorithm();
|
||||
}
|
||||
|
||||
QVariantMap QgsKMeansClusteringFromSeedLayerAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
|
||||
|
||||
std::unique_ptr<QgsProcessingFeatureSource> seedSource( parameterAsSource( parameters, QStringLiteral( "SEED" ), context ) );
|
||||
if ( !seedSource )
|
||||
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "SEED" ) ) );
|
||||
|
||||
QgsFields outputFields = source->fields();
|
||||
QgsFields newFields;
|
||||
const QString clusterFieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context );
|
||||
newFields.append( QgsField( clusterFieldName, QMetaType::Type::Int ) );
|
||||
const QString clusterSizeFieldName = parameterAsString( parameters, QStringLiteral( "SIZE_FIELD_NAME" ), context );
|
||||
newFields.append( QgsField( clusterSizeFieldName, QMetaType::Type::Int ) );
|
||||
outputFields = QgsProcessingUtils::combineFields( outputFields, newFields );
|
||||
|
||||
QString dest;
|
||||
std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outputFields, source->wkbType(), source->sourceCrs() ) );
|
||||
if ( !sink )
|
||||
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
|
||||
|
||||
// build list of point inputs - if it's already a point, use that. If not, take the centroid.
|
||||
feedback->pushInfo( QObject::tr( "Collecting input points" ) );
|
||||
const double step = source->featureCount() + seedSource->featureCount() > 0 ? 50.0 / static_cast< double >( source->featureCount() + seedSource->featureCount() ) : 1;
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
int featureWithGeometryCount = 0;
|
||||
QgsFeature feat;
|
||||
|
||||
std::vector<Feature> clusterFeatures;
|
||||
QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setNoAttributes() );
|
||||
QHash<QgsFeatureId, std::size_t> idToObj;
|
||||
while ( features.nextFeature( feat ) )
|
||||
{
|
||||
if ( feedback && feedback->isCanceled() )
|
||||
i++;
|
||||
if ( feedback->isCanceled() )
|
||||
{
|
||||
break;
|
||||
|
||||
findNearest( objs, centers, k, changed );
|
||||
updateMeans( objs, centers, weights, k );
|
||||
converged = !changed;
|
||||
}
|
||||
|
||||
if ( !converged && feedback )
|
||||
feedback->reportError( QObject::tr( "Clustering did not converge after %n iteration(s)", nullptr, static_cast<int>( i ) ) );
|
||||
else if ( feedback )
|
||||
feedback->pushInfo( QObject::tr( "Clustering converged after %n iteration(s)", nullptr, static_cast<int>( i ) ) );
|
||||
}
|
||||
|
||||
// ported from https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/lwkmeans.c
|
||||
|
||||
void QgsKMeansClusteringAlgorithm::findNearest( std::vector<QgsKMeansClusteringAlgorithm::Feature> &points, const std::vector<QgsPointXY> ¢ers, const int k, bool &changed )
|
||||
{
|
||||
changed = false;
|
||||
const std::size_t n = points.size();
|
||||
for ( std::size_t i = 0; i < n; i++ )
|
||||
{
|
||||
Feature &point = points[i];
|
||||
|
||||
// Initialize with distance to first cluster
|
||||
double currentDistance = point.point.sqrDist( centers[0] );
|
||||
int currentCluster = 0;
|
||||
|
||||
// Check all other cluster centers and find the nearest
|
||||
for ( int cluster = 1; cluster < k; cluster++ )
|
||||
{
|
||||
const double distance = point.point.sqrDist( centers[cluster] );
|
||||
if ( distance < currentDistance )
|
||||
{
|
||||
currentDistance = distance;
|
||||
currentCluster = cluster;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the nearest cluster this object is in
|
||||
if ( point.cluster != currentCluster )
|
||||
feedback->setProgress( i * step );
|
||||
if ( !feat.hasGeometry() )
|
||||
continue;
|
||||
featureWithGeometryCount++;
|
||||
|
||||
QgsPointXY point;
|
||||
if ( QgsWkbTypes::flatType( feat.geometry().wkbType() ) == Qgis::WkbType::Point )
|
||||
point = QgsPointXY( *qgsgeometry_cast<const QgsPoint *>( feat.geometry().constGet() ) );
|
||||
else
|
||||
{
|
||||
changed = true;
|
||||
point.cluster = currentCluster;
|
||||
const QgsGeometry centroid = feat.geometry().centroid();
|
||||
if ( centroid.isNull() )
|
||||
continue; // centroid failed, e.g. empty linestring
|
||||
|
||||
point = QgsPointXY( *qgsgeometry_cast<const QgsPoint *>( centroid.constGet() ) );
|
||||
}
|
||||
|
||||
n++;
|
||||
|
||||
idToObj[feat.id()] = clusterFeatures.size();
|
||||
clusterFeatures.emplace_back( Feature( point ) );
|
||||
}
|
||||
|
||||
feedback->pushInfo( QObject::tr( "Collecting seed points" ) );
|
||||
std::vector<QgsPointXY> centers;
|
||||
QgsFeatureIterator seedFeatures = seedSource->getFeatures( QgsFeatureRequest().setNoAttributes() );
|
||||
while ( seedFeatures.nextFeature( feat ) )
|
||||
{
|
||||
i++;
|
||||
if ( feedback->isCanceled() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
feedback->setProgress( i * step );
|
||||
if ( !feat.hasGeometry() )
|
||||
continue;
|
||||
|
||||
centers.emplace_back( QgsPointXY( *qgsgeometry_cast<const QgsPoint *>( feat.geometry().constGet() ) ) );
|
||||
}
|
||||
|
||||
int k = centers.size();
|
||||
|
||||
if ( n < k )
|
||||
{
|
||||
feedback->reportError( QObject::tr( "Number of geometries is less than the number of clusters requested, not all clusters will get data" ) );
|
||||
k = n;
|
||||
}
|
||||
|
||||
if ( k > 1 )
|
||||
{
|
||||
feedback->pushInfo( QObject::tr( "Calculating clusters" ) );
|
||||
|
||||
calculateKMeans( clusterFeatures, centers, k, feedback );
|
||||
}
|
||||
|
||||
// cluster size
|
||||
std::unordered_map<int, int> clusterSize;
|
||||
for ( auto it = idToObj.constBegin(); it != idToObj.constEnd(); ++it )
|
||||
{
|
||||
clusterSize[clusterFeatures[it.value()].cluster]++;
|
||||
}
|
||||
|
||||
features = source->getFeatures();
|
||||
i = 0;
|
||||
while ( features.nextFeature( feat ) )
|
||||
{
|
||||
i++;
|
||||
if ( feedback->isCanceled() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
feedback->setProgress( 50 + i * step );
|
||||
QgsAttributes attr = feat.attributes();
|
||||
const auto obj = idToObj.find( feat.id() );
|
||||
if ( !feat.hasGeometry() || obj == idToObj.end() )
|
||||
{
|
||||
attr << QVariant() << QVariant();
|
||||
}
|
||||
else if ( k <= 1 )
|
||||
{
|
||||
attr << 0 << featureWithGeometryCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int cluster = clusterFeatures[*obj].cluster;
|
||||
attr << cluster << clusterSize[cluster];
|
||||
}
|
||||
feat.setAttributes( attr );
|
||||
if ( !sink->addFeature( feat, QgsFeatureSink::FastInsert ) )
|
||||
throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
|
||||
}
|
||||
|
||||
sink->finalize();
|
||||
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
// ported from https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/lwkmeans.c
|
||||
|
||||
void QgsKMeansClusteringAlgorithm::updateMeans( const std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, std::vector<uint> &weights, const int k )
|
||||
{
|
||||
const uint n = points.size();
|
||||
std::fill( weights.begin(), weights.end(), 0 );
|
||||
for ( int i = 0; i < k; i++ )
|
||||
{
|
||||
centers[i].setX( 0.0 );
|
||||
centers[i].setY( 0.0 );
|
||||
}
|
||||
for ( uint i = 0; i < n; i++ )
|
||||
{
|
||||
const int cluster = points[i].cluster;
|
||||
centers[cluster] += QgsVector( points[i].point.x(), points[i].point.y() );
|
||||
weights[cluster] += 1;
|
||||
}
|
||||
for ( int i = 0; i < k; i++ )
|
||||
{
|
||||
centers[i] /= weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///@endcond
|
||||
|
@ -26,28 +26,14 @@
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
|
||||
/**
|
||||
* Native k-means clustering algorithm.
|
||||
*/
|
||||
class ANALYSIS_EXPORT QgsKMeansClusteringAlgorithm : public QgsProcessingAlgorithm
|
||||
class ANALYSIS_EXPORT QgsKMeansClusteringAlgorithmBase : public QgsProcessingAlgorithm
|
||||
{
|
||||
public:
|
||||
QgsKMeansClusteringAlgorithm() = default;
|
||||
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QString name() const override;
|
||||
QString displayName() const override;
|
||||
QStringList tags() const override;
|
||||
QString group() const override;
|
||||
QString groupId() const override;
|
||||
QString shortHelpString() const override;
|
||||
QString shortDescription() const override;
|
||||
QgsKMeansClusteringAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
|
||||
protected:
|
||||
QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
struct Feature
|
||||
{
|
||||
Feature( QgsPointXY point )
|
||||
@ -58,13 +44,46 @@ class ANALYSIS_EXPORT QgsKMeansClusteringAlgorithm : public QgsProcessingAlgorit
|
||||
int cluster = -1;
|
||||
};
|
||||
|
||||
static void initClustersFarthestPoints( std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback );
|
||||
static void initClustersPlusPlus( std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback );
|
||||
static void calculateKMeans( std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback );
|
||||
static void findNearest( std::vector<Feature> &points, const std::vector<QgsPointXY> ¢ers, int k, bool &changed );
|
||||
static void updateMeans( const std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, std::vector<uint> &weights, int k );
|
||||
};
|
||||
|
||||
class ANALYSIS_EXPORT QgsKMeansClusteringAlgorithm : public QgsKMeansClusteringAlgorithmBase
|
||||
{
|
||||
public:
|
||||
QgsKMeansClusteringAlgorithm() = default;
|
||||
|
||||
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QString name() const override;
|
||||
QString displayName() const override;
|
||||
QString shortHelpString() const override;
|
||||
QString shortDescription() const override;
|
||||
QgsKMeansClusteringAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
|
||||
private:
|
||||
static void initClustersFarthestPoints( std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback );
|
||||
static void initClustersPlusPlus( std::vector<Feature> &points, std::vector<QgsPointXY> ¢ers, int k, QgsProcessingFeedback *feedback );
|
||||
friend class TestQgsProcessingAlgsPt1;
|
||||
|
||||
protected:
|
||||
QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
};
|
||||
|
||||
class ANALYSIS_EXPORT QgsKMeansClusteringFromSeedLayerAlgorithm : public QgsKMeansClusteringAlgorithmBase
|
||||
{
|
||||
public:
|
||||
QgsKMeansClusteringFromSeedLayerAlgorithm() = default;
|
||||
|
||||
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QString name() const override;
|
||||
QString displayName() const override;
|
||||
QString shortHelpString() const override;
|
||||
QString shortDescription() const override;
|
||||
QgsKMeansClusteringFromSeedLayerAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
|
||||
protected:
|
||||
QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
@ -483,6 +483,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsJoinWithLinesAlgorithm() );
|
||||
addAlgorithm( new QgsKeepNBiggestPartsAlgorithm() );
|
||||
addAlgorithm( new QgsKMeansClusteringAlgorithm() );
|
||||
addAlgorithm( new QgsKMeansClusteringFromSeedLayerAlgorithm() );
|
||||
addAlgorithm( new QgsLayerToBookmarksAlgorithm() );
|
||||
addAlgorithm( new QgsLayoutMapExtentToLayerAlgorithm() );
|
||||
addAlgorithm( new QgsLayoutAtlasToImageAlgorithm() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user