mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[processing][feature] Port 'offset lines' to c++, support dynamic offset parameter
Adds data defined support for the offset line distance parameter.
This commit is contained in:
parent
76c84f14d7
commit
d1d6840a5f
@ -280,15 +280,6 @@ qgis:numberofuniquevaluesinclasses: >
|
||||
|
||||
The resulting layer contains the same features as the input layer, but with an additional attribute containing the count of unique values for that class.
|
||||
|
||||
qgis:offsetline: >
|
||||
This algorithm offsets lines by a specified distance. Positive distances will offset lines to the left, and negative distances will offset to the right of lines.
|
||||
|
||||
The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets.
|
||||
|
||||
The join style parameter specifies whether round, miter or beveled joins should be used when offsetting corners in a line.
|
||||
|
||||
The miter limit parameter is only applicable for miter join styles, and controls the maximum distance from the offset curve to use when creating a mitered join.
|
||||
|
||||
qgis:minimalenclosingcircle: >
|
||||
This algorithm takes a vector layer and generate a new one with the minimum enclosing circle that covers all the input features.
|
||||
|
||||
|
@ -1,117 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
OffsetLine.py
|
||||
--------------
|
||||
Date : July 2016
|
||||
Copyright : (C) 2016 by Nyall Dawson
|
||||
Email : nyall dot dawson at gmail 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. *
|
||||
* *
|
||||
***************************************************************************
|
||||
"""
|
||||
|
||||
__author__ = 'Nyall Dawson'
|
||||
__date__ = 'July 2016'
|
||||
__copyright__ = '(C) 2016, Nyall Dawson'
|
||||
|
||||
# This will get replaced with a git SHA1 when you do a git archive323
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
|
||||
from qgis.core import (QgsFeatureSink,
|
||||
QgsProcessing,
|
||||
QgsProcessingException,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterDistance,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterFeatureSink)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
|
||||
class OffsetLine(QgisFeatureBasedAlgorithm):
|
||||
|
||||
DISTANCE = 'DISTANCE'
|
||||
SEGMENTS = 'SEGMENTS'
|
||||
JOIN_STYLE = 'JOIN_STYLE'
|
||||
MITER_LIMIT = 'MITER_LIMIT'
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector geometry')
|
||||
|
||||
def groupId(self):
|
||||
return 'vectorgeometry'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.distance = None
|
||||
self.segments = None
|
||||
self.join_style = None
|
||||
self.miter_limit = None
|
||||
|
||||
def initParameters(self, config=None):
|
||||
self.addParameter(QgsProcessingParameterDistance(self.DISTANCE,
|
||||
self.tr('Distance'),
|
||||
defaultValue=10.0,
|
||||
parentParameterName='INPUT'))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.SEGMENTS,
|
||||
self.tr('Segments'),
|
||||
type=QgsProcessingParameterNumber.Integer,
|
||||
minValue=1, defaultValue=8))
|
||||
self.join_styles = [self.tr('Round'),
|
||||
'Miter',
|
||||
'Bevel']
|
||||
self.addParameter(QgsProcessingParameterEnum(
|
||||
self.JOIN_STYLE,
|
||||
self.tr('Join style'),
|
||||
options=self.join_styles))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.MITER_LIMIT,
|
||||
self.tr('Miter limit'), type=QgsProcessingParameterNumber.Double,
|
||||
minValue=1, defaultValue=2))
|
||||
|
||||
def name(self):
|
||||
return 'offsetline'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Offset line')
|
||||
|
||||
def outputName(self):
|
||||
return self.tr('Offset')
|
||||
|
||||
def inputLayerTypes(self):
|
||||
return [QgsProcessing.TypeVectorLine]
|
||||
|
||||
def outputType(self):
|
||||
return QgsProcessing.TypeVectorLine
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.distance = self.parameterAsDouble(parameters, self.DISTANCE, context)
|
||||
self.segments = self.parameterAsInt(parameters, self.SEGMENTS, context)
|
||||
self.join_style = self.parameterAsEnum(parameters, self.JOIN_STYLE, context) + 1
|
||||
self.miter_limit = self.parameterAsDouble(parameters, self.MITER_LIMIT, context)
|
||||
return True
|
||||
|
||||
def processFeature(self, feature, context, feedback):
|
||||
input_geometry = feature.geometry()
|
||||
if input_geometry:
|
||||
output_geometry = input_geometry.offsetCurve(self.distance, self.segments, self.join_style, self.miter_limit)
|
||||
if not output_geometry:
|
||||
raise QgsProcessingException(
|
||||
self.tr('Error calculating line offset'))
|
||||
|
||||
feature.setGeometry(output_geometry)
|
||||
|
||||
return [feature]
|
@ -86,7 +86,6 @@ from .KeepNBiggestParts import KeepNBiggestParts
|
||||
from .LinesToPolygons import LinesToPolygons
|
||||
from .MinimumBoundingGeometry import MinimumBoundingGeometry
|
||||
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
|
||||
from .OffsetLine import OffsetLine
|
||||
from .Orthogonalize import Orthogonalize
|
||||
from .PointDistance import PointDistance
|
||||
from .PointsAlongGeometry import PointsAlongGeometry
|
||||
@ -201,7 +200,6 @@ class QgisAlgorithmProvider(QgsProcessingProvider):
|
||||
LinesToPolygons(),
|
||||
MinimumBoundingGeometry(),
|
||||
NearestNeighbourAnalysis(),
|
||||
OffsetLine(),
|
||||
Orthogonalize(),
|
||||
PointDistance(),
|
||||
PointsAlongGeometry(),
|
||||
|
@ -984,7 +984,7 @@ tests:
|
||||
name: expected/reverse_multiline.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:offsetline
|
||||
- algorithm: native:offsetline
|
||||
name: Offset line positive
|
||||
params:
|
||||
DISTANCE: 1.0
|
||||
@ -1002,7 +1002,7 @@ tests:
|
||||
geometry:
|
||||
precision: 7
|
||||
|
||||
- algorithm: qgis:offsetline
|
||||
- algorithm: native:offsetline
|
||||
name: Offset line negative
|
||||
params:
|
||||
DISTANCE: -1.0
|
||||
@ -1020,7 +1020,7 @@ tests:
|
||||
geometry:
|
||||
precision: 7
|
||||
|
||||
- algorithm: qgis:offsetline
|
||||
- algorithm: native:offsetline
|
||||
name: Offset line miter
|
||||
params:
|
||||
DISTANCE: 1.0
|
||||
@ -1038,7 +1038,7 @@ tests:
|
||||
geometry:
|
||||
precision: 7
|
||||
|
||||
- algorithm: qgis:offsetline
|
||||
- algorithm: native:offsetline
|
||||
name: Offset line bevel
|
||||
params:
|
||||
DISTANCE: 1.0
|
||||
@ -1056,7 +1056,7 @@ tests:
|
||||
geometry:
|
||||
precision: 7
|
||||
|
||||
- algorithm: qgis:offsetline
|
||||
- algorithm: native:offsetline
|
||||
name: Offset multilines
|
||||
params:
|
||||
DISTANCE: 1.0
|
||||
|
@ -58,6 +58,7 @@ SET(QGIS_ANALYSIS_SRCS
|
||||
processing/qgsalgorithmminimumenclosingcircle.cpp
|
||||
processing/qgsalgorithmmultiparttosinglepart.cpp
|
||||
processing/qgsalgorithmmultiringconstantbuffer.cpp
|
||||
processing/qgsalgorithmoffsetlines.cpp
|
||||
processing/qgsalgorithmorderbyexpression.cpp
|
||||
processing/qgsalgorithmorientedminimumboundingbox.cpp
|
||||
processing/qgsalgorithmpackage.cpp
|
||||
|
139
src/analysis/processing/qgsalgorithmoffsetlines.cpp
Normal file
139
src/analysis/processing/qgsalgorithmoffsetlines.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmoffsetlines.cpp
|
||||
---------------------
|
||||
begin : July 2018
|
||||
copyright : (C) 2018 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail 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 "qgsalgorithmoffsetlines.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::name() const
|
||||
{
|
||||
return QStringLiteral( "offsetline" );
|
||||
}
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::displayName() const
|
||||
{
|
||||
return QObject::tr( "Offset lines" );
|
||||
}
|
||||
|
||||
QStringList QgsOffsetLinesAlgorithm::tags() const
|
||||
{
|
||||
return QObject::tr( "offset,linestring" ).split( ',' );
|
||||
}
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::group() const
|
||||
{
|
||||
return QObject::tr( "Vector geometry" );
|
||||
}
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::groupId() const
|
||||
{
|
||||
return QStringLiteral( "vectorgeometry" );
|
||||
}
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::outputName() const
|
||||
{
|
||||
return QObject::tr( "Offset" );
|
||||
}
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm offsets lines by a specified distance. Positive distances will offset lines to the left, and negative distances "
|
||||
"will offset to the right of lines.\n\n"
|
||||
"The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets.\n\n"
|
||||
"The join style parameter specifies whether round, miter or beveled joins should be used when offsetting corners in a line.\n\n"
|
||||
"The miter limit parameter is only applicable for miter join styles, and controls the maximum distance from the offset curve to "
|
||||
"use when creating a mitered join." );
|
||||
}
|
||||
|
||||
QString QgsOffsetLinesAlgorithm::shortDescription() const
|
||||
{
|
||||
return QObject::tr( "Offsets lines by a specified distance." );
|
||||
}
|
||||
|
||||
QgsOffsetLinesAlgorithm *QgsOffsetLinesAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsOffsetLinesAlgorithm();
|
||||
}
|
||||
|
||||
void QgsOffsetLinesAlgorithm::initParameters( const QVariantMap & )
|
||||
{
|
||||
std::unique_ptr< QgsProcessingParameterDistance > offset = qgis::make_unique< QgsProcessingParameterDistance >( QStringLiteral( "DISTANCE" ),
|
||||
QObject::tr( "Distance" ),
|
||||
10.0, QStringLiteral( "INPUT" ) );
|
||||
offset->setIsDynamic( true );
|
||||
offset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance" ), QgsPropertyDefinition::Double ) );
|
||||
offset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
|
||||
addParameter( offset.release() );
|
||||
|
||||
auto segmentParam = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "SEGMENTS" ), QObject::tr( "Segments" ), QgsProcessingParameterNumber::Integer, 8, false, 1 );
|
||||
addParameter( segmentParam.release() );
|
||||
|
||||
auto joinStyleParam = qgis::make_unique< QgsProcessingParameterEnum>( QStringLiteral( "JOIN_STYLE" ), QObject::tr( "Join style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Miter" ) << QObject::tr( "Bevel" ), false, 0 );
|
||||
addParameter( joinStyleParam.release() );
|
||||
|
||||
auto miterLimitParam = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "MITER_LIMIT" ), QObject::tr( "Miter limit" ), QgsProcessingParameterNumber::Double, 2, false, 1 );
|
||||
addParameter( miterLimitParam.release() );
|
||||
}
|
||||
|
||||
QList<int> QgsOffsetLinesAlgorithm::inputLayerTypes() const
|
||||
{
|
||||
return QList< int >() << QgsProcessing::TypeVectorLine;
|
||||
}
|
||||
|
||||
QgsProcessing::SourceType QgsOffsetLinesAlgorithm::outputLayerType() const
|
||||
{
|
||||
return QgsProcessing::TypeVectorLine;
|
||||
}
|
||||
|
||||
bool QgsOffsetLinesAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
{
|
||||
mOffset = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
|
||||
mDynamicOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
|
||||
if ( mDynamicOffset )
|
||||
mOffsetProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
|
||||
|
||||
mSegments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
|
||||
mJoinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
|
||||
mMiterLimit = parameterAsDouble( parameters, QStringLiteral( "MITER_LIMIT" ), context );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsFeatureList QgsOffsetLinesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
{
|
||||
if ( feature.hasGeometry() )
|
||||
{
|
||||
QgsFeature f = feature;
|
||||
const QgsGeometry geometry = feature.geometry();
|
||||
|
||||
double offset = mOffset;
|
||||
if ( mDynamicOffset )
|
||||
offset = mOffsetProperty.valueAsDouble( context.expressionContext(), offset );
|
||||
|
||||
const QgsGeometry offsetGeometry = geometry.offsetCurve( offset, mSegments, mJoinStyle, mMiterLimit );
|
||||
f.setGeometry( offsetGeometry );
|
||||
return QgsFeatureList() << f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QgsFeatureList() << feature;
|
||||
}
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
|
72
src/analysis/processing/qgsalgorithmoffsetlines.h
Normal file
72
src/analysis/processing/qgsalgorithmoffsetlines.h
Normal file
@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmoffsetlines.h
|
||||
---------------------
|
||||
begin : July 2018
|
||||
copyright : (C) 2018 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail 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 QGSALGORITHMOFFSETLINES_H
|
||||
#define QGSALGORITHMOFFSETLINES_H
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsprocessingalgorithm.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
/**
|
||||
* Native offset lines algorithm.
|
||||
*/
|
||||
class QgsOffsetLinesAlgorithm : public QgsProcessingFeatureBasedAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
QgsOffsetLinesAlgorithm() = default;
|
||||
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;
|
||||
QgsOffsetLinesAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QList<int> inputLayerTypes() const override;
|
||||
QgsProcessing::SourceType outputLayerType() const override;
|
||||
|
||||
protected:
|
||||
QString outputName() const override;
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
double mOffset = 0.0;
|
||||
bool mDynamicOffset = false;
|
||||
QgsProperty mOffsetProperty;
|
||||
|
||||
int mSegments = 8;
|
||||
QgsGeometry::JoinStyle mJoinStyle = QgsGeometry::JoinStyleRound;
|
||||
double mMiterLimit = 2;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
||||
#endif // QGSALGORITHMOFFSETLINES_H
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "qgsalgorithmminimumenclosingcircle.h"
|
||||
#include "qgsalgorithmmultiparttosinglepart.h"
|
||||
#include "qgsalgorithmmultiringconstantbuffer.h"
|
||||
#include "qgsalgorithmoffsetlines.h"
|
||||
#include "qgsalgorithmorderbyexpression.h"
|
||||
#include "qgsalgorithmorientedminimumboundingbox.h"
|
||||
#include "qgsalgorithmpackage.h"
|
||||
@ -171,6 +172,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsMinimumEnclosingCircleAlgorithm() );
|
||||
addAlgorithm( new QgsMultipartToSinglepartAlgorithm() );
|
||||
addAlgorithm( new QgsMultiRingConstantBufferAlgorithm() );
|
||||
addAlgorithm( new QgsOffsetLinesAlgorithm() );
|
||||
addAlgorithm( new QgsOrderByExpressionAlgorithm() );
|
||||
addAlgorithm( new QgsOrientedMinimumBoundingBoxAlgorithm() );
|
||||
addAlgorithm( new QgsPackageAlgorithm() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user