QGIS API Documentation  2.99.0-Master (f1c3692)
qgsrasterpipe.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterpipe.cpp - Internal raster processing modules interface
3  --------------------------------------
4  Date : Jun 21, 2012
5  Copyright : (C) 2012 by Radim Blazek
6  email : radim dot blazek 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 <typeinfo>
19 
20 #include <QByteArray>
21 
22 #include "qgslogger.h"
23 #include "qgsrasterpipe.h"
24 #include "qgsrasterdataprovider.h"
25 #include "qgsrasterrenderer.h"
28 #include "qgshuesaturationfilter.h"
29 #include "qgsrasterprojector.h"
30 #include "qgsrasternuller.h"
31 
33 {
34  for ( int i = 0; i < pipe.size(); i++ )
35  {
36  QgsRasterInterface *interface = pipe.at( i );
37  QgsRasterInterface *clone = interface->clone();
38 
39  Role role = interfaceRole( clone );
40  QgsDebugMsgLevel( QString( "cloned interface with role %1" ).arg( role ), 4 );
41  if ( i > 0 )
42  {
43  clone->setInput( mInterfaces.at( i - 1 ) );
44  }
45  mInterfaces.append( clone );
46  if ( role != UnknownRole )
47  {
48  mRoleMap.insert( role, i );
49  }
50  }
51 }
52 
54 {
55  Q_FOREACH ( QgsRasterInterface *interface, mInterfaces )
56  {
57  delete interface;
58  }
59 }
60 
61 bool QgsRasterPipe::connect( QVector<QgsRasterInterface *> interfaces )
62 {
63  QgsDebugMsgLevel( "Entered", 4 );
64  for ( int i = 1; i < interfaces.size(); i++ )
65  {
66  if ( ! interfaces[i]->setInput( interfaces[i - 1] ) )
67  {
68 #ifdef QGISDEBUG
69  const QgsRasterInterface &a = *interfaces[i];
70  const QgsRasterInterface &b = *interfaces[i - 1];
71  QgsDebugMsg( QString( "cannot connect %1 to %2" ).arg( typeid( a ).name(), typeid( b ).name() ) );
72 #endif
73  return false;
74  }
75  }
76  return true;
77 }
78 
79 bool QgsRasterPipe::insert( int idx, QgsRasterInterface *interface )
80 {
81  QgsDebugMsgLevel( QString( "insert %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
82  if ( idx > mInterfaces.size() )
83  {
84  idx = mInterfaces.size();
85  }
86  // make a copy of pipe to test connection, we test the connections
87  // of the whole pipe, because the types and band numbers may change
88  QVector<QgsRasterInterface *> interfaces = mInterfaces;
89 
90  interfaces.insert( idx, interface );
91  bool success = false;
92  if ( connect( interfaces ) )
93  {
94  success = true;
95  mInterfaces.insert( idx, interface );
96  setRole( interface, idx );
97  QgsDebugMsgLevel( "inserted OK", 4 );
98  }
99 
100  // Connect or reconnect (after the test) interfaces
101  connect( mInterfaces );
102  return success;
103 }
104 
105 bool QgsRasterPipe::replace( int idx, QgsRasterInterface *interface )
106 {
107  if ( !interface ) return false;
108 
109  QgsDebugMsgLevel( QString( "replace by %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
110  if ( !checkBounds( idx ) ) return false;
111 
112  // make a copy of pipe to test connection, we test the connections
113  // of the whole pipe, because the types and band numbers may change
114  QVector<QgsRasterInterface *> interfaces = mInterfaces;
115 
116  interfaces[idx] = interface;
117  bool success = false;
118  if ( connect( interfaces ) )
119  {
120  success = true;
121  delete mInterfaces.at( idx );
122  mInterfaces[idx] = interface;
123  setRole( interface, idx );
124  QgsDebugMsgLevel( "replaced OK", 4 );
125  }
126 
127  // Connect or reconnect (after the test) interfaces
128  connect( mInterfaces );
129  return success;
130 }
131 
132 QgsRasterPipe::Role QgsRasterPipe::interfaceRole( QgsRasterInterface *interface ) const
133 {
134  Role role = UnknownRole;
135  if ( dynamic_cast<QgsRasterDataProvider *>( interface ) ) role = ProviderRole;
136  else if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) role = RendererRole;
137  else if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) role = ResamplerRole;
138  else if ( dynamic_cast<QgsBrightnessContrastFilter *>( interface ) ) role = BrightnessRole;
139  else if ( dynamic_cast<QgsHueSaturationFilter *>( interface ) ) role = HueSaturationRole;
140  else if ( dynamic_cast<QgsRasterProjector *>( interface ) ) role = ProjectorRole;
141  else if ( dynamic_cast<QgsRasterNuller *>( interface ) ) role = NullerRole;
142 
143  QgsDebugMsgLevel( QString( "%1 role = %2" ).arg( typeid( *interface ).name() ).arg( role ), 4 );
144  return role;
145 }
146 
147 void QgsRasterPipe::setRole( QgsRasterInterface *interface, int idx )
148 {
149  Role role = interfaceRole( interface );
150  if ( role == UnknownRole ) return;
151  mRoleMap.insert( role, idx );
152 }
153 
154 void QgsRasterPipe::unsetRole( QgsRasterInterface *interface )
155 {
156  Role role = interfaceRole( interface );
157  if ( role == UnknownRole ) return;
158  mRoleMap.remove( role );
159 }
160 
162 {
163  if ( !interface ) return false;
164 
165  QgsDebugMsgLevel( QString( "%1" ).arg( typeid( *interface ).name() ), 4 );
166  Role role = interfaceRole( interface );
167 
168  // We don't know where to place unknown interface
169  if ( role == UnknownRole ) return false;
170 
171  //if ( mInterfacesMap.value ( role ) )
172  if ( mRoleMap.contains( role ) )
173  {
174  // An old interface of the same role exists -> replace
175  // replace may still fail and return false
176  return replace( mRoleMap.value( role ), interface );
177  }
178 
179  int idx = 0;
180 
181  // Not found, find the best default position for this kind of interface
182  // QgsRasterDataProvider - ProviderRole
183  // QgsRasterRenderer - RendererRole
184  // QgsRasterResampler - ResamplerRole
185  // QgsRasterProjector - ProjectorRole
186 
187  int providerIdx = mRoleMap.value( ProviderRole, -1 );
188  int rendererIdx = mRoleMap.value( RendererRole, -1 );
189  int resamplerIdx = mRoleMap.value( ResamplerRole, -1 );
190  int brightnessIdx = mRoleMap.value( BrightnessRole, -1 );
191  int hueSaturationIdx = mRoleMap.value( HueSaturationRole, -1 );
192 
193  if ( role == ProviderRole )
194  {
195  idx = 0;
196  }
197  else if ( role == RendererRole )
198  {
199  idx = providerIdx + 1;
200  }
201  else if ( role == BrightnessRole )
202  {
203  idx = std::max( providerIdx, rendererIdx ) + 1;
204  }
205  else if ( role == HueSaturationRole )
206  {
207  idx = std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ) + 1;
208  }
209  else if ( role == ResamplerRole )
210  {
211  idx = std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ) + 1;
212  }
213  else if ( role == ProjectorRole )
214  {
215  idx = std::max( std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ), resamplerIdx ) + 1;
216  }
217 
218  return insert( idx, interface ); // insert may still fail and return false
219 }
220 
221 QgsRasterInterface *QgsRasterPipe::interface( Role role ) const
222 {
223  QgsDebugMsgLevel( QString( "role = %1" ).arg( role ), 4 );
224  if ( mRoleMap.contains( role ) )
225  {
226  return mInterfaces.value( mRoleMap.value( role ) );
227  }
228  return nullptr;
229 }
230 
232 {
233  return dynamic_cast<QgsRasterDataProvider *>( interface( ProviderRole ) );
234 }
235 
237 {
238  return dynamic_cast<QgsRasterRenderer *>( interface( RendererRole ) );
239 }
240 
242 {
243  return dynamic_cast<QgsRasterResampleFilter *>( interface( ResamplerRole ) );
244 }
245 
247 {
248  return dynamic_cast<QgsBrightnessContrastFilter *>( interface( BrightnessRole ) );
249 }
250 
252 {
253  return dynamic_cast<QgsHueSaturationFilter *>( interface( HueSaturationRole ) );
254 }
255 
257 {
258  return dynamic_cast<QgsRasterProjector *>( interface( ProjectorRole ) );
259 }
260 
262 {
263  return dynamic_cast<QgsRasterNuller *>( interface( NullerRole ) );
264 }
265 
266 bool QgsRasterPipe::remove( int idx )
267 {
268  QgsDebugMsgLevel( QString( "remove at %1" ).arg( idx ), 4 );
269 
270  if ( !checkBounds( idx ) ) return false;
271 
272  // make a copy of pipe to test connection, we test the connections
273  // of the whole pipe, because the types and band numbers may change
274  QVector<QgsRasterInterface *> interfaces = mInterfaces;
275 
276  interfaces.remove( idx );
277  bool success = false;
278  if ( connect( interfaces ) )
279  {
280  success = true;
281  unsetRole( mInterfaces.at( idx ) );
282  delete mInterfaces.at( idx );
283  mInterfaces.remove( idx );
284  QgsDebugMsgLevel( "removed OK", 4 );
285  }
286 
287  // Connect or reconnect (after the test) interfaces
288  connect( mInterfaces );
289  return success;
290 }
291 
293 {
294  if ( !interface ) return false;
295 
296  return remove( mInterfaces.indexOf( interface ) );
297 }
298 
299 bool QgsRasterPipe::canSetOn( int idx, bool on )
300 {
301  QgsDebugMsgLevel( QString( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
302  if ( !checkBounds( idx ) ) return false;
303 
304  // Because setting interface on/off may change its output we must check if
305  // connection is OK after such switch
306  bool onOrig = mInterfaces.at( idx )->on();
307 
308  if ( onOrig == on ) return true;
309 
310  mInterfaces.at( idx )->setOn( on );
311 
312  bool success = connect( mInterfaces );
313 
314  mInterfaces.at( idx )->setOn( onOrig );
315  connect( mInterfaces );
316  return success;
317 }
318 
319 bool QgsRasterPipe::setOn( int idx, bool on )
320 {
321  QgsDebugMsgLevel( QString( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
322  if ( !checkBounds( idx ) ) return false;
323 
324  bool onOrig = mInterfaces.at( idx )->on();
325 
326  if ( onOrig == on ) return true;
327 
328  mInterfaces.at( idx )->setOn( on );
329 
330  if ( connect( mInterfaces ) ) return true;
331 
332  mInterfaces.at( idx )->setOn( onOrig );
333  connect( mInterfaces );
334 
335  return false;
336 }
337 
338 bool QgsRasterPipe::checkBounds( int idx ) const
339 {
340  return !( idx < 0 || idx >= mInterfaces.size() );
341 }
Base class for processing modules.
Definition: qgsrasterpipe.h:46
QgsRasterRenderer * renderer() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
QgsRasterResampleFilter * resampleFilter() const
QgsRasterProjector * projector() const
Raster pipe that deals with null values.
bool insert(int idx, QgsRasterInterface *interface)
Try to insert interface at specified index and connect if connection would fail, the interface is not...
Resample filter pipe for rasters.
bool replace(int idx, QgsRasterInterface *interface)
Try to replace interface at specified index and connect if connection would fail, the interface is no...
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:38
Base class for processing filters like renderers, reprojector, resampler etc.
int size() const
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
bool canSetOn(int idx, bool on)
Test if interface at index may be swithed on/off.
bool set(QgsRasterInterface *interface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
bool remove(int idx)
Remove and delete interface at given index if possible.
bool setOn(int idx, bool on)
Set interface at index on/off Returns true on success.
virtual QgsRasterInterface * clone() const =0
Clone itself, create deep copy.
Brightness/contrast filter pipe for rasters.
Color and saturation filter pipe for rasters.
QgsRasterDataProvider * provider() const
QgsRasterNuller * nuller() const
QgsBrightnessContrastFilter * brightnessFilter() const
QgsHueSaturationFilter * hueSaturationFilter() const
Raster renderer pipe that applies colors to a raster.
Base class for raster data providers.
QgsRasterPipe()=default
Constructor for QgsRasterPipe.