New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature][processing] Initial port of Create Grid algorithm to C++ #32070
Conversation
This commit includes the source files for the ported algorithm, integration into cmake and disabling (not yet dropping) the python algorithm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great!
A couple of formatting changes needed, and I've made some extra suggestions on potential improvements we could add. Note that these aren't directly related to your c++ port, but would be nice to address while we're aiming for a super-fast algorithm!
@@ -180,7 +179,7 @@ def getAlgs(self): | |||
FindProjection(), | |||
GeometryByExpression(), | |||
GeometryConvert(), | |||
Grid(), | |||
#Grid(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can totally remove this line
addParameter( new QgsProcessingParameterExtent(QStringLiteral("EXTENT"), QObject::tr( "Grid extent" ))); | ||
|
||
//add Distance Parameter for horizontal and vertical spacing | ||
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HSPACING"), QObject::tr( "Horizontal Spacing" ), 1, QString( "CRS" ), false, 0, 1000000000.0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HSPACING"), QObject::tr( "Horizontal Spacing" ), 1, QString( "CRS" ), false, 0, 1000000000.0)); | |
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HSPACING"), QObject::tr( "Horizontal spacing" ), 1, QStringLiteral( "CRS" ), false, 0, 1000000000.0)); |
|
||
//add Distance Parameter for horizontal and vertical spacing | ||
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HSPACING"), QObject::tr( "Horizontal Spacing" ), 1, QString( "CRS" ), false, 0, 1000000000.0)); | ||
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "VSPACING"), QObject::tr( "Vertical Spacing" ), 1, QString( "CRS" ), false, 0, 1000000000.0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "VSPACING"), QObject::tr( "Vertical Spacing" ), 1, QString( "CRS" ), false, 0, 1000000000.0)); | |
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "VSPACING"), QObject::tr( "Vertical spacing" ), 1, QStringLiteral( "CRS" ), false, 0, 1000000000.0)); |
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "VSPACING"), QObject::tr( "Vertical Spacing" ), 1, QString( "CRS" ), false, 0, 1000000000.0)); | ||
|
||
//add Distance Parameter for horizontal and vertical overlay | ||
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HOVERLAY"), QObject::tr( "Horizontal Overlay" ), 0, QString( "CRS" ), false, 0, 1000000000.0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HOVERLAY"), QObject::tr( "Horizontal Overlay" ), 0, QString( "CRS" ), false, 0, 1000000000.0)); | |
addParameter( new QgsProcessingParameterDistance( QStringLiteral( "HOVERLAY"), QObject::tr( "Horizontal overlay" ), 0, QStringLiteral( "CRS" ), false, 0, 1000000000.0)); |
{ | ||
for(int row = 0; row < rows; row++) | ||
{ | ||
double x = mGridExtent.xMinimum() + (col * mHSpacing - col * mHOverlay); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could potentially be moved up into the outer loop, as we don't need to calculate it for every row.
double x = mGridExtent.xMinimum() + (col * mHSpacing - col * mHOverlay); | ||
double y = mGridExtent.yMaximum() - (row * mVSpacing - row * mVOverlay); | ||
|
||
f.setGeometry(QgsGeometry().fromPointXY(QgsPoint( x, y ))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might get a little speed boost by simplifying this to:
f.setGeometry( QgsGeometry( new QgsPoint( x, y ) ) );
id++; | ||
cnt++; | ||
|
||
if(std::fmod(static_cast<double>(cnt),cnt_log) == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another potential speed boost (optional!):
Instead of calculating the mod for every feature, we could have an int variable of "int lastProgress". Then here this would become something like:
int thisProgress = cnt / cellcnt;
if ( thisProgress != lastProgress )
{
lastProgress= thisProgress;
feedback->setProgress( lastProgress );
}
{ | ||
QgsFeature f = QgsFeature(); | ||
|
||
QVector<double> hSpace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much more efficient c++ would be to use a fixed array size here, e.g.
double hSpace[2];
if( mHOverlay > 0)
{
hSpace[0] = mHSpacing - mHOverlay;
hSpace[1] = mHOverlay;
}
etc
QVector<QgsPoint> lineNodes = QVector<QgsPoint>() << pt1 << pt2; | ||
|
||
QgsPolyline line = QgsPolyline(lineNodes); | ||
f.setGeometry(QgsGeometry::fromPolyline(line)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use an optimised line string constructor here (for raw speeeed!):
f.setGeometry( QgsGeometry( new QgsLineString( pt1, pt2 ) ) );
Re the prepare-commit script -- you need to run this before you make the commit, and the files already need to be checked in to git. So there's two ways to do this:
In order to update the formatting post-commit, try running scripts/astyle-all.sh which will apply the formatting script to all files in the repo. After this, you'll need to run scripts/remove_temporary_files.sh to cleanup the mess astyle-all leaves behind. Ping me if you run into difficulties here! Overall, a fantastic contribution -- great stuff!! |
|
||
bool QgsGridAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) | ||
{ | ||
//retrieve grid type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need all these comments for obvious things?
@root676 there are some unrelated commits in your branch. |
Co-Authored-By: Nyall Dawson <nyall.dawson@gmail.com>
@alexbruy thank you for the review! Yes - I have had a little trouble with the git branch, I have it now fixed locally and will update the PR as soon as I have the suggested changes implemented. |
9d7ccc0
to
4e3fd40
Compare
Hi! I have fine tuned the code according to the suggestions. Should I also delete the original Python algorithm file from the repository? |
Yes please! |
The CRS of the output layer must be defined. The grid extent and the spacing values must be expressed in the coordinates and units of this CRS. | ||
|
||
The top-left point (minX, maxY) is used as the reference point. That means that, at that point, an element is guaranteed to be placed. Unless the width and height of the selected extent is a multiple of the selected spacing, that is not true for the other points that define that extent. | ||
This algorithm creates a vector layer with a grid covering a given extent. Elements in the grid can be points, lines or polygons.The size and/or placement of each element in the grid is defined using a horizontal and vertical spacing. The CRS of the output layer must be defined. The grid extent and the spacing values must be expressed in the coordinates and units of this CRS. The top-left point (minX, maxY) is used as the reference point. That means that, at that point, an element is guaranteed to be placed. Unless the width and height of the selected extent is a multiple of the selected spacing, that is not true for the other points that define that extent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be totally removed -- it won't be used anymore
Ok, travis is happy! |
Thanks for your hard work here @root676 ! |
Description
This PR proposes the port of the Create Grid algorithm from Python to C++. No other functionality has been added to the algorithm, it is a 1:1 port of the original Python implementation. An overall algorithm speedup of multiple orders of magnitude can be achieved by this port.
Reviews and guidance (especially with prepare scripts, etc.) are very welcome as this is my first PR to the QGIS project.
Checklist
Fixes #11111
at the bottom of the commit messagescripts/prepare-commit.sh
script before each commit