mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -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
|
:rtype: set of QVariant
|
||||||
%End
|
%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 QgsCoordinateReferenceSystem sourceCrs() const;
|
||||||
|
|
||||||
|
virtual QgsRectangle sourceExtent() const;
|
||||||
|
|
||||||
|
|
||||||
virtual QString dataComment() const;
|
virtual QString dataComment() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
|
@ -1103,10 +1103,8 @@ Synchronises with changes in the datasource
|
|||||||
|
|
||||||
virtual QgsRectangle extent() const;
|
virtual QgsRectangle extent() const;
|
||||||
|
|
||||||
%Docstring
|
virtual QgsRectangle sourceExtent() const;
|
||||||
Return the extent of the layer
|
|
||||||
:rtype: QgsRectangle
|
|
||||||
%End
|
|
||||||
|
|
||||||
virtual QgsFields fields() const;
|
virtual QgsFields fields() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
|
@ -36,6 +36,11 @@ from qgis.core import (QgsField,
|
|||||||
QgsFeature,
|
QgsFeature,
|
||||||
QgsWkbTypes,
|
QgsWkbTypes,
|
||||||
QgsProcessingUtils,
|
QgsProcessingUtils,
|
||||||
|
QgsProcessingParameterFeatureSource,
|
||||||
|
QgsProcessingParameterFeatureSink,
|
||||||
|
QgsProcessingOutputVectorLayer,
|
||||||
|
QgsProcessingParameterBoolean,
|
||||||
|
QgsProcessingParameterDefinition,
|
||||||
QgsFields)
|
QgsFields)
|
||||||
|
|
||||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||||
@ -65,12 +70,13 @@ class ExtentFromLayer(QgisAlgorithm):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.addParameter(ParameterVector(self.INPUT_LAYER,
|
|
||||||
self.tr('Input layer')))
|
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER, self.tr('Input layer')))
|
||||||
self.addParameter(ParameterBoolean(self.BY_FEATURE,
|
self.addParameter(QgsProcessingParameterBoolean(self.BY_FEATURE,
|
||||||
self.tr('Calculate extent for each feature separately'), False))
|
self.tr('Calculate extent for each feature separately'), False))
|
||||||
|
|
||||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Extent'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
|
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extent')))
|
||||||
|
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Extent"), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return 'polygonfromlayerextent'
|
return 'polygonfromlayerextent'
|
||||||
@ -79,8 +85,8 @@ class ExtentFromLayer(QgisAlgorithm):
|
|||||||
return self.tr('Polygon from layer extent')
|
return self.tr('Polygon from layer extent')
|
||||||
|
|
||||||
def processAlgorithm(self, parameters, context, feedback):
|
def processAlgorithm(self, parameters, context, feedback):
|
||||||
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
|
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||||
byFeature = self.getParameterValue(self.BY_FEATURE)
|
byFeature = self.parameterAsBool(parameters, self.BY_FEATURE, context)
|
||||||
|
|
||||||
fields = QgsFields()
|
fields = QgsFields()
|
||||||
fields.append(QgsField('MINX', QVariant.Double))
|
fields.append(QgsField('MINX', QVariant.Double))
|
||||||
@ -94,17 +100,19 @@ class ExtentFromLayer(QgisAlgorithm):
|
|||||||
fields.append(QgsField('HEIGHT', QVariant.Double))
|
fields.append(QgsField('HEIGHT', QVariant.Double))
|
||||||
fields.append(QgsField('WIDTH', 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:
|
if byFeature:
|
||||||
self.featureExtent(layer, context, writer, feedback)
|
self.featureExtent(source, context, sink, feedback)
|
||||||
else:
|
else:
|
||||||
self.layerExtent(layer, writer, feedback)
|
self.layerExtent(source, sink, feedback)
|
||||||
|
|
||||||
del writer
|
return {self.OUTPUT: dest_id}
|
||||||
|
|
||||||
def layerExtent(self, layer, writer, feedback):
|
def layerExtent(self, source, sink, feedback):
|
||||||
rect = layer.extent()
|
rect = source.sourceExtent()
|
||||||
|
geometry = QgsGeometry.fromRect(rect)
|
||||||
minx = rect.xMinimum()
|
minx = rect.xMinimum()
|
||||||
miny = rect.yMinimum()
|
miny = rect.yMinimum()
|
||||||
maxx = rect.xMaximum()
|
maxx = rect.xMaximum()
|
||||||
@ -116,9 +124,6 @@ class ExtentFromLayer(QgisAlgorithm):
|
|||||||
area = width * height
|
area = width * height
|
||||||
perim = 2 * width + 2 * 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 = QgsFeature()
|
||||||
feat.setGeometry(geometry)
|
feat.setGeometry(geometry)
|
||||||
attrs = [
|
attrs = [
|
||||||
@ -134,13 +139,16 @@ class ExtentFromLayer(QgisAlgorithm):
|
|||||||
width,
|
width,
|
||||||
]
|
]
|
||||||
feat.setAttributes(attrs)
|
feat.setAttributes(attrs)
|
||||||
writer.addFeature(feat)
|
sink.addFeature(feat)
|
||||||
|
|
||||||
def featureExtent(self, layer, context, writer, feedback):
|
def featureExtent(self, source, context, sink, feedback):
|
||||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
features = source.getFeatures()
|
||||||
total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
|
total = 100.0 / source.featureCount()
|
||||||
feat = QgsFeature()
|
feat = QgsFeature()
|
||||||
for current, f in enumerate(features):
|
for current, f in enumerate(features):
|
||||||
|
if feedback.isCanceled():
|
||||||
|
break
|
||||||
|
|
||||||
rect = f.geometry().boundingBox()
|
rect = f.geometry().boundingBox()
|
||||||
minx = rect.xMinimum()
|
minx = rect.xMinimum()
|
||||||
miny = rect.yMinimum()
|
miny = rect.yMinimum()
|
||||||
@ -171,5 +179,5 @@ class ExtentFromLayer(QgisAlgorithm):
|
|||||||
]
|
]
|
||||||
feat.setAttributes(attrs)
|
feat.setAttributes(attrs)
|
||||||
|
|
||||||
writer.addFeature(feat)
|
sink.addFeature(feat)
|
||||||
feedback.setProgress(int(current * total))
|
feedback.setProgress(int(current * total))
|
||||||
|
@ -79,7 +79,7 @@ from .Clip import Clip
|
|||||||
# from .Difference import Difference
|
# from .Difference import Difference
|
||||||
# from .Dissolve import Dissolve
|
# from .Dissolve import Dissolve
|
||||||
# from .Intersection import Intersection
|
# from .Intersection import Intersection
|
||||||
# from .ExtentFromLayer import ExtentFromLayer
|
from .ExtentFromLayer import ExtentFromLayer
|
||||||
# from .RandomSelection import RandomSelection
|
# from .RandomSelection import RandomSelection
|
||||||
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
|
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
|
||||||
# from .SelectByLocation import SelectByLocation
|
# from .SelectByLocation import SelectByLocation
|
||||||
@ -210,7 +210,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
|||||||
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
|
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
|
||||||
# ConvexHull(), FixedDistanceBuffer(),
|
# ConvexHull(), FixedDistanceBuffer(),
|
||||||
# VariableDistanceBuffer(), Dissolve(), Difference(),
|
# VariableDistanceBuffer(), Dissolve(), Difference(),
|
||||||
# Intersection(), Union(), ExtentFromLayer(),
|
# Intersection(), Union(),
|
||||||
# RandomSelection(), RandomSelectionWithinSubsets(),
|
# RandomSelection(), RandomSelectionWithinSubsets(),
|
||||||
# SelectByLocation(), RandomExtract(), DeleteHoles(),
|
# SelectByLocation(), RandomExtract(), DeleteHoles(),
|
||||||
# RandomExtractWithinSubsets(), ExtractByLocation(),
|
# RandomExtractWithinSubsets(), ExtractByLocation(),
|
||||||
@ -265,7 +265,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
|||||||
Boundary(),
|
Boundary(),
|
||||||
BoundingBox(),
|
BoundingBox(),
|
||||||
Clip(),
|
Clip(),
|
||||||
DeleteColumn()
|
DeleteColumn(),
|
||||||
|
ExtentFromLayer()
|
||||||
]
|
]
|
||||||
|
|
||||||
if hasPlotly:
|
if hasPlotly:
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<gml:featureMember>
|
<gml:featureMember>
|
||||||
<ogr:polygon_from_extent fid="polygon_from_extent.0">
|
<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:MINX>-1</ogr:MINX>
|
||||||
<ogr:MINY>-3</ogr:MINY>
|
<ogr:MINY>-3</ogr:MINY>
|
||||||
<ogr:MAXX>10</ogr:MAXX>
|
<ogr:MAXX>10</ogr:MAXX>
|
||||||
|
@ -2342,18 +2342,18 @@ tests:
|
|||||||
# name: expected/find_projection.html
|
# name: expected/find_projection.html
|
||||||
# type: file
|
# type: file
|
||||||
#
|
#
|
||||||
# - algorithm: qgis:polygonfromlayerextent
|
- algorithm: qgis:polygonfromlayerextent
|
||||||
# name: Standard polygon from layer extent
|
name: Standard polygon from layer extent
|
||||||
# params:
|
params:
|
||||||
# BY_FEATURE: false
|
BY_FEATURE: false
|
||||||
# INPUT_LAYER:
|
INPUT_LAYER:
|
||||||
# name: polys.gml
|
name: polys.gml
|
||||||
# type: vector
|
type: vector
|
||||||
# results:
|
results:
|
||||||
# OUTPUT:
|
OUTPUT:
|
||||||
# name: expected/polygon_from_extent.gml
|
name: expected/polygon_from_extent.gml
|
||||||
# type: vector
|
type: vector
|
||||||
#
|
|
||||||
# - algorithm: qgis:topologicalcoloring
|
# - algorithm: qgis:topologicalcoloring
|
||||||
# name: Topological coloring
|
# name: Topological coloring
|
||||||
# params:
|
# params:
|
||||||
|
@ -40,3 +40,20 @@ QSet<QVariant> QgsFeatureSource::uniqueValues( int fieldIndex, int limit ) const
|
|||||||
return values;
|
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;
|
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 * )
|
Q_DECLARE_METATYPE( QgsFeatureSource * )
|
||||||
|
@ -52,6 +52,11 @@ QgsCoordinateReferenceSystem QgsVectorDataProvider::sourceCrs() const
|
|||||||
return crs();
|
return crs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsRectangle QgsVectorDataProvider::sourceExtent() const
|
||||||
|
{
|
||||||
|
return extent();
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsVectorDataProvider::dataComment() const
|
QString QgsVectorDataProvider::dataComment() const
|
||||||
{
|
{
|
||||||
return QString();
|
return QString();
|
||||||
|
@ -159,6 +159,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider, public QgsFeat
|
|||||||
virtual QgsFields fields() const override = 0;
|
virtual QgsFields fields() const override = 0;
|
||||||
|
|
||||||
QgsCoordinateReferenceSystem sourceCrs() const override;
|
QgsCoordinateReferenceSystem sourceCrs() const override;
|
||||||
|
QgsRectangle sourceExtent() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a short comment for the data that this provider is
|
* Return a short comment for the data that this provider is
|
||||||
|
@ -879,6 +879,11 @@ QgsRectangle QgsVectorLayer::extent() const
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsRectangle QgsVectorLayer::sourceExtent() const
|
||||||
|
{
|
||||||
|
return extent();
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsVectorLayer::subsetString() const
|
QString QgsVectorLayer::subsetString() const
|
||||||
{
|
{
|
||||||
if ( !mValid || !mDataProvider )
|
if ( !mValid || !mDataProvider )
|
||||||
|
@ -1077,8 +1077,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
|||||||
*/
|
*/
|
||||||
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
|
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
|
||||||
|
|
||||||
//! Return the extent of the layer
|
|
||||||
QgsRectangle extent() const override;
|
QgsRectangle extent() const override;
|
||||||
|
QgsRectangle sourceExtent() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of fields of this layer.
|
* Returns the list of fields of this layer.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user