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