Skip to content
Permalink
Browse files

Merge pull request #4684 from nyalldawson/processing_pt3

Add sourceExtent method to QgsFeatureSource
  • Loading branch information
nyalldawson committed Jun 6, 2017
2 parents 39b5f4e + 448f019 commit de9e70e6ba05895b292a089436d6e11401b40d58
@@ -78,6 +78,14 @@ class QgsFeatureSource
:rtype: set of QVariant
%End

virtual QgsRectangle sourceExtent() const;
%Docstring
Returns the extent of all geometries from the source.
The base class implementation uses a non-optimised approach of looping through
all features in the source.
:rtype: QgsRectangle
%End

};


@@ -126,6 +126,8 @@ Bitmask of all provider's editing capabilities

virtual QgsCoordinateReferenceSystem sourceCrs() const;

virtual QgsRectangle sourceExtent() const;


virtual QString dataComment() const;
%Docstring
@@ -1103,10 +1103,8 @@ Synchronises with changes in the datasource

virtual QgsRectangle extent() const;

%Docstring
Return the extent of the layer
:rtype: QgsRectangle
%End
virtual QgsRectangle sourceExtent() const;


virtual QgsFields fields() const;
%Docstring
@@ -36,6 +36,11 @@
QgsFeature,
QgsWkbTypes,
QgsProcessingUtils,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputVectorLayer,
QgsProcessingParameterBoolean,
QgsProcessingParameterDefinition,
QgsFields)

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
@@ -65,12 +70,13 @@ def group(self):

def __init__(self):
super().__init__()
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer')))
self.addParameter(ParameterBoolean(self.BY_FEATURE,
self.tr('Calculate extent for each feature separately'), False))

self.addOutput(OutputVector(self.OUTPUT, self.tr('Extent'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER, self.tr('Input layer')))
self.addParameter(QgsProcessingParameterBoolean(self.BY_FEATURE,
self.tr('Calculate extent for each feature separately'), False))

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extent')))
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Extent"), QgsProcessingParameterDefinition.TypeVectorPolygon))

def name(self):
return 'polygonfromlayerextent'
@@ -79,8 +85,8 @@ def displayName(self):
return self.tr('Polygon from layer extent')

def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
byFeature = self.getParameterValue(self.BY_FEATURE)
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
byFeature = self.parameterAsBool(parameters, self.BY_FEATURE, context)

fields = QgsFields()
fields.append(QgsField('MINX', QVariant.Double))
@@ -94,17 +100,19 @@ def processAlgorithm(self, parameters, context, feedback):
fields.append(QgsField('HEIGHT', QVariant.Double))
fields.append(QgsField('WIDTH', QVariant.Double))

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs(), context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.Polygon, source.sourceCrs())

if byFeature:
self.featureExtent(layer, context, writer, feedback)
self.featureExtent(source, context, sink, feedback)
else:
self.layerExtent(layer, writer, feedback)
self.layerExtent(source, sink, feedback)

del writer
return {self.OUTPUT: dest_id}

def layerExtent(self, layer, writer, feedback):
rect = layer.extent()
def layerExtent(self, source, sink, feedback):
rect = source.sourceExtent()
geometry = QgsGeometry.fromRect(rect)
minx = rect.xMinimum()
miny = rect.yMinimum()
maxx = rect.xMaximum()
@@ -116,9 +124,6 @@ def layerExtent(self, layer, writer, feedback):
area = width * height
perim = 2 * width + 2 * height

rect = [QgsPointXY(minx, miny), QgsPointXY(minx, maxy), QgsPointXY(maxx,
maxy), QgsPointXY(maxx, miny), QgsPointXY(minx, miny)]
geometry = QgsGeometry().fromPolygon([rect])
feat = QgsFeature()
feat.setGeometry(geometry)
attrs = [
@@ -134,13 +139,16 @@ def layerExtent(self, layer, writer, feedback):
width,
]
feat.setAttributes(attrs)
writer.addFeature(feat)
sink.addFeature(feat)

def featureExtent(self, layer, context, writer, feedback):
features = QgsProcessingUtils.getFeatures(layer, context)
total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
def featureExtent(self, source, context, sink, feedback):
features = source.getFeatures()
total = 100.0 / source.featureCount()
feat = QgsFeature()
for current, f in enumerate(features):
if feedback.isCanceled():
break

rect = f.geometry().boundingBox()
minx = rect.xMinimum()
miny = rect.yMinimum()
@@ -171,5 +179,5 @@ def featureExtent(self, layer, context, writer, feedback):
]
feat.setAttributes(attrs)

writer.addFeature(feat)
sink.addFeature(feat)
feedback.setProgress(int(current * total))
@@ -79,7 +79,7 @@
# from .Difference import Difference
# from .Dissolve import Dissolve
# from .Intersection import Intersection
# from .ExtentFromLayer import ExtentFromLayer
from .ExtentFromLayer import ExtentFromLayer
# from .RandomSelection import RandomSelection
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
# from .SelectByLocation import SelectByLocation
@@ -210,7 +210,7 @@ def getAlgs(self):
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
# ConvexHull(), FixedDistanceBuffer(),
# VariableDistanceBuffer(), Dissolve(), Difference(),
# Intersection(), Union(), ExtentFromLayer(),
# Intersection(), Union(),
# RandomSelection(), RandomSelectionWithinSubsets(),
# SelectByLocation(), RandomExtract(), DeleteHoles(),
# RandomExtractWithinSubsets(), ExtractByLocation(),
@@ -265,7 +265,8 @@ def getAlgs(self):
Boundary(),
BoundingBox(),
Clip(),
DeleteColumn()
DeleteColumn(),
ExtentFromLayer()
]

if hasPlotly:
@@ -13,7 +13,7 @@

<gml:featureMember>
<ogr:polygon_from_extent fid="polygon_from_extent.0">
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-3 -1,6 10,6 10,-3 -1,-3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-3 10,-3 10,6 -1,6 -1,-3</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:MINX>-1</ogr:MINX>
<ogr:MINY>-3</ogr:MINY>
<ogr:MAXX>10</ogr:MAXX>
@@ -2342,18 +2342,18 @@ tests:
# name: expected/find_projection.html
# type: file
#
# - algorithm: qgis:polygonfromlayerextent
# name: Standard polygon from layer extent
# params:
# BY_FEATURE: false
# INPUT_LAYER:
# name: polys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/polygon_from_extent.gml
# type: vector
#
- algorithm: qgis:polygonfromlayerextent
name: Standard polygon from layer extent
params:
BY_FEATURE: false
INPUT_LAYER:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/polygon_from_extent.gml
type: vector

# - algorithm: qgis:topologicalcoloring
# name: Topological coloring
# params:
@@ -40,3 +40,20 @@ QSet<QVariant> QgsFeatureSource::uniqueValues( int fieldIndex, int limit ) const
return values;
}

QgsRectangle QgsFeatureSource::sourceExtent() const
{
QgsRectangle r;

QgsFeatureRequest req;
req.setSubsetOfAttributes( QgsAttributeList() );

QgsFeatureIterator it = getFeatures( req );
QgsFeature f;
while ( it.nextFeature( f ) )
{
if ( f.hasGeometry() )
r.combineExtentWith( f.geometry().boundingBox() );
}
return r;
}

@@ -87,6 +87,13 @@ class CORE_EXPORT QgsFeatureSource
*/
virtual QSet<QVariant> uniqueValues( int fieldIndex, int limit = -1 ) const;

/**
* Returns the extent of all geometries from the source.
* The base class implementation uses a non-optimised approach of looping through
* all features in the source.
*/
virtual QgsRectangle sourceExtent() const;

};

Q_DECLARE_METATYPE( QgsFeatureSource * )
@@ -52,6 +52,11 @@ QgsCoordinateReferenceSystem QgsVectorDataProvider::sourceCrs() const
return crs();
}

QgsRectangle QgsVectorDataProvider::sourceExtent() const
{
return extent();
}

QString QgsVectorDataProvider::dataComment() const
{
return QString();
@@ -159,6 +159,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider, public QgsFeat
virtual QgsFields fields() const override = 0;

QgsCoordinateReferenceSystem sourceCrs() const override;
QgsRectangle sourceExtent() const override;

/**
* Return a short comment for the data that this provider is
@@ -879,6 +879,11 @@ QgsRectangle QgsVectorLayer::extent() const
return rect;
}

QgsRectangle QgsVectorLayer::sourceExtent() const
{
return extent();
}

QString QgsVectorLayer::subsetString() const
{
if ( !mValid || !mDataProvider )
@@ -1077,8 +1077,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;

//! Return the extent of the layer
QgsRectangle extent() const override;
QgsRectangle sourceExtent() const override;

/**
* Returns the list of fields of this layer.

0 comments on commit de9e70e

Please sign in to comment.
You can’t perform that action at this time.