Skip to content

Commit 3a2710e

Browse files
authoredJul 16, 2017
Merge pull request #4870 from nyalldawson/algs3
Port 4 more algs to new API
2 parents 97c1def + 38a13ff commit 3a2710e

File tree

11 files changed

+430
-286
lines changed

11 files changed

+430
-286
lines changed
 

‎python/plugins/processing/algs/qgis/OffsetLine.py

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,22 @@
2727

2828
import os
2929

30-
from qgis.core import (QgsApplication,
31-
QgsWkbTypes,
32-
QgsFeatureSink,
33-
QgsProcessingUtils)
30+
from qgis.core import (QgsFeatureSink,
31+
QgsProcessing,
32+
QgsProcessingException,
33+
QgsProcessingParameterFeatureSource,
34+
QgsProcessingParameterNumber,
35+
QgsProcessingParameterEnum,
36+
QgsProcessingParameterFeatureSink)
3437

3538
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
36-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
37-
from processing.core.parameters import ParameterVector, ParameterSelection, ParameterNumber
38-
from processing.core.outputs import OutputVector
39-
from processing.tools import dataobjects
4039

4140
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4241

4342

4443
class OffsetLine(QgisAlgorithm):
45-
46-
INPUT_LAYER = 'INPUT_LAYER'
47-
OUTPUT_LAYER = 'OUTPUT_LAYER'
44+
INPUT = 'INPUT'
45+
OUTPUT = 'OUTPUT'
4846
DISTANCE = 'DISTANCE'
4947
SEGMENTS = 'SEGMENTS'
5048
JOIN_STYLE = 'JOIN_STYLE'
@@ -57,23 +55,29 @@ def __init__(self):
5755
super().__init__()
5856

5957
def initAlgorithm(self, config=None):
60-
self.addParameter(ParameterVector(self.INPUT_LAYER,
61-
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_LINE]))
62-
self.addParameter(ParameterNumber(self.DISTANCE,
63-
self.tr('Distance'), default=10.0))
64-
self.addParameter(ParameterNumber(self.SEGMENTS,
65-
self.tr('Segments'), 1, default=8))
58+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
59+
[QgsProcessing.TypeVectorLine]))
60+
self.addParameter(QgsProcessingParameterNumber(self.DISTANCE,
61+
self.tr('Distance'),
62+
type=QgsProcessingParameterNumber.Double,
63+
defaultValue=10.0))
64+
self.addParameter(QgsProcessingParameterNumber(self.SEGMENTS,
65+
self.tr('Segments'),
66+
type=QgsProcessingParameterNumber.Integer,
67+
minValue=1, defaultValue=8))
6668
self.join_styles = [self.tr('Round'),
6769
'Mitre',
6870
'Bevel']
69-
self.addParameter(ParameterSelection(
71+
self.addParameter(QgsProcessingParameterEnum(
7072
self.JOIN_STYLE,
7173
self.tr('Join style'),
72-
self.join_styles))
73-
self.addParameter(ParameterNumber(self.MITRE_LIMIT,
74-
self.tr('Mitre limit'), 1, default=2))
74+
options=self.join_styles))
75+
self.addParameter(QgsProcessingParameterNumber(self.MITRE_LIMIT,
76+
self.tr('Mitre limit'), type=QgsProcessingParameterNumber.Double,
77+
minValue=1, defaultValue=2))
7578

76-
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Offset'), datatype=[dataobjects.TYPE_VECTOR_LINE]))
79+
self.addParameter(
80+
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Offset'), QgsProcessing.TypeVectorLine))
7781

7882
def name(self):
7983
return 'offsetline'
@@ -82,31 +86,33 @@ def displayName(self):
8286
return self.tr('Offset line')
8387

8488
def processAlgorithm(self, parameters, context, feedback):
85-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
86-
87-
writer = self.getOutputFromName(
88-
self.OUTPUT_LAYER).getVectorWriter(layer.fields(), QgsWkbTypes.LineString, layer.crs(), context)
89+
source = self.parameterAsSource(parameters, self.INPUT, context)
90+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
91+
source.fields(), source.wkbType(), source.sourceCrs())
8992

90-
distance = self.getParameterValue(self.DISTANCE)
91-
segments = int(self.getParameterValue(self.SEGMENTS))
92-
join_style = self.getParameterValue(self.JOIN_STYLE) + 1
93-
miter_limit = self.getParameterValue(self.MITRE_LIMIT)
93+
distance = self.parameterAsDouble(parameters, self.DISTANCE, context)
94+
segments = self.parameterAsInt(parameters, self.SEGMENTS, context)
95+
join_style = self.parameterAsEnum(parameters, self.JOIN_STYLE, context) + 1
96+
miter_limit = self.parameterAsDouble(parameters, self.MITRE_LIMIT, context)
9497

95-
features = QgsProcessingUtils.getFeatures(layer, context)
96-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
98+
features = source.getFeatures()
99+
total = 100.0 / source.featureCount() if source.featureCount() else 0
97100

98101
for current, input_feature in enumerate(features):
102+
if feedback.isCanceled():
103+
break
104+
99105
output_feature = input_feature
100106
input_geometry = input_feature.geometry()
101107
if input_geometry:
102108
output_geometry = input_geometry.offsetCurve(distance, segments, join_style, miter_limit)
103109
if not output_geometry:
104-
raise GeoAlgorithmExecutionException(
110+
raise QgsProcessingException(
105111
self.tr('Error calculating line offset'))
106112

107113
output_feature.setGeometry(output_geometry)
108114

109-
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
115+
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
110116
feedback.setProgress(int(current * total))
111117

112-
del writer
118+
return {self.OUTPUT: dest_id}

‎python/plugins/processing/algs/qgis/Orthogonalize.py

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,19 @@
2525

2626
__revision__ = '$Format:%H$'
2727

28-
from qgis.core import (QgsApplication,
29-
QgsFeatureSink,
30-
QgsProcessingUtils,
31-
QgsProcessingParameterDefinition)
28+
from qgis.core import (QgsFeatureSink,
29+
QgsProcessingException,
30+
QgsProcessing,
31+
QgsProcessingParameterDefinition,
32+
QgsProcessingParameterFeatureSource,
33+
QgsProcessingParameterNumber,
34+
QgsProcessingParameterFeatureSink)
3235
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
33-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
34-
from processing.core.parameters import ParameterVector, ParameterNumber
35-
from processing.core.outputs import OutputVector
36-
from processing.tools import dataobjects
3736

3837

3938
class Orthogonalize(QgisAlgorithm):
40-
41-
INPUT_LAYER = 'INPUT_LAYER'
42-
OUTPUT_LAYER = 'OUTPUT_LAYER'
39+
INPUT = 'INPUT'
40+
OUTPUT = 'OUTPUT'
4341
MAX_ITERATIONS = 'MAX_ITERATIONS'
4442
DISTANCE_THRESHOLD = 'DISTANCE_THRESHOLD'
4543
ANGLE_TOLERANCE = 'ANGLE_TOLERANCE'
@@ -54,20 +52,24 @@ def __init__(self):
5452
super().__init__()
5553

5654
def initAlgorithm(self, config=None):
57-
self.addParameter(ParameterVector(self.INPUT_LAYER,
58-
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_LINE,
59-
dataobjects.TYPE_VECTOR_POLYGON]))
60-
self.addParameter(ParameterNumber(self.ANGLE_TOLERANCE,
61-
self.tr('Maximum angle tolerance (degrees)'),
62-
0.0, 45.0, 15.0))
63-
64-
max_iterations = ParameterNumber(self.MAX_ITERATIONS,
65-
self.tr('Maximum algorithm iterations'),
66-
1, 10000, 1000)
55+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
56+
[QgsProcessing.TypeVectorLine,
57+
QgsProcessing.TypeVectorPolygon]))
58+
59+
self.addParameter(QgsProcessingParameterNumber(self.ANGLE_TOLERANCE,
60+
self.tr('Maximum angle tolerance (degrees)'),
61+
type=QgsProcessingParameterNumber.Double,
62+
minValue=0.0, maxValue=45.0, defaultValue=15.0))
63+
64+
max_iterations = QgsProcessingParameterNumber(self.MAX_ITERATIONS,
65+
self.tr('Maximum algorithm iterations'),
66+
type=QgsProcessingParameterNumber.Integer,
67+
minValue=1, maxValue=10000, defaultValue=1000)
6768
max_iterations.setFlags(max_iterations.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
6869
self.addParameter(max_iterations)
6970

70-
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Orthogonalized')))
71+
self.addParameter(
72+
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Orthogonalized')))
7173

7274
def name(self):
7375
return 'orthogonalize'
@@ -76,27 +78,31 @@ def displayName(self):
7678
return self.tr('Orthogonalize')
7779

7880
def processAlgorithm(self, parameters, context, feedback):
79-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
80-
max_iterations = self.getParameterValue(self.MAX_ITERATIONS)
81-
angle_tolerance = self.getParameterValue(self.ANGLE_TOLERANCE)
82-
writer = self.getOutputFromName(
83-
self.OUTPUT_LAYER).getVectorWriter(layer.fields(), layer.wkbType(), layer.crs(), context)
81+
source = self.parameterAsSource(parameters, self.INPUT, context)
82+
max_iterations = self.parameterAsInt(parameters, self.MAX_ITERATIONS, context)
83+
angle_tolerance = self.parameterAsDouble(parameters, self.ANGLE_TOLERANCE, context)
84+
85+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
86+
source.fields(), source.wkbType(), source.sourceCrs())
8487

85-
features = QgsProcessingUtils.getFeatures(layer, context)
86-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
88+
features = source.getFeatures()
89+
total = 100.0 / source.featureCount() if source.featureCount() else 0
8790

8891
for current, input_feature in enumerate(features):
92+
if feedback.isCanceled():
93+
break
94+
8995
output_feature = input_feature
9096
input_geometry = input_feature.geometry()
9197
if input_geometry:
9298
output_geometry = input_geometry.orthogonalize(1.0e-8, max_iterations, angle_tolerance)
9399
if not output_geometry:
94-
raise GeoAlgorithmExecutionException(
100+
raise QgsProcessingException(
95101
self.tr('Error orthogonalizing geometry'))
96102

97103
output_feature.setGeometry(output_geometry)
98104

99-
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
105+
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
100106
feedback.setProgress(int(current * total))
101107

102-
del writer
108+
return {self.OUTPUT: dest_id}

‎python/plugins/processing/algs/qgis/PoleOfInaccessibility.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,29 @@
2727

2828
import os
2929

30-
from qgis.core import QgsWkbTypes, QgsField, NULL, QgsFeatureSink, QgsProcessingUtils
30+
from qgis.core import (QgsWkbTypes,
31+
QgsField,
32+
NULL,
33+
QgsFeatureSink,
34+
QgsProcessing,
35+
QgsProcessingException,
36+
QgsProcessingParameterFeatureSource,
37+
QgsProcessingParameterNumber,
38+
QgsProcessingParameterFeatureSink)
3139

3240
from qgis.PyQt.QtCore import QVariant
3341
from qgis.PyQt.QtGui import QIcon
3442

3543
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
36-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
37-
from processing.core.parameters import ParameterVector, ParameterNumber
38-
from processing.core.outputs import OutputVector
39-
from processing.tools import dataobjects
4044

4145
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4246

4347

4448
class PoleOfInaccessibility(QgisAlgorithm):
4549

46-
INPUT_LAYER = 'INPUT_LAYER'
50+
INPUT = 'INPUT'
4751
TOLERANCE = 'TOLERANCE'
48-
OUTPUT_LAYER = 'OUTPUT_LAYER'
52+
OUTPUT = 'OUTPUT'
4953

5054
def icon(self):
5155
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'centroids.png'))
@@ -60,12 +64,15 @@ def __init__(self):
6064
super().__init__()
6165

6266
def initAlgorithm(self, config=None):
63-
self.addParameter(ParameterVector(self.INPUT_LAYER,
64-
self.tr('Input layer'),
65-
[dataobjects.TYPE_VECTOR_POLYGON]))
66-
self.addParameter(ParameterNumber(self.TOLERANCE,
67-
self.tr('Tolerance (layer units)'), default=1.0, minValue=0.0))
68-
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Point'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
67+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
68+
[QgsProcessing.TypeVectorPolygon]))
69+
self.addParameter(QgsProcessingParameterNumber(self.TOLERANCE,
70+
self.tr('Tolerance (layer units)'),
71+
type=QgsProcessingParameterNumber.Double,
72+
defaultValue=1.0, minValue=0.0))
73+
74+
self.addParameter(
75+
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Point'), QgsProcessing.TypeVectorPoint))
6976

7077
def name(self):
7178
return 'poleofinaccessibility'
@@ -74,25 +81,27 @@ def displayName(self):
7481
return self.tr('Pole of Inaccessibility')
7582

7683
def processAlgorithm(self, parameters, context, feedback):
77-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
78-
tolerance = self.getParameterValue(self.TOLERANCE)
84+
source = self.parameterAsSource(parameters, self.INPUT, context)
85+
tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
7986

80-
fields = layer.fields()
87+
fields = source.fields()
8188
fields.append(QgsField('dist_pole', QVariant.Double))
89+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
90+
fields, QgsWkbTypes.Point, source.sourceCrs())
8291

83-
writer = self.getOutputFromName(
84-
self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.Point, layer.crs(), context)
85-
86-
features = QgsProcessingUtils.getFeatures(layer, context)
87-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
92+
features = source.getFeatures()
93+
total = 100.0 / source.featureCount() if source.featureCount() else 0
8894

8995
for current, input_feature in enumerate(features):
96+
if feedback.isCanceled():
97+
break
98+
9099
output_feature = input_feature
91100
input_geometry = input_feature.geometry()
92101
if input_geometry:
93102
output_geometry, distance = input_geometry.poleOfInaccessibility(tolerance)
94103
if not output_geometry:
95-
raise GeoAlgorithmExecutionException(
104+
raise QgsProcessingException(
96105
self.tr('Error calculating pole of inaccessibility'))
97106
attrs = input_feature.attributes()
98107
attrs.append(distance)
@@ -104,7 +113,7 @@ def processAlgorithm(self, parameters, context, feedback):
104113
attrs.append(NULL)
105114
output_feature.setAttributes(attrs)
106115

107-
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
116+
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
108117
feedback.setProgress(int(current * total))
109118

110-
del writer
119+
return {self.OUTPUT: dest_id}

‎python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,19 @@
7070
from .MeanCoords import MeanCoords
7171
from .Merge import Merge
7272
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
73+
from .OffsetLine import OffsetLine
74+
from .Orthogonalize import Orthogonalize
7375
from .PointDistance import PointDistance
7476
from .PointOnSurface import PointOnSurface
7577
from .PointsInPolygon import PointsInPolygon
7678
from .PointsLayerFromTable import PointsLayerFromTable
79+
from .PoleOfInaccessibility import PoleOfInaccessibility
7780
from .PolygonsToLines import PolygonsToLines
7881
from .PostGISExecuteSQL import PostGISExecuteSQL
7982
from .RandomExtract import RandomExtract
8083
from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
8184
from .RegularPoints import RegularPoints
85+
from .ReverseLineDirection import ReverseLineDirection
8286
from .Ruggedness import Ruggedness
8387
from .SaveSelectedFeatures import SaveSelectedFeatures
8488
from .SelectByAttribute import SelectByAttribute
@@ -139,13 +143,11 @@
139143
# from .FieldsMapper import FieldsMapper
140144
# from .Datasources2Vrt import Datasources2Vrt
141145
# from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
142-
# from .ReverseLineDirection import ReverseLineDirection
143146
# from .SpatialIndex import SpatialIndex
144147
# from .DefineProjection import DefineProjection
145148
# from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
146149
# from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
147150
# from .MergeLines import MergeLines
148-
# from .OffsetLine import OffsetLine
149151
# from .Translate import Translate
150152
# from .SingleSidedBuffer import SingleSidedBuffer
151153
# from .PointsAlongGeometry import PointsAlongGeometry
@@ -155,9 +157,7 @@
155157
# from .ExtendLines import ExtendLines
156158
# from .ExtractSpecificNodes import ExtractSpecificNodes
157159
# from .GeometryByExpression import GeometryByExpression
158-
# from .PoleOfInaccessibility import PoleOfInaccessibility
159160
# from .RasterCalculator import RasterCalculator
160-
# from .Orthogonalize import Orthogonalize
161161
# from .ShortestPathPointToPoint import ShortestPathPointToPoint
162162
# from .ShortestPathPointToLayer import ShortestPathPointToLayer
163163
# from .ShortestPathLayerToPoint import ShortestPathLayerToPoint
@@ -211,19 +211,16 @@ def getAlgs(self):
211211
# SplitWithLines(), CreateConstantRaster(),
212212
# FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(),
213213
# OrientedMinimumBoundingBox(),
214-
# ReverseLineDirection(), SpatialIndex(), DefineProjection(),
214+
# SpatialIndex(), DefineProjection(),
215215
# RectanglesOvalsDiamondsVariable(),
216216
# RectanglesOvalsDiamondsFixed(), MergeLines(),
217-
# OffsetLine(), Translate(),
217+
# Translate(),
218218
# SingleSidedBuffer(), PointsAlongGeometry(),
219-
# Slope(), Ruggedness(), Hillshade(),
220219
# Relief(),
221220
# IdwInterpolation(), TinInterpolation(),
222221
# ExtendLines(), ExtractSpecificNodes(),
223222
# GeometryByExpression(),
224-
# PoleOfInaccessibility(),
225-
#
226-
# RasterCalculator(), Heatmap(), Orthogonalize(),
223+
# RasterCalculator(),
227224
# ShortestPathPointToPoint(), ShortestPathPointToLayer(),
228225
# ShortestPathLayerToPoint(), ServiceAreaFromPoint(),
229226
# ServiceAreaFromLayer(), TruncateTable(), Polygonize(),
@@ -260,15 +257,19 @@ def getAlgs(self):
260257
MeanCoords(),
261258
Merge(),
262259
NearestNeighbourAnalysis(),
260+
OffsetLine(),
261+
Orthogonalize(),
263262
PointDistance(),
264263
PointOnSurface(),
265264
PointsInPolygon(),
266265
PointsLayerFromTable(),
266+
PoleOfInaccessibility(),
267267
PolygonsToLines(),
268268
PostGISExecuteSQL(),
269269
RandomExtract(),
270270
RandomExtractWithinSubsets(),
271271
RegularPoints(),
272+
ReverseLineDirection(),
272273
Ruggedness(),
273274
SaveSelectedFeatures(),
274275
SelectByAttribute(),

‎python/plugins/processing/algs/qgis/ReverseLineDirection.py

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,20 @@
2525

2626
__revision__ = '$Format:%H$'
2727

28-
from qgis.core import (QgsApplication,
29-
QgsGeometry,
28+
from qgis.core import (QgsGeometry,
3029
QgsFeature,
3130
QgsFeatureSink,
32-
QgsProcessingUtils)
31+
QgsProcessingException,
32+
QgsProcessing,
33+
QgsProcessingParameterFeatureSource,
34+
QgsProcessingParameterFeatureSink)
3335
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
34-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
35-
from processing.core.parameters import ParameterVector
36-
from processing.core.outputs import OutputVector
37-
from processing.tools import dataobjects
3836

3937

4038
class ReverseLineDirection(QgisAlgorithm):
4139

42-
INPUT_LAYER = 'INPUT_LAYER'
43-
OUTPUT_LAYER = 'OUTPUT_LAYER'
40+
INPUT = 'INPUT'
41+
OUTPUT = 'OUTPUT'
4442

4543
def group(self):
4644
return self.tr('Vector geometry tools')
@@ -49,9 +47,10 @@ def __init__(self):
4947
super().__init__()
5048

5149
def initAlgorithm(self, config=None):
52-
self.addParameter(ParameterVector(self.INPUT_LAYER,
53-
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_LINE]))
54-
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Reversed'), datatype=[dataobjects.TYPE_VECTOR_LINE]))
50+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
51+
[QgsProcessing.TypeVectorLine]))
52+
self.addParameter(
53+
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Reversed'), QgsProcessing.TypeVectorLine))
5554

5655
def name(self):
5756
return 'reverselinedirection'
@@ -60,30 +59,28 @@ def displayName(self):
6059
return self.tr('Reverse line direction')
6160

6261
def processAlgorithm(self, parameters, context, feedback):
63-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
62+
source = self.parameterAsSource(parameters, self.INPUT, context)
6463

65-
writer = self.getOutputFromName(
66-
self.OUTPUT_LAYER).getVectorWriter(layer.fields(), layer.wkbType(), layer.crs(), context)
64+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
65+
source.fields(), source.wkbType(), source.sourceCrs())
6766

68-
outFeat = QgsFeature()
69-
70-
features = QgsProcessingUtils.getFeatures(layer, context)
71-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
67+
features = source.getFeatures()
68+
total = 100.0 / source.featureCount() if source.featureCount() else 0
7269
for current, inFeat in enumerate(features):
73-
inGeom = inFeat.geometry()
74-
attrs = inFeat.attributes()
70+
if feedback.isCanceled():
71+
break
7572

76-
outGeom = None
77-
if not inGeom.isNull():
73+
outFeat = inFeat
74+
if inFeat.geometry():
75+
inGeom = inFeat.geometry()
7876
reversedLine = inGeom.geometry().reversed()
7977
if not reversedLine:
80-
raise GeoAlgorithmExecutionException(
78+
raise QgsProcessingException(
8179
self.tr('Error reversing line'))
8280
outGeom = QgsGeometry(reversedLine)
8381

84-
outFeat.setGeometry(outGeom)
85-
outFeat.setAttributes(attrs)
86-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
82+
outFeat.setGeometry(outGeom)
83+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
8784
feedback.setProgress(int(current * total))
8885

89-
del writer
86+
return {self.OUTPUT: dest_id}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>lines_reversed</Name>
4+
<ElementPath>lines_reversed</ElementPath>
5+
<!--LINESTRING-->
6+
<GeometryType>2</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>7</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>11.00000</ExtentXMax>
12+
<ExtentYMin>-3.00000</ExtentYMin>
13+
<ExtentYMax>5.00000</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
</GMLFeatureClass>
16+
</GMLFeatureClassList>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:lines_reversed fid="lines.0">
16+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>11,5 9,3 9,2 6,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
17+
</ogr:lines_reversed>
18+
</gml:featureMember>
19+
<gml:featureMember>
20+
<ogr:lines_reversed fid="lines.1">
21+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,-1 -1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
22+
</ogr:lines_reversed>
23+
</gml:featureMember>
24+
<gml:featureMember>
25+
<ogr:lines_reversed fid="lines.2">
26+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 3,2 2,2 2,0</gml:coordinates></gml:LineString></ogr:geometryProperty>
27+
</ogr:lines_reversed>
28+
</gml:featureMember>
29+
<gml:featureMember>
30+
<ogr:lines_reversed fid="lines.3">
31+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,1 3,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
32+
</ogr:lines_reversed>
33+
</gml:featureMember>
34+
<gml:featureMember>
35+
<ogr:lines_reversed fid="lines.4">
36+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10,-3 7,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
37+
</ogr:lines_reversed>
38+
</gml:featureMember>
39+
<gml:featureMember>
40+
<ogr:lines_reversed fid="lines.5">
41+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10,1 6,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
42+
</ogr:lines_reversed>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:lines_reversed fid="lines.6">
46+
</ogr:lines_reversed>
47+
</gml:featureMember>
48+
</ogr:FeatureCollection>

‎python/plugins/processing/tests/testdata/expected/multiline_offset.gml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313

1414
<gml:featureMember>
1515
<ogr:multiline_offset fid="lines.1">
16-
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,0 1,0</gml:coordinates></gml:LineString></ogr:geometryProperty>
16+
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,0 1,0</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
1717
</ogr:multiline_offset>
1818
</gml:featureMember>
1919
<gml:featureMember>
2020
<ogr:multiline_offset fid="lines.2">
21-
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 5,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>6.024038190337471,2.397687750474408 5.999853929301003,0.982908479841009</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
21+
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 5,2</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>6.02403819033747,2.39768775047441 5.999853929301,0.982908479841009</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
2222
</ogr:multiline_offset>
2323
</gml:featureMember>
2424
<gml:featureMember>
@@ -27,7 +27,7 @@
2727
</gml:featureMember>
2828
<gml:featureMember>
2929
<ogr:multiline_offset fid="lines.4">
30-
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>1,0 1,2 1.01921471959677,2.195090322016128 1.076120467488713,2.38268343236509 1.168530387697455,2.555570233019602 1.292893218813453,2.707106781186547 1.444429766980398,2.831469612302545 1.61731656763491,2.923879532511287 1.804909677983872,2.98078528040323 2,3</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.915503652020259,5.046801099766013 5.430666799812965,5.119353882875417</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3.020599614854323,3.999787805420657 5.601021879729563,3.946620818856359</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
30+
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>1,0 1,2 1.01921471959677,2.19509032201613 1.07612046748871,2.38268343236509 1.16853038769745,2.5555702330196 1.29289321881345,2.70710678118655 1.4444297669804,2.83146961230255 1.61731656763491,2.92387953251129 1.80490967798387,2.98078528040323 2,3</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.91550365202026,5.04680109976601 5.43066679981296,5.11935388287542</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3.02059961485432,3.99978780542066 5.60102187972956,3.94662081885636</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
3131
</ogr:multiline_offset>
3232
</gml:featureMember>
3333
</ogr:FeatureCollection>

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 147 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -555,96 +555,110 @@ tests:
555555
name: expected/point_on_line.gml
556556
type: vector
557557

558-
# - algorithm: qgis:offsetline
559-
# name: Offset line positive
560-
# params:
561-
# DISTANCE: 1.0
562-
# INPUT_LAYER:
563-
# name: lines.gml
564-
# type: vector
565-
# JOIN_STYLE: '0'
566-
# MITRE_LIMIT: 2
567-
# SEGMENTS: 8
568-
# results:
569-
# OUTPUT_LAYER:
570-
# name: expected/line_offset_round_positive.gml
571-
# type: vector
572-
# compare:
573-
# geometry:
574-
# precision: 7
575-
#
576-
# - algorithm: qgis:offsetline
577-
# name: Offset line negative
578-
# params:
579-
# DISTANCE: -1.0
580-
# INPUT_LAYER:
581-
# name: lines.gml
582-
# type: vector
583-
# JOIN_STYLE: '0'
584-
# MITRE_LIMIT: 2
585-
# SEGMENTS: 8
586-
# results:
587-
# OUTPUT_LAYER:
588-
# name: expected/line_offset_round_negative.gml
589-
# type: vector
590-
# compare:
591-
# geometry:
592-
# precision: 7
593-
#
594-
# - algorithm: qgis:offsetline
595-
# name: Offset line mitre
596-
# params:
597-
# DISTANCE: 1.0
598-
# INPUT_LAYER:
599-
# name: lines.gml
600-
# type: vector
601-
# JOIN_STYLE: '1'
602-
# MITRE_LIMIT: 2
603-
# SEGMENTS: 4
604-
# results:
605-
# OUTPUT_LAYER:
606-
# name: expected/line_offset_mitre.gml
607-
# type: vector
608-
# compare:
609-
# geometry:
610-
# precision: 7
611-
#
612-
# - algorithm: qgis:offsetline
613-
# name: Offset line bevel
614-
# params:
615-
# DISTANCE: 1.0
616-
# INPUT_LAYER:
617-
# name: lines.gml
618-
# type: vector
619-
# JOIN_STYLE: '2'
620-
# MITRE_LIMIT: 2
621-
# SEGMENTS: 8
622-
# results:
623-
# OUTPUT_LAYER:
624-
# name: expected/line_offset_bevel.gml
625-
# type: vector
626-
# compare:
627-
# geometry:
628-
# precision: 7
629-
#
630-
# - algorithm: qgis:offsetline
631-
# name: Offset multilines
632-
# params:
633-
# DISTANCE: 1.0
634-
# INPUT_LAYER:
635-
# name: multilines.gml
636-
# type: vector
637-
# JOIN_STYLE: '0'
638-
# MITRE_LIMIT: 2
639-
# SEGMENTS: 8
640-
# results:
641-
# OUTPUT_LAYER:
642-
# name: expected/multiline_offset.gml
643-
# type: vector
644-
# compare:
645-
# geometry:
646-
# precision: 7
647-
#
558+
- algorithm: qgis:reverselinedirection
559+
name: Reverse line direction
560+
params:
561+
INPUT:
562+
name: lines.gml
563+
type: vector
564+
results:
565+
OUTPUT:
566+
name: expected/lines_reversed.gml
567+
type: vector
568+
compare:
569+
geometry:
570+
precision: 7
571+
572+
- algorithm: qgis:offsetline
573+
name: Offset line positive
574+
params:
575+
DISTANCE: 1.0
576+
INPUT:
577+
name: lines.gml
578+
type: vector
579+
JOIN_STYLE: '0'
580+
MITRE_LIMIT: 2
581+
SEGMENTS: 8
582+
results:
583+
OUTPUT:
584+
name: expected/line_offset_round_positive.gml
585+
type: vector
586+
compare:
587+
geometry:
588+
precision: 7
589+
590+
- algorithm: qgis:offsetline
591+
name: Offset line negative
592+
params:
593+
DISTANCE: -1.0
594+
INPUT:
595+
name: lines.gml
596+
type: vector
597+
JOIN_STYLE: '0'
598+
MITRE_LIMIT: 2
599+
SEGMENTS: 8
600+
results:
601+
OUTPUT:
602+
name: expected/line_offset_round_negative.gml
603+
type: vector
604+
compare:
605+
geometry:
606+
precision: 7
607+
608+
- algorithm: qgis:offsetline
609+
name: Offset line mitre
610+
params:
611+
DISTANCE: 1.0
612+
INPUT:
613+
name: lines.gml
614+
type: vector
615+
JOIN_STYLE: '1'
616+
MITRE_LIMIT: 2
617+
SEGMENTS: 4
618+
results:
619+
OUTPUT:
620+
name: expected/line_offset_mitre.gml
621+
type: vector
622+
compare:
623+
geometry:
624+
precision: 7
625+
626+
- algorithm: qgis:offsetline
627+
name: Offset line bevel
628+
params:
629+
DISTANCE: 1.0
630+
INPUT:
631+
name: lines.gml
632+
type: vector
633+
JOIN_STYLE: '2'
634+
MITRE_LIMIT: 2
635+
SEGMENTS: 8
636+
results:
637+
OUTPUT:
638+
name: expected/line_offset_bevel.gml
639+
type: vector
640+
compare:
641+
geometry:
642+
precision: 7
643+
644+
- algorithm: qgis:offsetline
645+
name: Offset multilines
646+
params:
647+
DISTANCE: 1.0
648+
INPUT:
649+
name: multilines.gml
650+
type: vector
651+
JOIN_STYLE: '0'
652+
MITRE_LIMIT: 2
653+
SEGMENTS: 8
654+
results:
655+
OUTPUT:
656+
name: expected/multiline_offset.gml
657+
type: vector
658+
compare:
659+
geometry:
660+
precision: 7
661+
648662
# - algorithm: qgis:fixeddistancebuffer
649663
# name: Buffer polygons using bevel
650664
# params:
@@ -1481,21 +1495,21 @@ tests:
14811495
name: expected/snap_internal.gml
14821496
type: vector
14831497

1484-
# - algorithm: qgis:poleofinaccessibility
1485-
# name: Pole of inaccessibility (polygons)
1486-
# params:
1487-
# INPUT_LAYER:
1488-
# name: polys.gml
1489-
# type: vector
1490-
# TOLERANCE: 1.0e-05
1491-
# results:
1492-
# OUTPUT_LAYER:
1493-
# name: expected/pole_inaccessibility_polys.gml
1494-
# type: vector
1495-
# compare:
1496-
# geometry:
1497-
# precision: 7
1498-
#
1498+
- algorithm: qgis:poleofinaccessibility
1499+
name: Pole of inaccessibility (polygons)
1500+
params:
1501+
INPUT:
1502+
name: polys.gml
1503+
type: vector
1504+
TOLERANCE: 1.0e-05
1505+
results:
1506+
OUTPUT:
1507+
name: expected/pole_inaccessibility_polys.gml
1508+
type: vector
1509+
compare:
1510+
geometry:
1511+
precision: 7
1512+
14991513
- algorithm: native:extractbyattribute
15001514
name: Extract by attribute (is null)
15011515
params:
@@ -1945,34 +1959,34 @@ tests:
19451959
# compare:
19461960
# geometry:
19471961
# precision: 7
1948-
#
1949-
# - algorithm: qgis:orthogonalize
1950-
# name: Orthogonalize polys
1951-
# params:
1952-
# INPUT_LAYER:
1953-
# name: custom/polys_to_orth.gml
1954-
# type: vector
1955-
# results:
1956-
# OUTPUT_LAYER:
1957-
# name: expected/orthagonal_polys.gml
1958-
# type: vector
1959-
# compare:
1960-
# geometry:
1961-
# precision: 7
1962-
#
1963-
# - algorithm: qgis:orthogonalize
1964-
# name: Orthogonalize lines
1965-
# params:
1966-
# INPUT_LAYER:
1967-
# name: custom/lines_to_orth.gml
1968-
# type: vector
1969-
# results:
1970-
# OUTPUT_LAYER:
1971-
# name: expected/orthagonal_lines.gml
1972-
# type: vector
1973-
# compare:
1974-
# geometry:
1975-
# precision: 7
1962+
1963+
- algorithm: qgis:orthogonalize
1964+
name: Orthogonalize polys
1965+
params:
1966+
INPUT:
1967+
name: custom/polys_to_orth.gml
1968+
type: vector
1969+
results:
1970+
OUTPUT:
1971+
name: expected/orthagonal_polys.gml
1972+
type: vector
1973+
compare:
1974+
geometry:
1975+
precision: 7
1976+
1977+
- algorithm: qgis:orthogonalize
1978+
name: Orthogonalize lines
1979+
params:
1980+
INPUT:
1981+
name: custom/lines_to_orth.gml
1982+
type: vector
1983+
results:
1984+
OUTPUT:
1985+
name: expected/orthagonal_lines.gml
1986+
type: vector
1987+
compare:
1988+
geometry:
1989+
precision: 7
19761990

19771991

19781992
- algorithm: native:reprojectlayer

‎src/core/geometry/qgsinternalgeometryengine.cpp

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -155,25 +155,10 @@ Cell *getCentroidCell( const QgsPolygonV2 *polygon )
155155
return new Cell( x / area, y / area, 0.0, polygon );
156156
}
157157

158-
///@endcond
159-
160-
QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision, double *distanceFromBoundary ) const
158+
QgsPoint surfacePoleOfInaccessibility( const QgsSurface *surface, double precision, double &distanceFromBoundary )
161159
{
162-
if ( distanceFromBoundary )
163-
*distanceFromBoundary = DBL_MAX;
164-
165-
if ( !mGeometry || mGeometry->isEmpty() )
166-
return QgsGeometry();
167-
168-
if ( precision <= 0 )
169-
return QgsGeometry();
170-
171-
const QgsSurface *surface = dynamic_cast< const QgsSurface * >( mGeometry );
172-
if ( !surface )
173-
return QgsGeometry();
174-
175160
std::unique_ptr< QgsPolygonV2 > segmentizedPoly;
176-
const QgsPolygonV2 *polygon = dynamic_cast< const QgsPolygonV2 * >( mGeometry );
161+
const QgsPolygonV2 *polygon = dynamic_cast< const QgsPolygonV2 * >( surface );
177162
if ( !polygon )
178163
{
179164
segmentizedPoly.reset( static_cast< QgsPolygonV2 *>( surface->segmentize() ) );
@@ -187,7 +172,7 @@ QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision,
187172
double cellSize = qMin( bounds.width(), bounds.height() );
188173

189174
if ( qgsDoubleNear( cellSize, 0.0 ) )
190-
return QgsGeometry( new QgsPoint( bounds.xMinimum(), bounds.yMinimum() ) );
175+
return QgsPoint( bounds.xMinimum(), bounds.yMinimum() );
191176

192177
double h = cellSize / 2.0;
193178
std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
@@ -238,15 +223,70 @@ QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision,
238223
cellQueue.push( new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
239224
}
240225

226+
distanceFromBoundary = bestCell->d;
227+
228+
return QgsPoint( bestCell->x, bestCell->y );
229+
}
230+
231+
///@endcond
232+
233+
QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision, double *distanceFromBoundary ) const
234+
{
241235
if ( distanceFromBoundary )
242-
*distanceFromBoundary = bestCell->d;
236+
*distanceFromBoundary = DBL_MAX;
243237

244-
return QgsGeometry( new QgsPoint( bestCell->x, bestCell->y ) );
238+
if ( !mGeometry || mGeometry->isEmpty() )
239+
return QgsGeometry();
240+
241+
if ( precision <= 0 )
242+
return QgsGeometry();
243+
244+
if ( const QgsGeometryCollection *gc = dynamic_cast< const QgsGeometryCollection *>( mGeometry ) )
245+
{
246+
int numGeom = gc->numGeometries();
247+
double maxDist = 0;
248+
QgsPoint bestPoint;
249+
bool found = false;
250+
for ( int i = 0; i < numGeom; ++i )
251+
{
252+
const QgsSurface *surface = dynamic_cast< const QgsSurface * >( gc->geometryN( i ) );
253+
if ( !surface )
254+
continue;
255+
256+
found = true;
257+
double dist = DBL_MAX;
258+
QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
259+
if ( dist > maxDist )
260+
{
261+
maxDist = dist;
262+
bestPoint = p;
263+
}
264+
}
265+
266+
if ( !found )
267+
return QgsGeometry();
268+
269+
if ( distanceFromBoundary )
270+
*distanceFromBoundary = maxDist;
271+
return QgsGeometry( new QgsPoint( bestPoint ) );
272+
}
273+
else
274+
{
275+
const QgsSurface *surface = dynamic_cast< const QgsSurface * >( mGeometry );
276+
if ( !surface )
277+
return QgsGeometry();
278+
279+
double dist = DBL_MAX;
280+
QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
281+
if ( distanceFromBoundary )
282+
*distanceFromBoundary = dist;
283+
return QgsGeometry( new QgsPoint( p ) );
284+
}
245285
}
246286

247287

248288
// helpers for orthogonalize
249-
// adapted from original code in potlach/id osm editor
289+
// adapted from original code in potlatch/id osm editor
250290

251291
bool dotProductWithinAngleTolerance( double dotProduct, double lowerThreshold, double upperThreshold )
252292
{

‎tests/src/core/testqgsgeometry.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5451,6 +5451,13 @@ void TestQgsGeometry::poleOfInaccessibility()
54515451
point = curved.poleOfInaccessibility( 0.01 ).asPoint();
54525452
QGSCOMPARENEAR( point.x(), -0.4324, 0.0001 );
54535453
QGSCOMPARENEAR( point.y(), -0.2434, 0.0001 );
5454+
5455+
// multipolygon
5456+
QgsGeometry multiPoly = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0)),((30 30, 50 30, 50 60, 30 60, 30 30)))" ) );
5457+
point = multiPoly.poleOfInaccessibility( 0.01, &distance ).asPoint();
5458+
QGSCOMPARENEAR( point.x(), 40, 0.0001 );
5459+
QGSCOMPARENEAR( point.y(), 45, 0.0001 );
5460+
QGSCOMPARENEAR( distance, 10.0, 0.00001 );
54545461
}
54555462

54565463
void TestQgsGeometry::makeValid()

0 commit comments

Comments
 (0)
Please sign in to comment.