1 /***************************************************************************
2   qgstessellator.h
3   --------------------------------------
4   Date                 : July 2017
5   Copyright            : (C) 2017 by Martin Dobias
6   Email                : wonder dot sk at gmail dot com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 #ifndef QGSTESSELLATOR_H
17 #define QGSTESSELLATOR_H
18 
19 #include "qgis_core.h"
20 #include "qgis_sip.h"
21 #include "qgsrectangle.h"
22 
23 class QgsPolygon;
24 class QgsMultiPolygon;
25 
26 #include <QVector>
27 #include <memory>
28 
29 /**
30  * \ingroup core
31  * \brief Class that takes care of tessellation of polygons into triangles.
32  *
33  * It is expected that client code will create the tessellator object, then repeatedly call
34  * addPolygon() method that will generate triangles, and finally call data() to get final vertex data.
35  *
36  * Optionally provides extrusion by adding triangles that serve as walls when extrusion height is non-zero.
37  *
38  * \since QGIS 3.4 (since QGIS 3.0 in QGIS_3D library)
39  */
40 class CORE_EXPORT QgsTessellator
41 {
42   public:
43     //! Creates tessellator with a specified origin point of the world (in map coordinates)
44     QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false,
45                     bool addTextureCoords = false, int facade = 3, float textureRotation = 0.0f );
46 
47     /**
48      * Creates tessellator with a specified \a bounds of input geometry coordinates.
49      * This constructor allows the tessellator to map input coordinates to a desirable range for numerical
50      * stability during calculations.
51      *
52      * If \a noZ is TRUE, then a 2-dimensional tessellation only will be performed and all z coordinates will be ignored.
53      *
54      * \since QGIS 3.10
55      */
56     QgsTessellator( const QgsRectangle &bounds, bool addNormals, bool invertNormals = false, bool addBackFaces = false, bool noZ = false,
57                     bool addTextureCoords = false, int facade = 3, float textureRotation = 0.0f );
58 
59     //! Tessellates a triangle and adds its vertex entries to the output data array
60     void addPolygon( const QgsPolygon &polygon, float extrusionHeight );
61 
62     /**
63      * Returns array of triangle vertex data
64      *
65      * Vertice coordinates are stored as (x, z, -y)
66      */
data()67     QVector<float> data() const { return mData; }
68 
69     //! Returns the number of vertices stored in the output data array
70     int dataVerticesCount() const;
71 
72     //! Returns size of one vertex entry in bytes
stride()73     int stride() const { return mStride; }
74 
75     /**
76      * Returns the triangulation as a multipolygon geometry.
77      */
78     std::unique_ptr< QgsMultiPolygon > asMultiPolygon() const SIP_SKIP;
79 
80     /**
81      * Returns minimal Z value of the data (in world coordinates)
82      * \since QGIS 3.12
83      */
zMinimum()84     float zMinimum() const { return mZMin; }
85 
86     /**
87      * Returns maximal Z value of the data (in world coordinates)
88      * \since QGIS 3.12
89      */
zMaximum()90     float zMaximum() const { return mZMax; }
91 
92   private:
93     void init();
94 
95     QgsRectangle mBounds;
96     double mOriginX = 0, mOriginY = 0;
97     bool mAddNormals = false;
98     bool mInvertNormals = false;
99     bool mAddBackFaces = false;
100     bool mAddTextureCoords = false;
101     QVector<float> mData;
102     int mStride;
103     bool mNoZ = false;
104     int mTessellatedFacade = 3;
105     float mTextureRotation = 0.0f;
106 
107     float mZMin = std::numeric_limits<float>::max();
108     float mZMax = std::numeric_limits<float>::min();
109 };
110 
111 #endif // QGSTESSELLATOR_H
112