QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsalgorithmnearestneighbouranalysis.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmnearestneighbouranalysis.cpp
3  ---------------------
4  begin : December 2019
5  copyright : (C) 2019 by Alexander Bruy
6  email : alexander dot bruy at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsapplication.h"
20 
22 
23 QString QgsNearestNeighbourAnalysisAlgorithm::name() const
24 {
25  return QStringLiteral( "nearestneighbouranalysis" );
26 }
27 
28 QString QgsNearestNeighbourAnalysisAlgorithm::displayName() const
29 {
30  return QObject::tr( "Nearest neighbour analysis" );
31 }
32 
33 QStringList QgsNearestNeighbourAnalysisAlgorithm::tags() const
34 {
35  return QObject::tr( "point,node,vertex,nearest,neighbour,distance" ).split( ',' );
36 }
37 
38 QString QgsNearestNeighbourAnalysisAlgorithm::group() const
39 {
40  return QObject::tr( "Vector analysis" );
41 }
42 
43 QString QgsNearestNeighbourAnalysisAlgorithm::groupId() const
44 {
45  return QStringLiteral( "vectoranalysis" );
46 }
47 
48 QString QgsNearestNeighbourAnalysisAlgorithm::shortHelpString() const
49 {
50  return QObject::tr( "This algorithm performs nearest neighbor analysis for a point layer.\n\n"
51  "The output describes how the data are distributed (clustered, randomly or distributed).\n\n"
52  "Output is generated as an HTML file with the computed statistical values." );
53 }
54 
55 QString QgsNearestNeighbourAnalysisAlgorithm::svgIconPath() const
56 {
57  return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmNearestNeighbour.svg" ) );
58 }
59 
60 QIcon QgsNearestNeighbourAnalysisAlgorithm::icon() const
61 {
62  return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmNearestNeighbour.svg" ) );
63 }
64 
65 QgsNearestNeighbourAnalysisAlgorithm *QgsNearestNeighbourAnalysisAlgorithm::createInstance() const
66 {
67  return new QgsNearestNeighbourAnalysisAlgorithm();
68 }
69 
70 void QgsNearestNeighbourAnalysisAlgorithm::initAlgorithm( const QVariantMap & )
71 {
72  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorPoint ) );
73  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_HTML_FILE" ), QObject::tr( "Nearest neighbour" ),
74  QObject::tr( "HTML files (*.html *.HTML)" ), QVariant(), true ) );
75  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "OBSERVED_MD" ), QObject::tr( "Observed mean distance" ) ) );
76  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "EXPECTED_MD" ), QObject::tr( "Expected mean distance" ) ) );
77  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "NN_INDEX" ), QObject::tr( "Nearest neighbour index" ) ) );
78  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "POINT_COUNT" ), QObject::tr( "Number of points" ) ) );
79  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "Z_SCORE" ), QObject::tr( "Z-score" ) ) );
80 }
81 
82 QVariantMap QgsNearestNeighbourAnalysisAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
83 {
84  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
85  if ( !source )
86  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
87 
88  QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT_HTML_FILE" ), context );
89 
90  QgsSpatialIndex spatialIndex( *source, feedback, QgsSpatialIndex::FlagStoreFeatureGeometries );
91  QgsDistanceArea da;
92  da.setSourceCrs( source->sourceCrs(), context.transformContext() );
93  da.setEllipsoid( context.ellipsoid() );
94 
95  double step = source->featureCount() ? 100.0 / source->featureCount() : 1;
96  QgsFeatureIterator it = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QList< int >() ) );
97 
98  QgsFeatureRequest request;
99  QgsFeature neighbour;
100  double sumDist = 0.0;
101  double area = source->sourceExtent().width() * source->sourceExtent().height();
102 
103  int i = 0;
104  QgsFeature f;
105  while ( it.nextFeature( f ) )
106  {
107  if ( feedback->isCanceled() )
108  {
109  break;
110  }
111 
112  QgsFeatureId neighbourId = spatialIndex.nearestNeighbor( f.geometry().asPoint(), 2 ).at( 1 );
113  sumDist += da.measureLine( spatialIndex.geometry( neighbourId ).asPoint(), f.geometry().asPoint() );
114 
115  i++;
116  feedback->setProgress( i * step );
117  }
118 
119  int count = source->featureCount() > 0 ? source->featureCount() : 1;
120  double observedDistance = sumDist / count;
121  double expectedDistance = 0.5 / std::sqrt( count / area );
122  double nnIndex = observedDistance / expectedDistance;
123  double se = 0.26136 / std::sqrt( std::pow( count, 2 ) / area );
124  double zScore = ( observedDistance - expectedDistance ) / se;
125 
126  QVariantMap outputs;
127  outputs.insert( QStringLiteral( "OBSERVED_MD" ), observedDistance );
128  outputs.insert( QStringLiteral( "EXPECTED_MD" ), expectedDistance );
129  outputs.insert( QStringLiteral( "NN_INDEX" ), nnIndex );
130  outputs.insert( QStringLiteral( "POINT_COUNT" ), count );
131  outputs.insert( QStringLiteral( "Z_SCORE" ), zScore );
132 
133  if ( !outputFile.isEmpty() )
134  {
135  QFile file( outputFile );
136  if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
137  {
138  QTextStream out( &file );
139  out << QStringLiteral( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
140  out << QObject::tr( "<p>Observed mean distance: %1</p>\n" ).arg( observedDistance, 0, 'f', 11 );
141  out << QObject::tr( "<p>Expected mean distance: %1</p>\n" ).arg( expectedDistance, 0, 'f', 11 );
142  out << QObject::tr( "<p>Nearest neighbour index: %1</p>\n" ).arg( nnIndex, 0, 'f', 11 );
143  out << QObject::tr( "<p>Number of points: %1</p>\n" ).arg( count );
144  out << QObject::tr( "<p>Z-Score: %1</p>\n" ).arg( zScore, 0, 'f', 11 );
145  out << QStringLiteral( "</body></html>" );
146 
147  outputs.insert( QStringLiteral( "OUTPUT_HTML_FILE" ), outputFile );
148  }
149  }
150 
151  return outputs;
152 }
153 
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:62
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:38
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsProcessingParameterFeatureSource
An input feature source (such as vector layers) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2734
QgsApplication::iconPath
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Definition: qgsapplication.cpp:615
QgsProcessing::TypeVectorPoint
@ TypeVectorPoint
Vector point layers.
Definition: qgsprocessing.h:48
QgsProcessingOutputNumber
A numeric output for processing algorithms.
Definition: qgsprocessingoutputs.h:295
qgsapplication.h
QgsDistanceArea::setEllipsoid
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Definition: qgsdistancearea.cpp:66
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:76
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsProcessingParameterFileDestination
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
Definition: qgsprocessingparameters.h:3127
QgsDistanceArea::measureLine
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
Definition: qgsdistancearea.cpp:273
QgsProcessingContext::ellipsoid
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
Definition: qgsprocessingcontext.cpp:131
QgsSpatialIndex
A spatial index for QgsFeature objects.
Definition: qgsspatialindex.h:68
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:149
QgsDistanceArea::setSourceCrs
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
Definition: qgsdistancearea.cpp:60
QgsSpatialIndex::FlagStoreFeatureGeometries
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
Definition: qgsspatialindex.h:77
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:53
QgsGeometry::asPoint
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Definition: qgsgeometry.cpp:1544
qgsalgorithmnearestneighbouranalysis.h
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:374
QgsDistanceArea
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
Definition: qgsdistancearea.h:50
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:265
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28