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: ossimRectangleCutFilter.cpp 22953 2014-11-05 19:19:28Z dburken $
12 #include <ossim/imaging/ossimRectangleCutFilter.h>
13 #include <ossim/base/ossimTrace.h>
14 #include <ossim/base/ossimNotifyContext.h>
15 #include <ossim/base/ossimCommon.h>
16 #include <ossim/imaging/ossimImageData.h>
17 #include <ossim/imaging/ossimImageGeometry.h>
18 
19 using namespace std;
20 
21 static ossimTrace traceDebug("ossimRectangleCutFilter:debug");
22 
23 RTTI_DEF1(ossimRectangleCutFilter,
24           "ossimRectangleCutFilter",
25           ossimImageSourceFilter);
26 
ossimRectangleCutFilter(ossimObject * owner,ossimImageSource * inputSource)27 ossimRectangleCutFilter::ossimRectangleCutFilter(ossimObject* owner,
28                                      ossimImageSource* inputSource)
29    :ossimImageSourceFilter(owner, inputSource),
30     theCutType(OSSIM_RECTANGLE_NULL_OUTSIDE)
31 {
32    theRectangle.makeNan();
33 }
34 
ossimRectangleCutFilter(ossimImageSource * inputSource)35 ossimRectangleCutFilter::ossimRectangleCutFilter(ossimImageSource* inputSource)
36    :ossimImageSourceFilter(NULL, inputSource),
37     theCutType(OSSIM_RECTANGLE_NULL_OUTSIDE)
38 {
39    theRectangle.makeNan();
40 }
41 
42 
getTile(const ossimIrect & rect,ossim_uint32 resLevel)43 ossimRefPtr<ossimImageData> ossimRectangleCutFilter::getTile(
44    const ossimIrect& rect,
45    ossim_uint32 resLevel)
46 {
47    ossimRefPtr<ossimImageData> tile = 0;
48 
49    if ( theInputConnection && isSourceEnabled() && ( theRectangle.hasNans() == false ) )
50    {
51       ossim_int32 decimationIndex = min((ossim_int32)resLevel,
52                                         (ossim_int32)theDecimationList.size()-1);
53 
54       // Compute cut rect for resLevel:
55       ossimIrect cutRect = theRectangle*theDecimationList[decimationIndex];
56 
57       // Check intersection of our cut rect:
58       bool requestIntersects = rect.intersects( cutRect );
59       bool requestCompletelyWithin = rect.completely_within(cutRect);
60 
61       if ( ( ( theCutType == OSSIM_RECTANGLE_NULL_OUTSIDE ) && requestIntersects ) ||
62            ( ( theCutType == OSSIM_RECTANGLE_NULL_INSIDE ) && !requestCompletelyWithin ) )
63       {
64          // Grab tile from the input.
65          tile = theInputConnection->getTile(rect, resLevel);
66 
67          if ( tile.valid() )
68          {
69             if ( tile->getDataObjectStatus() != OSSIM_NULL &&
70                  tile->getDataObjectStatus() != OSSIM_EMPTY )
71             {
72                ossimIrect inputRectangle = tile->getImageRectangle();
73 
74                if( theCutType == OSSIM_RECTANGLE_NULL_OUTSIDE ) // Typical case...
75                {
76                   if ( !requestCompletelyWithin )
77                   {
78                      // Clip the tile:
79                      ossim_int32 ulx = inputRectangle.ul().x;
80                      ossim_int32 uly = inputRectangle.ul().y;
81                      ossim_int32 w   = tile->getWidth();
82                      ossim_int32 h   = tile->getHeight();
83                      ossim_int32 offset = 0;
84                      ossimIpt tempPoint(ulx, uly);
85 
86                      for(ossim_int32 y = 0;  y < h; ++tempPoint.y,++y)
87                      {
88                         tempPoint.x = ulx;
89                         for(ossim_int32 x = 0; x < w; ++tempPoint.x,++x)
90                         {
91                            if(!cutRect.pointWithin(tempPoint))
92                            {
93                               tile->setNull(offset);
94                            }
95                            ++offset;
96                         }
97                      }
98                      tile->validate();
99                   }
100                }
101                else // Null inside...
102                {
103                   // Note if complete within requested rect this block was bypassed entirely.
104                   ossim_int32 ulx = inputRectangle.ul().x;
105                   ossim_int32 uly = inputRectangle.ul().y;
106                   ossim_int32 w   = tile->getWidth();
107                   ossim_int32 h   = tile->getHeight();
108                   ossim_int32 offset = 0;
109                   ossimIpt tempPoint(ulx, uly);
110 
111                   for(ossim_int32 y = 0;  y < h; ++tempPoint.y,++y)
112                   {
113                      tempPoint.x = ulx;
114                      for(ossim_int32 x = 0; x < w; ++tempPoint.x,++x)
115                      {
116                         if(cutRect.pointWithin(tempPoint))
117                         {
118                            tile->setNull(offset);
119                         }
120                         ++offset;
121                      }
122                   }
123                   tile->validate();
124                }
125 
126             } // Matches: if ( tile->getDataObjectStatus() ...
127 
128          } // Matches: if ( tile.valid() )
129 
130       } // Matches: if ( ( ( theCutType == OSSI ...
131 
132    } // Matches: if ( theInputConnection && enabled && ...
133 
134    return tile;
135 } // End: ossimRectangleCutFilter::getTile( ... )
136 
setRectangle(const ossimIrect & rect)137 void ossimRectangleCutFilter::setRectangle(const ossimIrect& rect)
138 {
139    theRectangle = rect;
140 
141    if(theRectangle.hasNans())
142    {
143       if(theInputConnection)
144       {
145          theRectangle = theInputConnection->getBoundingRect();
146       }
147    }
148 }
149 
getValidImageVertices(vector<ossimIpt> & validVertices,ossimVertexOrdering ordering,ossim_uint32) const150 void ossimRectangleCutFilter::getValidImageVertices(
151    vector<ossimIpt>& validVertices,
152    ossimVertexOrdering ordering,
153    ossim_uint32 /* resLevel */)const
154 {
155    ossimIrect rect = getBoundingRect();
156 
157    if(ordering == OSSIM_CLOCKWISE_ORDER)
158    {
159       validVertices.push_back(rect.ul());
160       validVertices.push_back(rect.ur());
161       validVertices.push_back(rect.lr());
162       validVertices.push_back(rect.ll());
163    }
164    else
165    {
166       validVertices.push_back(rect.ul());
167       validVertices.push_back(rect.ll());
168       validVertices.push_back(rect.lr());
169       validVertices.push_back(rect.ur());
170    }
171 }
172 
getBoundingRect(ossim_uint32 resLevel) const173 ossimIrect ossimRectangleCutFilter::getBoundingRect(ossim_uint32 resLevel)const
174 {
175    if(traceDebug())
176    {
177       ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRectangleCutFilter::getBoundingRect DEBUG: entered..." << std::endl;
178    }
179    ossimIrect result;
180 
181    result.makeNan();
182    if(!theInputConnection)
183    {
184       if(traceDebug())
185       {
186          ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRectangleCutFilter::getBoundingRect DEBUG: Input connection was not valid so leaving" << std::endl;
187       }
188       return result;
189    }
190 
191    result = theInputConnection->getBoundingRect(resLevel);
192    if(isSourceEnabled())
193    {
194       if(theCutType == OSSIM_RECTANGLE_NULL_OUTSIDE)
195       {
196          ossimDpt decimation;
197          getDecimationFactor(resLevel, decimation);
198          ossimIrect cutRect = theRectangle;
199          if(!decimation.hasNans())
200          {
201             cutRect = theRectangle*decimation;
202          }
203          result = cutRect;
204       }
205    }
206 
207    if(traceDebug())
208    {
209       ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRectangleCutFilter::getBoundingRect DEBUG: cut rect = " << result  << std::endl;
210    }
211    return result;
212 }
213 
initialize()214 void ossimRectangleCutFilter::initialize()
215 {
216    theDecimationList.clear();
217    if(theInputConnection)
218    {
219       getDecimationFactors(theDecimationList);
220    }
221    if(theDecimationList.empty())
222    {
223       theDecimationList.push_back(ossimDpt(1,1));
224    }
225    if(theRectangle.hasNans())
226    {
227       setRectangle(theRectangle);
228    }
229 }
230 
saveState(ossimKeywordlist & kwl,const char * prefix) const231 bool ossimRectangleCutFilter::saveState(ossimKeywordlist& kwl,
232                                         const char* prefix)const
233 {
234    ossimString newPrefix = prefix;
235    newPrefix+="clip_rect.";
236 
237    theRectangle.saveState(kwl, newPrefix);
238 
239    if(theCutType == OSSIM_RECTANGLE_NULL_INSIDE)
240    {
241       kwl.add(prefix,
242               "cut_type",
243               "null_inside",
244               true);
245    }
246    else if(theCutType == OSSIM_RECTANGLE_NULL_OUTSIDE)
247    {
248       kwl.add(prefix,
249               "cut_type",
250               "null_outside",
251               true);
252    }
253 
254    return ossimImageSourceFilter::saveState(kwl, prefix);
255 }
256 
loadState(const ossimKeywordlist & kwl,const char * prefix)257 bool ossimRectangleCutFilter::loadState(const ossimKeywordlist& kwl,
258                                         const char* prefix)
259 {
260    ossimString newPrefix = prefix;
261 
262    ossimString rect = kwl.find(prefix, "rect");
263    if(!rect.empty())
264    {
265       theRectangle.toRect(rect);
266    }
267    else
268    {
269       newPrefix+="clip_rect.";
270 
271       theRectangle.loadState(kwl, newPrefix.c_str());
272    }
273 
274    const char* cutType = kwl.find(prefix, "cut_type");
275    if(cutType)
276    {
277       ossimString c = cutType;
278       if(c == "null_inside")
279       {
280          theCutType = OSSIM_RECTANGLE_NULL_INSIDE;
281       }
282       else if(c == "null_outside")
283       {
284          theCutType = OSSIM_RECTANGLE_NULL_OUTSIDE;
285       }
286       else
287       {
288          theCutType = static_cast<ossimRectangleCutType>(ossimString(cutType).toLong());
289       }
290    }
291 
292    return ossimImageSourceFilter::loadState(kwl, prefix);
293 }
294 
getRectangle() const295 const ossimIrect& ossimRectangleCutFilter::getRectangle()const
296 {
297    return theRectangle;
298 }
299 
getCutType() const300 ossimRectangleCutFilter::ossimRectangleCutType ossimRectangleCutFilter::getCutType()const
301 {
302    return theCutType;
303 }
304 
setCutType(ossimRectangleCutType cutType)305 void ossimRectangleCutFilter::setCutType(ossimRectangleCutType cutType)
306 {
307    theCutType = cutType;
308 }
309