1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License:  MIT
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossimImageChain.h 20316 2011-12-02 15:56:38Z oscarkramer $
12 #ifndef ossimImageChain_HEADER
13 #define ossimImageChain_HEADER
14 #include <vector>
15 #include <map>
16 #include <ossim/imaging/ossimImageSource.h>
17 #include <ossim/base/ossimConnectableObjectListener.h>
18 #include <ossim/base/ossimId.h>
19 #include <ossim/base/ossimConnectableContainerInterface.h>
20 
21 class OSSIMDLLEXPORT ossimImageChain : public ossimImageSource,
22                                        public ossimConnectableObjectListener,
23                                        public ossimConnectableContainerInterface
24 {
25 public:
26    ossimImageChain();
27    virtual ~ossimImageChain();
28 
getChainList()29    ossimConnectableObject::ConnectableObjectList& getChainList(){return theImageChainList;}
getChainList()30    const ossimConnectableObject::ConnectableObjectList& getChainList()const{return theImageChainList;}
31 
32    /**
33     * @param index Index of object to get.
34     *
35     * @see getNumberOfObjects(false) to get the number of objects inside
36     * the container.
37     *
38     * @return Container's object at that index or NULL if out of range.
39     */
40    ossimConnectableObject* operator[](ossim_uint32 index);
41 
42    /**
43     * Same as operator[](ossim_uint32 i)
44     *
45     * @param index Index of object to get.
46     *
47     * @see getNumberOfObjects(false) to get the number of objects inside
48     * the container.
49     *
50     * @return Container's object at that index or NULL if out of range.
51     *
52     * @note This does not recurse into other containers.
53     */
54    virtual ossimConnectableObject* getConnectableObject(ossim_uint32 index);
55 
56    virtual ossim_int32 indexOf(ossimConnectableObject* obj)const;
57    /**
58     * Return the first source which is the one that first receives the
59     * getTile request
60     */
61    virtual ossimImageSource* getFirstSource();
62    virtual const ossimImageSource* getFirstSource() const;
63 
64    virtual ossimObject* getFirstObject();
65 
66    /**
67     * Return the last source which is the one that last receives the
68     * getTile request.
69     */
70    virtual ossimImageSource* getLastSource();
71    virtual const ossimImageSource* getLastSource() const;
72 
73    virtual ossimObject* getLastObject();
74 
75 
76    /**
77     * Adds it to the start of the chain.  This is the first one to receive
78     * the getTile request.  This basically inserts it to the right of the
79     * right most filter.
80     * Returns true on success, false on error.
81     */
82    bool addFirst(ossimConnectableObject* obj);
83 
84    /**
85     * Adds it to the end.  this is the last one to receive the getTile
86     * request.  This basically inserts it to the left of the left most filter.
87     * Returns true on success, false on error.
88     */
89    bool addLast(ossimConnectableObject* obj);
90 
91    /**
92     * Deletes the first object.
93     * Note this is really most right of the chain.
94     * Returns true if deletion occurred, false if the chain is empty.
95     */
96    bool deleteFirst();
97 
98    /**
99     * Deletes the last object.
100     * Note this is really most left of the chain.
101     * Returns true if deletion occurred, false if the chain is empty.
102     */
103    bool deleteLast();
104 
105    /**
106     *
107     */
108    bool insertRight(ossimConnectableObject* newObj,
109                     ossimConnectableObject* rightOfThisObj);
110 
111    /**
112     *
113     */
114    bool insertRight(ossimConnectableObject* newObj,
115                     const ossimId& id);
116 
117    /**
118     *
119     */
120    bool insertLeft(ossimConnectableObject* newObj,
121                    const ossimId& id);
122    /**
123     *
124     */
125    bool insertLeft(ossimConnectableObject* newObj,
126                    ossimConnectableObject* leftOfThisObj);
127 
128    bool replace(ossimConnectableObject* newObj,
129                 ossimConnectableObject* oldObj);
130    /**
131     * Will return true or false if an image source was
132     * added to the chain.  It will add and do a connection
133     * to the previous source automatically.  This is a
134     * chain and the order of insertion matters. It adds it to the beginning
135     * of the list.  The last one added is the first one to receive
136     * the getTile.  Basically inserts to the right of the rightmost filter
137     *
138     */
139    virtual bool add(ossimConnectableObject* source);
140 
141    /**
142     * Within the image chain will pass the head of the
143     * list.
144     */
145    virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
146                                                ossim_uint32 resLevel=0);
147 
148    /**
149     * this call is passed to the head of the list.
150     */
151    virtual ossim_uint32 getNumberOfInputBands() const;
152 
153    /**
154     * This call is passed to the head of the list.
155     */
156    virtual ossimScalarType getOutputScalarType() const;
157 
158    virtual double getNullPixelValue(ossim_uint32 band=0)const;
159    virtual double getMinPixelValue(ossim_uint32 band=0)const;
160    virtual double getMaxPixelValue(ossim_uint32 band=0)const;
161 
162    virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const;
163 
164    /**
165     * This call is passed to the head of the list.
166     */
167    virtual ossim_uint32 getTileWidth()const;
168 
169    /**
170     * This call is passed to the head of the list.
171     */
172    virtual ossim_uint32 getTileHeight()const;
173 
174    /**
175     * Will pass this call to the head of the list.
176     */
177    virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const;
178    virtual void getValidImageVertices(std::vector<ossimIpt>& validVertices,
179                                       ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER,
180                                       ossim_uint32 resLevel=0)const;
181 
182    virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
183 
184    virtual void getDecimationFactor(ossim_uint32 resLevel,
185                                     ossimDpt& result) const;
186    virtual void getDecimationFactors(std::vector<ossimDpt>& decimations) const;
187    virtual ossim_uint32 getNumberOfDecimationLevels()const;
188 
189    /**
190     * Will save the state of the chain.
191     */
192    virtual bool saveState(ossimKeywordlist& kwl,
193                           const char* prefix=NULL)const;
194 
195    /**
196     * Will load the state.
197     */
198    virtual bool loadState(const ossimKeywordlist& kwl,
199                           const char* prefix=NULL);
200 
201    virtual void initialize();
202    virtual void enableSource();
203    virtual void disableSource();
204 
canConnectMyInputTo(ossim_int32 myInputIndex,const ossimConnectableObject * object)205    bool canConnectMyInputTo(ossim_int32 myInputIndex,
206                             const ossimConnectableObject* object)const
207       {
208          if(theImageChainList.size()&&
209             theImageChainList[theImageChainList.size()-1].valid())
210          {
211             ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, theImageChainList[theImageChainList.size()-1].get());
212             if(obj)
213             {
214                return obj->canConnectMyInputTo(myInputIndex,
215                                                object);
216             }
217          }
218          else if(!theImageChainList.size())
219          {
220             return true;
221          }
222          return false;
223       }
224 
225 //    bool canConnectMyOutputTo(int32 myOutputIndex,
226 //                              const ossimConnectableObject* object)const
227 //       {
228 //          if(theImageChainList.size()&&theImageChainList[0])
229 //          {
230 // 	   ossimConnectableObject* obj = PTR_CAST(ossimConnectableObject, theImageChainList[0]);
231 // 	   if(obj)
232 // 	     {
233 // 	       return obj->canConnectMyOutputTo(myOutputIndex,
234 // 						object);
235 // 	     }
236 //          }
237 
238 //          return false;
239 //       }
240 
241    // ________________________CONNECTABLE CONTAINER DEFINTIONS_________________
242    //
243 
244    /*!
245     * These methods are now deprecated.  You can achieve the same thing by using the new visitor design pattern.  If this does not
246     * achieve exactly what you want then you can derive new rules by overriding the virtual visit method in ossimVisitor
247     *
248     * <pre>
249     *    ossimTypeIdVisitor visitor(tyeId, false, ossimVisitor::VISIT_CHILDREN);
250     *    connectableObject->accept(visitor);
251     *    ossimCollectionVisitor::List& collection = visitor.getObjects();
252     * </pre>
253     */
254    OSSIM_DEPRECATE_METHOD( virtual ossimConnectableObject::ConnectableObjectList findAllObjectsOfType(const RTTItypeid& typeInfo,
255                                                                      bool recurse=true));
256    /*!
257     * These methods are now deprecated.  You can achieve the same thing by using the new visitor design pattern.  If this does not
258     * achieve exactly what you want then you can derive new rules by overriding the virtual visit method in ossimVisitor
259     *
260     * <pre>
261     *    ossimTypeNameVisitor visitor(typeName, false, ossimVisitor::VISIT_CHILDREN);
262     *    connectableObject->accept(visitor);
263     *    ossimCollectionVisitor::List& collection = visitor.getObjects();
264     * </pre>
265     */
266    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject::ConnectableObjectList findAllObjectsOfType(const ossimString& className,
267                                                                      bool recurse=true));
268 
269    /*!
270     * These methods are now deprecated.  You can achieve the same thing by using the new visitor design pattern.  If this does not
271     * achieve exactly what you want then you can derive new rules by overriding the virtual visit method in ossimVisitor
272     *
273     * <pre>
274     *    ossimTypeIdVisitor visitor(tyeId, true, ossimVisitor::VISIT_CHILDREN);
275     *    connectableObject->accept(visitor);
276     *    ossimRefPtr<ossimConnectableObject> obj = visitor.getObject();
277     * </pre>
278     */
279    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findFirstObjectOfType(const RTTItypeid& typeInfo,
280                                                          bool recurse=true));
281    /*!
282     * These methods are now deprecated.  You can achieve the same thing by using the new visitor design pattern.  If this does not
283     * achieve exactly what you want then you can derive new rules by overriding the virtual visit method in ossimVisitor
284     *
285     * <pre>
286     *    ossimTypeNameVisitor visitor(className, true, ossimVisitor::VISIT_CHILDREN);
287     *    connectableObject->accept(visitor);
288     *    ossimRefPtr<ossimConnectableObject> obj = visitor.getObject();
289     * </pre>
290     */
291    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findFirstObjectOfType(const ossimString& className,
292                                                          bool recurse=true));
293 
294    /*!
295     * These methods are now deprecated.  You can achieve the same thing by using the new visitor design pattern.  If this does not
296     * achieve exactly what you want then you can derive new rules by overriding the virtual visit method in ossimVisitor
297     *
298     * <pre>
299     *    ossimIdVisitor visitor(tyeId, true, ossimVisitor::VISIT_CHILDREN);
300     *    connectableObject->accept(visitor);
301     *    ossimRefPtr<ossimConnectableObject> obj = visitor.getObject();
302     * </pre>
303     */
304    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findObject(const ossimId& id,
305                                               bool recurse=true));
306 
307    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findObject(const ossimConnectableObject* obj,
308                                               bool recurse=true));
309 
310    /**
311     * Will cycle through all sources setting their ids. the idLast wlil
312     * be updated
313     * so we can recurse into other containers.
314     */
315    virtual void makeUniqueIds();
316 
317    /**
318     * Returns the number of objects within this container and all child
319     * containers.
320     *
321     * @param recurse If true and object is a contains containers; all objects
322     * will be conter.  If false only the objects of this container will be
323     * counted (theImageChainList.size()).
324     */
325    virtual ossim_uint32 getNumberOfObjects(bool recurse=true)const;
326 
327    /**
328     * Deprecated! Please use getNumberOfObjects(false).
329     *
330     * @return The number of objects in this container or
331     * (theImageChainList.size()).
332     */
333    virtual ossim_uint32 getNumberOfSources() const;
334 
335    /**
336     * Will add an object to the container and then set the added objects owner
337     * to this.
338     */
339    virtual bool addChild(ossimConnectableObject* attachableObject);
340 
341    /**
342     * Will remove the child from the container.  Changes the owner of the
343     * child to be NULL;
344     */
345    virtual bool removeChild(ossimConnectableObject* object);
346    virtual ossimConnectableObject* removeChild(const ossimId& id);
347 
348    virtual void getChildren(std::vector<ossimConnectableObject*>& children,
349                             bool immediateChildrenOnlyFlag);
350    //______________END CONNECTABLE CONTAINER INTERFACE____________
351 
352    virtual void disconnectInputEvent(ossimConnectionEvent& event);
353    virtual void disconnectOutputEvent(ossimConnectionEvent& event);
354    virtual void connectInputEvent(ossimConnectionEvent& event);
355    virtual void connectOutputEvent(ossimConnectionEvent& event);
356    virtual void objectDestructingEvent(ossimObjectDestructingEvent& event);
357 
358    virtual void propagateEventToOutputs(ossimEvent& event);
359    virtual void propagateEventToInputs(ossimEvent& event);
360 
361    virtual void processEvent(ossimEvent& event);
362 
363    virtual void accept(ossimVisitor& visitor);
364    void deleteList();
365 
366    /**
367     * These access methods greatly facilitate the implementation of an image chain adaptor class.
368     * They shouldn't be accessed directly by any other classes.  These methods really should be
369     * "protected" but the compiler complains if this base class' declarations are "protected".
370     */
imageChainList()371    virtual ossimConnectableObject::ConnectableObjectList& imageChainList() { return theImageChainList; }
imageChainList()372    virtual const ossimConnectableObject::ConnectableObjectList& imageChainList() const { return theImageChainList; }
373 
374    /**
375     * Inserts all of this object's children and inputs into the container provided. Since this is
376     * itself a form of container, this method will consolidate this chain with the argument
377     * container. Consequently, this chain object will not be represented in the container, but its
378     * children will be, with correct input and output connections to external objects. Ownership
379     * of children will pass to the argument container.
380     * @return Returns TRUE if successful.
381     */
382    //virtual bool fillContainer(ossimConnectableContainer& container);
383 
384 protected:
385    void prepareForRemoval(ossimConnectableObject* connectableObject);
386 
387   /**
388     * This will hold a sequence of image sources.
389     * theFirst one in the list will be the head of the
390     * list and the last one is the tail.
391     */
392    ossimConnectableObject::ConnectableObjectList theImageChainList;
393 
394    ossimRefPtr<ossimImageData>     theBlankTile;
395   // mutable bool                    thePropagateEventFlag;
396    mutable bool                    theLoadStateFlag;
397    /**
398     * For dynamic loading to take place we must allocate all objects first and
399     * then assign id's later.  We must remember the id's so we can do this.
400     * we will create a map that takes the id of the source as a key and a
401     * vector of input id's to connect it's inputs to.
402     */
403    bool addAllSources(std::map<ossimId, std::vector<ossimId> >& idMapping,
404                       const ossimKeywordlist& kwl,
405                       const char* prefix = NULL);
406    void findInputConnectionIds(std::vector<ossimId>& result,
407                                const ossimKeywordlist& kwl,
408                                const char* prefix=NULL);
409    bool connectAllSources(const std::map<ossimId, std::vector<ossimId> >& idMapping);
410 
411 
412 TYPE_DATA
413 };
414 #endif /* #ifndef ossimImageChain_HEADER */
415