1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License:  LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossimEquationCombiner.cpp 23407 2015-07-06 15:59:23Z okramer $
12 
13 #include <cstdlib>
14 #include <sstream>
15 using namespace std;
16 
17 #include <ossim/imaging/ossimEquationCombiner.h>
18 #include <ossim/imaging/ossimCastTileSourceFilter.h>
19 #include <ossim/imaging/ossimImageDataFactory.h>
20 #include <ossim/imaging/ossimConvolutionSource.h>
21 #include <ossim/imaging/ossimSubImageTileSource.h>
22 #include <ossim/base/ossimStringProperty.h>
23 #include <ossim/matrix/newmatio.h>
24 #include <ossim/base/ossimScalarTypeLut.h>
25 #include <ossim/base/ossimNotifyContext.h>
26 
27 RTTI_DEF1(ossimEquationCombiner, "ossimEquationCombiner", ossimImageCombiner);
28 
29 static const char* EQUATION_KW = "equation";
30 
31 
32 class ossimBinaryOpAdd : public ossimEquationCombiner::ossimBinaryOp
33 {
34 public:
apply(double v1,double v2) const35    virtual double apply(double v1, double v2)const
36       {
37          return v1 + v2;
38       }
39 };
40 
41 class ossimBinaryOpAnd : public ossimEquationCombiner::ossimBinaryOp
42 {
43 public:
apply(double v1,double v2) const44    virtual double apply(double v1, double v2)const
45       {
46          return (double)(((ossim_uint32)v1) & ((ossim_uint32)v2));
47       }
48 };
49 
50 class ossimBinaryOpOr : public ossimEquationCombiner::ossimBinaryOp
51 {
52 public:
apply(double v1,double v2) const53    virtual double apply(double v1, double v2)const
54       {
55          return (double)(((ossim_uint32)v1) | ((ossim_uint32)v2));
56       }
57 };
58 
59 class ossimBinaryOpXor : public ossimEquationCombiner::ossimBinaryOp
60 {
61 public:
apply(double v1,double v2) const62    virtual double apply(double v1, double v2)const
63       {
64          return (double)(((ossim_uint32)v1) ^ ((ossim_uint32)v2));
65       }
66 };
67 
68 class ossimBinaryOpSub : public ossimEquationCombiner::ossimBinaryOp
69 {
70 public:
apply(double v1,double v2) const71    virtual double apply(double v1, double v2)const
72       {
73          return v1 - v2;
74       }
75 };
76 
77 class ossimBinaryOpMax : public ossimEquationCombiner::ossimBinaryOp
78 {
79 public:
apply(double v1,double v2) const80    virtual double apply(double v1, double v2)const
81       {
82          return std::max(v1, v2);
83       }
84 };
85 
86 class ossimBinaryOpMin : public ossimEquationCombiner::ossimBinaryOp
87 {
88 public:
apply(double v1,double v2) const89    virtual double apply(double v1, double v2)const
90       {
91          return std::min(v1, v2);
92       }
93 };
94 
95 class ossimBinaryOpMul : public ossimEquationCombiner::ossimBinaryOp
96 {
97 public:
apply(double v1,double v2) const98    virtual double apply(double v1, double v2)const
99       {
100          return v1 * v2;
101       }
102 };
103 
104 class ossimBinaryOpDiv : public ossimEquationCombiner::ossimBinaryOp
105 {
106 public:
apply(double v1,double v2) const107    virtual double apply(double v1, double v2)const
108       {
109          if(fabs(v2)>FLT_EPSILON)
110             return v1 / v2;
111 
112          return 1.0/FLT_EPSILON;
113       }
114 };
115 
116 class ossimBinaryOpMod : public ossimEquationCombiner::ossimBinaryOp
117 {
118 public:
apply(double v1,double v2) const119    virtual double apply(double v1, double v2)const
120       {
121          if(fabs(v2)>FLT_EPSILON)
122             return fmod(v1,v2);
123 
124          return 1.0/FLT_EPSILON;
125       }
126 };
127 
128 class ossimBinaryOpPow : public ossimEquationCombiner::ossimBinaryOp
129 {
130 public:
apply(double v1,double v2) const131    virtual double apply(double v1, double v2)const
132       {
133          return pow(v1, v2);
134       }
135 };
136 // boolean operators
137 class ossimBinaryOpEqual : public ossimEquationCombiner::ossimBinaryOp
138 {
139 public:
apply(double v1,double v2) const140    virtual double apply(double v1, double v2)const
141       {
142          return (v1==v2)?1.0:0.0;
143       }
144 };
145 class ossimBinaryOpGreater : public ossimEquationCombiner::ossimBinaryOp
146 {
147 public:
apply(double v1,double v2) const148    virtual double apply(double v1, double v2)const
149       {
150          return (v1>v2)?1.0:0.0;
151       }
152 };
153 class ossimBinaryOpGreaterOrEqual : public ossimEquationCombiner::ossimBinaryOp
154 {
155 public:
apply(double v1,double v2) const156    virtual double apply(double v1, double v2)const
157       {
158          return (v1>=v2)?1.0:0.0;
159       }
160 };
161 class ossimBinaryOpLess : public ossimEquationCombiner::ossimBinaryOp
162 {
163 public:
apply(double v1,double v2) const164    virtual double apply(double v1, double v2)const
165       {
166          return (v1<v2)?1.0:0.0;
167       }
168 };
169 class ossimBinaryOpLessOrEqual : public ossimEquationCombiner::ossimBinaryOp
170 {
171 public:
apply(double v1,double v2) const172    virtual double apply(double v1, double v2)const
173       {
174          return (v1<=v2)?1.0:0.0;
175       }
176 };
177 class ossimBinaryOpDifferent : public ossimEquationCombiner::ossimBinaryOp
178 {
179 public:
apply(double v1,double v2) const180    virtual double apply(double v1, double v2)const
181       {
182          return (v1!=v2)?1.0:0.0;
183       }
184 };
185 class ossimUnaryOpNot : public ossimEquationCombiner::ossimUnaryOp
186 {
187 public:
apply(double v) const188    virtual double apply(double v)const
189       {
190          return 1-v;
191       }
192 };
193 
194 class ossimUnaryOpAbs : public ossimEquationCombiner::ossimUnaryOp
195 {
196 public:
apply(double v) const197    virtual double apply(double v)const
198       {
199          return fabs(v);
200       }
201 };
202 
203 class ossimUnaryOpOnesComplement : public ossimEquationCombiner::ossimUnaryOp
204 {
205 public:
apply(double v) const206    virtual double apply(double v)const
207       {
208          return (double)((ossim_uint8)~((ossim_uint8)v));
209       }
210 };
211 
212 class ossimUnaryOpLog : public ossimEquationCombiner::ossimUnaryOp
213 {
214 public:
apply(double v) const215    virtual double apply(double v)const
216       {
217          return log(v);
218       }
219 };
220 
221 class ossimUnaryOpLog10 : public ossimEquationCombiner::ossimUnaryOp
222 {
223 public:
apply(double v) const224    virtual double apply(double v)const
225       {
226          return log10(v);
227       }
228 };
229 
230 class ossimUnaryOpNeg : public ossimEquationCombiner::ossimUnaryOp
231 {
232 public:
apply(double v) const233    virtual double apply(double v)const
234       {
235          return -v;
236       }
237 };
238 
239 class ossimUnaryOpSqrt : public ossimEquationCombiner::ossimUnaryOp
240 {
241 public:
apply(double v) const242    virtual double apply(double v)const
243       {
244          if(v >= 0)
245          {
246             return sqrt(v);
247          }
248 
249          return -1;
250       }
251 };
252 
253 class ossimUnaryOpExp : public ossimEquationCombiner::ossimUnaryOp
254 {
255 public:
apply(double v) const256    virtual double apply(double v)const
257       {
258          return exp(v);
259       }
260 };
261 
262 class ossimUnaryOpSin : public ossimEquationCombiner::ossimUnaryOp
263 {
264 public:
apply(double v) const265    virtual double apply(double v)const
266       {
267          return sin(v);
268       }
269 };
270 
271 class ossimUnaryOpSind : public ossimEquationCombiner::ossimUnaryOp
272 {
273 public:
apply(double v) const274    virtual double apply(double v)const
275       {
276          return sin(v*M_PI/180.0);
277       }
278 };
279 
280 class ossimUnaryOpASin : public ossimEquationCombiner::ossimUnaryOp
281 {
282 public:
apply(double v) const283    virtual double apply(double v)const
284       {
285          if(v > 1) v = 1;
286          if(v < -1) v = -1;
287          return asin(v);
288       }
289 };
290 
291 class ossimUnaryOpASind : public ossimEquationCombiner::ossimUnaryOp
292 {
293 public:
apply(double v) const294    virtual double apply(double v)const
295       {
296          if(v > 1) v = 1;
297          if(v < -1) v = -1;
298          return (180/M_PI)*asin(v);
299       }
300 };
301 
302 class ossimUnaryOpACos : public ossimEquationCombiner::ossimUnaryOp
303 {
304 public:
apply(double v) const305    virtual double apply(double v)const
306       {
307          if(v > 1) v = 1;
308          if(v < -1) v = -1;
309          return acos(v);
310       }
311 };
312 
313 class ossimUnaryOpACosd : public ossimEquationCombiner::ossimUnaryOp
314 {
315 public:
apply(double v) const316    virtual double apply(double v)const
317       {
318          if(v > 1) v = 1;
319          if(v < -1) v = -1;
320          return (180/M_PI)*acos(v);
321       }
322 };
323 
324 class ossimUnaryOpCos : public ossimEquationCombiner::ossimUnaryOp
325 {
326 public:
apply(double v) const327    virtual double apply(double v)const
328       {
329          return cos(v);
330       }
331 };
332 
333 class ossimUnaryOpCosd : public ossimEquationCombiner::ossimUnaryOp
334 {
335 public:
apply(double v) const336    virtual double apply(double v)const
337       {
338          return cos(v*M_PI/180.0);
339       }
340 };
341 
342 class ossimUnaryOpTan : public ossimEquationCombiner::ossimUnaryOp
343 {
344 public:
apply(double v) const345    virtual double apply(double v)const
346       {
347          return tan(v);
348       }
349 };
350 
351 class ossimUnaryOpTand : public ossimEquationCombiner::ossimUnaryOp
352 {
353 public:
apply(double v) const354    virtual double apply(double v)const
355       {
356          return tan(v*M_PI/180.0);
357       }
358 };
359 
360 class ossimUnaryOpATan : public ossimEquationCombiner::ossimUnaryOp
361 {
362 public:
apply(double v) const363    virtual double apply(double v)const
364       {
365          return atan(v);
366       }
367 };
368 
369 class ossimUnaryOpATand : public ossimEquationCombiner::ossimUnaryOp
370 {
371 public:
apply(double v) const372    virtual double apply(double v)const
373       {
374          return (180/M_PI)*atan(v);
375       }
376 };
377 
378 
ossimEquationCombiner()379 ossimEquationCombiner::ossimEquationCombiner()
380    :ossimImageCombiner(),
381     theOutputScalarType(OSSIM_FLOAT64),
382     theEquation(""),
383     theLexer(NULL),
384     theTile(NULL),
385     theCastFilter(NULL),
386     theCastOutputFilter(NULL),
387     theCurrentId(0),
388     theCurrentResLevel(0)
389 {
390    theLexer      = new ossimEquTokenizer;
391    theCastFilter = new ossimCastTileSourceFilter;
392    theCastFilter->setOutputScalarType(OSSIM_FLOAT64);
393 }
394 
ossimEquationCombiner(ossimConnectableObject::ConnectableObjectList & inputs)395 ossimEquationCombiner::ossimEquationCombiner(ossimConnectableObject::ConnectableObjectList& inputs)
396    :ossimImageCombiner(inputs),
397     theOutputScalarType(OSSIM_FLOAT64),
398     theEquation(""),
399     theLexer(NULL),
400     theTile(NULL),
401     theCastFilter(NULL),
402     theCastOutputFilter(NULL),
403     theCurrentId(0),
404     theCurrentResLevel(0)
405 {
406    theLexer      = new ossimEquTokenizer;
407    theCastFilter = new ossimCastTileSourceFilter;
408    theCastFilter->setOutputScalarType(OSSIM_FLOAT64);
409 }
410 
~ossimEquationCombiner()411 ossimEquationCombiner::~ossimEquationCombiner()
412 {
413    if(theLexer)
414    {
415       delete theLexer;
416       theLexer = NULL;
417    }
418 
419    if(theCastFilter.valid())
420    {
421       theCastFilter->disconnect();
422       theCastFilter = 0;
423    }
424 
425    if(theCastOutputFilter.valid())
426    {
427       theCastOutputFilter->disconnect();
428       theCastOutputFilter = 0;
429    }
430    // make sure they are cleared
431    clearStacks();
432 }
433 
getNullPixelValue(ossim_uint32 band) const434 double ossimEquationCombiner::getNullPixelValue(ossim_uint32 band)const
435 {
436 
437    if(theEquation == "")
438    {
439       if(getInput())
440       {
441          ossimImageSource* inter = PTR_CAST(ossimImageSource, getInput());
442          if(inter)
443          {
444             return inter->getNullPixelValue(band);
445          }
446       }
447    }
448    return ossim::defaultNull(getOutputScalarType());
449 }
450 
getMinPixelValue(ossim_uint32 band) const451 double ossimEquationCombiner::getMinPixelValue(ossim_uint32 band)const
452 {
453    if(theEquation == "")
454    {
455       if(getInput())
456       {
457          ossimImageSource* inter = PTR_CAST(ossimImageSource, getInput());
458          if(inter)
459          {
460             return inter->getMinPixelValue(band);
461          }
462       }
463    }
464    return ossim::defaultMin(getOutputScalarType());
465 }
466 
getMaxPixelValue(ossim_uint32 band) const467 double ossimEquationCombiner::getMaxPixelValue(ossim_uint32 band)const
468 {
469    if(theEquation == "")
470    {
471       if(getInput())
472       {
473          ossimImageSource* inter = PTR_CAST(ossimImageSource, getInput());
474          if(inter)
475          {
476             return inter->getMaxPixelValue(band);
477          }
478       }
479    }
480    return ossim::defaultMax(getOutputScalarType());
481 }
482 
getOutputScalarType() const483 ossimScalarType ossimEquationCombiner::getOutputScalarType() const
484 {
485 
486    if(theEquation == "")
487    {
488       if(getInput())
489       {
490          ossimImageSource* inter = PTR_CAST(ossimImageSource, getInput());
491          if(inter)
492          {
493             return inter->getOutputScalarType();
494          }
495       }
496    }
497 
498    return theOutputScalarType;
499 }
500 
501 
getTile(const ossimIrect & tileRect,ossim_uint32 resLevel)502 ossimRefPtr<ossimImageData> ossimEquationCombiner::getTile(
503    const ossimIrect& tileRect,
504    ossim_uint32 resLevel)
505 {
506    if(!theTile)
507    {
508       initialize();
509    }
510    long w = tileRect.width();
511    long h = tileRect.height();
512    long tw = theTile->getWidth();
513    long th = theTile->getHeight();
514 
515    if(theEquation != "")
516    {
517       theTile->setImageRectangle(tileRect);
518 
519       if(w*h != tw*th)
520       {
521          theTile->initialize();
522       }
523       else
524       {
525          theTile->makeBlank();
526       }
527       theCurrentResLevel = resLevel;
528 
529       ossimRefPtr<ossimImageData> outputTile =  parseEquation();
530 
531       if(theCastOutputFilter.valid())
532       {
533          outputTile = theCastOutputFilter->applyCast(outputTile);
534       }
535 
536       return outputTile;
537    }
538    else
539    {
540       if(getInput())
541       {
542          ossimImageSource* inter =
543             PTR_CAST(ossimImageSource, getInput());
544          if(inter)
545          {
546             return inter->getTile(tileRect, resLevel);
547          }
548       }
549    }
550 
551    return ossimRefPtr<ossimImageData>();
552 }
553 
setOutputScalarType(ossimScalarType scalarType)554 void ossimEquationCombiner::setOutputScalarType(ossimScalarType scalarType)
555 {
556    if(theOutputScalarType != scalarType)
557    {
558       theOutputScalarType = scalarType;
559 
560       if(theOutputScalarType == OSSIM_SCALAR_UNKNOWN)
561       {
562          theOutputScalarType = OSSIM_FLOAT64;
563       }
564       if(theCastOutputFilter.valid())
565       {
566          theCastOutputFilter = 0;
567       }
568 
569       if(theOutputScalarType != OSSIM_FLOAT64)
570       {
571          theCastOutputFilter = new ossimCastTileSourceFilter;
572          theCastOutputFilter->setOutputScalarType(theOutputScalarType);
573          theCastOutputFilter->connectMyInputTo(0, this);
574          theCastOutputFilter->initialize();
575       }
576    }
577 }
578 
setProperty(ossimRefPtr<ossimProperty> property)579 void ossimEquationCombiner::setProperty(ossimRefPtr<ossimProperty> property)
580 {
581    if(!property) return;
582 
583    if(property->getName() == "Equation")
584    {
585       theEquation = property->valueToString();
586    }
587    else if(property->getName() == "Output scalar type")
588    {
589       setOutputScalarType(ossimScalarTypeLut::instance()->
590                           getScalarTypeFromString(property->valueToString()));
591    }
592    else
593    {
594       ossimImageCombiner::setProperty(property);
595    }
596 }
597 
getProperty(const ossimString & name) const598 ossimRefPtr<ossimProperty> ossimEquationCombiner::getProperty(const ossimString& name)const
599 {
600    if(name == "Equation")
601    {
602       ossimStringProperty* stringProp = new ossimStringProperty("Equation",
603 								theEquation,
604 								false);
605       stringProp->clearChangeType();
606       stringProp->setReadOnlyFlag(false);
607       stringProp->setCacheRefreshBit();
608 
609       return stringProp;
610    }
611    else if(name == "Output scalar type")
612    {
613       ossimScalarTypeLut* sl = ossimScalarTypeLut::instance();
614 
615       std::vector<ossimString> scalarNames;
616 
617       ossim_int32 tableSize = (ossim_int32)sl->getTableSize();
618       ossim_int32 idx;
619 
620       for(idx = 0; idx < tableSize; ++idx)
621       {
622          scalarNames.push_back(sl->getEntryString(idx));
623       }
624       ossimStringProperty* stringProp = new ossimStringProperty("Output scalar type",
625 								sl->getEntryString((ossim_int32)theOutputScalarType),
626 								false,
627 								scalarNames);
628       stringProp->clearChangeType();
629       stringProp->setReadOnlyFlag(false);
630       stringProp->setCacheRefreshBit();
631 
632       return stringProp;
633 
634    }
635 
636    return ossimImageCombiner::getProperty(name);
637 }
638 
getPropertyNames(std::vector<ossimString> & propertyNames) const639 void ossimEquationCombiner::getPropertyNames(std::vector<ossimString>& propertyNames)const
640 {
641    ossimImageCombiner::getPropertyNames(propertyNames);
642    propertyNames.push_back("Equation");
643    propertyNames.push_back("Output scalar type");
644 }
645 
646 
initialize()647 void ossimEquationCombiner::initialize()
648 {
649    ossimImageCombiner::initialize();
650 
651    theTile = ossimImageDataFactory::instance()->create(this, OSSIM_FLOAT64, getNumberOfOutputBands(), getTileWidth(), getTileHeight());
652    theTile->initialize();
653    if(theCastOutputFilter.valid())
654    {
655       theCastOutputFilter->initialize();
656    }
657 }
658 
assignValue()659 void ossimEquationCombiner::assignValue()
660 {
661    if(!theValueStack.empty())
662    {
663       if(theValueStack.top().type == OSSIM_EQU_IMAGE_DATA_TYPE)
664       {
665          ossimImageData* topData = theValueStack.top().d.imageDataValue;
666          ossim_uint32 minBands = std::min(theTile->getNumberOfBands(),
667                                     topData->getNumberOfBands());
668          ossim_uint32 maxBands = theTile->getNumberOfBands();
669          ossim_uint32 band   = 0;
670          ossim_uint32 offset = 0;
671          ossim_uint32 size = theTile->getWidth()*theTile->getHeight();
672 
673          if(topData->getDataObjectStatus() == OSSIM_PARTIAL)
674          {
675             for(band = 0; band < minBands; ++band)
676             {
677                double* inBuf  = (double*)topData->getBuf(band);
678                double* outBuf = (double*)theTile->getBuf(band);
679                double np      = topData->getNullPix(band);
680                if(outBuf && inBuf)
681                {
682                   for(offset = 0; offset < size; ++offset)
683                   {
684                      if(*inBuf != np)
685                      {
686                         *outBuf = *inBuf;
687                      }
688                      ++outBuf;
689                      ++inBuf;
690                   }
691                }
692             }
693             for(;band < maxBands; ++band)
694             {
695                double* inBuf  = (double*)topData->getBuf(minBands-1);
696                double* outBuf = (double*)theTile->getBuf(band);
697                double np      = topData->getNullPix(band);
698 
699                if(outBuf && inBuf)
700                {
701                   for(offset = 0; offset < size; ++offset)
702                   {
703                      if(*inBuf != np)
704                      {
705                         *outBuf = *inBuf;
706                      }
707                      ++outBuf;
708                      ++inBuf;
709                   }
710                }
711             }
712 
713          }
714          else if(topData->getDataObjectStatus() == OSSIM_FULL)
715          {
716             for(band = 0; band < minBands; ++band)
717             {
718                double* inBuf  = (double*)theValueStack.top().d.imageDataValue->getBuf(band);
719                double* outBuf = (double*)theTile->getBuf(band);
720                if(outBuf && inBuf)
721                {
722                   for(offset = 0; offset < size; ++offset)
723                   {
724                      *outBuf = *inBuf;
725                      ++outBuf;
726                      ++inBuf;
727                   }
728                }
729             }
730             for(;band < maxBands; ++band)
731             {
732                double* inBuf  = (double*)theValueStack.top().d.imageDataValue->getBuf(minBands-1);
733                double* outBuf = (double*)theTile->getBuf(band);
734 
735                if(outBuf && inBuf)
736                {
737                   for(offset = 0; offset < size; ++offset)
738                   {
739                      *outBuf = *inBuf;
740                      ++outBuf;
741                      ++inBuf;
742                   }
743                }
744             }
745          }
746 
747          // Delete the object indirectly through an ossimRefPtr.
748          ossimRefPtr<ossimImageData> id = theValueStack.top().d.imageDataValue;
749          id = NULL;
750       }
751       else
752       {
753          double* buf  = static_cast<double*>(theTile->getBuf());
754          ossim_uint32 size = theTile->getSize();
755          double value = (double)theValueStack.top().d.doubleValue;
756 
757          for(ossim_uint32 offset = 0; offset < size; ++offset)
758          {
759             *buf = value;
760             ++buf;
761          }
762       }
763 
764       theValueStack.pop();
765    }
766 }
767 
clearStacks()768 void ossimEquationCombiner::clearStacks()
769 {
770 
771    while(!theValueStack.empty())
772    {
773       if(theValueStack.top().type == OSSIM_EQU_IMAGE_DATA_TYPE)
774       {
775          // Delete the object indirectly through an ossimRefPtr.
776          ossimRefPtr<ossimImageData> id = theValueStack.top().d.imageDataValue;
777          id = NULL;
778       }
779 
780       theValueStack.pop();
781    }
782 }
783 
clearArgList(vector<ossimEquValue> & argList)784 void ossimEquationCombiner::clearArgList(vector<ossimEquValue>& argList)
785 {
786    for(ossim_uint32 i = 0; i < argList.size(); ++i)
787    {
788       if(argList[i].type == OSSIM_EQU_IMAGE_DATA_TYPE)
789       {
790          if(argList[i].d.imageDataValue)
791          {
792             // Delete the object indirectly through an ossimRefPtr.
793             ossimRefPtr<ossimImageData> id = argList[i].d.imageDataValue;
794             id = NULL;
795             argList[i].d.imageDataValue = (ossimImageData*)NULL;
796          }
797       }
798    }
799    argList.clear();
800 }
801 
deleteArgList(vector<ossimEquValue> & args)802 void ossimEquationCombiner::deleteArgList(vector<ossimEquValue>& args)
803 {
804    int i = 0;
805 
806    for(i = 0; i < (int)args.size(); ++i)
807    {
808       if(args[i].type == OSSIM_EQU_IMAGE_DATA_TYPE)
809       {
810          if(args[i].d.imageDataValue)
811          {
812             // Delete the object indirectly through an ossimRefPtr.
813             ossimRefPtr<ossimImageData> id = args[i].d.imageDataValue;
814             id = NULL;
815             args[i].d.imageDataValue = NULL;
816          }
817       }
818    }
819 
820    args.clear();
821 }
822 
parseArgList(vector<ossimEquValue> & args,bool popValueStack)823 bool ossimEquationCombiner::parseArgList(vector<ossimEquValue>& args,
824                                          bool popValueStack)
825 {
826    bool result = true;
827 
828    if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
829    {
830       theCurrentId = theLexer->yylex();
831       do
832       {
833          if(parseExpression())
834          {
835             if(!theValueStack.empty())
836             {
837                args.push_back(theValueStack.top());
838                if(popValueStack)
839                {
840                   theValueStack.pop();
841                }
842             }
843             else
844             {
845                ossimNotify(ossimNotifyLevel_WARN)
846                   << "The expression at  arg " << (args.size()+1)
847                   << " is empty" << endl;
848 
849                result = false;
850             }
851          }
852          else
853          {
854             ossimNotify(ossimNotifyLevel_WARN)
855                <<"Unable to parse expression" << endl;
856             result = false;
857          }
858 
859          if(theCurrentId == OSSIM_EQU_TOKEN_COMMA)
860          {
861             theCurrentId = theLexer->yylex();
862          }
863          else if(theCurrentId != OSSIM_EQU_TOKEN_RIGHT_PAREN)
864          {
865             ossimNotify(ossimNotifyLevel_WARN)
866                <<"Missing comma in argument list" << endl;
867             result = false;
868          }
869 
870       }while(result&&(theCurrentId != OSSIM_EQU_TOKEN_RIGHT_PAREN));
871    }
872    else
873    {
874       ossimNotify(ossimNotifyLevel_WARN)
875          << "Starting left parenthesis missing from arg list" << endl;
876       result = false;
877    }
878 
879    if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
880    {
881       theCurrentId = theLexer->yylex(); // skip past right parenthesis
882    }
883    else
884    {
885       ossimNotify(ossimNotifyLevel_WARN)
886          <<"No matching right parenthesis for arg list" << endl;
887       result = false;
888    }
889 
890    if(!result && popValueStack)
891    {
892       clearArgList(args);
893    }
894    return result;
895 }
896 
parseAssignBand()897 bool ossimEquationCombiner::parseAssignBand()
898 {
899    bool result = true;
900 
901    vector<ossimEquValue> argList;
902 
903    if(parseArgList(argList))
904    {
905       if((argList.size() == 3) ||
906          (argList.size() == 4))
907       {
908          ossimEquValue v3 = argList[2];
909          ossimEquValue v2 = argList[1];
910          ossimEquValue v1 = argList[0];
911 
912          if(argList.size() == 3)
913          {
914             if((v1.type == OSSIM_EQU_IMAGE_DATA_TYPE) &&
915                (v2.type == OSSIM_EQU_DOUBLE_TYPE))
916             {
917                ossimImageData *data = (ossimImageData*)v1.d.imageDataValue->dup();
918                ossimEquValue v;
919 
920                if(v3.type == OSSIM_EQU_IMAGE_DATA_TYPE)
921                {
922                   if(data->getBuf()&&
923                      v3.d.imageDataValue->getBuf())
924                   {
925                      if((ossim_uint32)(v2.d.doubleValue) < data->getNumberOfBands())
926                      {
927                         data->assignBand(v3.d.imageDataValue,
928                                          0,
929                                          (ossim_uint32)v2.d.doubleValue);
930 
931                      }
932                   }
933                }
934                else
935                {
936                   if(data->getBuf()&&
937                      (ossim_uint32)v2.d.doubleValue < data->getNumberOfBands())
938                   {
939                      ossim_uint32 upper = data->getWidth()*data->getHeight();
940                      double* buf = (double*)data->getBuf((ossim_uint32)v2.d.doubleValue);
941                      double value = v3.d.doubleValue;
942                      if(buf)
943                      {
944                         for(ossim_uint32 i = 0; i < upper; ++i)
945                         {
946                            *buf = value;
947                            ++buf;
948                         }
949                      }
950                      else
951                      {
952                         result = false;
953                      }
954                   }
955                }
956                if(result)
957                {
958                   data->validate();
959                   v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
960                   v.d.imageDataValue = data;
961                   theValueStack.push(v);
962                }
963             }
964             else
965             {
966                result = false;
967             }
968          }
969          else
970          {
971             ossimEquValue v4 = argList[3];
972             if((v1.type == OSSIM_EQU_IMAGE_DATA_TYPE) &&
973                (v2.type == OSSIM_EQU_DOUBLE_TYPE)&&
974                (v3.type == OSSIM_EQU_IMAGE_DATA_TYPE)&&
975                (v4.type == OSSIM_EQU_DOUBLE_TYPE))
976             {
977                ossimImageData *data = (ossimImageData*)v1.d.imageDataValue->dup();
978                ossimEquValue v;
979                v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
980                v.d.imageDataValue = data;
981                if(data->getBuf()&&v3.d.imageDataValue->getBuf())
982                {
983 
984                   ossim_uint32 index1 = (ossim_uint32)v4.d.doubleValue;
985                   ossim_uint32 index2 = (ossim_uint32)v2.d.doubleValue;
986 
987                   if((index1 > data->getNumberOfBands()) ||
988                      (index1 > v3.d.imageDataValue->getNumberOfBands()))
989                   {
990                      result = false;
991                   }
992                   else
993                   {
994                      data->assignBand(v3.d.imageDataValue,
995                                       index1,
996                                       index2);
997                      data->validate();
998                   }
999 
1000                }
1001 
1002                theValueStack.push(v);
1003             }
1004          }
1005       }
1006       else
1007       {
1008          ossimNotify(ossimNotifyLevel_WARN)
1009             << "Invalid number of arguments to assign_band" << endl;
1010          result = false;
1011       }
1012    }
1013    else
1014    {
1015       ossimNotify(ossimNotifyLevel_WARN)
1016          << "unable to parse arguments for assign band" << endl;
1017       result = false;
1018    }
1019 
1020    clearArgList(argList);
1021 
1022    return result;
1023 }
1024 
parseStdFuncs()1025 bool ossimEquationCombiner::parseStdFuncs()
1026 {
1027    bool result = true;
1028 
1029    switch(theCurrentId)
1030    {
1031    case OSSIM_EQU_TOKEN_ASSIGN_BAND:
1032    {
1033       theCurrentId = theLexer->yylex();
1034       if(!parseAssignBand())
1035       {
1036          result = false;
1037       }
1038 
1039       break;
1040    }
1041    case OSSIM_EQU_TOKEN_CONV:
1042    {
1043       theCurrentId = theLexer->yylex();
1044       vector<ossimEquValue> args;
1045       if(parseArgList(args))
1046       {
1047          ossimImageData* resultImage = (ossimImageData*)NULL;
1048          if(applyConvolution(resultImage,
1049                               args))
1050          {
1051             if(resultImage)
1052             {
1053                ossimEquValue v;
1054                v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
1055                v.d.imageDataValue = resultImage;
1056 
1057                theValueStack.push(v);
1058             }
1059             else
1060             {
1061                ossimNotify(ossimNotifyLevel_WARN)
1062                   << "function conv error: resulting image is NULL" << endl;
1063                result = false;
1064             }
1065          }
1066          else
1067          {
1068             ossimNotify(ossimNotifyLevel_WARN)
1069                << "Unable to apply convolution" << endl;
1070             result = false;
1071          }
1072       }
1073       else
1074       {
1075          result = false;
1076       }
1077 
1078       break;
1079    }
1080    case OSSIM_EQU_TOKEN_CLAMP:
1081    {
1082       theCurrentId = theLexer->yylex();
1083       vector<ossimEquValue> args;
1084       if(parseArgList(args))
1085       {
1086          ossimImageData* resultImage = (ossimImageData*)NULL;
1087          if(applyClamp(resultImage,
1088                        args))
1089          {
1090             if(resultImage)
1091             {
1092                ossimEquValue v;
1093                v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
1094                v.d.imageDataValue = resultImage;
1095 
1096                theValueStack.push(v);
1097             }
1098             else
1099             {
1100                ossimNotify(ossimNotifyLevel_WARN)
1101                   << "function clamp error: resulting image is NULL" << endl;
1102                result = false;
1103             }
1104 
1105          }
1106          else
1107          {
1108             ossimNotify(ossimNotifyLevel_WARN)
1109                << "Unable to apply clamp" << endl;
1110             result = false;
1111          }
1112       }
1113       else
1114       {
1115          result = false;
1116       }
1117 
1118       break;
1119    }
1120    case OSSIM_EQU_TOKEN_BAND:
1121    {
1122     // need to parse the following rule for blurr function
1123       //
1124       // band(image data, number)
1125       theCurrentId = theLexer->yylex();
1126 
1127 
1128       vector<ossimEquValue> argList;
1129 
1130       if(parseArgList(argList))
1131       {
1132          if(argList.size() == 2)
1133          {
1134             ossimEquValue v1 = argList[0];
1135             ossimEquValue v2 = argList[1];
1136             ossimImageData* tempData = NULL;
1137             ossim_uint32 bandNumber           = 0;
1138             if(v1.type == OSSIM_EQU_IMAGE_DATA_TYPE)
1139             {
1140                tempData = v1.d.imageDataValue;
1141             }
1142             else
1143             {
1144                result = false;
1145             }
1146             if(v2.type == OSSIM_EQU_DOUBLE_TYPE)
1147             {
1148                bandNumber = (ossim_uint32)(v2.d.doubleValue);
1149             }
1150             else
1151             {
1152                result = false;
1153             }
1154             if(bandNumber > tempData->getNumberOfBands())
1155             {
1156                result = false;
1157             }
1158             if(result)
1159             {
1160                ossimImageData* data = new ossimImageData(this,
1161                                                          OSSIM_FLOAT64,
1162                                                          1);
1163                data->setWidthHeight(tempData->getWidth(),
1164                                     tempData->getHeight());
1165                data->setOrigin(tempData->getOrigin());
1166                data->setNullPix(tempData->getNullPix(bandNumber),
1167                                 0);
1168                data->setMinPix(tempData->getMinPix(bandNumber),
1169                                0);
1170                data->setMaxPix(tempData->getMaxPix(bandNumber),
1171                                0);
1172                data->initialize();
1173 
1174                if((tempData->getBuf())&&
1175                   (bandNumber < tempData->getNumberOfBands()))
1176                {
1177                   data->assignBand(tempData,
1178                                    bandNumber,
1179                                    0);
1180                   data->validate();
1181                }
1182                ossimEquValue v;
1183                v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
1184                v.d.imageDataValue = data;
1185                theValueStack.push(v);
1186             }
1187 
1188             if(tempData)
1189             {
1190                // Delete the object indirectly through an ossimRefPtr.
1191                ossimRefPtr<ossimImageData> id = tempData;
1192                tempData = NULL;
1193             }
1194          }
1195          else
1196          {
1197             ossimNotify(ossimNotifyLevel_WARN)
1198                << "Invalid number of args in function band" << endl;
1199 
1200             result = false;
1201          }
1202       }
1203       else
1204       {
1205          result = false;
1206       }
1207 
1208       break;
1209    }
1210    case OSSIM_EQU_TOKEN_BLURR:
1211    {
1212       theCurrentId = theLexer->yylex();
1213       vector<ossimEquValue> args;
1214       if(parseArgList(args))
1215       {
1216          ossimImageData* resultImage = (ossimImageData*)NULL;
1217          if(applyBlurr(resultImage,
1218                        args))
1219          {
1220             if(resultImage)
1221             {
1222                ossimEquValue v;
1223                v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
1224                v.d.imageDataValue = resultImage;
1225 
1226                theValueStack.push(v);
1227             }
1228             else
1229             {
1230                result = false;
1231             }
1232          }
1233          else
1234          {
1235             result = false;
1236          }
1237       }
1238       else
1239       {
1240          result = false;
1241       }
1242 
1243       break;
1244    }
1245    case OSSIM_EQU_TOKEN_SHIFT:
1246    {
1247       theCurrentId = theLexer->yylex();
1248       vector<ossimEquValue> args;
1249       if(parseArgList(args))
1250       {
1251          ossimImageData* resultImage = (ossimImageData*)NULL;
1252          if(applyShift(resultImage,
1253                        args))
1254          {
1255             if(resultImage)
1256             {
1257                ossimEquValue v;
1258                v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
1259                v.d.imageDataValue = resultImage;
1260 
1261                theValueStack.push(v);
1262             }
1263             else
1264             {
1265                result = false;
1266             }
1267          }
1268          else
1269          {
1270             result = false;
1271          }
1272       }
1273       else
1274       {
1275          result = false;
1276       }
1277 
1278       break;
1279    }
1280    case OSSIM_EQU_TOKEN_MAX:
1281    case OSSIM_EQU_TOKEN_MIN:
1282    {
1283       ossimBinaryOp* op = NULL;
1284       if(theCurrentId == OSSIM_EQU_TOKEN_MIN) op = new ossimBinaryOpMin;
1285       else op = new ossimBinaryOpMax;
1286 
1287       int argCount = 0;
1288       theCurrentId = theLexer->yylex();
1289       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1290       {
1291          theCurrentId = theLexer->yylex();
1292          bool done = false;
1293          while(!done)
1294          {
1295             if(parseExpression())
1296             {
1297 
1298                ++argCount;
1299                if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1300                {
1301                   theCurrentId = theLexer->yylex();
1302 
1303                   done = true;
1304                }
1305                else if(theCurrentId == OSSIM_EQU_TOKEN_COMMA)
1306                {
1307                   theCurrentId = theLexer->yylex();
1308                }
1309                else
1310                {
1311                   result = false;
1312                   done = true;
1313                }
1314             }
1315             else
1316             {
1317                done = true;
1318                result = false;
1319             }
1320          }
1321          if((argCount > 1)&&result)
1322          {
1323             result = true;
1324 
1325             ossimEquValue v;
1326             ossimEquValue v1;
1327             ossimEquValue v2;
1328 
1329             v2 = theValueStack.top();
1330             theValueStack.pop();
1331             v1 = theValueStack.top();
1332             theValueStack.pop();
1333             argCount -=2;
1334 
1335             do
1336             {
1337                if(applyOp(*op,
1338                           v,
1339                           v1,
1340                           v2))
1341                {
1342                   theValueStack.push(v);
1343                }
1344                else
1345                {
1346                   result = false;
1347                   argCount = 0;
1348 
1349                }
1350                --argCount;
1351 
1352                if((argCount>0)&&result)
1353                {
1354                   v2 = theValueStack.top();
1355                   theValueStack.pop();
1356                   v1 = theValueStack.top();
1357                   theValueStack.pop();
1358                }
1359 
1360             }while((argCount > 0)&&(result));
1361          }
1362          else
1363          {
1364             result = false;
1365          }
1366       }
1367       else
1368       {
1369          result = false;
1370       }
1371       if(op)
1372       {
1373          delete op;
1374          op = NULL;
1375       }
1376       break;
1377    }
1378    case OSSIM_EQU_TOKEN_ABS:
1379    {
1380       theCurrentId = theLexer->yylex();
1381       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1382       {
1383          theCurrentId = theLexer->yylex();
1384          result = parseExpression();
1385          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1386          {
1387             if(theValueStack.size() > 0)
1388             {
1389                theCurrentId = theLexer->yylex();
1390                ossimEquValue v;
1391                ossimEquValue v1 = theValueStack.top();
1392                theValueStack.pop();
1393 
1394                applyOp(ossimUnaryOpAbs(),
1395                        v,
1396                        v1);
1397 
1398                theValueStack.push(v);
1399             }
1400             else
1401             {
1402                result = false;
1403             }
1404          }
1405       }
1406       else
1407       {
1408          result = false;
1409       }
1410       break;
1411    }
1412    case OSSIM_EQU_TOKEN_SIN:
1413    {
1414       theCurrentId = theLexer->yylex();
1415       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1416       {
1417          theCurrentId = theLexer->yylex();
1418          result = parseExpression();
1419          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1420          {
1421             if(theValueStack.size() > 0)
1422             {
1423                theCurrentId = theLexer->yylex();
1424                ossimEquValue v;
1425                ossimEquValue v1 = theValueStack.top();
1426                theValueStack.pop();
1427 
1428                applyOp(ossimUnaryOpSin(),
1429                        v,
1430                        v1);
1431 
1432                theValueStack.push(v);
1433             }
1434             else
1435             {
1436                result = false;
1437             }
1438          }
1439       }
1440       else
1441       {
1442          result = false;
1443       }
1444       break;
1445    }
1446    case OSSIM_EQU_TOKEN_SIND:
1447    {
1448       theCurrentId = theLexer->yylex();
1449       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1450       {
1451          theCurrentId = theLexer->yylex();
1452          result = parseExpression();
1453          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1454          {
1455             if(theValueStack.size() > 0)
1456             {
1457                theCurrentId = theLexer->yylex();
1458                ossimEquValue v;
1459                ossimEquValue v1 = theValueStack.top();
1460                theValueStack.pop();
1461 
1462                applyOp(ossimUnaryOpSind(),
1463                        v,
1464                        v1);
1465 
1466                theValueStack.push(v);
1467             }
1468             else
1469             {
1470                result = false;
1471             }
1472          }
1473       }
1474       else
1475       {
1476          result = false;
1477       }
1478       break;
1479    }
1480    case OSSIM_EQU_TOKEN_ASIN:
1481    {
1482       theCurrentId = theLexer->yylex();
1483       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1484       {
1485          theCurrentId = theLexer->yylex();
1486          result = parseExpression();
1487          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1488          {
1489             if(theValueStack.size() > 0)
1490             {
1491                theCurrentId = theLexer->yylex();
1492                ossimEquValue v;
1493                ossimEquValue v1 = theValueStack.top();
1494                theValueStack.pop();
1495 
1496                applyOp(ossimUnaryOpASin(),
1497                        v,
1498                        v1);
1499 
1500                theValueStack.push(v);
1501             }
1502             else
1503             {
1504                result = false;
1505             }
1506          }
1507       }
1508       else
1509       {
1510          result = false;
1511       }
1512       break;
1513    }
1514    case OSSIM_EQU_TOKEN_ASIND:
1515    {
1516       theCurrentId = theLexer->yylex();
1517       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1518       {
1519          theCurrentId = theLexer->yylex();
1520          result = parseExpression();
1521          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1522          {
1523             if(theValueStack.size() > 0)
1524             {
1525                theCurrentId = theLexer->yylex();
1526                ossimEquValue v;
1527                ossimEquValue v1 = theValueStack.top();
1528                theValueStack.pop();
1529 
1530                applyOp(ossimUnaryOpASind(),
1531                        v,
1532                        v1);
1533 
1534                theValueStack.push(v);
1535             }
1536             else
1537             {
1538                result = false;
1539             }
1540          }
1541       }
1542       else
1543       {
1544          result = false;
1545       }
1546       break;
1547    }
1548    case OSSIM_EQU_TOKEN_COS:
1549    {
1550       theCurrentId = theLexer->yylex();
1551       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1552       {
1553          theCurrentId = theLexer->yylex();
1554          result = parseExpression();
1555          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1556          {
1557             if(theValueStack.size() > 0)
1558             {
1559                theCurrentId = theLexer->yylex();
1560                ossimEquValue v;
1561                ossimEquValue v1 = theValueStack.top();
1562                theValueStack.pop();
1563 
1564                applyOp(ossimUnaryOpCos(),
1565                        v,
1566                        v1);
1567 
1568                theValueStack.push(v);
1569             }
1570             else
1571             {
1572                result = false;
1573             }
1574          }
1575       }
1576       else
1577       {
1578          result = false;
1579       }
1580       break;
1581    }
1582    case OSSIM_EQU_TOKEN_COSD:
1583    {
1584       theCurrentId = theLexer->yylex();
1585       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1586       {
1587          theCurrentId = theLexer->yylex();
1588          result = parseExpression();
1589          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1590          {
1591             if(theValueStack.size() > 0)
1592             {
1593                theCurrentId = theLexer->yylex();
1594                ossimEquValue v;
1595                ossimEquValue v1 = theValueStack.top();
1596                theValueStack.pop();
1597 
1598                applyOp(ossimUnaryOpCosd(),
1599                        v,
1600                        v1);
1601 
1602                theValueStack.push(v);
1603             }
1604             else
1605             {
1606                result = false;
1607             }
1608          }
1609       }
1610       else
1611       {
1612          result = false;
1613       }
1614       break;
1615    }
1616    case OSSIM_EQU_TOKEN_ACOS:
1617    {
1618       theCurrentId = theLexer->yylex();
1619       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1620       {
1621          theCurrentId = theLexer->yylex();
1622          result = parseExpression();
1623          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1624          {
1625             if(theValueStack.size() > 0)
1626             {
1627                theCurrentId = theLexer->yylex();
1628                ossimEquValue v;
1629                ossimEquValue v1 = theValueStack.top();
1630                theValueStack.pop();
1631 
1632                applyOp(ossimUnaryOpACos(),
1633                        v,
1634                        v1);
1635 
1636                theValueStack.push(v);
1637             }
1638             else
1639             {
1640                result = false;
1641             }
1642          }
1643       }
1644       else
1645       {
1646          result = false;
1647       }
1648       break;
1649    }
1650    case OSSIM_EQU_TOKEN_ACOSD:
1651    {
1652       theCurrentId = theLexer->yylex();
1653       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1654       {
1655          theCurrentId = theLexer->yylex();
1656          result = parseExpression();
1657          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1658          {
1659             if(theValueStack.size() > 0)
1660             {
1661                theCurrentId = theLexer->yylex();
1662                ossimEquValue v;
1663                ossimEquValue v1 = theValueStack.top();
1664                theValueStack.pop();
1665 
1666                applyOp(ossimUnaryOpACosd(),
1667                        v,
1668                        v1);
1669 
1670                theValueStack.push(v);
1671             }
1672             else
1673             {
1674                result = false;
1675             }
1676          }
1677       }
1678       else
1679       {
1680          result = false;
1681       }
1682       break;
1683    }
1684    case OSSIM_EQU_TOKEN_TAN:
1685    {
1686       theCurrentId = theLexer->yylex();
1687       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1688       {
1689          theCurrentId = theLexer->yylex();
1690          result = parseExpression();
1691          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1692          {
1693             if(theValueStack.size() > 0)
1694             {
1695                theCurrentId = theLexer->yylex();
1696                ossimEquValue v;
1697                ossimEquValue v1 = theValueStack.top();
1698                theValueStack.pop();
1699 
1700                applyOp(ossimUnaryOpTan(),
1701                        v,
1702                        v1);
1703 
1704                theValueStack.push(v);
1705             }
1706             else
1707             {
1708                result = false;
1709             }
1710          }
1711       }
1712       else
1713       {
1714          result = false;
1715       }
1716       break;
1717    }
1718    case OSSIM_EQU_TOKEN_TAND:
1719    {
1720       theCurrentId = theLexer->yylex();
1721       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1722       {
1723          theCurrentId = theLexer->yylex();
1724          result = parseExpression();
1725          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1726          {
1727             if(theValueStack.size() > 0)
1728             {
1729                theCurrentId = theLexer->yylex();
1730                ossimEquValue v;
1731                ossimEquValue v1 = theValueStack.top();
1732                theValueStack.pop();
1733 
1734                applyOp(ossimUnaryOpTand(),
1735                        v,
1736                        v1);
1737 
1738                theValueStack.push(v);
1739             }
1740             else
1741             {
1742                result = false;
1743             }
1744          }
1745       }
1746       else
1747       {
1748          result = false;
1749       }
1750       break;
1751    }
1752    case OSSIM_EQU_TOKEN_ATAN:
1753    {
1754       theCurrentId = theLexer->yylex();
1755       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1756       {
1757          theCurrentId = theLexer->yylex();
1758          result = parseExpression();
1759          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1760          {
1761             if(theValueStack.size() > 0)
1762             {
1763                theCurrentId = theLexer->yylex();
1764                ossimEquValue v;
1765                ossimEquValue v1 = theValueStack.top();
1766                theValueStack.pop();
1767 
1768                applyOp(ossimUnaryOpATan(),
1769                        v,
1770                        v1);
1771 
1772                theValueStack.push(v);
1773             }
1774             else
1775             {
1776                result = false;
1777             }
1778          }
1779       }
1780       else
1781       {
1782          result = false;
1783       }
1784       break;
1785    }
1786    case OSSIM_EQU_TOKEN_ATAND:
1787    {
1788       theCurrentId = theLexer->yylex();
1789       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1790       {
1791          theCurrentId = theLexer->yylex();
1792          result = parseExpression();
1793          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1794          {
1795             if(theValueStack.size() > 0)
1796             {
1797                theCurrentId = theLexer->yylex();
1798                ossimEquValue v;
1799                ossimEquValue v1 = theValueStack.top();
1800                theValueStack.pop();
1801 
1802                applyOp(ossimUnaryOpATand(),
1803                        v,
1804                        v1);
1805 
1806                theValueStack.push(v);
1807             }
1808             else
1809             {
1810                result = false;
1811             }
1812          }
1813       }
1814       else
1815       {
1816          result = false;
1817       }
1818       break;
1819    }
1820    case OSSIM_EQU_TOKEN_LOG:
1821    {
1822       theCurrentId = theLexer->yylex();
1823       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1824       {
1825          theCurrentId = theLexer->yylex();
1826          result = parseExpression();
1827          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1828          {
1829             if(theValueStack.size() > 0)
1830             {
1831                theCurrentId = theLexer->yylex();
1832                ossimEquValue v;
1833                ossimEquValue v1 = theValueStack.top();
1834                theValueStack.pop();
1835 
1836                applyOp(ossimUnaryOpLog(),
1837                        v,
1838                        v1);
1839 
1840                theValueStack.push(v);
1841             }
1842             else
1843             {
1844                result = false;
1845             }
1846          }
1847       }
1848       else
1849       {
1850          result = false;
1851       }
1852       break;
1853    }
1854    case OSSIM_EQU_TOKEN_LOG10:
1855    {
1856       theCurrentId = theLexer->yylex();
1857       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1858       {
1859          theCurrentId = theLexer->yylex();
1860          result = parseExpression();
1861          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1862          {
1863             if(theValueStack.size() > 0)
1864             {
1865                theCurrentId = theLexer->yylex();
1866                ossimEquValue v;
1867                ossimEquValue v1 = theValueStack.top();
1868                theValueStack.pop();
1869 
1870                applyOp(ossimUnaryOpLog10(),
1871                        v,
1872                        v1);
1873 
1874                theValueStack.push(v);
1875             }
1876             else
1877             {
1878                result = false;
1879             }
1880          }
1881       }
1882       else
1883       {
1884          result = false;
1885       }
1886       break;
1887    }
1888    case OSSIM_EQU_TOKEN_SQRT:
1889    {
1890       theCurrentId = theLexer->yylex();
1891       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1892       {
1893          theCurrentId = theLexer->yylex();
1894          result = parseExpression();
1895          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1896          {
1897             if(theValueStack.size() > 0)
1898             {
1899                theCurrentId = theLexer->yylex();
1900                ossimEquValue v;
1901                ossimEquValue v1 = theValueStack.top();
1902                theValueStack.pop();
1903 
1904                applyOp(ossimUnaryOpSqrt(),
1905                        v,
1906                        v1);
1907 
1908                theValueStack.push(v);
1909             }
1910             else
1911             {
1912                result = false;
1913             }
1914          }
1915       }
1916       else
1917       {
1918          result = false;
1919       }
1920       break;
1921    }
1922    case OSSIM_EQU_TOKEN_EXP:
1923    {
1924       theCurrentId = theLexer->yylex();
1925       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_PAREN)
1926       {
1927          theCurrentId = theLexer->yylex();
1928          result = parseExpression();
1929          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
1930          {
1931             if(theValueStack.size() > 0)
1932             {
1933                theCurrentId = theLexer->yylex();
1934                ossimEquValue v;
1935                ossimEquValue v1 = theValueStack.top();
1936                theValueStack.pop();
1937 
1938                applyOp(ossimUnaryOpExp(),
1939                        v,
1940                        v1);
1941 
1942                theValueStack.push(v);
1943             }
1944             else
1945             {
1946                result = false;
1947             }
1948          }
1949       }
1950       else
1951       {
1952          result = false;
1953       }
1954       break;
1955    }
1956    default:
1957    {
1958       result = false;
1959    }
1960    }
1961 
1962    return result;
1963 }
1964 
parseUnaryFactor()1965 bool ossimEquationCombiner::parseUnaryFactor()
1966 {
1967    bool result = false;
1968 
1969 
1970    if(theCurrentId == OSSIM_EQU_TOKEN_MINUS)
1971    {
1972       theCurrentId = theLexer->yylex();
1973 
1974       if(parseFactor())
1975       {
1976          if(theValueStack.size() > 0)
1977          {
1978             ossimEquValue v;
1979             ossimEquValue v1 = theValueStack.top();
1980             theValueStack.pop();
1981 
1982             applyOp(ossimUnaryOpNeg(),
1983                     v,
1984                     v1);
1985 
1986             theValueStack.push(v);
1987          }
1988          else
1989          {
1990             result = false;
1991          }
1992 
1993          result = true;
1994       }
1995       else
1996       {
1997          result = false;
1998       }
1999    }
2000    else if(theCurrentId == OSSIM_EQU_TOKEN_TILDE)
2001    {
2002       theCurrentId = theLexer->yylex();
2003 
2004       if(parseFactor())
2005       {
2006          if(theValueStack.size() > 0)
2007          {
2008             ossimEquValue v;
2009             ossimEquValue v1 = theValueStack.top();
2010             theValueStack.pop();
2011 
2012             applyOp(ossimUnaryOpOnesComplement(),
2013                     v,
2014                     v1);
2015 
2016             theValueStack.push(v);
2017          }
2018          else
2019          {
2020             result = false;
2021          }
2022 
2023          result = true;
2024       }
2025       else
2026       {
2027          result = false;
2028       }
2029    }
2030    return result;
2031 }
2032 
parseFactor()2033 bool ossimEquationCombiner::parseFactor()
2034 {
2035    bool result = false;
2036 
2037    switch(theCurrentId)
2038    {
2039    case OSSIM_EQU_TOKEN_CONSTANT:
2040    {
2041       ossimEquValue v;
2042 
2043       v.type = OSSIM_EQU_DOUBLE_TYPE;
2044       v.d.doubleValue = atof(theLexer->YYText());
2045       theValueStack.push(v);
2046 
2047       theCurrentId = theLexer->yylex();
2048 
2049       result =  true;
2050       break;
2051    }
2052    case OSSIM_EQU_TOKEN_PI:
2053    {
2054       ossimEquValue v;
2055 
2056       v.type = OSSIM_EQU_DOUBLE_TYPE;
2057       v.d.doubleValue = M_PI;
2058       theValueStack.push(v);
2059 
2060       theCurrentId = theLexer->yylex();
2061 
2062       result =  true;
2063       break;
2064    }
2065    case OSSIM_EQU_TOKEN_IMAGE_VARIABLE:
2066    {
2067       theCurrentId = theLexer->yylex();
2068       if(theCurrentId == OSSIM_EQU_TOKEN_LEFT_ARRAY_BRACKET)
2069       {
2070          theCurrentId = theLexer->yylex();
2071          if(parseExpression())
2072          {
2073             if(!theValueStack.empty())
2074             {
2075                if(theValueStack.top().type == OSSIM_EQU_DOUBLE_TYPE)
2076                {
2077                   if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_ARRAY_BRACKET)
2078                   {
2079                      theCurrentId = theLexer->yylex();
2080                      ossim_uint32 index = (ossim_uint32)theValueStack.top().d.doubleValue;
2081                      theValueStack.pop();
2082                      ossimRefPtr<ossimImageData> data = getNewImageData(index);
2083                      result = true;
2084                      if(data.valid())
2085                      {
2086                         ossimEquValue v;
2087                         v.type = OSSIM_EQU_IMAGE_DATA_TYPE;
2088                         v.d.imageDataValue = data.release();
2089                         theValueStack.push(v);
2090 
2091                      }
2092                      else
2093                      {
2094                         ossimNotify(ossimNotifyLevel_WARN)
2095                            <<"Data is NULL for array operation" << endl;
2096                      }
2097                      result = true;
2098                   }
2099                   else
2100                   {
2101                      ossimNotify(ossimNotifyLevel_WARN)
2102                         << "Mismatched Right array bracket" << endl;
2103                   }
2104                }
2105                else
2106                {
2107                   ossimNotify(ossimNotifyLevel_WARN)
2108                      << "Expression between array brackets is not a number"
2109                      << endl;
2110                }
2111             }
2112             else
2113             {
2114                ossimNotify(ossimNotifyLevel_WARN)
2115                   << "no expression within array brackets" << endl;
2116             }
2117          }
2118          else
2119          {
2120             ossimNotify(ossimNotifyLevel_WARN)
2121                << "Unabel to parse expression"<<endl;
2122          }
2123       }
2124       else
2125       {
2126          ossimNotify(ossimNotifyLevel_WARN)
2127             <<"Need left array brackets to access an input source"<<endl;
2128       }
2129 
2130       break;
2131    }
2132    case OSSIM_EQU_TOKEN_LEFT_PAREN:
2133    {
2134       theCurrentId = theLexer->yylex();
2135       if(parseExpression())
2136       {
2137          if(theCurrentId == OSSIM_EQU_TOKEN_RIGHT_PAREN)
2138          {
2139             result       =  true;
2140             theCurrentId = theLexer->yylex();
2141          }
2142          else
2143          {
2144             ossimNotify(ossimNotifyLevel_WARN)
2145                << "Right parenthesis missing" << endl;
2146             result = false;
2147          }
2148       }
2149       else
2150       {
2151          ossimNotify(ossimNotifyLevel_WARN)
2152             << "Unable to parse expression within parenthesis" << endl;
2153          result = false;
2154       }
2155 
2156       break;
2157    }
2158    }
2159    if(!result) result = parseUnaryFactor();
2160 
2161    if(!result) result = parseStdFuncs();
2162 
2163    return result;
2164 }
2165 
parseRestOfTerm()2166 bool ossimEquationCombiner::parseRestOfTerm()
2167 {
2168    //---
2169    // Parse the following rule:
2170    // RestOfTerm: * Factor RestOfTerm | / Factor RestOfTerm |
2171    // ^ Factor RestOfTerm
2172    //---
2173    bool result = true;
2174 
2175    switch(theCurrentId)
2176    {
2177       case OSSIM_EQU_TOKEN_MULT:
2178       {
2179          theCurrentId = theLexer->yylex();
2180          if(parseFactor())
2181          {
2182             if(theValueStack.size() > 1)
2183             {
2184                ossimEquValue v;
2185 
2186                ossimEquValue v2 = theValueStack.top();
2187                theValueStack.pop();
2188                ossimEquValue v1 = theValueStack.top();
2189                theValueStack.pop();
2190 
2191                applyOp(ossimBinaryOpMul(),
2192                        v,
2193                        v1,
2194                        v2);
2195 
2196                theValueStack.push(v);
2197             }
2198             else
2199             {
2200                ossimNotify(ossimNotifyLevel_WARN)
2201                   << "Multiplication requires two arguments" << endl;
2202                result = false;
2203             }
2204             if(result)
2205             {
2206                result = parseRestOfTerm();
2207             }
2208          }
2209          else
2210          {
2211             result = false;
2212          }
2213          break;
2214       }
2215       case OSSIM_EQU_TOKEN_DIV:
2216       {
2217          theCurrentId = theLexer->yylex();
2218          if(parseFactor())
2219          {
2220             if(theValueStack.size() > 1)
2221             {
2222                ossimEquValue v;
2223 
2224                ossimEquValue v2 = theValueStack.top();
2225                theValueStack.pop();
2226                ossimEquValue v1 = theValueStack.top();
2227                theValueStack.pop();
2228 
2229                applyOp(ossimBinaryOpDiv(),
2230                        v,
2231                        v1,
2232                        v2);
2233 
2234                theValueStack.push(v);
2235             }
2236             else
2237             {
2238                result = false;
2239             }
2240             if(result)
2241             {
2242                result = parseRestOfTerm();
2243             }
2244          }
2245          else
2246          {
2247             result = false;
2248          }
2249 
2250          break;
2251       }
2252       case OSSIM_EQU_TOKEN_XOR:
2253       {
2254          theCurrentId = theLexer->yylex();
2255          if(parseFactor())
2256          {
2257             if(theValueStack.size() > 1)
2258             {
2259                ossimEquValue v;
2260 
2261                ossimEquValue v2 = theValueStack.top();
2262                theValueStack.pop();
2263                ossimEquValue v1 = theValueStack.top();
2264                theValueStack.pop();
2265 
2266                applyOp(ossimBinaryOpXor(),
2267                        v,
2268                        v1,
2269                        v2);
2270 
2271                theValueStack.push(v);
2272             }
2273             else
2274             {
2275                result = false;
2276             }
2277             if(result)
2278             {
2279                result = parseRestOfTerm();
2280             }
2281          }
2282          else
2283          {
2284             result = false;
2285          }
2286 
2287          break;
2288       }
2289       case OSSIM_EQU_TOKEN_AMPERSAND:
2290       {
2291          theCurrentId = theLexer->yylex();
2292          if(parseFactor())
2293          {
2294             if(theValueStack.size() > 1)
2295             {
2296                ossimEquValue v;
2297 
2298                ossimEquValue v2 = theValueStack.top();
2299                theValueStack.pop();
2300                ossimEquValue v1 = theValueStack.top();
2301                theValueStack.pop();
2302 
2303                applyOp(ossimBinaryOpAnd(),
2304                        v,
2305                        v1,
2306                        v2);
2307 
2308                theValueStack.push(v);
2309             }
2310             else
2311             {
2312                result = false;
2313             }
2314             if(result)
2315             {
2316                result = parseRestOfTerm();
2317             }
2318          }
2319          else
2320          {
2321             result = false;
2322          }
2323 
2324          break;
2325       }
2326       case OSSIM_EQU_TOKEN_OR_BAR:
2327       {
2328          theCurrentId = theLexer->yylex();
2329          if(parseFactor())
2330          {
2331             if(theValueStack.size() > 1)
2332             {
2333                ossimEquValue v;
2334 
2335                ossimEquValue v2 = theValueStack.top();
2336                theValueStack.pop();
2337                ossimEquValue v1 = theValueStack.top();
2338                theValueStack.pop();
2339 
2340                applyOp(ossimBinaryOpOr(),
2341                        v,
2342                        v1,
2343                        v2);
2344 
2345                theValueStack.push(v);
2346             }
2347             else
2348             {
2349                result = false;
2350             }
2351             if(result)
2352             {
2353                result = parseRestOfTerm();
2354             }
2355          }
2356          else
2357          {
2358             result = false;
2359          }
2360 
2361          break;
2362       }
2363       case OSSIM_EQU_TOKEN_MOD:
2364       {
2365          theCurrentId = theLexer->yylex();
2366          if(parseFactor())
2367          {
2368             if(theValueStack.size() > 1)
2369             {
2370                ossimEquValue v;
2371 
2372                ossimEquValue v2 = theValueStack.top();
2373                theValueStack.pop();
2374                ossimEquValue v1 = theValueStack.top();
2375                theValueStack.pop();
2376 
2377                applyOp(ossimBinaryOpMod(),
2378                        v,
2379                        v1,
2380                        v2);
2381 
2382                theValueStack.push(v);
2383             }
2384             else
2385             {
2386                result = false;
2387             }
2388             if(result)
2389             {
2390                result = parseRestOfTerm();
2391             }
2392          }
2393          else
2394          {
2395             result = false;
2396          }
2397 
2398          break;
2399       }
2400       case OSSIM_EQU_TOKEN_POWER:
2401       {
2402          theCurrentId = theLexer->yylex();
2403          if(parseFactor())
2404          {
2405             if(theValueStack.size() > 1)
2406             {
2407                ossimEquValue v;
2408 
2409                ossimEquValue v2 = theValueStack.top();
2410                theValueStack.pop();
2411                ossimEquValue v1 = theValueStack.top();
2412                theValueStack.pop();
2413 
2414                applyOp(ossimBinaryOpPow(),
2415                        v,
2416                        v1,
2417                        v2);
2418 
2419                theValueStack.push(v);
2420             }
2421             else
2422             {
2423                result = false;
2424             }
2425             if(result)
2426             {
2427                result = parseRestOfTerm();
2428             }
2429          }
2430          else
2431          {
2432             result = false;
2433          }
2434          break;
2435       }
2436       case OSSIM_EQU_TOKEN_BEQUAL:
2437       {
2438          theCurrentId = theLexer->yylex();
2439          if(parseFactor())
2440          {
2441             if(theValueStack.size() > 1)
2442             {
2443                ossimEquValue v;
2444 
2445                ossimEquValue v2 = theValueStack.top();
2446                theValueStack.pop();
2447                ossimEquValue v1 = theValueStack.top();
2448                theValueStack.pop();
2449 
2450                applyOp(ossimBinaryOpEqual(),
2451                        v,
2452                        v1,
2453                        v2);
2454 
2455                theValueStack.push(v);
2456             }
2457             else
2458             {
2459                result = false;
2460             }
2461             if(result)
2462             {
2463                result = parseRestOfTerm();
2464             }
2465          }
2466          else
2467          {
2468             result = false;
2469          }
2470 
2471          break;
2472       }
2473       case OSSIM_EQU_TOKEN_BGREATER:
2474       {
2475          theCurrentId = theLexer->yylex();
2476          if(parseFactor())
2477          {
2478             if(theValueStack.size() > 1)
2479             {
2480                ossimEquValue v;
2481 
2482                ossimEquValue v2 = theValueStack.top();
2483                theValueStack.pop();
2484                ossimEquValue v1 = theValueStack.top();
2485                theValueStack.pop();
2486 
2487                applyOp(ossimBinaryOpGreater(),
2488                        v,
2489                        v1,
2490                        v2);
2491 
2492                theValueStack.push(v);
2493             }
2494             else
2495             {
2496                result = false;
2497             }
2498             if(result)
2499             {
2500                result = parseRestOfTerm();
2501             }
2502          }
2503          else
2504          {
2505             result = false;
2506          }
2507 
2508          break;
2509       }
2510       case OSSIM_EQU_TOKEN_BGREATEROREQUAL:
2511       {
2512          theCurrentId = theLexer->yylex();
2513          if(parseFactor())
2514          {
2515             if(theValueStack.size() > 1)
2516             {
2517                ossimEquValue v;
2518 
2519                ossimEquValue v2 = theValueStack.top();
2520                theValueStack.pop();
2521                ossimEquValue v1 = theValueStack.top();
2522                theValueStack.pop();
2523 
2524                applyOp(ossimBinaryOpGreaterOrEqual(),
2525                        v,
2526                        v1,
2527                        v2);
2528 
2529                theValueStack.push(v);
2530             }
2531             else
2532             {
2533                result = false;
2534             }
2535             if(result)
2536             {
2537                result = parseRestOfTerm();
2538             }
2539          }
2540          else
2541          {
2542             result = false;
2543          }
2544 
2545          break;
2546       }
2547       case OSSIM_EQU_TOKEN_BLESS:
2548       {
2549          theCurrentId = theLexer->yylex();
2550          if(parseFactor())
2551          {
2552             if(theValueStack.size() > 1)
2553             {
2554                ossimEquValue v;
2555 
2556                ossimEquValue v2 = theValueStack.top();
2557                theValueStack.pop();
2558                ossimEquValue v1 = theValueStack.top();
2559                theValueStack.pop();
2560 
2561                applyOp(ossimBinaryOpLess(),
2562                        v,
2563                        v1,
2564                        v2);
2565 
2566                theValueStack.push(v);
2567             }
2568             else
2569             {
2570                result = false;
2571             }
2572             if(result)
2573             {
2574                result = parseRestOfTerm();
2575             }
2576          }
2577          else
2578          {
2579             result = false;
2580          }
2581 
2582          break;
2583       }
2584       case OSSIM_EQU_TOKEN_BLESSOREQUAL:
2585       {
2586          theCurrentId = theLexer->yylex();
2587          if(parseFactor())
2588          {
2589             if(theValueStack.size() > 1)
2590             {
2591                ossimEquValue v;
2592 
2593                ossimEquValue v2 = theValueStack.top();
2594                theValueStack.pop();
2595                ossimEquValue v1 = theValueStack.top();
2596                theValueStack.pop();
2597 
2598                applyOp(ossimBinaryOpLessOrEqual(),
2599                        v,
2600                        v1,
2601                        v2);
2602 
2603                theValueStack.push(v);
2604             }
2605             else
2606             {
2607                result = false;
2608             }
2609             if(result)
2610             {
2611                result = parseRestOfTerm();
2612             }
2613          }
2614          else
2615          {
2616             result = false;
2617          }
2618 
2619          break;
2620       }
2621       case OSSIM_EQU_TOKEN_BDIFFERENT:
2622       {
2623          theCurrentId = theLexer->yylex();
2624          if(parseFactor())
2625          {
2626             if(theValueStack.size() > 1)
2627             {
2628                ossimEquValue v;
2629 
2630                ossimEquValue v2 = theValueStack.top();
2631                theValueStack.pop();
2632                ossimEquValue v1 = theValueStack.top();
2633                theValueStack.pop();
2634 
2635                applyOp(ossimBinaryOpDifferent(),
2636                        v,
2637                        v1,
2638                        v2);
2639 
2640                theValueStack.push(v);
2641             }
2642             else
2643             {
2644                result = false;
2645             }
2646             if(result)
2647             {
2648                result = parseRestOfTerm();
2649             }
2650          }
2651          else
2652          {
2653             result = false;
2654          }
2655 
2656          break;
2657       }
2658 
2659    }
2660 
2661    return result;
2662 }
2663 
parseTerm()2664 bool ossimEquationCombiner::parseTerm()
2665 {
2666    // parse the following rule:
2667    //
2668    // Term : Factor RestOfTerm
2669 
2670    bool result = false;
2671 
2672    result = parseFactor();
2673 
2674    if(result)
2675    {
2676       result = parseRestOfTerm();
2677    }
2678 
2679    return result;
2680 }
2681 
parseRestOfExp()2682 bool ossimEquationCombiner::parseRestOfExp()
2683 {
2684    // parse the following rule:
2685    // RestOfExpression : + Term RestOfExpression | - Term RestOfExpression | epsilon
2686    //
2687    bool result = true;
2688 
2689    if(theCurrentId == OSSIM_EQU_TOKEN_PLUS)
2690    {
2691       theCurrentId = theLexer->yylex();
2692       if(parseTerm())
2693       {
2694 
2695          if(theValueStack.size() > 1)
2696          {
2697             ossimEquValue v;
2698 
2699             ossimEquValue v2 = theValueStack.top();
2700             theValueStack.pop();
2701             ossimEquValue v1 = theValueStack.top();
2702             theValueStack.pop();
2703 
2704 
2705             applyOp(ossimBinaryOpAdd(),
2706                     v,
2707                     v1,
2708                     v2);
2709 
2710             theValueStack.push(v);
2711          }
2712          else
2713          {
2714             result = false;
2715          }
2716          if(result)
2717          {
2718             result = parseRestOfExp();
2719          }
2720       }
2721       else
2722       {
2723         result =  false;
2724       }
2725    }
2726    else if(theCurrentId == OSSIM_EQU_TOKEN_MINUS)
2727    {
2728       theCurrentId = theLexer->yylex();
2729       if(parseTerm())
2730       {
2731          if(theValueStack.size() > 1)
2732          {
2733             ossimEquValue v;
2734 
2735             ossimEquValue v2 = theValueStack.top();
2736             theValueStack.pop();
2737             ossimEquValue v1 = theValueStack.top();
2738             theValueStack.pop();
2739 
2740             applyOp(ossimBinaryOpSub(),
2741                     v,
2742                     v1,
2743                     v2);
2744 
2745             theValueStack.push(v);
2746          }
2747          else
2748          {
2749             result = false;
2750          }
2751          if(result)
2752          {
2753             result = parseRestOfExp();
2754          }
2755       }
2756       else
2757       {
2758          result =  false;
2759       }
2760    }
2761 
2762    return result;
2763 }
2764 
getImageData(ossim_uint32 index)2765 ossimRefPtr<ossimImageData> ossimEquationCombiner::getImageData(ossim_uint32 index)
2766 {
2767    ossimRefPtr<ossimImageData> result;
2768    ossimConnectableObject* obj = getInput(index);
2769 
2770    if(obj)
2771    {
2772       theCastFilter->connectMyInputTo(0, obj);
2773       result= (theCastFilter->getTile(theTile->getImageRectangle(),
2774                                       theCurrentResLevel));
2775 
2776       if(result.valid())
2777       {
2778          result->setMinPix(theTile->getMinPix(), theTile->getNumberOfBands());
2779          result->setMaxPix(theTile->getMaxPix(), theTile->getNumberOfBands());
2780       }
2781    }
2782 
2783    return result;
2784 }
2785 
getNewImageData(ossim_uint32 index)2786 ossimRefPtr<ossimImageData> ossimEquationCombiner::getNewImageData(
2787    ossim_uint32 index)
2788 {
2789    ossimRefPtr<ossimImageData> result = getImageData(index);
2790 
2791    if(result.valid())
2792    {
2793       if(result->getBuf())
2794       {
2795          result = (ossimImageData*)result->dup();
2796       }
2797    }
2798 
2799    return result;
2800 }
2801 
parseExpression()2802 bool ossimEquationCombiner::parseExpression()
2803 {
2804    // parse the following rule:
2805    // expression : Term ResOfExpression
2806    //
2807 
2808    bool result = false;
2809 
2810    if(parseTerm())
2811    {
2812       result =  parseRestOfExp();
2813    }
2814 
2815    return result;
2816 }
2817 
parseEquation()2818 ossimRefPtr<ossimImageData> ossimEquationCombiner::parseEquation()
2819 {
2820    ostringstream s;
2821 
2822    s << theEquation;
2823 
2824    istringstream inS(s.str());
2825    theLexer->switch_streams(&inS, &ossimNotify(ossimNotifyLevel_WARN));
2826 
2827    theCurrentId = theLexer->yylex();
2828 
2829    while(theCurrentId)
2830    {
2831       if(!parseExpression())
2832       {
2833          break;
2834       }
2835    }
2836 
2837    if(!theValueStack.empty())
2838    {
2839       assignValue();
2840       theTile->validate();
2841       clearStacks();
2842    }
2843 
2844    return theTile;
2845 }
2846 
applyClamp(ossimImageData * & result,const vector<ossimEquValue> & argList)2847 bool ossimEquationCombiner::applyClamp(ossimImageData* &result,
2848                                        const vector<ossimEquValue>& argList)
2849 {
2850    if(result)
2851    {
2852       // Delete the object indirectly through an ossimRefPtr.
2853       ossimRefPtr<ossimImageData> id = result;
2854       id = NULL;
2855       result = (ossimImageData*) NULL;
2856    }
2857    if(argList.size() <3)
2858    {
2859       return false;
2860    }
2861 
2862    if(argList[0].type == OSSIM_EQU_DOUBLE_TYPE)
2863    {
2864       return false;
2865    }
2866    else if( (argList[1].type == OSSIM_EQU_DOUBLE_TYPE)&&
2867             (argList[2].type == OSSIM_EQU_DOUBLE_TYPE))
2868    {
2869       result = argList[0].d.imageDataValue;
2870 
2871       if(argList[0].d.imageDataValue)
2872       {
2873          ossimDataObjectStatus status = result->getDataObjectStatus();
2874          if((status != OSSIM_NULL) &&
2875             (status != OSSIM_EMPTY))
2876          {
2877             double minValue = argList[1].d.doubleValue;
2878             double maxValue = argList[2].d.doubleValue;
2879 
2880             if(minValue > maxValue)
2881             {
2882                std::swap(minValue, maxValue);
2883             }
2884 
2885             int band   = 0;
2886             int offset = 0;
2887 
2888             int upperBoundBand   = result->getNumberOfBands();
2889             int offsetUpperBound = result->getWidth()*result->getHeight();
2890 
2891             if(status == OSSIM_PARTIAL)
2892             {
2893                for(band = 0; band < upperBoundBand; ++band)
2894                {
2895                   double np = static_cast<double>(result->getNullPix(band));
2896                   double *buf = static_cast<double*>(result->getBuf(band));
2897                   for(offset = 0; offset < offsetUpperBound; ++ offset)
2898                   {
2899                      if( *buf != np )
2900                      {
2901                         if( (*buf) < minValue) *buf = minValue;
2902                         else if( (*buf) >maxValue) *buf = maxValue;
2903                      }
2904                      ++buf;
2905                   }
2906                }
2907             }
2908             else
2909             {
2910                for(band = 0; band < upperBoundBand; ++band)
2911                {
2912                   double *buf = static_cast<double*>(result->getBuf(band));
2913                   for(offset = 0; offset < offsetUpperBound; ++ offset)
2914                   {
2915                      if( (*buf) < minValue) *buf = minValue;
2916                      else if( (*buf) >maxValue) *buf = maxValue;
2917                      ++buf;
2918                   }
2919                }
2920             }
2921          }
2922       }
2923 
2924       return true;
2925    }
2926    return false;
2927 }
2928 
applyConvolution(ossimImageData * & result,const vector<ossimEquValue> & argList)2929 bool ossimEquationCombiner::applyConvolution(ossimImageData* &result,
2930                                              const vector<ossimEquValue>& argList)
2931 {
2932    if(result)
2933    {
2934       // Delete the object indirectly through an ossimRefPtr.
2935       ossimRefPtr<ossimImageData> id = result;
2936       id = NULL;
2937       result = (ossimImageData*) NULL;
2938    }
2939    if(argList.size() <4) return false;
2940 
2941    for(ossim_uint32 i = 0; i < argList.size(); ++i)
2942    {
2943       if(argList[i].type != OSSIM_EQU_DOUBLE_TYPE)
2944       {
2945          return false;
2946       }
2947    }
2948 
2949    ossim_uint32 index = (ossim_uint32)argList[0].d.doubleValue;
2950    int rows = (int)argList[1].d.doubleValue;
2951    int cols = (int)argList[2].d.doubleValue;
2952 
2953    if((rows*cols) != (int)(argList.size()-3))
2954    {
2955       return false;
2956    }
2957 
2958    NEWMAT::Matrix m(rows,cols);
2959 
2960     int count = 3;
2961     for(int r = 0; r< rows;++r)
2962     {
2963        for(int c=0;c<cols;++c)
2964        {
2965           m[r][c] = argList[count].d.doubleValue;
2966           ++count;
2967        }
2968     }
2969    ossimConnectableObject* obj = getInput(index);
2970    if(obj)
2971    {
2972       ossimRefPtr<ossimConvolutionSource> conv = new ossimConvolutionSource(NULL, m);
2973 
2974       conv->connectMyInputTo(0, obj);
2975       theCastFilter->connectMyInputTo(0, conv.get());
2976 
2977       ossimRefPtr<ossimImageData> tempData =
2978          theCastFilter->getTile(theTile->getImageRectangle(),
2979                                 theCurrentResLevel);
2980       if(tempData.valid())
2981       {
2982          result = (ossimImageData*)tempData->dup();
2983       }
2984       else
2985       {
2986          result = (ossimImageData*)theTile->dup();
2987       }
2988       conv->disconnect();
2989       conv = 0;
2990    }
2991    if(result)
2992    {
2993       return true;
2994    }
2995 
2996    return false;
2997 }
2998 
applyBlurr(ossimImageData * & result,const vector<ossimEquValue> & argList)2999 bool ossimEquationCombiner::applyBlurr(ossimImageData* &result,
3000                                        const vector<ossimEquValue>& argList)
3001 {
3002    if(result)
3003    {
3004       // Delete the object indirectly through an ossimRefPtr.
3005       ossimRefPtr<ossimImageData> id = result;
3006       id = NULL;
3007       result = (ossimImageData*) NULL;
3008    }
3009    if(argList.size() !=3) return false;
3010 
3011    for(ossim_uint32 i = 0; i < argList.size(); ++i)
3012    {
3013       if(argList[i].type != OSSIM_EQU_DOUBLE_TYPE)
3014       {
3015          return false;
3016       }
3017    }
3018 
3019    ossim_uint32 index = (ossim_uint32)argList[0].d.doubleValue;
3020    int rows = (int)argList[1].d.doubleValue;
3021    int cols = (int)argList[2].d.doubleValue;
3022 
3023    NEWMAT::Matrix m(rows, cols);
3024 
3025    m = 1.0/(rows*cols);
3026 
3027    ossimConnectableObject* obj = getInput(index);
3028    if(obj)
3029    {
3030       ossimRefPtr<ossimConvolutionSource> conv = new ossimConvolutionSource(NULL,
3031                                                                 m);
3032 
3033       conv->connectMyInputTo(0, obj);
3034       theCastFilter->connectMyInputTo(0, conv.get());
3035       theCastFilter->initialize();
3036 
3037       ossimRefPtr<ossimImageData> tempData =
3038          theCastFilter->getTile(theTile->getImageRectangle(),
3039                                 theCurrentResLevel);
3040       if(tempData.valid())
3041       {
3042          result = (ossimImageData*)tempData->dup();
3043       }
3044       conv->disconnect();
3045       conv = 0;
3046    }
3047 
3048    if(result)
3049    {
3050       return true;
3051    }
3052 
3053    return false;
3054 }
3055 
applyShift(ossimImageData * & result,const vector<ossimEquValue> & argList)3056 bool ossimEquationCombiner::applyShift(ossimImageData* &result,
3057                                        const vector<ossimEquValue>& argList)
3058 {
3059    if(result)
3060    {
3061       // Delete the object indirectly through an ossimRefPtr.
3062       ossimRefPtr<ossimImageData> id = result;
3063       id = NULL;
3064       result = (ossimImageData*) NULL;
3065    }
3066    if(argList.size() !=3) return false;
3067 
3068    for(ossim_uint32 i = 0; i < argList.size(); ++i)
3069    {
3070       if(argList[i].type != OSSIM_EQU_DOUBLE_TYPE)
3071       {
3072          return false;
3073       }
3074    }
3075 
3076    ossim_uint32 index = (ossim_uint32)argList[0].d.doubleValue;
3077    int x = (int)argList[1].d.doubleValue;
3078    int y = (int)argList[2].d.doubleValue;
3079 
3080    ossimConnectableObject* obj = getInput(index);
3081    if(obj)
3082    {
3083       ossimRefPtr<ossimSubImageTileSource> shiftSource =
3084          new ossimSubImageTileSource(NULL, ossimIpt(x, y));
3085 
3086       shiftSource->connectMyInputTo(0, obj);
3087       theCastFilter->connectMyInputTo(0, shiftSource.get());
3088 
3089        ossimRefPtr<ossimImageData> tempData =
3090           theCastFilter->getTile(theTile->getImageRectangle(),
3091                                  theCurrentResLevel);
3092        if(tempData.valid())
3093        {
3094           result = (ossimImageData*)tempData->dup();
3095        }
3096       shiftSource->disconnect();
3097       shiftSource = 0;
3098    }
3099 
3100    if(result)
3101    {
3102       return true;
3103    }
3104 
3105    return false;
3106 }
3107 
applyOp(const ossimBinaryOp & op,ossimEquValue & result,ossimEquValue & v1,ossimEquValue & v2)3108 bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op,
3109                                     ossimEquValue& result,
3110                                     ossimEquValue& v1,
3111                                     ossimEquValue& v2)
3112 {
3113    bool returnValue = true;
3114 
3115    if(v1.type == OSSIM_EQU_DOUBLE_TYPE)
3116    {
3117       if(v2.type == OSSIM_EQU_DOUBLE_TYPE)
3118       {
3119          result.type = OSSIM_EQU_DOUBLE_TYPE;
3120          result.d.doubleValue = op.apply(v1.d.doubleValue, v2.d.doubleValue);
3121       }
3122       else if(v2.type == OSSIM_EQU_IMAGE_DATA_TYPE)
3123       {
3124          returnValue = applyOp(op,
3125                                v1.d.doubleValue,
3126                                v2.d.imageDataValue);
3127 
3128          result.type = OSSIM_EQU_IMAGE_DATA_TYPE;
3129          result.d.imageDataValue = v2.d.imageDataValue;
3130       }
3131       else
3132       {
3133          returnValue = false;
3134       }
3135    }
3136    else if(v1.type == OSSIM_EQU_IMAGE_DATA_TYPE)
3137    {
3138       if(v2.type == OSSIM_EQU_DOUBLE_TYPE)
3139       {
3140 
3141          returnValue = applyOp(op,
3142                                v1.d.imageDataValue,
3143                                v2.d.doubleValue);
3144 
3145          result.type = OSSIM_EQU_IMAGE_DATA_TYPE;
3146          result.d.imageDataValue = v1.d.imageDataValue;
3147          returnValue = true;
3148       }
3149       else if(v2.type == OSSIM_EQU_IMAGE_DATA_TYPE)
3150       {
3151          returnValue = applyOp(op,
3152                                v1.d.imageDataValue,
3153                                v2.d.imageDataValue);
3154          result.type = OSSIM_EQU_IMAGE_DATA_TYPE;
3155          result.d.imageDataValue = v1.d.imageDataValue;
3156 
3157          // Delete the object indirectly through an ossimRefPtr.
3158          ossimRefPtr<ossimImageData> id = v2.d.imageDataValue;
3159          id = NULL;
3160          v2.d.imageDataValue = (ossimImageData*)NULL;
3161          returnValue = true;
3162       }
3163       else
3164       {
3165          returnValue = false;
3166       }
3167    }
3168    else
3169    {
3170       returnValue = false;
3171    }
3172 
3173    return returnValue;
3174 }
3175 
applyOp(const ossimBinaryOp & op,ossimImageData * v1,double v2)3176 bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op,
3177                                     ossimImageData* v1,
3178                                     double          v2)
3179 {
3180    double* buf = static_cast<double*>(v1->getBuf());
3181    if(!buf) return true;
3182    ossimDataObjectStatus status = v1->getDataObjectStatus();
3183 
3184    if(status == OSSIM_EMPTY || status == OSSIM_NULL)
3185    {
3186       return true;
3187    }
3188 
3189    if(status == OSSIM_FULL )
3190    {
3191       ossim_uint32 size = v1->getSize();
3192       double value = (static_cast<double>(v2));
3193 
3194       for(ossim_uint32 i = 0; i < size; ++i)
3195       {
3196          *buf = (double)op.apply(*buf, value);
3197          ++buf;
3198       }
3199    }
3200    else
3201    {
3202       ossim_uint32 sizePerBand = v1->getSizePerBand();
3203       ossim_uint32 numberOfBands = v1->getNumberOfBands();
3204 
3205       if(numberOfBands)
3206       {
3207          for(ossim_uint32 band = 0; band < numberOfBands; ++band)
3208          {
3209             double* buf = static_cast<double*>(v1->getBuf(band));
3210 
3211             if(buf)
3212             {
3213                double  np  = static_cast<double>(v1->getNullPix()[band]);
3214 
3215                for(ossim_uint32 offset = 0; offset < sizePerBand;++offset)
3216                {
3217                   if(*buf != np)
3218                   {
3219                      *buf = (double)op.apply(*buf, v2);
3220                   }
3221                   ++buf;
3222                }
3223             }
3224          }
3225       }
3226    }
3227    return true;
3228 }
3229 
applyOp(const ossimBinaryOp & op,double v1,ossimImageData * v2)3230 bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op,
3231                                     double          v1,
3232                                     ossimImageData* v2)
3233 {
3234    double* buf = static_cast<double*>(v2->getBuf());
3235    if(!buf) return true;
3236    ossimDataObjectStatus status = v2->getDataObjectStatus();
3237 
3238    if(status == OSSIM_EMPTY || status == OSSIM_NULL)
3239    {
3240       return true;
3241    }
3242 
3243    if(status == OSSIM_FULL )
3244    {
3245       ossim_uint32 size = v2->getSize();
3246       double value = (static_cast<double>(v1));
3247 
3248       for(ossim_uint32 i = 0; i < size; ++i)
3249       {
3250          *buf = (double)op.apply(value, *buf);
3251          ++buf;
3252       }
3253    }
3254    else
3255    {
3256       ossim_uint32 sizePerBand = v2->getSizePerBand();
3257       ossim_uint32 numberOfBands = v2->getNumberOfBands();
3258 
3259       if(numberOfBands)
3260       {
3261          for(ossim_uint32 band = 0; band < numberOfBands; ++band)
3262          {
3263             double* buf = static_cast<double*>(v2->getBuf(band));
3264 
3265             if(buf)
3266             {
3267                double  np  = static_cast<double>(v2->getNullPix()[band]);
3268 
3269                for(ossim_uint32 offset = 0; offset < sizePerBand; ++offset)
3270                {
3271                   if(*buf != np)
3272                   {
3273                      *buf = (double)op.apply((double)v1, *buf);
3274                   }
3275                   ++buf;
3276                }
3277             }
3278          }
3279       }
3280    }
3281 
3282    return true;
3283 }
3284 
applyOp(const ossimBinaryOp & op,ossimImageData * v1,ossimImageData * v2)3285 bool ossimEquationCombiner::applyOp(const ossimBinaryOp& op,
3286                                     ossimImageData* v1,
3287                                     ossimImageData* v2)
3288 {
3289    ossim_uint32 minNumberOfBands = std::min(v1->getNumberOfBands(), v2->getNumberOfBands());
3290    ossim_uint32 maxNumberOfBands = std::max(v1->getNumberOfBands(), v2->getNumberOfBands());
3291 
3292    ossim_uint32 size = v1->getWidth()*v1->getHeight();
3293    ossimDataObjectStatus status1 = v1->getDataObjectStatus();
3294    ossimDataObjectStatus status2 = v2->getDataObjectStatus();
3295 
3296    double** bandV1   = new double*[maxNumberOfBands];
3297    double** bandV2   = new double*[maxNumberOfBands];
3298    double* bandV1Np  = new double[maxNumberOfBands];
3299    double* bandV2Np  = new double[maxNumberOfBands];
3300    ossim_uint32 band = 0;
3301    for(band = 0; band < minNumberOfBands; ++band)
3302    {
3303       bandV1[band]   = (double*)v1->getBuf(band);
3304       bandV2[band]   = (double*)v2->getBuf(band);
3305       bandV1Np[band] = (double)v1->getNullPix(band);
3306       bandV2Np[band] = (double)v2->getNullPix(band);
3307    }
3308    if(v1->getNumberOfBands() < v2->getNumberOfBands())
3309    {
3310       for(band = 0; band < maxNumberOfBands; ++band)
3311       {
3312          bandV1[band]   = (double*)v1->getBuf(minNumberOfBands-1);
3313          bandV2[band]   = (double*)v2->getBuf(band);
3314          bandV1Np[band] = (double)v1->getNullPix(minNumberOfBands-1);
3315          bandV2Np[band] = (double)v2->getNullPix(band);
3316       }
3317    }
3318    else if(v2->getNumberOfBands() < v1->getNumberOfBands())
3319    {
3320       for(band = 0; band < maxNumberOfBands; ++band)
3321       {
3322          bandV1[band]   = (double*)v1->getBuf(band);
3323          bandV2[band]   = (double*)v2->getBuf(minNumberOfBands-1);
3324          bandV1Np[band] = (double)v1->getNullPix(band);
3325          bandV2Np[band] = (double)v2->getNullPix(minNumberOfBands-1);
3326       }
3327    }
3328 
3329    if(status1 == OSSIM_EMPTY)
3330    {
3331       if(status2 == OSSIM_FULL)
3332       {
3333          for(band = 0; band < maxNumberOfBands; ++band)
3334          {
3335             double* buf1 = bandV1[band];
3336             double* buf2 = bandV2[band];
3337 
3338             for(ossim_uint32 i = 0; i < size; ++i)
3339             {
3340                *buf1 = *buf2;
3341                ++buf1;
3342                ++buf2;
3343             }
3344          }
3345       }
3346       else if(status2 == OSSIM_PARTIAL)
3347       {
3348          for(band = 0; band < maxNumberOfBands; ++band)
3349          {
3350             double* buf1 = bandV1[band];
3351             double* buf2 = bandV2[band];
3352             double  nullPix2 = bandV2Np[band];
3353             for(ossim_uint32 i = 0; i < size; ++i)
3354             {
3355                if(*buf2 != nullPix2)
3356                {
3357                   *buf1 = *buf2;
3358                }
3359                ++buf1;
3360                ++buf2;
3361             }
3362          }
3363       }
3364       v1->setDataObjectStatus(status2);
3365    }
3366    else if((status1 == OSSIM_FULL)&&
3367            (status2 == OSSIM_FULL))
3368    {
3369       for(band = 0; band < maxNumberOfBands; ++band)
3370       {
3371          double* buf1 = bandV1[band];
3372          double* buf2 = bandV2[band];
3373 
3374          for(ossim_uint32 i = 0; i < size; ++i)
3375          {
3376             *buf1 = op.apply(*buf1, *buf2);
3377             ++buf1;
3378             ++buf2;
3379          }
3380       }
3381    }
3382    else if((status1 == OSSIM_FULL)&&
3383            (status2 == OSSIM_PARTIAL))
3384    {
3385       for(band = 0; band < maxNumberOfBands; ++band)
3386       {
3387          double* buf1 = bandV1[band];
3388          double* buf2 = bandV2[band];
3389          double  nullPix2 = bandV2Np[band];
3390          for(ossim_uint32 i = 0; i < size; ++i)
3391          {
3392             if(*buf2 != nullPix2)
3393             {
3394                *buf1 = op.apply(*buf1, *buf2);
3395             }
3396 
3397             ++buf1;
3398             ++buf2;
3399          }
3400       }
3401    }
3402    else if((status1 == OSSIM_PARTIAL)&&
3403            (status2 == OSSIM_FULL))
3404    {
3405       for(band = 0; band < maxNumberOfBands; ++band)
3406       {
3407          double* buf1 = bandV1[band];
3408          double* buf2 = bandV2[band];
3409          double  nullPix1 = bandV1Np[band];
3410          for(ossim_uint32 i = 0; i < size; ++i)
3411          {
3412             if(*buf1 != nullPix1)
3413             {
3414                *buf1 = op.apply(*buf1, *buf2);
3415             }
3416 
3417             ++buf1;
3418             ++buf2;
3419          }
3420       }
3421    }
3422    else if((status1 == OSSIM_PARTIAL)&&
3423            (status2 == OSSIM_PARTIAL))
3424    {
3425       for(band = 0; band < maxNumberOfBands; ++band)
3426       {
3427          double* buf1 = bandV1[band];
3428          double* buf2 = bandV2[band];
3429          double  nullPix1 = bandV1Np[band];
3430          double  nullPix2 = bandV2Np[band];
3431          for(ossim_uint32 i = 0; i < size; ++i)
3432          {
3433             if((*buf1 != nullPix1)&&
3434                (*buf2 != nullPix2))
3435             {
3436                *buf1 = op.apply(*buf1, *buf2);
3437             }
3438 
3439             ++buf1;
3440             ++buf2;
3441          }
3442       }
3443    }
3444 
3445    delete [] bandV1;
3446    delete [] bandV2;
3447    delete [] bandV1Np;
3448    delete [] bandV2Np;
3449 
3450    return true;
3451 }
3452 
3453 
applyOp(const ossimUnaryOp & op,ossimEquValue & result,ossimEquValue & v)3454 bool ossimEquationCombiner::applyOp(const ossimUnaryOp& op,
3455                                     ossimEquValue& result,
3456                                     ossimEquValue& v)
3457 {
3458    bool returnValue = true;
3459 
3460    if(v.type == OSSIM_EQU_DOUBLE_TYPE)
3461    {
3462       result.type = OSSIM_EQU_DOUBLE_TYPE;
3463       result.d.doubleValue = op.apply(v.d.doubleValue);
3464    }
3465    else if(v.type == OSSIM_EQU_IMAGE_DATA_TYPE)
3466    {
3467       returnValue = applyOp(op,
3468                             v.d.imageDataValue);
3469       result.type = OSSIM_EQU_IMAGE_DATA_TYPE;
3470       result.d.imageDataValue = v.d.imageDataValue;
3471       returnValue = true;
3472    }
3473    else
3474    {
3475       returnValue = false;
3476    }
3477 
3478    return returnValue;
3479 }
3480 
applyOp(const ossimUnaryOp & op,ossimImageData * v)3481 bool ossimEquationCombiner::applyOp(const ossimUnaryOp& op,
3482                                     ossimImageData* v)
3483 {
3484    double* buf = static_cast<double*>(v->getBuf());
3485    if(!buf) return true;
3486    ossimDataObjectStatus status = v->getDataObjectStatus();
3487 
3488    if(status == OSSIM_EMPTY || status == OSSIM_NULL)
3489    {
3490       return true;
3491    }
3492 
3493    if(status == OSSIM_FULL )
3494    {
3495       ossim_uint32 size = v->getSize();
3496 
3497       for(ossim_uint32 i = 0; i < size; ++i)
3498       {
3499          *buf = (double)op.apply(*buf);
3500          ++buf;
3501       }
3502    }
3503    else
3504    {
3505       ossim_uint32 sizePerBand   = v->getSizePerBand();
3506       ossim_uint32 numberOfBands = v->getNumberOfBands();
3507 
3508       if(numberOfBands)
3509       {
3510          for(ossim_uint32 band = 0; band < numberOfBands; ++band)
3511          {
3512             double* buf = static_cast<double*>(v->getBuf(band));
3513 
3514             if(buf)
3515             {
3516                double  np  = static_cast<double>(v->getNullPix()[band]);
3517 
3518                for(ossim_uint32 offset = 0; offset < sizePerBand;++offset)
3519                {
3520                   if(*buf != np)
3521                   {
3522                      *buf = (double)op.apply(*buf);
3523                   }
3524                   ++buf;
3525                }
3526             }
3527          }
3528       }
3529    }
3530 
3531    return true;
3532 }
3533 
saveState(ossimKeywordlist & kwl,const char * prefix) const3534 bool ossimEquationCombiner::saveState(ossimKeywordlist& kwl,
3535                                       const char* prefix)const
3536 {
3537    ossimString outputScalarType =
3538       ossimScalarTypeLut::instance()->getEntryString(theOutputScalarType);
3539 
3540    kwl.add(prefix,
3541            EQUATION_KW,
3542            theEquation.c_str(),
3543            true);
3544 
3545    kwl.add(prefix,
3546            "output_scalar_type",
3547            outputScalarType.c_str(),
3548            true);
3549 
3550    return ossimImageCombiner::saveState(kwl,
3551                                         prefix);
3552 }
3553 
loadState(const ossimKeywordlist & kwl,const char * prefix)3554 bool ossimEquationCombiner::loadState(const ossimKeywordlist& kwl,
3555                                       const char* prefix)
3556 {
3557    const char* equ    = kwl.find(prefix, EQUATION_KW);
3558    const char* scalar = kwl.find(prefix, "output_scalar_type");
3559 
3560    bool result = ossimImageCombiner::loadState(kwl,
3561                                                prefix);
3562 
3563    if(equ)
3564    {
3565       theEquation = equ;
3566    }
3567 
3568    if(scalar)
3569    {
3570       setOutputScalarType(ossimScalarTypeLut::instance()->
3571                           getScalarTypeFromString(scalar));
3572    }
3573 
3574    return result;
3575 }
3576 
3577