All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ArithmeticOperations.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/rp/GeoMosaic.cpp
22  \brief Create a mosaic from a set of geo-referenced rasters.
23 */
24 
25 #include "ArithmeticOperations.h"
26 
27 #include "Functions.h"
28 #include "Macros.h"
29 
30 #include "../common/progress/TaskProgress.h"
31 #include "../common/StringUtils.h"
32 #include "../raster/Raster.h"
33 
34 #include <cfloat>
35 
36 namespace te
37 {
38  namespace rp
39  {
40 
42  {
43  reset();
44  }
45 
47  {
48  reset();
49  operator=( other );
50  }
51 
53  {
54  reset();
55  }
56 
57  void ArithmeticOperations::InputParameters::reset() throw( te::rp::Exception )
58  {
59  m_rasterVec.clear();
60  m_arithmeticString.clear();
61  m_normalize = false;
62  m_enableProgress = false;
63  }
64 
67  {
68  reset();
69 
70  m_rasterVec = params.m_rasterVec;
71  m_arithmeticString = params.m_arithmeticString;
72  m_normalize = params.m_normalize;
73  m_enableProgress = params.m_enableProgress;
74 
75  return *this;
76  }
77 
79  {
80  return new InputParameters( *this );
81  }
82 
84  {
85  reset();
86  }
87 
89  {
90  reset();
91  operator=( other );
92  }
93 
95  {
96  reset();
97  }
98 
99  void ArithmeticOperations::OutputParameters::reset() throw( te::rp::Exception )
100  {
101  m_rType.clear();
102  m_rInfo.clear();
103  m_outputRasterPtr.reset();
104  }
105 
108  {
109  reset();
110 
111  m_rType = params.m_rType;
112  m_rInfo = params.m_rInfo;
113  m_outputRasterPtr.reset();
114 
115  return *this;
116  }
117 
119  {
120  return new OutputParameters( *this );
121  }
122 
124  {
125  reset();
126  }
127 
129  {
130  }
131 
133  throw( te::rp::Exception )
134  {
135  TERP_TRUE_OR_RETURN_FALSE( m_isInitialized, "Algoritm not initialized" );
136 
137  ArithmeticOperations::OutputParameters* outParamsPtr = dynamic_cast<
138  ArithmeticOperations::OutputParameters* >( &outputParams );
139  TERP_TRUE_OR_THROW( outParamsPtr, "Invalid paramters" );
140 
141  // Initializing the output raster
142 
143  std::vector< te::rst::BandProperty* > bandsProperties;
144  bandsProperties.push_back( new te::rst::BandProperty(
145  *( m_inputParameters.m_rasterVec[0]->getBand(0)->getProperty() ) ) );
146  bandsProperties[ 0 ]->m_type = te::dt::DOUBLE_TYPE;
147 
148  outParamsPtr->m_outputRasterPtr.reset(
150  outParamsPtr->m_rType,
151  new te::rst::Grid( *( m_inputParameters.m_rasterVec[0]->getGrid() ) ),
152  bandsProperties,
153  outParamsPtr->m_rInfo,
154  0,
155  0 ) );
156  TERP_TRUE_OR_RETURN_FALSE( outParamsPtr->m_outputRasterPtr.get(),
157  "Output raster creation error" );
158 
159 
160  // Counting the number of operations to be done
161  std::string arithmetic_string = m_inputParameters.m_arithmeticString;
162 
163  unsigned int operationsNumber = 0;
164  {
165  for( unsigned sIdx = 0 ; sIdx < arithmetic_string.size() ; ++sIdx )
166  {
167  std::string auxStr;
168  auxStr.push_back( arithmetic_string[ sIdx ] );
169 
170  if( isOperator( auxStr ) ) ++operationsNumber;
171  }
172  }
173 
174  // progress
175 
176  std::auto_ptr< te::common::TaskProgress > progressPtr;
178  {
179  progressPtr.reset( new te::common::TaskProgress );
180 
181  progressPtr->setTotalSteps( operationsNumber );
182 
183  progressPtr->setMessage( "Arithmetic Operations" );
184  }
185 
186  // Executing the arithmetic string
187 
188  std::vector< boost::shared_ptr<te::rst::Raster> > vecRaster = m_inputParameters.m_rasterVec;
189 
190  boost::shared_ptr<te::rst::Raster> auxRaster;
191  te::rst::Raster* output_raster = outParamsPtr->m_outputRasterPtr.get();
192  TERP_TRUE_OR_RETURN_FALSE( executeString( arithmetic_string, vecRaster, auxRaster, true ),
193  "Arithmetic string execution error" );
194 
195  // Copy result data to output raster
196 
197  bool normalize_output = m_inputParameters.m_normalize;
198 
199  const unsigned int nLines = (unsigned int)auxRaster->getNumberOfRows();
200  const unsigned int nCols = (unsigned int)auxRaster->getNumberOfColumns();
201  unsigned int line = 0;
202  unsigned int col = 0;
203  double value = 0;
204  te::rst::Raster& auxRasterRef = *auxRaster;
205  te::rst::Raster& outRasterRef = *output_raster;
206 
207  double outAllowedMin = 0;
208  double outAllowedMax = 0;
209  GetDataTypeRange( te::dt::DOUBLE_TYPE , outAllowedMin, outAllowedMax );
210 
211  if( normalize_output && ( output_raster->getBand(0)->getProperty()->getType() !=
213  {
214  // Calculating the output gain and offset
215 
216  double auxMin = DBL_MAX;
217  double auxMax = -1.0 * auxMin;
218 
219  for( line = 0 ; line < nLines ; ++line )
220  {
221  for( col = 0 ; col < nCols ; ++col )
222  {
223  auxRasterRef.getValue( col, line, value, 0 );
224 
225  if( auxMin > value ) auxMin = value;
226  if( auxMax < value ) auxMax = value;
227  }
228 
229  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
230  }
231 
232  double outputOffset = 0;
233  double outputGain = 1.0;
234  if( auxMax != auxMin )
235  {
236  outputOffset = -1.0 * auxMin;
237  outputGain = ( ( outAllowedMax - outAllowedMin ) / ( auxMax - auxMin ) );
238  }
239 
240  for( line = 0 ; line < nLines ; ++line )
241  {
242  for( col = 0 ; col < nCols ; ++col )
243  {
244  auxRasterRef.getValue( col, line, value, 0 );
245 
246  value += outputOffset;
247  value *= outputGain;
248 
249  value = MIN( value, outAllowedMax );
250  value = MAX( value, outAllowedMin );
251 
252  outRasterRef.setValue( col, line, value, 0 );
253  }
254 
255  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
256  }
257  }
258  else
259  {
260  for( line = 0 ; line < nLines ; ++line )
261  {
262  for( col = 0 ; col < nCols ; ++col )
263  {
264  auxRasterRef.getValue( col, line, value, 0 );
265 
266  value = MIN( value, outAllowedMax );
267  value = MAX( value, outAllowedMin );
268 
269  outRasterRef.setValue( col, line, value, 0 );
270  }
271 
272  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
273  }
274  }
275 
276  return true;
277  }
278 
279  void ArithmeticOperations::reset() throw( te::rp::Exception )
280  {
282  m_isInitialized = false;
283  }
284 
286  throw( te::rp::Exception )
287  {
288  reset();
289 
290  ArithmeticOperations::InputParameters const* inputParamsPtr = dynamic_cast<
291  ArithmeticOperations::InputParameters const* >( &inputParams );
292  TERP_TRUE_OR_THROW( inputParamsPtr, "Invalid paramters pointer" );
293 
294  m_inputParameters = *inputParamsPtr;
295 
296  // Checking the feeder
297 
299  "Invalid number of rasters" );
300 
301  for( std::size_t t = 0; t < m_inputParameters.m_rasterVec.size(); ++t )
302  {
304  "Invalid raster" )
305 
307  m_inputParameters.m_rasterVec[0]->getNumberOfRows(),
308  "Invalid raster" )
309 
310  TERP_TRUE_OR_RETURN_FALSE( m_inputParameters.m_rasterVec[t]->getNumberOfColumns() ==
311  m_inputParameters.m_rasterVec[0]->getNumberOfColumns(),
312  "Invalid raster" )
313  }
314 
315  // Checking the expression
316 
318  "Arithmetic string is empty" )
319 
320  boost::shared_ptr<te::rst::Raster> rasterNull;
322  m_inputParameters.m_rasterVec, rasterNull, false), "Invalid arithmetic string" )
323 
324  m_isInitialized = true;
325 
326  return true;
327  }
328 
330  {
331  return m_isInitialized;
332  }
333 
334  bool ArithmeticOperations::executeString( const std::string& aStr,
335  std::vector< boost::shared_ptr<te::rst::Raster> > inRasters,
336  boost::shared_ptr<te::rst::Raster>& outRaster,
337  bool generateOutput ) const
338  {
339  std::vector< std::string > infixTokensVec;
340  getTokensStrs( aStr, infixTokensVec );
341 
342  if( infixTokensVec.size() )
343  {
344  std::vector< std::string > postfixTokensVec;
345 
346  inFix2PostFix( infixTokensVec, postfixTokensVec );
347 
348  ExecStackT execStack;
349  unsigned int auxRasterIdx = 0;
350  unsigned int auxBandIdx = 0;
351  double auxRealValue = 0;
352 
353  for( unsigned int tIdx = 0 ; tIdx < postfixTokensVec.size() ; ++tIdx )
354  {
355  const std::string& curToken = postfixTokensVec[ tIdx ];
356 
357  if( isRasterBandToken( curToken, auxRasterIdx, auxBandIdx ) )
358  {
359  TERP_TRUE_OR_RETURN_FALSE( auxRasterIdx < inRasters.size(),
360  "Invalid raster index found at " + curToken );
361 
362  TERP_TRUE_OR_RETURN_FALSE( (std::size_t)auxBandIdx < inRasters[auxRasterIdx]->getNumberOfBands(),
363  "Invalid band index" );
364 
365  ExecStackElement auxEle;
366  auxEle.m_isRaster = true;
367  auxEle.m_raster = inRasters[auxRasterIdx];
368  auxEle.m_rasterBand = auxBandIdx;
369 
370  execStack.push( auxEle );
371  }
372  else if( isRealNumberToken( curToken, auxRealValue ) )
373  {
374  ExecStackElement auxEle;
375  auxEle.m_isRealNumber = true;
376  auxEle.m_realNumberValue = auxRealValue;
377 
378  execStack.push( auxEle );
379  }
380  else if( isBinaryOperator( curToken ) )
381  {
382  TERP_TRUE_OR_RETURN_FALSE( execBinaryOperator( curToken, execStack, generateOutput ),
383  "Operator " + curToken + " execution error" );
384  }
385  else if( isUnaryOperator( curToken ) )
386  {
387  TERP_TRUE_OR_RETURN_FALSE( execUnaryOperator( curToken, execStack, generateOutput ),
388  "Operator " + curToken + " execution error" );
389  }
390  else
391  {
392  TERP_LOG_AND_RETURN_FALSE( "Invalid operator found: " + curToken );
393  }
394  }
395 
396  TERP_TRUE_OR_RETURN_FALSE( execStack.size() == 1, "Invalid stack size" );
397  TERP_TRUE_OR_RETURN_FALSE( execStack.top().m_raster, "Stack result error" );
398 
399  outRaster = execStack.top().m_raster;
400  }
401 
402  return true;
403  }
404 
405  void ArithmeticOperations::inFix2PostFix( const std::vector< std::string >& input,
406  std::vector< std::string >& output ) const
407  {
408  output.clear();
409 
410  std::stack< std::string > auxStack;
411  const unsigned int inputSize = (unsigned int)input.size();
412 
413  for( unsigned int inIdx = 0 ; inIdx < inputSize ; ++inIdx )
414  {
415  const std::string& currInToken = input[ inIdx ];
416 
417  if( isOperator( currInToken ) )
418  {
419  while( ( ! auxStack.empty() ) && ( auxStack.top() != "(" ) )
420  {
421  if ( op1HasGreaterOrEqualPrecedence( auxStack.top(), currInToken ) )
422  {
423  output.push_back( auxStack.top() );
424 
425  auxStack.pop();
426  }
427  else
428  {
429  break;
430  }
431  }
432 
433  auxStack.push( currInToken );
434  }
435  else if( currInToken == "(" )
436  {
437  auxStack.push( currInToken );
438  }
439  else if( currInToken == ")" )
440  {
441  while ( ( ! auxStack.empty() ) && ( auxStack.top() != "(" ) )
442  {
443  output.push_back( auxStack.top() );
444 
445  auxStack.pop();
446  }
447 
448  if ( ! auxStack.empty() )
449  {
450  auxStack.pop();
451  }
452  }
453  else
454  {
455  output.push_back( currInToken );
456  }
457  }
458 
459  while ( ! auxStack.empty() )
460  {
461  output.push_back( auxStack.top() );
462 
463  auxStack.pop();
464  }
465  }
466 
467  void ArithmeticOperations::printTokens( const std::vector< std::string >& input ) const
468  {
469  std::cout << std::endl;
470 
471  for( unsigned int idx = 0 ; idx < input.size() ; ++idx )
472  {
473  std::cout << "[" << input[ idx ] << "]";
474  }
475 
476  std::cout << std::endl;
477  }
478 
479  bool ArithmeticOperations::isOperator( const std::string& inputToken ) const
480  {
481  return ( isBinaryOperator( inputToken ) ||
482  isUnaryOperator( inputToken ) );
483  }
484 
485  bool ArithmeticOperations::isBinaryOperator( const std::string& inputToken ) const
486  {
487  return ( ( inputToken == "+" ) || ( inputToken == "-" ) ||
488  ( inputToken == "*" ) || ( inputToken == "/" ) ) ?
489  true : false;
490  }
491 
492  bool ArithmeticOperations::isUnaryOperator( const std::string& inputToken ) const
493  {
494  return false;
495  }
496 
497  bool ArithmeticOperations::op1HasGreaterOrEqualPrecedence( const std::string& operator1,
498  const std::string& operator2 ) const
499  {
500  if( ( operator1 == "*" ) || ( operator1 == "/" ) )
501  {
502  return true;
503  }
504  else
505  {
506  if( ( operator2 == "+" ) || ( operator2 == "-" ) )
507  {
508  return true;
509  }
510  }
511 
512  return false;
513  }
514 
515  bool ArithmeticOperations::isRasterBandToken( const std::string& token, unsigned int& rasterIdx,
516  unsigned int& bandIdx ) const
517  {
518  if( token.size() < 4 ) return false;
519  if( token[ 0 ] != 'R' ) return false;
520 
521  std::string rasterIdxStr;
522  unsigned int tIdx = 1;
523 
524  while( ( tIdx < token.size() ) && isdigit( token[ tIdx ] ) )
525  {
526  rasterIdxStr.push_back( token[ tIdx ] );
527  ++tIdx;
528  }
529 
530  if( token[ tIdx ] != ':' ) return false;
531  ++tIdx;
532 
533  std::string bandIdxStr;
534 
535  while( ( tIdx < token.size() ) && isdigit( token[ tIdx ] ) )
536  {
537  bandIdxStr.push_back( token[ tIdx ] );
538  ++tIdx;
539  }
540 
541  if( ( rasterIdxStr.size() ) && ( bandIdxStr.size() ) )
542  {
543  rasterIdx = (unsigned int)atoi( rasterIdxStr.c_str() );
544  bandIdx = (unsigned int)atoi( bandIdxStr.c_str() );
545  return true;
546  }
547  else
548  {
549  return false;
550  }
551  }
552 
553  bool ArithmeticOperations::execBinaryOperator( const std::string& token, ExecStackT&
554  execStack, bool generateOutput ) const
555  {
556  if( execStack.size() < 2 )
557  {
558  return false;
559  }
560  else
561  {
562  ExecStackElement sElem1 = execStack.top();
563  execStack.pop();
564 
565  ExecStackElement sElem2 = execStack.top();
566  execStack.pop();
567 
568  if( token == "+" )
569  {
570  if( ( sElem1.m_isRaster ) && ( sElem2.m_isRaster ) )
571  {
572  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
573  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
574 
575  ExecStackElement outElement;
576  outElement.m_isRaster = true;
577  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
578  "Raster allocation error" );
579 
580  te::rst::Raster& outRasterRef = *outElement.m_raster;
581  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
582  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
583 
584  if( generateOutput )
585  {
586  unsigned int line = 0;
587  unsigned int col = 0;
588  double value1 = 0;
589  double value2 = 0;
590 
591  for( line = 0 ; line < nLines ; ++line )
592  {
593  for( col = 0 ; col < nCols ; ++col )
594  {
595  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
596  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
597 
598  outRasterRef.setValue( col, line, value1 + value2, 0 );
599  }
600 
601  // TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
602  }
603  }
604 
605  execStack.push( outElement );
606  }
607  else if( ( sElem1.m_isRaster ) && ( sElem2.m_isRealNumber ) )
608  {
609  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
610  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
611 
612  ExecStackElement outElement;
613  outElement.m_isRaster = true;
614  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
615  "Raster allocation error" );
616 
617  te::rst::Raster& outRasterRef = *outElement.m_raster;
618  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
619 
620  if( generateOutput )
621  {
622  unsigned int line = 0;
623  unsigned int col = 0;
624  double value1 = 0;
625 
626  for( line = 0 ; line < nLines ; ++line )
627  {
628  for( col = 0 ; col < nCols ; ++col )
629  {
630  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
631 
632  outRasterRef.setValue( col, line, value1 + sElem2.m_realNumberValue, 0 );
633  }
634 
635  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
636  }
637  }
638 
639  execStack.push( outElement );
640  }
641  else if( ( sElem1.m_isRealNumber ) && ( sElem2.m_isRaster ) )
642  {
643  const unsigned int nLines = (unsigned int) sElem2.m_raster->getNumberOfRows();
644  const unsigned int nCols = (unsigned int) sElem2.m_raster->getNumberOfColumns();
645 
646  ExecStackElement outElement;
647  outElement.m_isRaster = true;
648  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
649  "Raster allocation error" );
650 
651  te::rst::Raster& outRasterRef = *outElement.m_raster;
652  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
653 
654  if( generateOutput )
655  {
656  unsigned int line = 0;
657  unsigned int col = 0;
658  double value2 = 0;
659 
660  for( line = 0 ; line < nLines ; ++line )
661  {
662  for( col = 0 ; col < nCols ; ++col )
663  {
664  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
665 
666  outRasterRef.setValue( col, line, value2 + sElem1.m_realNumberValue, 0 );
667  }
668 
669  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
670  }
671  }
672 
673  execStack.push( outElement );
674  }
675  else
676  {
677  TERP_LOG_AND_RETURN_FALSE( "Invalid operation" );
678  }
679  }
680  else if( token == "-" )
681  {
682  if( ( sElem1.m_isRaster ) && ( sElem2.m_isRaster ) )
683  {
684  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
685  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
686 
687  ExecStackElement outElement;
688  outElement.m_isRaster = true;
689  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
690  "Raster allocation error" );
691 
692  te::rst::Raster& outRasterRef = *outElement.m_raster;
693  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
694  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
695 
696  if( generateOutput )
697  {
698  unsigned int line = 0;
699  unsigned int col = 0;
700  double value1 = 0;
701  double value2 = 0;
702 
703  for( line = 0 ; line < nLines ; ++line )
704  {
705  for( col = 0 ; col < nCols ; ++col )
706  {
707  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
708  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
709 
710  outRasterRef.setValue( col, line, value2 - value1, 0 );
711  }
712 
713  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
714  }
715  }
716 
717  execStack.push( outElement );
718  }
719  else if( ( sElem1.m_isRaster ) && ( sElem2.m_isRealNumber ) )
720  {
721  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
722  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
723 
724  ExecStackElement outElement;
725  outElement.m_isRaster = true;
726  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
727  "Raster allocation error" );
728 
729  te::rst::Raster& outRasterRef = *outElement.m_raster;
730  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
731 
732  if( generateOutput )
733  {
734  unsigned int line = 0;
735  unsigned int col = 0;
736  double value1 = 0;
737 
738  for( line = 0 ; line < nLines ; ++line )
739  {
740  for( col = 0 ; col < nCols ; ++col )
741  {
742  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
743 
744  outRasterRef.setValue( col, line, sElem2.m_realNumberValue - value1, 0 );
745  }
746 
747  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
748  }
749  }
750 
751  execStack.push( outElement );
752  }
753  else if( ( sElem1.m_isRealNumber ) && ( sElem2.m_isRaster ) )
754  {
755  const unsigned int nLines = (unsigned int) sElem2.m_raster->getNumberOfRows();
756  const unsigned int nCols = (unsigned int)sElem2.m_raster->getNumberOfColumns();
757 
758  ExecStackElement outElement;
759  outElement.m_isRaster = true;
760  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
761  "Raster allocation error" );
762 
763  te::rst::Raster& outRasterRef = *outElement.m_raster;
764  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
765 
766  if( generateOutput )
767  {
768  unsigned int line = 0;
769  unsigned int col = 0;
770  double value2 = 0;
771 
772  for( line = 0 ; line < nLines ; ++line )
773  {
774  for( col = 0 ; col < nCols ; ++col )
775  {
776  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
777 
778  outRasterRef.setValue( col, line, value2 - sElem1.m_realNumberValue, 0 );
779  }
780 
781  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
782  }
783  }
784 
785  execStack.push( outElement );
786  }
787  else
788  {
789  TERP_LOG_AND_RETURN_FALSE( "Invalid operation" );
790  }
791  }
792  else if( token == "*" )
793  {
794  if( ( sElem1.m_isRaster ) && ( sElem2.m_isRaster ) )
795  {
796  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
797  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
798 
799  ExecStackElement outElement;
800  outElement.m_isRaster = true;
801  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
802  "Raster allocation error" );
803 
804  te::rst::Raster& outRasterRef = *outElement.m_raster;
805  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
806  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
807 
808  if( generateOutput )
809  {
810  unsigned int line = 0;
811  unsigned int col = 0;
812  double value1 = 0;
813  double value2 = 0;
814 
815  for( line = 0 ; line < nLines ; ++line )
816  {
817  for( col = 0 ; col < nCols ; ++col )
818  {
819  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
820  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
821 
822  outRasterRef.setValue( col, line, value1 * value2, 0 );
823  }
824 
825  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
826  }
827  }
828 
829  execStack.push( outElement );
830  }
831  else if( ( sElem1.m_isRaster ) && ( sElem2.m_isRealNumber ) )
832  {
833  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
834  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
835 
836  ExecStackElement outElement;
837  outElement.m_isRaster = true;
838  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
839  "Raster allocation error" );
840 
841  te::rst::Raster& outRasterRef = *outElement.m_raster;
842  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
843 
844  if( generateOutput )
845  {
846  unsigned int line = 0;
847  unsigned int col = 0;
848  double value1 = 0;
849 
850  for( line = 0 ; line < nLines ; ++line )
851  {
852  for( col = 0 ; col < nCols ; ++col )
853  {
854  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
855 
856  outRasterRef.setValue( col, line, value1 * sElem2.m_realNumberValue, 0 );
857  }
858 
859  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
860  }
861  }
862 
863  execStack.push( outElement );
864  }
865  else if( ( sElem1.m_isRealNumber ) && ( sElem2.m_isRaster ) )
866  {
867  const unsigned int nLines = (unsigned int) sElem2.m_raster->getNumberOfRows();
868  const unsigned int nCols = (unsigned int) sElem2.m_raster->getNumberOfColumns();
869 
870  ExecStackElement outElement;
871  outElement.m_isRaster = true;
872  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
873  "Raster allocation error" );
874 
875  te::rst::Raster& outRasterRef = *outElement.m_raster;
876  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
877 
878  if( generateOutput )
879  {
880  unsigned int line = 0;
881  unsigned int col = 0;
882  double value2 = 0;
883 
884  for( line = 0 ; line < nLines ; ++line )
885  {
886  for( col = 0 ; col < nCols ; ++col )
887  {
888  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
889 
890  outRasterRef.setValue( col, line, value2 * sElem1.m_realNumberValue, 0 );
891  }
892 
893  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
894  }
895  }
896 
897  execStack.push( outElement );
898  }
899  else
900  {
901  TERP_LOG_AND_RETURN_FALSE( "Invalid operation" );
902  }
903  }
904  else if( token == "/" )
905  {
906  if( ( sElem1.m_isRaster ) && ( sElem2.m_isRaster ) )
907  {
908  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
909  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
910 
911  ExecStackElement outElement;
912  outElement.m_isRaster = true;
913  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
914  "Raster allocation error" );
915 
916  te::rst::Raster& outRasterRef = *outElement.m_raster;
917  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
918  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
919 
920  if( generateOutput )
921  {
922  unsigned int line = 0;
923  unsigned int col = 0;
924  double value1 = 0;
925  double value2 = 0;
926 
927  for( line = 0 ; line < nLines ; ++line )
928  {
929  for( col = 0 ; col < nCols ; ++col )
930  {
931  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
932  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
933 
934  outRasterRef.setValue( col, line, value2 / value1, 0 );
935  }
936 
937  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
938  }
939  }
940 
941  execStack.push( outElement );
942  }
943  else if( ( sElem1.m_isRaster ) && ( sElem2.m_isRealNumber ) )
944  {
945  const unsigned int nLines = (unsigned int) sElem1.m_raster->getNumberOfRows();
946  const unsigned int nCols = (unsigned int) sElem1.m_raster->getNumberOfColumns();
947 
948  ExecStackElement outElement;
949  outElement.m_isRaster = true;
950  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
951  "Raster allocation error" );
952 
953  te::rst::Raster& outRasterRef = *outElement.m_raster;
954  te::rst::Raster& inRaster1Ref = *sElem1.m_raster;
955 
956  if( generateOutput )
957  {
958  unsigned int line = 0;
959  unsigned int col = 0;
960  double value1 = 0;
961 
962  for( line = 0 ; line < nLines ; ++line )
963  {
964  for( col = 0 ; col < nCols ; ++col )
965  {
966  inRaster1Ref.getValue( col, line, value1, sElem1.m_rasterBand );
967 
968  outRasterRef.setValue( col, line, sElem2.m_realNumberValue / value1, 0 );
969  }
970 
971  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
972  }
973  }
974 
975  execStack.push( outElement );
976  }
977  else if( ( sElem1.m_isRealNumber ) && ( sElem2.m_isRaster ) )
978  {
979  const unsigned int nLines = (unsigned int) sElem2.m_raster->getNumberOfRows();
980  const unsigned int nCols = (unsigned int) sElem2.m_raster->getNumberOfColumns();
981 
982  ExecStackElement outElement;
983  outElement.m_isRaster = true;
984  TERP_TRUE_OR_RETURN_FALSE( allocResultRaster( nLines, nCols, outElement.m_raster ),
985  "Raster allocation error" );
986 
987  te::rst::Raster& outRasterRef = *outElement.m_raster;
988  te::rst::Raster& inRaster2Ref = *sElem2.m_raster;
989 
990  if( generateOutput )
991  {
992  unsigned int line = 0;
993  unsigned int col = 0;
994  double value2 = 0;
995 
996  for( line = 0 ; line < nLines ; ++line )
997  {
998  for( col = 0 ; col < nCols ; ++col )
999  {
1000  inRaster2Ref.getValue( col, line, value2, sElem2.m_rasterBand );
1001 
1002  outRasterRef.setValue( col, line, value2 / sElem1.m_realNumberValue, 0 );
1003  }
1004 
1005  //TERP_FALSE_OR_RETURN( progress_.Increment(), "Canceled by the user" );
1006  }
1007  }
1008 
1009  execStack.push( outElement );
1010  }
1011  else
1012  {
1013  TERP_LOG_AND_RETURN_FALSE( "Invalid operation" );
1014  }
1015  }
1016  else
1017  {
1018  TERP_LOG_AND_RETURN_FALSE( "Invalid operator" );
1019  }
1020  }
1021 
1022  return true;
1023  }
1024 
1025  bool ArithmeticOperations::execUnaryOperator( const std::string& token, ExecStackT&
1026  execStack, bool generateOutput ) const
1027  {
1028  return false;
1029  }
1030 
1031  bool ArithmeticOperations::isRealNumberToken( const std::string& token, double& realValue ) const
1032  {
1033  if( token.size() == 0 ) return false;
1034  bool hasDot = false;
1035 
1036  unsigned int initIdx = 0;
1037  if( ( token[ 0 ] == '+' ) || ( token[ 0 ] == '-' ) )
1038  {
1039  if( token.size() == 1 ) return false;
1040  initIdx = 1;
1041  }
1042 
1043  for( unsigned int tIdx = initIdx ; tIdx < token.size() ; ++tIdx )
1044  {
1045  if( token[ tIdx ] == '.' )
1046  {
1047  if( hasDot ) return false;
1048  hasDot = true;
1049  }
1050  else if( ! isdigit( token[ tIdx ] ) ) return false;
1051  }
1052 
1053  realValue = atof( token.c_str() );
1054 
1055  return true;
1056  }
1057 
1058  bool ArithmeticOperations::allocResultRaster( unsigned int nLines, unsigned int nCols,
1059  boost::shared_ptr<te::rst::Raster>& rasterPtr ) const
1060  {
1061  std::map<std::string, std::string> rinfo;
1062 
1063  rinfo["MEM_RASTER_NROWS"] = boost::lexical_cast<std::string>(nLines);
1064  rinfo["MEM_RASTER_NCOLS"] = boost::lexical_cast<std::string>(nCols);
1065  rinfo["MEM_RASTER_DATATYPE"] = te::common::Convert2String(te::dt::DOUBLE_TYPE);
1066  rinfo["MEM_RASTER_NBANDS"] = "1";
1067 
1068  rasterPtr.reset(te::rst::RasterFactory::make("MEM", 0, std::vector<te::rst::BandProperty*>(), rinfo));
1069 
1070  return true;
1071  }
1072 
1073  void ArithmeticOperations::getTokensStrs( const std::string& inputStr,
1074  std::vector< std::string >& outTokens ) const
1075  {
1076  outTokens.clear();
1077 
1078  const unsigned int inputStrSize = (unsigned int)inputStr.size();
1079  std::string bufferStr;
1080 
1081  for( unsigned int inputStrIdx = 0 ; inputStrIdx < inputStrSize ;
1082  ++inputStrIdx )
1083  {
1084  if( inputStr[ inputStrIdx ] == ' ' )
1085  {
1086  // flush the last formed token
1087  if( bufferStr.size() )
1088  {
1089  outTokens.push_back( bufferStr );
1090  bufferStr.clear();
1091  }
1092  }
1093  else
1094  {
1095  if( ( inputStr[ inputStrIdx ] == '+' ) ||
1096  ( inputStr[ inputStrIdx ] == '-' ) )
1097  {
1098  bufferStr.append( inputStr.substr( inputStrIdx, 1 ) );
1099  }
1100  else if( ( inputStr[ inputStrIdx ] == ')' ) ||
1101  ( inputStr[ inputStrIdx ] == '(' ) ||
1102  isOperator( inputStr.substr( inputStrIdx, 1 ) ) )
1103  {
1104  // flush the last formed token
1105  if( bufferStr.size() )
1106  {
1107  outTokens.push_back( bufferStr );
1108  bufferStr.clear();
1109  }
1110 
1111  outTokens.push_back( inputStr.substr( inputStrIdx, 1 ) );
1112  }
1113  else
1114  {
1115  bufferStr.append( inputStr.substr( inputStrIdx, 1 ) );
1116  }
1117  }
1118  }
1119 
1120  if( bufferStr.size() )
1121  {
1122  outTokens.push_back( bufferStr );
1123  }
1124  }
1125  }
1126 }
void getTokensStrs(const std::string &inputStr, std::vector< std::string > &outTokens) const
Split the input string into a vector of token strings.
void printTokens(const std::vector< std::string > &input) const
Print tokens to stout.
virtual void setValue(unsigned int c, unsigned int r, const double value, std::size_t b=0)
Sets the attribute value in a band of a cell.
Definition: Raster.cpp:233
std::string m_rType
Output raster data source type (as described in te::raster::RasterFactory ).
bool isUnaryOperator(const std::string &inputToken) const
Returns true if the given token is a unary operator.
const OutputParameters & operator=(const OutputParameters &params)
AbstractParameters * clone() const
Create a clone copy of this instance.
A raster band description.
Definition: BandProperty.h:61
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
bool isBinaryOperator(const std::string &inputToken) const
Returns true if the given token is a binary operator.
void reset()
Clear all internal allocated objects and reset the algorithm to its initial state.
void TERPEXPORT GetDataTypeRange(const int dataType, double &min, double &max)
Returns the real data type range (all values that can be represented by the given data type)...
Definition: Functions.h:146
bool m_isInitialized
Tells if this instance is initialized.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
Raster Processing algorithm output parameters base interface.
#define MIN(a, b)
Macro that returns min between two values.
bool execUnaryOperator(const std::string &token, ExecStackT &execStack, bool generateOutput) const
Execute the given unary operator using the current given execution stack.
bool m_normalize
Output values normalization will be performed to fit the allowed values range (default:false).
ArithmeticOperations::InputParameters m_inputParameters
Input execution parameters.
std::map< std::string, std::string > m_rInfo
The necessary information to create the output rasters (as described in te::raster::RasterFactory).
bool allocResultRaster(unsigned int nLines, unsigned int nCols, boost::shared_ptr< te::rst::Raster > &rasterPtr) const
Allocate a new RAM memory raster.
std::vector< boost::shared_ptr< te::rst::Raster > > m_rasterVec
Input rasters vector.
Performs arithmetic operation over raster data.
bool m_enableProgress
Enable/Disable the progress interface (default:false).
#define MAX(a, b)
Macro that returns max between two values.
bool m_isRaster
true if this is a raster pointer element.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
std::stack< ExecStackElement > ExecStackT
Execution stack type definition.
Raster Processing functions.
#define TERP_TRUE_OR_RETURN_FALSE(value, message)
Checks if value is true. For false values a warning message will be logged and a return of context wi...
Definition: Macros.h:183
const Algorithm & operator=(const Algorithm &)
Definition: Algorithm.cpp:43
An abstract class for raster data strucutures.
Definition: Raster.h:71
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:370
ArithmeticOperations output parameters.
bool isRasterBandToken(const std::string &token, unsigned int &rasterIdx, unsigned int &bandIdx) const
Returns true if the given token is a raster data token.
virtual void getValue(unsigned int c, unsigned int r, double &value, std::size_t b=0) const
Returns the attribute value of a band of a cell.
Definition: Raster.cpp:228
Abstract parameters base interface.
bool executeString(const std::string &aStr, std::vector< boost::shared_ptr< te::rst::Raster > > inRasters, boost::shared_ptr< te::rst::Raster > &outRaster, bool generateOutput) const
Execute the automata parsing the given input string.
#define TERP_LOG_AND_RETURN_FALSE(message)
Logs a warning message will and return false.
Definition: Macros.h:236
bool isRealNumberToken(const std::string &token, double &realValue) const
Returns true if the given token is a real number.
std::auto_ptr< te::rst::Raster > m_outputRasterPtr
The generated output registered raster.
static Raster * make()
It creates and returns an empty raster with default raster driver.
void inFix2PostFix(const std::vector< std::string > &input, std::vector< std::string > &output) const
Convert the input tokens vector from the infix notation to postfix notation.
Raster Processing algorithm input parameters base interface.
bool op1HasGreaterOrEqualPrecedence(const std::string &operator1, const std::string &operator2) const
Returns true if operator1 has greater of equal precedence over operator2.
bool initialize(const AlgorithmInputParameters &inputParams)
Initialize the algorithm instance making it ready for execution.
int getType() const
It returns the data type of the elements in the band.
Definition: BandProperty.h:113
bool execBinaryOperator(const std::string &token, ExecStackT &execStack, bool generateOutput) const
Execute the given binary operator using the current given execution stack.
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:51
bool isInitialized() const
Returns true if the algorithm instance is initialized and ready for execution.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
bool isOperator(const std::string &inputToken) const
Returns true if the given token is an operator.
bool m_isRealNumber
true if this is a real number element.
bool execute(AlgorithmOutputParameters &outputParams)
Executes the algorithm using the supplied parameters.
const InputParameters & operator=(const InputParameters &params)
ArithmeticOperations input parameters.
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149
boost::shared_ptr< te::rst::Raster > m_raster
Raster pointer.
AbstractParameters * clone() const
Create a clone copy of this instance.
std::string m_arithmeticString
Arithmetic string.