QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgslayoututils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoututils.cpp
3 ------------------
4 begin : July 2017
5 copyright : (C) 2017 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
18#include "qgslayoututils.h"
19#include "qgslayout.h"
21#include "qgslayoutitemmap.h"
23#include "qgsrendercontext.h"
24#include "qgssettings.h"
26
27#include <QStyleOptionGraphicsItem>
28#include <QPainter>
29#include <cmath>
30
31#ifndef M_DEG2RAD
32#define M_DEG2RAD 0.0174532925
33#endif
34
35void QgsLayoutUtils::rotate( double angle, double &x, double &y )
36{
37 double rotToRad = angle * M_PI / 180.0;
38 double xRot, yRot;
39 xRot = x * std::cos( rotToRad ) - y * std::sin( rotToRad );
40 yRot = x * std::sin( rotToRad ) + y * std::cos( rotToRad );
41 x = xRot;
42 y = yRot;
43}
44
45double QgsLayoutUtils::normalizedAngle( const double angle, const bool allowNegative )
46{
47 double clippedAngle = angle;
48 if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
49 {
50 clippedAngle = std::fmod( clippedAngle, 360.0 );
51 }
52 if ( !allowNegative && clippedAngle < 0.0 )
53 {
54 clippedAngle += 360.0;
55 }
56 return clippedAngle;
57}
58
60{
61 //normalize angle to 0-360 degrees
62 double clippedAngle = normalizedAngle( angle );
63
64 //snap angle to 45 degree
65 if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
66 {
67 return 45.0;
68 }
69 else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
70 {
71 return 90.0;
72 }
73 else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
74 {
75 return 135.0;
76 }
77 else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
78 {
79 return 180.0;
80 }
81 else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
82 {
83 return 225.0;
84 }
85 else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
86 {
87 return 270.0;
88 }
89 else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
90 {
91 return 315.0;
92 }
93 else
94 {
95 return 0.0;
96 }
97}
98
100{
101 if ( !map )
102 {
103 QgsRenderContext context;
104 context.setPainter( painter );
105 if ( dpi < 0 && painter && painter->device() )
106 {
107 context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
108 }
109 else if ( dpi > 0 )
110 {
111 context.setScaleFactor( dpi / 25.4 );
112 }
113 else
114 {
115 context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
116 }
117 return context;
118 }
119 else
120 {
121 // default to 88 dpi if no painter specified
122 if ( dpi < 0 )
123 {
124 dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
125 }
126 double dotsPerMM = dpi / 25.4;
127
128 // get map settings from reference map
129 QgsRectangle extent = map->extent();
130 QSizeF mapSizeLayoutUnits = map->rect().size();
131 QSizeF mapSizeMM = map->layout()->convertFromLayoutUnits( mapSizeLayoutUnits, Qgis::LayoutUnit::Millimeters ).toQSizeF();
132 QgsMapSettings ms = map->mapSettings( extent, mapSizeMM * dotsPerMM, dpi, false );
134 if ( painter )
135 context.setPainter( painter );
136
137 context.setFlags( map->layout()->renderContext().renderContextFlags() );
139 return context;
140 }
141}
142
144{
145 QgsLayoutItemMap *referenceMap = layout ? layout->referenceMap() : nullptr;
146 QgsRenderContext context = createRenderContextForMap( referenceMap, painter, dpi );
147 if ( layout )
148 {
149 context.setFlags( layout->renderContext().renderContextFlags() );
151 }
152
153 return context;
154}
155
156void QgsLayoutUtils::relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter )
157{
158 //linearly scale rectToResize relative to the scaling from boundsBefore to boundsAfter
159 double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
160 double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
161 double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
162 double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
163
164 rectToResize.setRect( left, top, right - left, bottom - top );
165}
166
167double QgsLayoutUtils::relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax )
168{
169 //calculate parameters for linear scale between before and after ranges
170 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
171 double c = afterMin - ( beforeMin * m );
172
173 //return linearly scaled position
174 return m * position + c;
175}
176QFont QgsLayoutUtils::scaledFontPixelSize( const QFont &font )
177{
178 //upscale using FONT_WORKAROUND_SCALE
179 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
180 QFont scaledFont = font;
181 double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
182 scaledFont.setPixelSize( pixelSize );
183 return scaledFont;
184}
185
186double QgsLayoutUtils::fontAscentMM( const QFont &font )
187{
188 //upscale using FONT_WORKAROUND_SCALE
189 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
190 QFont metricsFont = scaledFontPixelSize( font );
191 QFontMetricsF fontMetrics( metricsFont );
192 return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
193}
194
195double QgsLayoutUtils::fontDescentMM( const QFont &font )
196{
197 //upscale using FONT_WORKAROUND_SCALE
198 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
199 QFont metricsFont = scaledFontPixelSize( font );
200 QFontMetricsF fontMetrics( metricsFont );
201 return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
202
203}
204
205double QgsLayoutUtils::fontHeightMM( const QFont &font )
206{
207 //upscale using FONT_WORKAROUND_SCALE
208 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
209 QFont metricsFont = scaledFontPixelSize( font );
210 QFontMetricsF fontMetrics( metricsFont );
211 return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
212
213}
214
215double QgsLayoutUtils::fontHeightCharacterMM( const QFont &font, QChar character )
216{
217 //upscale using FONT_WORKAROUND_SCALE
218 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
219 QFont metricsFont = scaledFontPixelSize( font );
220 QFontMetricsF fontMetrics( metricsFont );
221 return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
222}
223
224double QgsLayoutUtils::textWidthMM( const QFont &font, const QString &text )
225{
226 //upscale using FONT_WORKAROUND_SCALE
227 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
228
229 const QStringList multiLineSplit = text.split( '\n' );
230 QFont metricsFont = scaledFontPixelSize( font );
231 QFontMetricsF fontMetrics( metricsFont );
232
233 double maxWidth = 0;
234 for ( const QString &line : multiLineSplit )
235 {
236 maxWidth = std::max( maxWidth, ( fontMetrics.horizontalAdvance( line ) / FONT_WORKAROUND_SCALE ) );
237 }
238 return maxWidth;
239}
240
241double QgsLayoutUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
242{
243 QStringList multiLineSplit = text.split( '\n' );
244 int lines = multiLineSplit.size();
245
246 //upscale using FONT_WORKAROUND_SCALE
247 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
248 QFont metricsFont = scaledFontPixelSize( font );
249 QFontMetricsF fontMetrics( metricsFont );
250
251 double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
252 double textHeight = fontMetrics.ascent() + static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
253
254 return textHeight / FONT_WORKAROUND_SCALE;
255}
256
257void QgsLayoutUtils::drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color )
258{
259 if ( !painter )
260 {
261 return;
262 }
263
264 //upscale using FONT_WORKAROUND_SCALE
265 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
266 QFont textFont = scaledFontPixelSize( font );
267
268 QgsScopedQPainterState painterState( painter );
269 painter->setFont( textFont );
270 if ( color.isValid() )
271 {
272 painter->setPen( color );
273 }
274 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
275 painter->scale( scaleFactor, scaleFactor );
276 painter->drawText( position * FONT_WORKAROUND_SCALE, text );
277}
278
279void QgsLayoutUtils::drawText( QPainter *painter, const QRectF &rect, const QString &text, const QFont &font, const QColor &color, const Qt::AlignmentFlag halignment, const Qt::AlignmentFlag valignment, const int flags )
280{
281 if ( !painter )
282 {
283 return;
284 }
285
286 //upscale using FONT_WORKAROUND_SCALE
287 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
288 QFont textFont = scaledFontPixelSize( font );
289
290 QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
291 rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
292
293 QgsScopedQPainterState painterState( painter );
294 painter->setFont( textFont );
295 if ( color.isValid() )
296 {
297 painter->setPen( color );
298 }
299 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
300 painter->scale( scaleFactor, scaleFactor );
301 painter->drawText( scaledRect, halignment | valignment | flags, text );
302}
303
304QRectF QgsLayoutUtils::largestRotatedRectWithinBounds( const QRectF &originalRect, const QRectF &boundsRect, const double rotation )
305{
306 double originalWidth = originalRect.width();
307 double originalHeight = originalRect.height();
308 double boundsWidth = boundsRect.width();
309 double boundsHeight = boundsRect.height();
310 double ratioBoundsRect = boundsWidth / boundsHeight;
311
312 double clippedRotation = normalizedAngle( rotation );
313
314 //shortcut for some rotation values
315 if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 90.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) || qgsDoubleNear( clippedRotation, 270.0 ) )
316 {
317 double rectScale;
318 if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
319 {
320 rectScale = ( ( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
321 }
322 else
323 {
324 rectScale = ( ( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
325 }
326 double rectScaledWidth = rectScale * originalWidth;
327 double rectScaledHeight = rectScale * originalHeight;
328
329 if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
330 {
331 return QRectF( ( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
332 }
333 else
334 {
335 return QRectF( ( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
336 }
337 }
338
339 //convert angle to radians and flip
340 double angleRad = -clippedRotation * M_DEG2RAD;
341 double cosAngle = std::cos( angleRad );
342 double sinAngle = std::sin( angleRad );
343
344 //calculate size of bounds of rotated rectangle
345 double widthBoundsRotatedRect = originalWidth * std::fabs( cosAngle ) + originalHeight * std::fabs( sinAngle );
346 double heightBoundsRotatedRect = originalHeight * std::fabs( cosAngle ) + originalWidth * std::fabs( sinAngle );
347
348 //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
349 //rect to fit within bounds
350 double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
351 double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
352 double rectScaledWidth = rectScale * originalWidth;
353 double rectScaledHeight = rectScale * originalHeight;
354
355 //now calculate offset so that rotated rectangle is centered within bounds
356 //first calculate min x and y coordinates
357 double currentCornerX = 0;
358 double minX = 0;
359 currentCornerX += rectScaledWidth * cosAngle;
360 minX = minX < currentCornerX ? minX : currentCornerX;
361 currentCornerX += rectScaledHeight * sinAngle;
362 minX = minX < currentCornerX ? minX : currentCornerX;
363 currentCornerX -= rectScaledWidth * cosAngle;
364 minX = minX < currentCornerX ? minX : currentCornerX;
365
366 double currentCornerY = 0;
367 double minY = 0;
368 currentCornerY -= rectScaledWidth * sinAngle;
369 minY = minY < currentCornerY ? minY : currentCornerY;
370 currentCornerY += rectScaledHeight * cosAngle;
371 minY = minY < currentCornerY ? minY : currentCornerY;
372 currentCornerY += rectScaledWidth * sinAngle;
373 minY = minY < currentCornerY ? minY : currentCornerY;
374
375 //now calculate offset position of rotated rectangle
376 double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
377 offsetX += std::fabs( minX );
378 double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
379 offsetY += std::fabs( minY );
380
381 return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
382}
383
385{
386 QString s = string.trimmed();
387 if ( s.compare( QLatin1String( "Portrait" ), Qt::CaseInsensitive ) == 0 )
388 {
389 ok = true;
391 }
392 else if ( s.compare( QLatin1String( "Landscape" ), Qt::CaseInsensitive ) == 0 )
393 {
394 ok = true;
396 }
397 ok = false;
398 return QgsLayoutItemPage::Landscape; // default to landscape
399}
400
401double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style )
402{
403#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
404 // workaround Qt bug 66185
405
406 // Refs #18027 - if a QGraphicsItem is rotated by 90 or 270 degrees, then the item
407 // style given to QGraphicsItem::paint incorrectly uses the shear parameter of the matrix (m12)
408 // to store the current view scale, instead of the horizontal scale parameter (m11) which
409 // is used in all other cases
410
411 // TODO - ifdef this out if Qt fixes upstream
412 return !qgsDoubleNear( style->matrix.m11(), 0.0 ) ? style->matrix.m11() : style->matrix.m12();
413#else
414 Q_UNUSED( style )
415 return 1;
416#endif
417}
418
419double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style, QPainter *painter )
420{
421 Q_UNUSED( style );
422 return QStyleOptionGraphicsItem::levelOfDetailFromTransform( painter->worldTransform() );
423}
424
426{
427 // Maybe it's a layer id?
428 if ( QgsMapLayer *ml = project->mapLayer( string ) )
429 return ml;
430
431 // Still nothing? Check for layer name
432 if ( QgsMapLayer *ml = project->mapLayersByName( string ).value( 0 ) )
433 return ml;
434
435 // Still nothing? Check for layer name, case-insensitive
436 const auto layers = project->mapLayers();
437 for ( auto it = layers.constBegin(); it != layers.constEnd(); ++it )
438 {
439 if ( it.value()->name().compare( string, Qt::CaseInsensitive ) == 0 )
440 return it.value();
441 }
442
443 return nullptr;
444}
445
446// nextNiceNumber(4573.23, d) = 5000 (d=1) -> 4600 (d=10) -> 4580 (d=100) -> 4574 (d=1000) -> etc
447inline double nextNiceNumber( double a, double d = 1 )
448{
449 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
450 return std::ceil( a / s ) * s;
451}
452
453// prevNiceNumber(4573.23, d) = 4000 (d=1) -> 4500 (d=10) -> 4570 (d=100) -> 4573 (d=1000) -> etc
454inline double prevNiceNumber( double a, double d = 1 )
455{
456 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
457 return std::floor( a / s ) * s;
458}
459
460double QgsLayoutUtils::calculatePrettySize( const double minimumSize, const double maximumSize )
461{
462 if ( maximumSize < minimumSize )
463 {
464 return 0;
465 }
466 else
467 {
468 // Start with coarsest "nice" number closest to minimumSize resp
469 // maximumSize, then proceed to finer numbers as long as neither
470 // lowerNiceUnitsPerSeg nor upperNiceUnitsPerSeg are in
471 // [minimumSize, maximumSize]
472 double lowerNiceUnitsPerSeg = nextNiceNumber( minimumSize );
473 double upperNiceUnitsPerSeg = prevNiceNumber( maximumSize );
474
475 double d = 1;
476 while ( lowerNiceUnitsPerSeg > maximumSize && upperNiceUnitsPerSeg < minimumSize )
477 {
478 d *= 10;
479 lowerNiceUnitsPerSeg = nextNiceNumber( minimumSize, d );
480 upperNiceUnitsPerSeg = prevNiceNumber( maximumSize, d );
481 }
482
483 // Pick size from {lowerNiceUnitsPerSeg, upperNiceUnitsPerSeg}, use the larger if possible
484 return upperNiceUnitsPerSeg < minimumSize ? lowerNiceUnitsPerSeg : upperNiceUnitsPerSeg;
485 }
486}
487
489{
491 return false; // not a clipping provider, so shortcut out
492
493 // current only maps can be clipped
494 QList< QgsLayoutItemMap * > maps;
495 item->layout()->layoutItems( maps );
496 for ( QgsLayoutItemMap *map : std::as_const( maps ) )
497 {
498 if ( map->itemClippingSettings()->isActive() && map->itemClippingSettings()->sourceItem() == item )
499 return true;
500 }
501 return false;
502}
503
504double QgsLayoutUtils::pointsToMM( const double pointSize )
505{
506 //conversion to mm based on 1 point = 1/72 inch
507 return ( pointSize * 0.3527 );
508}
509
510double QgsLayoutUtils::mmToPoints( const double mmSize )
511{
512 //conversion to points based on 1 point = 1/72 inch
513 return ( mmSize / 0.3527 );
514}
515
516QVector< double > QgsLayoutUtils::predefinedScales( const QgsLayout *layout )
517{
518 QgsProject *lProject = layout ? layout->project() : nullptr;
519 QVector< double > mapScales;
520 if ( lProject )
521 mapScales = lProject->viewSettings()->mapScales();
522
523 bool hasProjectScales( lProject ? lProject->viewSettings()->useProjectScales() : false );
524 if ( !hasProjectScales || mapScales.isEmpty() )
525 {
526 // default to global map tool scales
527 QgsSettings settings;
528 const QStringList scales = QgsSettingsRegistryCore::settingsMapScales->value();
529 for ( const QString &scale : scales )
530 {
531 QStringList parts( scale.split( ':' ) );
532 if ( parts.size() == 2 )
533 {
534 mapScales.push_back( parts[1].toDouble() );
535 }
536 }
537 }
538
539 return mapScales;
540}
@ Millimeters
Millimeters.
Layout graphical items for displaying a map.
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings) const
Returns map settings that will be used for drawing of the map.
QgsRectangle extent() const
Returns the current map extent.
Orientation
Page orientation.
@ Landscape
Landscape orientation.
@ Portrait
Portrait orientation.
Base class for graphical items within a QgsLayout.
@ FlagProvidesClipPath
Item can act as a clipping path provider (see clipPath())
virtual Flags itemFlags() const
Returns the item's flags, which indicate how the item behaves.
const QgsLayout * layout() const
Returns the layout the object is attached to.
Qgis::TextRenderFormat textRenderFormat() const
Returns the text render format, which dictates how text is rendered (e.g.
Qgis::RenderContextFlags renderContextFlags() const
Returns the combination of render context flags matched to the layout context's settings.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static QVector< double > predefinedScales(const QgsLayout *layout)
Returns a list of predefined scales associated with a layout.
static double fontHeightMM(const QFont &font)
Calculate a font height in millimeters, including workarounds for QT font rendering issues.
static double relativePosition(double position, double beforeMin, double beforeMax, double afterMin, double afterMax)
Returns a scaled position given a before and after range.
static double fontDescentMM(const QFont &font)
Calculate a font descent in millimeters, including workarounds for QT font rendering issues.
static double fontAscentMM(const QFont &font)
Calculates a font ascent in millimeters, including workarounds for QT font rendering issues.
static QRectF largestRotatedRectWithinBounds(const QRectF &originalRect, const QRectF &boundsRect, double rotation)
Calculates the largest scaled version of originalRect which fits within boundsRect,...
static QFont scaledFontPixelSize(const QFont &font)
Returns a font where size is set in points and the size has been upscaled with FONT_WORKAROUND_SCALE ...
static QgsRenderContext createRenderContextForMap(QgsLayoutItemMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout map and painter destination.
static bool itemIsAClippingSource(const QgsLayoutItem *item)
Returns true if an item is a clipping item for another layout item.
static double snappedAngle(double angle)
Snaps an angle (in degrees) to its closest 45 degree angle.
static double textHeightMM(const QFont &font, const QString &text, double multiLineHeight=1.0)
Calculate a font height in millimeters for a text string, including workarounds for QT font rendering...
static QgsLayoutItemPage::Orientation decodePaperOrientation(const QString &string, bool &ok)
Decodes a string representing a paper orientation and returns the decoded orientation.
static void rotate(double angle, double &x, double &y)
Rotates a point / vector around the origin.
static double fontHeightCharacterMM(const QFont &font, QChar character)
Calculate a font height in millimeters of a single character, including workarounds for QT font rende...
static double normalizedAngle(double angle, bool allowNegative=false)
Ensures that an angle (in degrees) is in the range 0 <= angle < 360.
static void drawText(QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color=QColor())
Draws text on a painter at a specific position, taking care of layout specific issues (calculation to...
static double textWidthMM(const QFont &font, const QString &text)
Calculate a font width in millimeters for a text string, including workarounds for QT font rendering ...
static double calculatePrettySize(double minimumSize, double maximumSize)
Calculates a "pretty" size which falls between the range [minimumSize, maximumSize].
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProject *project)
Resolves a string into a map layer from a given project.
static Q_DECL_DEPRECATED double scaleFactorFromItemStyle(const QStyleOptionGraphicsItem *style)
Extracts the scale factor from an item style.
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
Definition: qgslayout.cpp:376
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:120
QgsLayoutItemMap * referenceMap() const
Returns the map item which will be used to generate corresponding world files when the layout is expo...
Definition: qgslayout.cpp:447
QgsLayoutMeasurement convertFromLayoutUnits(double length, Qgis::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
Definition: qgslayout.cpp:361
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:141
Base class for all map layer types.
Definition: qgsmaplayer.h:75
The QgsMapSettings class contains configuration for rendering of the map.
bool useProjectScales() const
Returns true if project mapScales() are enabled.
QVector< double > mapScales() const
Returns the list of custom project map scales.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:107
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
const QgsProjectViewSettings * viewSettings() const
Returns the project's view settings, which contains settings and properties relating to how a QgsProj...
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Contains information about the context of a rendering operation.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
void setTextRenderFormat(Qgis::TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
void setFlags(Qgis::RenderContextFlags flags)
Set combination of flags that will be used for rendering.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
Scoped object for saving and restoring a QPainter object's state.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
static const QgsSettingsEntryStringList * settingsMapScales
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:716
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:5207
double prevNiceNumber(double a, double d=1)
#define M_DEG2RAD
double nextNiceNumber(double a, double d=1)