QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsalgorithmextractlayoutmapextent.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmextractlayoutmapextent.cpp
3  ---------------------
4  begin : March 2019
5  copyright : (C) 2019 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
21 #include "layout/qgslayout.h"
22 #include "layout/qgsprintlayout.h"
23 #include "qgsprocessingoutputs.h"
24 
26 
27 QString QgsLayoutMapExtentToLayerAlgorithm::name() const
28 {
29  return QStringLiteral( "printlayoutmapextenttolayer" );
30 }
31 
32 QString QgsLayoutMapExtentToLayerAlgorithm::displayName() const
33 {
34  return QObject::tr( "Print layout map extent to layer" );
35 }
36 
37 QStringList QgsLayoutMapExtentToLayerAlgorithm::tags() const
38 {
39  return QObject::tr( "layout,composer,composition,visible" ).split( ',' );
40 }
41 
42 QString QgsLayoutMapExtentToLayerAlgorithm::group() const
43 {
44  return QObject::tr( "Cartography" );
45 }
46 
47 QString QgsLayoutMapExtentToLayerAlgorithm::groupId() const
48 {
49  return QStringLiteral( "cartography" );
50 }
51 
52 QString QgsLayoutMapExtentToLayerAlgorithm::shortDescription() const
53 {
54  return QObject::tr( "Creates a polygon layer containing the extent of a print layout map item." );
55 }
56 
57 void QgsLayoutMapExtentToLayerAlgorithm::initAlgorithm( const QVariantMap & )
58 {
59  addParameter( new QgsProcessingParameterLayout( QStringLiteral( "LAYOUT" ), QObject::tr( "Print layout" ) ) );
60  addParameter( new QgsProcessingParameterLayoutItem( QStringLiteral( "MAP" ), QObject::tr( "Map item" ), QVariant(), QStringLiteral( "LAYOUT" ), QgsLayoutItemRegistry::LayoutMap, true ) );
61  auto crsParam = std::make_unique< QgsProcessingParameterCrs >( QStringLiteral( "CRS" ), QObject::tr( "Override CRS" ), QVariant(), true );
62  crsParam->setFlags( crsParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
63  addParameter( crsParam.release() );
64  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Extent" ), QgsProcessing::TypeVectorPolygon ) );
65  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "WIDTH" ), QObject::tr( "Map width" ) ) );
66  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "HEIGHT" ), QObject::tr( "Map height" ) ) );
67  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "SCALE" ), QObject::tr( "Map scale" ) ) );
68  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "ROTATION" ), QObject::tr( "Map rotation" ) ) );
69 }
70 
71 QString QgsLayoutMapExtentToLayerAlgorithm::shortHelpString() const
72 {
73  return QObject::tr( "This algorithm creates a polygon layer containing the extent of a print layout map item (or items), "
74  "with attributes specifying the map size (in layout units), scale and rotation.\n\n"
75  "If the map item parameter is specified, then only the matching map extent will be exported. If it "
76  "is not specified, all map extents from the layout will be exported.\n\n"
77  "Optionally, a specific output CRS can be specified. If it is not specified, the original map "
78  "item CRS will be used." );
79 }
80 
81 QgsLayoutMapExtentToLayerAlgorithm *QgsLayoutMapExtentToLayerAlgorithm::createInstance() const
82 {
83  return new QgsLayoutMapExtentToLayerAlgorithm();
84 }
85 
86 bool QgsLayoutMapExtentToLayerAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
87 {
88  // this needs to be done in main thread, layouts are not thread safe
89  QgsPrintLayout *layout = parameterAsLayout( parameters, QStringLiteral( "LAYOUT" ), context );
90  if ( !layout )
91  throw QgsProcessingException( QObject::tr( "Cannot find layout with name \"%1\"" ).arg( parameters.value( QStringLiteral( "LAYOUT" ) ).toString() ) );
92 
93  QgsLayoutItemMap *map = qobject_cast< QgsLayoutItemMap * >( parameterAsLayoutItem( parameters, QStringLiteral( "MAP" ), context, layout ) );
94  if ( !map && parameters.value( QStringLiteral( "MAP" ) ).isValid() )
95  throw QgsProcessingException( QObject::tr( "Cannot find matching map item with ID %1" ).arg( parameters.value( QStringLiteral( "MAP" ) ).toString() ) );
96 
97  QList< QgsLayoutItemMap *> maps;
98  if ( map )
99  maps << map;
100  else
101  layout->layoutItems( maps );
102 
103  const QgsCoordinateReferenceSystem overrideCrs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
104 
105  mFeatures.reserve( maps.size() );
106  for ( QgsLayoutItemMap *map : maps )
107  {
108  if ( !mCrs.isValid() )
109  mCrs = !overrideCrs.isValid() ? map->crs() : overrideCrs;
110 
111  QgsGeometry extent = QgsGeometry::fromQPolygonF( map->visibleExtentPolygon() );
112  if ( map->crs() != mCrs )
113  {
114  try
115  {
116  extent.transform( QgsCoordinateTransform( map->crs(), mCrs, context.transformContext() ) );
117  }
118  catch ( QgsCsException & )
119  {
120  feedback->reportError( QObject::tr( "Error reprojecting map to destination CRS" ) );
121  continue;
122  }
123  }
124 
125  mWidth = map->rect().width();
126  mHeight = map->rect().height();
127  mScale = map->scale();
128  mRotation = map->mapRotation();
129 
130  QgsFeature f;
131  f.setAttributes( QgsAttributes() << map->displayName() << mWidth << mHeight << mScale << mRotation );
132  f.setGeometry( extent );
133 
134  mFeatures << f;
135  }
136  return true;
137 }
138 
139 QVariantMap QgsLayoutMapExtentToLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
140 {
141  QgsFields fields;
142  fields.append( QgsField( QStringLiteral( "map" ), QVariant::String ) );
143  fields.append( QgsField( QStringLiteral( "width" ), QVariant::Double ) );
144  fields.append( QgsField( QStringLiteral( "height" ), QVariant::Double ) );
145  fields.append( QgsField( QStringLiteral( "scale" ), QVariant::Double ) );
146  fields.append( QgsField( QStringLiteral( "rotation" ), QVariant::Double ) );
147 
148  QString dest;
149  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Polygon, mCrs ) );
150  if ( !sink )
151  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
152 
153  for ( QgsFeature &f : mFeatures )
154  {
155  if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
156  throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
157  }
158 
159  feedback->setProgress( 100 );
160 
161  QVariantMap outputs;
162  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
163  // these numeric outputs only have value for single-map layouts
164  outputs.insert( QStringLiteral( "WIDTH" ), mFeatures.size() == 1 ? mWidth : QVariant() );
165  outputs.insert( QStringLiteral( "HEIGHT" ), mFeatures.size() == 1 ? mHeight : QVariant() );
166  outputs.insert( QStringLiteral( "SCALE" ), mFeatures.size() == 1 ? mScale : QVariant() );
167  outputs.insert( QStringLiteral( "ROTATION" ), mFeatures.size() == 1 ? mRotation : QVariant() );
168  return outputs;
169 }
170 
172 
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:76
QgsLayout::layoutItems
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:122
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:37
QgsGeometry::transform
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:3128
QgsProcessingFeedback::reportError
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Definition: qgsprocessingfeedback.cpp:59
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsProcessingParameterDefinition::FlagAdvanced
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition: qgsprocessingparameters.h:451
QgsFields::append
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
QgsProcessingOutputNumber
A numeric output for processing algorithms.
Definition: qgsprocessingoutputs.h:312
QgsProcessingParameterFeatureSink
A feature sink output for processing algorithms.
Definition: qgsprocessingparameters.h:3219
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsPrintLayout
Print layout, a QgsLayout subclass for static or atlas-based layouts.
Definition: qgsprintlayout.h:30
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:46
QgsProcessingParameterLayoutItem
A print layout item parameter, allowing users to select a particular item from a print layout.
Definition: qgsprocessingparameters.h:3661
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:977
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:165
qgslayout.h
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsProcessingParameterLayout
A print layout parameter, allowing users to select a print layout.
Definition: qgsprocessingparameters.h:3623
qgsalgorithmextractlayoutmapextent.h
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
qgsprocessingoutputs.h
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
qgsprintlayout.h
QgsLayoutItemRegistry::LayoutMap
@ LayoutMap
Map item.
Definition: qgslayoutitemregistry.h:347
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsGeometry::fromQPolygonF
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Definition: qgsgeometry.cpp:3408
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
qgslayoutitemregistry.h
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
QgsFeatureSink::FastInsert
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Definition: qgsfeaturesink.h:70
qgslayoutitemmap.h
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50