QGIS API Documentation  2.99.0-Master (0a63d1f)
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:44
QgsRasterRenderer * renderer() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QgsRasterResampleFilter * resampleFilter() const
QgsRasterProjector * projector() const
Raster pipe that deals with null values.
Resample filter pipe for rasters.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
Base class for processing filters like renderers, reprojector, resampler etc.
int size() const
Definition: qgsrasterpipe.h:89
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.
QgsRasterDataProvider * provider() const
bool insert(int idx, QgsRasterInterface *theInterface)
Try to insert interface at specified index and connect if connection would fail, the interface is not...
QgsRasterNuller * nuller() const
bool replace(int idx, QgsRasterInterface *theInterface)
Try to replace interface at specified index and connect if connection would fail, the interface is no...
QgsBrightnessContrastFilter * brightnessFilter() const
QgsHueSaturationFilter * hueSaturationFilter() const
bool set(QgsRasterInterface *theInterface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
Raster renderer pipe that applies colors to a raster.
Base class for raster data providers.