QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsmaplayerutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaplayerutils.cpp
3  -------------------
4  begin : May 2021
5  copyright : (C) 2021 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 
18 #include "qgsmaplayerutils.h"
19 #include "qgsrectangle.h"
22 #include "qgsreferencedgeometry.h"
23 #include "qgslogger.h"
24 #include "qgsmaplayer.h"
25 
26 QgsRectangle QgsMapLayerUtils::combinedExtent( const QList<QgsMapLayer *> &layers, const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transformContext )
27 {
28  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
29  QgsRectangle fullExtent;
30  fullExtent.setMinimal();
31 
32  // iterate through the map layers and test each layers extent
33  // against the current min and max values
34  QgsDebugMsgLevel( QStringLiteral( "Layer count: %1" ).arg( layers.count() ), 5 );
35  for ( const QgsMapLayer *layer : layers )
36  {
37  QgsDebugMsgLevel( "Updating extent using " + layer->name(), 5 );
38  QgsDebugMsgLevel( "Input extent: " + layer->extent().toString(), 5 );
39 
40  if ( layer->extent().isNull() )
41  continue;
42 
43  // Layer extents are stored in the coordinate system (CS) of the
44  // layer. The extent must be projected to the canvas CS
45  QgsCoordinateTransform ct( layer->crs(), crs, transformContext );
47  try
48  {
49  const QgsRectangle extent = ct.transformBoundingBox( layer->extent() );
50 
51  QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 );
52  fullExtent.combineExtentWith( extent );
53  }
54  catch ( QgsCsException & )
55  {
56  QgsDebugMsg( QStringLiteral( "Could not reproject layer extent" ) );
57  }
58  }
59 
60  if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 )
61  {
62  // If all of the features are at the one point, buffer the
63  // rectangle a bit. If they are all at zero, do something a bit
64  // more crude.
65 
66  if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 &&
67  fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 )
68  {
69  fullExtent.set( -1.0, -1.0, 1.0, 1.0 );
70  }
71  else
72  {
73  const double padFactor = 1e-8;
74  double widthPad = fullExtent.xMinimum() * padFactor;
75  double heightPad = fullExtent.yMinimum() * padFactor;
76  double xmin = fullExtent.xMinimum() - widthPad;
77  double xmax = fullExtent.xMaximum() + widthPad;
78  double ymin = fullExtent.yMinimum() - heightPad;
79  double ymax = fullExtent.yMaximum() + heightPad;
80  fullExtent.set( xmin, ymin, xmax, ymax );
81  }
82  }
83 
84  QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 );
85  return fullExtent;
86 }
This class represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
static QgsRectangle combinedExtent(const QList< QgsMapLayer * > &layers, const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transformContext)
Returns the combined extent of a list of layers.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void set(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Sets the rectangle from two QgsPoints.
Definition: qgsrectangle.h:122
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs