mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Merge pull request #4684 from nyalldawson/processing_pt3
Add sourceExtent method to QgsFeatureSource
This commit is contained in:
commit
de9e70e6ba
@ -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 @@ from qgis.core import (QgsField,
|
||||
QgsFeature,
|
||||
QgsWkbTypes,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingOutputVectorLayer,
|
||||
QgsProcessingParameterBoolean,
|
||||
QgsProcessingParameterDefinition,
|
||||
QgsFields)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
@ -65,12 +70,13 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
|
||||
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 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
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 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
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 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
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 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
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 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
]
|
||||
feat.setAttributes(attrs)
|
||||
|
||||
writer.addFeature(feat)
|
||||
sink.addFeature(feat)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
@ -79,7 +79,7 @@ from .Clip import Clip
|
||||
# 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 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
|
||||
# ConvexHull(), FixedDistanceBuffer(),
|
||||
# VariableDistanceBuffer(), Dissolve(), Difference(),
|
||||
# Intersection(), Union(), ExtentFromLayer(),
|
||||
# Intersection(), Union(),
|
||||
# RandomSelection(), RandomSelectionWithinSubsets(),
|
||||
# SelectByLocation(), RandomExtract(), DeleteHoles(),
|
||||
# RandomExtractWithinSubsets(), ExtractByLocation(),
|
||||
@ -265,7 +265,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user