QGIS API Documentation  3.6.0-Noosa (5873452)
qgsmeshlayerutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshlayerutils.cpp
3  --------------------------
4  begin : August 2018
5  copyright : (C) 2018 by Martin Dobias
6  email : wonder dot sk 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 "qgsmeshlayerutils.h"
19 
20 #include <limits>
21 
23 
24 QVector<double> QgsMeshLayerUtils::calculateMagnitudes( const QgsMeshDataBlock &block )
25 {
26  Q_ASSERT( QgsMeshDataBlock::ActiveFlagInteger != block.type() );
27  int count = block.count();
28  QVector<double> ret( count );
29 
30  for ( int i = 0; i < count; ++i )
31  {
32  double mag = block.value( i ).scalar();
33  ret[i] = mag;
34  }
35  return ret;
36 }
37 
38 void QgsMeshLayerUtils::boundingBoxToScreenRectangle( const QgsMapToPixel &mtp,
39  const QSize &outputSize,
40  const QgsRectangle &bbox,
41  int &leftLim,
42  int &rightLim,
43  int &topLim,
44  int &bottomLim )
45 {
46  QgsPointXY ll = mtp.transform( bbox.xMinimum(), bbox.yMinimum() );
47  QgsPointXY ur = mtp.transform( bbox.xMaximum(), bbox.yMaximum() );
48  topLim = std::max( int( ur.y() ), 0 );
49  bottomLim = std::min( int( ll.y() ), outputSize.height() - 1 );
50  leftLim = std::max( int( ll.x() ), 0 );
51  rightLim = std::min( int( ur.x() ), outputSize.width() - 1 );
52 }
53 
54 static void lamTol( double &lam )
55 {
56  const static double eps = 1e-6;
57  if ( ( lam < 0.0 ) && ( lam > -eps ) )
58  {
59  lam = 0.0;
60  }
61 }
62 
63 static bool E3T_physicalToBarycentric( const QgsPointXY &pA, const QgsPointXY &pB, const QgsPointXY &pC, const QgsPointXY &pP,
64  double &lam1, double &lam2, double &lam3 )
65 {
66  if ( pA == pB || pA == pC || pB == pC )
67  return false; // this is not a valid triangle!
68 
69  // Compute vectors
70  QgsVector v0( pC - pA );
71  QgsVector v1( pB - pA );
72  QgsVector v2( pP - pA );
73 
74  // Compute dot products
75  double dot00 = v0 * v0;
76  double dot01 = v0 * v1;
77  double dot02 = v0 * v2;
78  double dot11 = v1 * v1;
79  double dot12 = v1 * v2;
80 
81  // Compute barycentric coordinates
82  double invDenom = 1.0 / ( dot00 * dot11 - dot01 * dot01 );
83  lam1 = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
84  lam2 = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
85  lam3 = 1.0 - lam1 - lam2;
86 
87  // Apply some tolerance to lam so we can detect correctly border points
88  lamTol( lam1 );
89  lamTol( lam2 );
90  lamTol( lam3 );
91 
92  // Return if POI is outside triangle
93  if ( ( lam1 < 0 ) || ( lam2 < 0 ) || ( lam3 < 0 ) )
94  {
95  return false;
96  }
97 
98  return true;
99 }
100 
101 double QgsMeshLayerUtils::interpolateFromVerticesData( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3,
102  double val1, double val2, double val3, const QgsPointXY &pt )
103 {
104  double lam1, lam2, lam3;
105  if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
106  return std::numeric_limits<double>::quiet_NaN();
107 
108  return lam1 * val3 + lam2 * val2 + lam3 * val1;
109 }
110 
111 double QgsMeshLayerUtils::interpolateFromFacesData( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3,
112  double val, const QgsPointXY &pt )
113 {
114  double lam1, lam2, lam3;
115  if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
116  return std::numeric_limits<double>::quiet_NaN();
117 
118  return val;
119 }
120 
121 QgsRectangle QgsMeshLayerUtils::triangleBoundingBox( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3 )
122 {
123  QgsRectangle bbox;
124  bbox.combineExtentWith( p1.x(), p1.y() );
125  bbox.combineExtentWith( p2.x(), p2.y() );
126  bbox.combineExtentWith( p3.x(), p3.y() );
127  return bbox;
128 }
129 
A rectangle specified with double values.
Definition: qgsrectangle.h:41
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
int count() const
Number of items stored in the block.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e...
DataType type() const
Type of data stored in the block.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
Integer boolean flag whether face is active.
double scalar() const
Returns magnitude of vector for vector data or scalar value for scalar data.
double x
Definition: qgspointxy.h:47
A class to represent a vector.
Definition: qgsvector.h:29
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:359
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172