Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgspointcloudrgbrenderer.h
3 : : --------------------
4 : : begin : October 2020
5 : : copyright : (C) 2020 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 "qgspointcloudrgbrenderer.h"
19 : : #include "qgspointcloudblock.h"
20 : : #include "qgscontrastenhancement.h"
21 : :
22 : 0 : QgsPointCloudRgbRenderer::QgsPointCloudRgbRenderer()
23 : 0 : {
24 : :
25 : 0 : }
26 : :
27 : 0 : QString QgsPointCloudRgbRenderer::type() const
28 : : {
29 : 0 : return QStringLiteral( "rgb" );
30 : : }
31 : :
32 : 0 : QgsPointCloudRenderer *QgsPointCloudRgbRenderer::clone() const
33 : : {
34 : 0 : std::unique_ptr< QgsPointCloudRgbRenderer > res = std::make_unique< QgsPointCloudRgbRenderer >();
35 : 0 : res->mRedAttribute = mRedAttribute;
36 : 0 : res->mGreenAttribute = mGreenAttribute;
37 : 0 : res->mBlueAttribute = mBlueAttribute;
38 : :
39 : 0 : if ( mRedContrastEnhancement )
40 : : {
41 : 0 : res->setRedContrastEnhancement( new QgsContrastEnhancement( *mRedContrastEnhancement ) );
42 : 0 : }
43 : 0 : if ( mGreenContrastEnhancement )
44 : : {
45 : 0 : res->setGreenContrastEnhancement( new QgsContrastEnhancement( *mGreenContrastEnhancement ) );
46 : 0 : }
47 : 0 : if ( mBlueContrastEnhancement )
48 : : {
49 : 0 : res->setBlueContrastEnhancement( new QgsContrastEnhancement( *mBlueContrastEnhancement ) );
50 : 0 : }
51 : :
52 : 0 : copyCommonProperties( res.get() );
53 : :
54 : 0 : return res.release();
55 : 0 : }
56 : :
57 : 0 : void QgsPointCloudRgbRenderer::renderBlock( const QgsPointCloudBlock *block, QgsPointCloudRenderContext &context )
58 : : {
59 : 0 : const QgsRectangle visibleExtent = context.renderContext().extent();
60 : :
61 : 0 : const char *ptr = block->data();
62 : 0 : int count = block->pointCount();
63 : 0 : const QgsPointCloudAttributeCollection request = block->attributes();
64 : :
65 : 0 : const std::size_t recordSize = request.pointRecordSize();
66 : 0 : int redOffset = 0;
67 : 0 : const QgsPointCloudAttribute *attribute = request.find( mRedAttribute, redOffset );
68 : 0 : if ( !attribute )
69 : 0 : return;
70 : 0 : const QgsPointCloudAttribute::DataType redType = attribute->type();
71 : :
72 : 0 : int greenOffset = 0;
73 : 0 : attribute = request.find( mGreenAttribute, greenOffset );
74 : 0 : if ( !attribute )
75 : 0 : return;
76 : 0 : const QgsPointCloudAttribute::DataType greenType = attribute->type();
77 : :
78 : 0 : int blueOffset = 0;
79 : 0 : attribute = request.find( mBlueAttribute, blueOffset );
80 : 0 : if ( !attribute )
81 : 0 : return;
82 : 0 : const QgsPointCloudAttribute::DataType blueType = attribute->type();
83 : :
84 : 0 : const bool useRedContrastEnhancement = mRedContrastEnhancement && mRedContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement;
85 : 0 : const bool useBlueContrastEnhancement = mBlueContrastEnhancement && mBlueContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement;
86 : 0 : const bool useGreenContrastEnhancement = mGreenContrastEnhancement && mGreenContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement;
87 : :
88 : 0 : const QgsDoubleRange zRange = context.renderContext().zRange();
89 : 0 : const bool considerZ = !zRange.isInfinite();
90 : :
91 : 0 : int rendered = 0;
92 : 0 : double x = 0;
93 : 0 : double y = 0;
94 : 0 : double z = 0;
95 : 0 : const QgsCoordinateTransform ct = context.renderContext().coordinateTransform();
96 : 0 : const bool reproject = ct.isValid();
97 : 0 : for ( int i = 0; i < count; ++i )
98 : : {
99 : 0 : if ( context.renderContext().renderingStopped() )
100 : : {
101 : 0 : break;
102 : : }
103 : :
104 : 0 : if ( considerZ )
105 : : {
106 : : // z value filtering is cheapest, if we're doing it...
107 : 0 : z = pointZ( context, ptr, i );
108 : 0 : if ( !zRange.contains( z ) )
109 : 0 : continue;
110 : 0 : }
111 : :
112 : 0 : pointXY( context, ptr, i, x, y );
113 : 0 : if ( visibleExtent.contains( x, y ) )
114 : : {
115 : 0 : if ( reproject )
116 : : {
117 : : try
118 : : {
119 : 0 : ct.transformInPlace( x, y, z );
120 : 0 : }
121 : : catch ( QgsCsException & )
122 : : {
123 : : continue;
124 : 0 : }
125 : 0 : }
126 : :
127 : 0 : int red = 0;
128 : 0 : context.getAttribute( ptr, i * recordSize + redOffset, redType, red );
129 : 0 : int green = 0;
130 : 0 : context.getAttribute( ptr, i * recordSize + greenOffset, greenType, green );
131 : 0 : int blue = 0;
132 : 0 : context.getAttribute( ptr, i * recordSize + blueOffset, blueType, blue );
133 : :
134 : : //skip if red, green or blue not in displayable range
135 : 0 : if ( ( useRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( red ) )
136 : 0 : || ( useGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( green ) )
137 : 0 : || ( useBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( blue ) ) )
138 : : {
139 : 0 : continue;
140 : : }
141 : :
142 : : //stretch color values
143 : 0 : if ( useRedContrastEnhancement )
144 : : {
145 : 0 : red = mRedContrastEnhancement->enhanceContrast( red );
146 : 0 : }
147 : 0 : if ( useGreenContrastEnhancement )
148 : : {
149 : 0 : green = mGreenContrastEnhancement->enhanceContrast( green );
150 : 0 : }
151 : 0 : if ( useBlueContrastEnhancement )
152 : : {
153 : 0 : blue = mBlueContrastEnhancement->enhanceContrast( blue );
154 : 0 : }
155 : :
156 : 0 : red = std::max( 0, std::min( 255, red ) );
157 : 0 : green = std::max( 0, std::min( 255, green ) );
158 : 0 : blue = std::max( 0, std::min( 255, blue ) );
159 : :
160 : 0 : drawPoint( x, y, QColor( red, green, blue ), context );
161 : 0 : rendered++;
162 : 0 : }
163 : 0 : }
164 : 0 : context.incrementPointsRendered( rendered );
165 : 0 : }
166 : :
167 : :
168 : 0 : QgsPointCloudRenderer *QgsPointCloudRgbRenderer::create( QDomElement &element, const QgsReadWriteContext &context )
169 : 0 : {
170 : 0 : std::unique_ptr< QgsPointCloudRgbRenderer > r = std::make_unique< QgsPointCloudRgbRenderer >();
171 : 0 :
172 : 0 : r->setRedAttribute( element.attribute( QStringLiteral( "red" ), QStringLiteral( "Red" ) ) );
173 : 0 : r->setGreenAttribute( element.attribute( QStringLiteral( "green" ), QStringLiteral( "Green" ) ) );
174 : 0 : r->setBlueAttribute( element.attribute( QStringLiteral( "blue" ), QStringLiteral( "Blue" ) ) );
175 : :
176 : 0 : r->restoreCommonProperties( element, context );
177 : :
178 : : //contrast enhancements
179 : 0 : QgsContrastEnhancement *redContrastEnhancement = nullptr;
180 : 0 : QDomElement redContrastElem = element.firstChildElement( QStringLiteral( "redContrastEnhancement" ) );
181 : 0 : if ( !redContrastElem.isNull() )
182 : : {
183 : 0 : redContrastEnhancement = new QgsContrastEnhancement( Qgis::UnknownDataType );
184 : 0 : redContrastEnhancement->readXml( redContrastElem );
185 : 0 : r->setRedContrastEnhancement( redContrastEnhancement );
186 : 0 : }
187 : :
188 : 0 : QgsContrastEnhancement *greenContrastEnhancement = nullptr;
189 : 0 : QDomElement greenContrastElem = element.firstChildElement( QStringLiteral( "greenContrastEnhancement" ) );
190 : 0 : if ( !greenContrastElem.isNull() )
191 : : {
192 : 0 : greenContrastEnhancement = new QgsContrastEnhancement( Qgis::UnknownDataType );
193 : 0 : greenContrastEnhancement->readXml( greenContrastElem );
194 : 0 : r->setGreenContrastEnhancement( greenContrastEnhancement );
195 : 0 : }
196 : :
197 : 0 : QgsContrastEnhancement *blueContrastEnhancement = nullptr;
198 : 0 : QDomElement blueContrastElem = element.firstChildElement( QStringLiteral( "blueContrastEnhancement" ) );
199 : 0 : if ( !blueContrastElem.isNull() )
200 : : {
201 : 0 : blueContrastEnhancement = new QgsContrastEnhancement( Qgis::UnknownDataType );
202 : 0 : blueContrastEnhancement->readXml( blueContrastElem );
203 : 0 : r->setBlueContrastEnhancement( blueContrastEnhancement );
204 : 0 : }
205 : :
206 : 0 : return r.release();
207 : 0 : }
208 : :
209 : 0 : QDomElement QgsPointCloudRgbRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
210 : : {
211 : 0 : QDomElement rendererElem = doc.createElement( QStringLiteral( "renderer" ) );
212 : :
213 : 0 : rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "rgb" ) );
214 : :
215 : 0 : rendererElem.setAttribute( QStringLiteral( "red" ), mRedAttribute );
216 : 0 : rendererElem.setAttribute( QStringLiteral( "green" ), mGreenAttribute );
217 : 0 : rendererElem.setAttribute( QStringLiteral( "blue" ), mBlueAttribute );
218 : :
219 : 0 : saveCommonProperties( rendererElem, context );
220 : :
221 : : //contrast enhancement
222 : 0 : if ( mRedContrastEnhancement )
223 : : {
224 : 0 : QDomElement redContrastElem = doc.createElement( QStringLiteral( "redContrastEnhancement" ) );
225 : 0 : mRedContrastEnhancement->writeXml( doc, redContrastElem );
226 : 0 : rendererElem.appendChild( redContrastElem );
227 : 0 : }
228 : 0 : if ( mGreenContrastEnhancement )
229 : : {
230 : 0 : QDomElement greenContrastElem = doc.createElement( QStringLiteral( "greenContrastEnhancement" ) );
231 : 0 : mGreenContrastEnhancement->writeXml( doc, greenContrastElem );
232 : 0 : rendererElem.appendChild( greenContrastElem );
233 : 0 : }
234 : 0 : if ( mBlueContrastEnhancement )
235 : : {
236 : 0 : QDomElement blueContrastElem = doc.createElement( QStringLiteral( "blueContrastEnhancement" ) );
237 : 0 : mBlueContrastEnhancement->writeXml( doc, blueContrastElem );
238 : 0 : rendererElem.appendChild( blueContrastElem );
239 : 0 : }
240 : :
241 : 0 : return rendererElem;
242 : 0 : }
243 : :
244 : 0 : QSet<QString> QgsPointCloudRgbRenderer::usedAttributes( const QgsPointCloudRenderContext & ) const
245 : : {
246 : 0 : QSet<QString> res;
247 : 0 : res << mRedAttribute << mGreenAttribute << mBlueAttribute;
248 : 0 : return res;
249 : 0 : }
250 : :
251 : 0 : QString QgsPointCloudRgbRenderer::redAttribute() const
252 : : {
253 : 0 : return mRedAttribute;
254 : : }
255 : :
256 : 0 : void QgsPointCloudRgbRenderer::setRedAttribute( const QString &redAttribute )
257 : : {
258 : 0 : mRedAttribute = redAttribute;
259 : 0 : }
260 : :
261 : 0 : QString QgsPointCloudRgbRenderer::greenAttribute() const
262 : : {
263 : 0 : return mGreenAttribute;
264 : : }
265 : :
266 : 0 : void QgsPointCloudRgbRenderer::setGreenAttribute( const QString &greenAttribute )
267 : : {
268 : 0 : mGreenAttribute = greenAttribute;
269 : 0 : }
270 : :
271 : 0 : QString QgsPointCloudRgbRenderer::blueAttribute() const
272 : : {
273 : 0 : return mBlueAttribute;
274 : : }
275 : :
276 : 0 : void QgsPointCloudRgbRenderer::setBlueAttribute( const QString &blueAttribute )
277 : : {
278 : 0 : mBlueAttribute = blueAttribute;
279 : 0 : }
280 : :
281 : 0 : const QgsContrastEnhancement *QgsPointCloudRgbRenderer::redContrastEnhancement() const
282 : : {
283 : 0 : return mRedContrastEnhancement.get();
284 : : }
285 : :
286 : 0 : void QgsPointCloudRgbRenderer::setRedContrastEnhancement( QgsContrastEnhancement *enhancement )
287 : : {
288 : 0 : mRedContrastEnhancement.reset( enhancement );
289 : 0 : }
290 : :
291 : 0 : const QgsContrastEnhancement *QgsPointCloudRgbRenderer::greenContrastEnhancement() const
292 : : {
293 : 0 : return mGreenContrastEnhancement.get();
294 : : }
295 : :
296 : 0 : void QgsPointCloudRgbRenderer::setGreenContrastEnhancement( QgsContrastEnhancement *enhancement )
297 : : {
298 : 0 : mGreenContrastEnhancement.reset( enhancement );
299 : 0 : }
300 : :
301 : 0 : const QgsContrastEnhancement *QgsPointCloudRgbRenderer::blueContrastEnhancement() const
302 : : {
303 : 0 : return mBlueContrastEnhancement.get();
304 : : }
305 : :
306 : 0 : void QgsPointCloudRgbRenderer::setBlueContrastEnhancement( QgsContrastEnhancement *enhancement )
307 : : {
308 : 0 : mBlueContrastEnhancement.reset( enhancement );
309 : 0 : }
|