Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ set(QGIS_ANALYSIS_SRCS
processing/pdal/qgsalgorithmpdalthinbydecimate.cpp
processing/pdal/qgsalgorithmpdalthinbyradius.cpp
processing/pdal/qgsalgorithmpdaltile.cpp
processing/pdal/qgsalgorithmpdalheightabovegroundnearestneighbour.cpp
processing/pdal/qgsalgorithmpdalheightabovegrounddelaunay.cpp
processing/pdal/qgsalgorithmpdalfilternoisestatistical.cpp
processing/pdal/qgsalgorithmpdalfilternoiseradius.cpp
processing/pdal/qgsalgorithmpdalclassifyground.cpp
processing/pdal/qgsalgorithmpdaltransform.cpp

raster/qgsalignraster.cpp
raster/qgsninecellfilter.cpp
Expand Down
116 changes: 116 additions & 0 deletions src/analysis/processing/pdal/qgsalgorithmpdalclassifyground.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/***************************************************************************
qgsalgorithmpdalclassifyground.cpp
---------------------
begin : December 2025
copyright : (C) 2025 by Jan Caha
email : jan.caha at outlook dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmpdalclassifyground.h"

#include "qgspointcloudlayer.h"
#include "qgsrunprocess.h"

///@cond PRIVATE

QString QgsPdalClassifyGroundAlgorithm::name() const
{
return QStringLiteral( "classifyground" );
}

QString QgsPdalClassifyGroundAlgorithm::displayName() const
{
return QObject::tr( "Classify Ground Points" );
}

QString QgsPdalClassifyGroundAlgorithm::group() const
{
return QObject::tr( "Point cloud data management" );
}

QString QgsPdalClassifyGroundAlgorithm::groupId() const
{
return QStringLiteral( "pointclouddatamanagement" );
}

QStringList QgsPdalClassifyGroundAlgorithm::tags() const
{
return QObject::tr( "pdal,lidar,classify,ground,elevation" ).split( ',' );
}

QString QgsPdalClassifyGroundAlgorithm::shortHelpString() const
{
return QObject::tr( "Classify ground points in a point cloud." )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Parameters:" )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Grid Cell Size - in map units. Smaller values give finer detail but may increase noise." )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Scalar - sets the grid cell size in map units. Smaller values give finer detail but may increase noise." )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Slope - controls how much terrain slope is tolerated as ground. Increase for steep terrain." )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Threshold - elevation threshold for separating ground from objects. Higher values allow larger deviations from ground." )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Window size - the maximum filter window size. Increase to better identify large buildings or objects, decrease to protect smaller features." );
}

QString QgsPdalClassifyGroundAlgorithm::shortDescription() const
{
return QObject::tr( "Classify ground points in a point cloud." );
}

QgsPdalClassifyGroundAlgorithm *QgsPdalClassifyGroundAlgorithm::createInstance() const
{
return new QgsPdalClassifyGroundAlgorithm();
}

void QgsPdalClassifyGroundAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterPointCloudLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );

addParameter( new QgsProcessingParameterNumber( QStringLiteral( "CELL_SIZE" ), QObject::tr( "Grid Cell Size" ), Qgis::ProcessingNumberParameterType::Double, 1.0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "SCALAR" ), QObject::tr( "Scalar" ), Qgis::ProcessingNumberParameterType::Double, 1.25 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "SLOPE" ), QObject::tr( "Slope" ), Qgis::ProcessingNumberParameterType::Double, 0.15 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "THRESHOLD" ), QObject::tr( "Threshold" ), Qgis::ProcessingNumberParameterType::Double, 0.5 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "WINDOW_SIZE" ), QObject::tr( "Window size" ), Qgis::ProcessingNumberParameterType::Double, 18.0 ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this label (and maybe some above) be more verbose, i.e., "Maximum filter window size"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mirrors parameters names in PDAL and PDAL Wrench, I would oppose changing the name.


addParameter( new QgsProcessingParameterPointCloudDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Filtered (radius algorithm)" ) ) );
}

QStringList QgsPdalClassifyGroundAlgorithm::createArgumentLists( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
Q_UNUSED( feedback );

QgsPointCloudLayer *layer = parameterAsPointCloudLayer( parameters, QStringLiteral( "INPUT" ), context, QgsProcessing::LayerOptionsFlag::SkipIndexGeneration );
if ( !layer )
throw QgsProcessingException( invalidPointCloudError( parameters, QStringLiteral( "INPUT" ) ) );

const QString outputName = parameterAsOutputLayer( parameters, QStringLiteral( "OUTPUT" ), context );
QString outputFile = fixOutputFileName( layer->source(), outputName, context );
checkOutputFormat( layer->source(), outputFile );
setOutputValue( QStringLiteral( "OUTPUT" ), outputFile );

double cellSize = parameterAsDouble( parameters, QStringLiteral( "CELL_SIZE" ), context );
double scalar = parameterAsDouble( parameters, QStringLiteral( "SCALAR" ), context );
double slope = parameterAsDouble( parameters, QStringLiteral( "SLOPE" ), context );
double threshold = parameterAsDouble( parameters, QStringLiteral( "THRESHOLD" ), context );
double windowSize = parameterAsDouble( parameters, QStringLiteral( "WINDOW_SIZE" ), context );

QStringList args = { QStringLiteral( "classify_ground" ), QStringLiteral( "--input=%1" ).arg( layer->source() ), QStringLiteral( "--output=%1" ).arg( outputFile ), QStringLiteral( "--cell-size=%1" ).arg( cellSize ), QStringLiteral( "--scalar=%1" ).arg( scalar ), QStringLiteral( "--slope=%1" ).arg( slope ), QStringLiteral( "--threshold=%1" ).arg( threshold ), QStringLiteral( "--window-size=%1" ).arg( windowSize ) };

applyCommonParameters( args, layer->crs(), parameters, context );
applyThreadsParameter( args, context );
return args;
}

///@endcond
52 changes: 52 additions & 0 deletions src/analysis/processing/pdal/qgsalgorithmpdalclassifyground.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/***************************************************************************
qgsalgorithmpdalclassifyground.h
---------------------
begin : December 2025
copyright : (C) 2025 by Jan Caha
email : jan.caha at outlook dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMPDALCLASSIFYGROUND_H
#define QGSALGORITHMPDALCLASSIFYGROUND_H

#define SIP_NO_FILE

#include "qgis_sip.h"
#include "qgspdalalgorithmbase.h"

///@cond PRIVATE

/**
* Native point cloud filter noise using radius algorithm.
*/
class QgsPdalClassifyGroundAlgorithm : public QgsPdalAlgorithmBase
{
public:
QgsPdalClassifyGroundAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
QString name() const override;
QString displayName() const override;
QString group() const override;
QString groupId() const override;
QStringList tags() const override;
QString shortHelpString() const override;
QString shortDescription() const override;
QgsPdalClassifyGroundAlgorithm *createInstance() const override SIP_FACTORY;

QStringList createArgumentLists( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

friend class TestQgsProcessingPdalAlgs;
};

///@endcond PRIVATE

#endif // QGSALGORITHMPDALCLASSIFYGROUND_H
105 changes: 105 additions & 0 deletions src/analysis/processing/pdal/qgsalgorithmpdalfilternoiseradius.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/***************************************************************************
qgsalgorithmpdalfilternoiseradius.cpp
---------------------
begin : December 2025
copyright : (C) 2025 by Jan Caha
email : jan.caha at outlook dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmpdalfilternoiseradius.h"

#include "qgspointcloudlayer.h"
#include "qgsrunprocess.h"

///@cond PRIVATE

QString QgsPdalFilterNoiseRadiusAlgorithm::name() const
{
return QStringLiteral( "filternoiseradius" );
}

QString QgsPdalFilterNoiseRadiusAlgorithm::displayName() const
{
return QObject::tr( "Filter Noise (by radius algorithm)" );
}

QString QgsPdalFilterNoiseRadiusAlgorithm::group() const
{
return QObject::tr( "Point cloud data management" );
}

QString QgsPdalFilterNoiseRadiusAlgorithm::groupId() const
{
return QStringLiteral( "pointclouddatamanagement" );
}

QStringList QgsPdalFilterNoiseRadiusAlgorithm::tags() const
{
return QObject::tr( "pdal,lidar,filter,noise,radius" ).split( ',' );
}

QString QgsPdalFilterNoiseRadiusAlgorithm::shortHelpString() const
{
return QObject::tr( "Filter noise in a point cloud using radius algorithm." );
}

QString QgsPdalFilterNoiseRadiusAlgorithm::shortDescription() const
{
return QObject::tr( "Filter noise in a point cloud using radius algorithm." );
}

QgsPdalFilterNoiseRadiusAlgorithm *QgsPdalFilterNoiseRadiusAlgorithm::createInstance() const
{
return new QgsPdalFilterNoiseRadiusAlgorithm();
}

void QgsPdalFilterNoiseRadiusAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterPointCloudLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "REMOVE_NOISE_POINTS" ), QObject::tr( "Remove noise points" ), false ) );

addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MIN_K" ), QObject::tr( "Minimum number of neighbors in radius" ), Qgis::ProcessingNumberParameterType::Double, 2.0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "RADIUS" ), QObject::tr( "Standard deviation threshold" ), Qgis::ProcessingNumberParameterType::Double, 1.0 ) );

addParameter( new QgsProcessingParameterPointCloudDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Filtered (radius algorithm)" ) ) );
}

QStringList QgsPdalFilterNoiseRadiusAlgorithm::createArgumentLists( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
Q_UNUSED( feedback );

QgsPointCloudLayer *layer = parameterAsPointCloudLayer( parameters, QStringLiteral( "INPUT" ), context, QgsProcessing::LayerOptionsFlag::SkipIndexGeneration );
if ( !layer )
throw QgsProcessingException( invalidPointCloudError( parameters, QStringLiteral( "INPUT" ) ) );

const QString outputName = parameterAsOutputLayer( parameters, QStringLiteral( "OUTPUT" ), context );
QString outputFile = fixOutputFileName( layer->source(), outputName, context );
checkOutputFormat( layer->source(), outputFile );
setOutputValue( QStringLiteral( "OUTPUT" ), outputFile );

double minK = parameterAsDouble( parameters, QStringLiteral( "MIN_K" ), context );
double radius = parameterAsDouble( parameters, QStringLiteral( "RADIUS" ), context );

QString removeNoisePoints = "false";
if ( parameterAsBoolean( parameters, QStringLiteral( "REMOVE_NOISE_POINTS" ), context ) )
{
removeNoisePoints = "true";
}

QStringList args = { QStringLiteral( "filter_noise" ), QStringLiteral( "--input=%1" ).arg( layer->source() ), QStringLiteral( "--output=%1" ).arg( outputFile ), QStringLiteral( "--algorithm=radius" ), QStringLiteral( "--remove-noise-points=%1" ).arg( removeNoisePoints ), QStringLiteral( "--radius-min-k=%1" ).arg( minK ), QStringLiteral( "--radius-radius=%1" ).arg( radius ) };

applyCommonParameters( args, layer->crs(), parameters, context );
applyThreadsParameter( args, context );
return args;
}

///@endcond
52 changes: 52 additions & 0 deletions src/analysis/processing/pdal/qgsalgorithmpdalfilternoiseradius.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/***************************************************************************
qgsalgorithmpdalfilternoiseradius.h
---------------------
begin : December 2025
copyright : (C) 2025 by Jan Caha
email : jan.caha at outlook dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMPDALFILTERNOISERADIUS_H
#define QGSALGORITHMPDALFILTERNOISERADIUS_H

#define SIP_NO_FILE

#include "qgis_sip.h"
#include "qgspdalalgorithmbase.h"

///@cond PRIVATE

/**
* Native point cloud filter noise using radius algorithm.
*/
class QgsPdalFilterNoiseRadiusAlgorithm : public QgsPdalAlgorithmBase
{
public:
QgsPdalFilterNoiseRadiusAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
QString name() const override;
QString displayName() const override;
QString group() const override;
QString groupId() const override;
QStringList tags() const override;
QString shortHelpString() const override;
QString shortDescription() const override;
QgsPdalFilterNoiseRadiusAlgorithm *createInstance() const override SIP_FACTORY;

QStringList createArgumentLists( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

friend class TestQgsProcessingPdalAlgs;
};

///@endcond PRIVATE

#endif // QGSALGORITHMPDALFILTERNOISERADIUS_H
Loading
Loading