OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimImageRenderer.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: MIT
4 //
5 // Author: Garrett Potts
6 //
7 //*******************************************************************
8 // $Id: ossimImageRenderer.cpp 23663 2015-12-11 21:10:54Z dburken $
9 
11 #include <ossim/base/ossimDpt.h>
12 #include <ossim/base/ossimDpt3d.h>
13 #include <ossim/base/ossimDrect.h>
15 #include <ossim/base/ossimCommon.h>
16 #include <ossim/base/ossimTrace.h>
37 #include <iostream>
38 #include <stack>
39 // using namespace std;
40 
41 #ifdef OSSIM_ID_ENABLED
42 static const char OSSIM_ID[] = "$Id: ossimImageRenderer.cpp 23663 2015-12-11 21:10:54Z dburken $";
43 #endif
44 
45 static ossimTrace traceDebug("ossimImageRenderer:debug");
46 
48 
49 
50 
51 void ossimImageRenderer::ossimRendererSubRectInfo::splitHorizontal(std::vector<ossimRendererSubRectInfo>& result)const
52 {
53  ossimIrect vrect(m_Vul,
54  m_Vur,
55  m_Vlr,
56  m_Vll);
57  ossim_int32 w = vrect.width();
58  // ossim_int32 h = vrect.height();
59  ossim_int32 w2 = w>>1;
60  ossimIrect tempLeftRect(m_Vul.x,
61  m_Vul.y,
62  m_Vul.x+w2-1,
63  m_Vlr.y);
64  ossimIrect tempRightRect(tempLeftRect.ur().x+1,
65  m_Vul.y,
66  m_Vur.x,
67  m_Vlr.y);
68 
69 
72 
74  right.m_viewBounds = m_viewBounds;
75 
76  left.m_Vul = tempLeftRect.ul();
77  left.m_Vur = tempLeftRect.ur();
78  left.m_Vlr = tempLeftRect.lr();
79  left.m_Vll = tempLeftRect.ll();
80 
81  right.m_Vul = tempRightRect.ul();
82  right.m_Vur = tempRightRect.ur();
83  right.m_Vlr = tempRightRect.lr();
84  right.m_Vll = tempRightRect.ll();
85 
86  left.transformViewToImage();
87  right.transformViewToImage();
88 
89  if(left.imageIsNan())
90  {
91  if(left.m_viewBounds->intersects(left.getViewRect()))
92  {
93  result.push_back(left);
94  }
95  }
96  else
97  {
98  result.push_back(left);
99  }
100  if(right.imageIsNan())
101  {
102  if(right.m_viewBounds->intersects(right.getViewRect()))
103  {
104  result.push_back(right);
105  }
106  }
107  else
108  {
109  result.push_back(right);
110  }
111 }
112 
113 void ossimImageRenderer::ossimRendererSubRectInfo::splitVertical(std::vector<ossimRendererSubRectInfo>& result)const
114 {
115  ossimIrect vrect(m_Vul,
116  m_Vur,
117  m_Vlr,
118  m_Vll);
119  // ossim_int32 w = vrect.width();
120  ossim_int32 h = vrect.height();
121  ossim_int32 h2 = h>>1;
122  ossimIrect tempTopRect(m_Vul.x,
123  m_Vul.y,
124  m_Vlr.x,
125  m_Vul.y+h2-1);
126  ossimIrect tempBottomRect(m_Vul.x,
127  tempTopRect.lr().y+1,
128  m_Vlr.x,
129  m_Vlr.y);
130 
131  ossimRendererSubRectInfo top(m_transform.get());
132  ossimRendererSubRectInfo bottom(m_transform.get());
133 
134  top.m_viewBounds = m_viewBounds;
135  bottom.m_viewBounds = m_viewBounds;
136 
137  top.m_Vul = tempTopRect.ul();
138  top.m_Vur = tempTopRect.ur();
139  top.m_Vlr = tempTopRect.lr();
140  top.m_Vll = tempTopRect.ll();
141 
142  bottom.m_Vul = tempBottomRect.ul();
143  bottom.m_Vur = tempBottomRect.ur();
144  bottom.m_Vlr = tempBottomRect.lr();
145  bottom.m_Vll = tempBottomRect.ll();
146 
147  top.transformViewToImage();
148  bottom.transformViewToImage();
149 
150  if(top.imageIsNan())
151  {
152  if(top.m_viewBounds->intersects(top.getViewRect()))
153  {
154  result.push_back(top);
155  }
156  }
157  else
158  {
159  result.push_back(top);
160  }
161  if(bottom.imageIsNan())
162  {
163  if(bottom.m_viewBounds->intersects(bottom.getViewRect()))
164  {
165  result.push_back(bottom);
166  }
167  }
168  else
169  {
170  result.push_back(bottom);
171  }
172 }
173 
174 void ossimImageRenderer::ossimRendererSubRectInfo::splitAll(std::vector<ossimRendererSubRectInfo>& result)const
175 {
176  //std::cout << "FULL Split\n" << std::endl;
177  // let splitAll for now. We can still optimize but will do that later
178  ossimIrect tempUlRect;
179  ossimIrect tempUrRect;
180  ossimIrect tempLrRect;
181  ossimIrect tempLlRect;
182  ossimIrect vrect(m_Vul,
183  m_Vur,
184  m_Vlr,
185  m_Vll);
186  ossim_int32 w = vrect.width();
187  ossim_int32 h = vrect.height();
188  ossim_int32 w2 = w>>1;
189  ossim_int32 h2 = h>>1;
190 
191  tempUlRect = ossimIrect(m_Vul.x,
192  m_Vul.y,
193  m_Vul.x + (w2 - 1),
194  m_Vul.y + (h2 - 1));
195 
196  tempUrRect = ossimIrect(tempUlRect.ur().x+1,
197  m_Vul.y,
198  m_Vur.x,
199  m_Vul.y + (h2 - 1));
200 
201  tempLrRect = ossimIrect(tempUlRect.lr().x,
202  tempUlRect.lr().y+1,
203  m_Vlr.x,
204  m_Vlr.y);
205 
206  tempLlRect = ossimIrect(m_Vul.x,
207  tempUlRect.ll().y+1,
208  tempLrRect.ul().x,
209  tempLrRect.ll().y);
210 
211 // std::cout << "VR: " << vrect.width() << ", " << vrect.height() << "\n"
212 // << "UL: " << tempUlRect.width() << ", " << tempUlRect.height() << "\n"
213 // << "UR: " << tempUrRect.width() << ", " << tempUrRect.height() << "\n"
214 // << "LR: " << tempLrRect.width() << ", " << tempLrRect.height() << "\n"
215 // << "LL: " << tempLlRect.width() << ", " << tempLlRect.height() << "\n";
216 
217  ossimRendererSubRectInfo ul(m_transform.get(),tempUlRect.ul(), tempUlRect.ur(),tempUlRect.lr(), tempUlRect.ll());
218  ossimRendererSubRectInfo ur(m_transform.get(),tempUrRect.ul(), tempUrRect.ur(),tempUrRect.lr(), tempUrRect.ll());
219  ossimRendererSubRectInfo lr(m_transform.get(),tempLrRect.ul(), tempLrRect.ur(),tempLrRect.lr(), tempLrRect.ll());
220  ossimRendererSubRectInfo ll(m_transform.get(),tempLlRect.ul(), tempLlRect.ur(),tempLlRect.lr(), tempLlRect.ll());
221 
222  ul.m_viewBounds = m_viewBounds;
223  ur.m_viewBounds = m_viewBounds;
224  lr.m_viewBounds = m_viewBounds;
225  ll.m_viewBounds = m_viewBounds;
226 
227  ul.transformViewToImage();
228  ur.transformViewToImage();
229  lr.transformViewToImage();
230  ll.transformViewToImage();
231 
232  if(ul.imageIsNan())
233  {
234  if(ul.m_viewBounds->intersects(ul.getViewRect()))
235  {
236  result.push_back(ul);
237  }
238  }
239  else
240  {
241  result.push_back(ul);
242  }
243  if(ur.imageIsNan())
244  {
245  if(ur.m_viewBounds->intersects(ur.getViewRect()))
246  {
247  result.push_back(ur);
248  }
249  }
250  else
251  {
252  result.push_back(ur);
253  }
254  if(lr.imageIsNan())
255  {
256  if(lr.m_viewBounds->intersects(lr.getViewRect()))
257  {
258  result.push_back(lr);
259  }
260  }
261  else
262  {
263  result.push_back(lr);
264  }
265  if(ll.imageIsNan())
266  {
267  if(ll.m_viewBounds->intersects(ll.getViewRect()))
268  {
269  result.push_back(ll);
270  }
271  }
272  else
273  {
274  result.push_back(ll);
275  }
276 }
277 
278 void ossimImageRenderer::ossimRendererSubRectInfo::splitView(std::vector<ossimRendererSubRectInfo>& result)const
279 {
280  ossim_uint16 splitFlags = getSplitFlags();
281  if(!splitFlags)
282  {
283  return;
284  }
285 
286 
287  // just do horizontal split for test
288  ossimIrect vrect(m_Vul,
289  m_Vur,
290  m_Vlr,
291  m_Vll);
292  ossim_int32 w = vrect.width();
293  ossim_int32 h = vrect.height();
294  ossim_int32 w2 = w>>1;
295  ossim_int32 h2 = h>>1;
296 
297  if((w2 <2)&&(h2<2))
298  {
299  ossimRendererSubRectInfo rect(m_transform.get(),m_Vul,
300  m_Vul,
301  m_Vul,
302  m_Vul);
303  rect.m_viewBounds = m_viewBounds;
304  rect.transformViewToImage();
305 
306  if(rect.imageHasNans())
307  {
308  if(rect.m_viewBounds->intersects(rect.getViewRect()))
309  {
310  result.push_back(rect);
311  }
312  }
313  }
314  // horizontal split if only the upper left and lower left
315  // vertices need splitting
316  else if((splitFlags==(UPPER_LEFT_SPLIT_FLAG|LOWER_LEFT_SPLIT_FLAG))||
317  (splitFlags==(UPPER_RIGHT_SPLIT_FLAG|LOWER_RIGHT_SPLIT_FLAG)))
318  {
319  // std::cout << "Horizontal Split\n" << std::endl;
320  if(w > 1)
321  {
322  splitHorizontal(result);
323  }
324  }
325  // check vertical only split
326  else if((splitFlags==(UPPER_LEFT_SPLIT_FLAG|UPPER_RIGHT_SPLIT_FLAG))||
327  (splitFlags==(LOWER_RIGHT_SPLIT_FLAG|LOWER_LEFT_SPLIT_FLAG)))
328  {
329  //std::cout << "Vertical Split\n" << std::endl;
330 
331  if(h>1)
332  {
333  splitVertical(result);
334  }
335  }
336  else//if((w>1)&&(h>1)&&(splitFlags))
337  {
338  if((w<2)&&(h>1))
339  {
340  splitVertical(result);
341  }
342  else if((w>1)&&(h<2))
343  {
344  splitHorizontal(result);
345  }
346  else
347  {
348  splitAll(result);
349  }
350  }
351 }
352 
354 {
355  ossimDpt vul;
356  ossimDpt vur;
357  ossimDpt vlr;
358  ossimDpt vll;
359  m_transform->imageToView(m_Iul,
360  vul);
361  m_transform->imageToView(m_Iur,
362  vur);
363  m_transform->imageToView(m_Ilr,
364  vlr);
365  m_transform->imageToView(m_Ill,
366  vll);
367 
368  m_Vul = vul;
369  m_Vur = vur;
370  m_Vlr = vlr;
371  m_Vll = vll;
372 }
373 
375 {
376  ossimDrect vRect = getViewRect();
377 
378  return ((vRect.width() > 32) || (vRect.height() > 32));
379 }
380 
382 {
383  #if 0
384  ossim_uint16 result = SPLIT_NONE;
385  ossimDrect vRect = getViewRect();
386 
387  //---
388  // Don't allow splits beyond 8x8 pixel. ossim2dBilinearTransform was core dumping with
389  // very small rectangles in canBilinearInterpolate(...) method.
390  // DRB 05 Dec. 2017
391  //---
392  if ( imageHasNans()||(vRect.width() < 8 && vRect.height() < 8) )
393  {
394  return result;
395  }
396 
397  if(imageHasNans())
398  {
399  if(m_viewBounds->intersects(vRect))
400  {
401  result = SPLIT_ALL;
402  }
403  else
404  {
405  return result;
406  }
407  }
408  /*
409  if(result != SPLIT_ALL)
410  {
411  if(m_ulRoundTripError.hasNans()&&m_urRoundTripError.hasNans()&&
412  m_lrRoundTripError.hasNans()&&m_llRoundTripError.hasNans())
413  {
414  if(m_viewBounds->intersects(getViewRect()))
415  {
416  result = SPLIT_ALL;
417  }
418  return result;
419  }
420  else if(tooBig())
421  {
422  result = SPLIT_ALL;
423  }
424  }
425 
426  if(result != SPLIT_ALL)
427  {
428  if(m_ulRoundTripError.hasNans()) result |= UPPER_LEFT_SPLIT_FLAG;
429  if(m_urRoundTripError.hasNans()) result |= UPPER_RIGHT_SPLIT_FLAG;
430  if(m_lrRoundTripError.hasNans()) result |= LOWER_RIGHT_SPLIT_FLAG;
431  if(m_llRoundTripError.hasNans()) result |= LOWER_LEFT_SPLIT_FLAG;
432  }
433  */
434  if(result != SPLIT_ALL)
435  {
436  ossim_float64 bias = m_ImageToViewScale.length();
437  if(bias < 1.0) bias = 1.0/bias;
438  bias = std::sqrt(bias);
439 
440  if(bias < 1) bias = 1.0;
441 
442  // if((m_ulRoundTripError.length() > bias)||
443  // (m_urRoundTripError.length() > bias)||
444  // (m_lrRoundTripError.length() > bias)||
445  // (m_llRoundTripError.length() > bias))
446  // {
447  // std::cout << "________________\n";
448 
449  // std::cout << "Bias: " << bias << "\n"
450  // << "View: " << getViewRect() << "\n"
451  // << "UL: " << m_ulRoundTripError.length() << "\n"
452  // << "UR: " << m_urRoundTripError.length() << "\n"
453  // << "LR: " << m_lrRoundTripError.length() << "\n"
454  // << "LL: " << m_llRoundTripError.length() << "\n";
455 // }
456  // if(m_ulRoundTripError.length() > sensitivityScale) result |= UPPER_LEFT_SPLIT_FLAG;
457  // if(m_urRoundTripError.length() > sensitivityScale) result |= UPPER_RIGHT_SPLIT_FLAG;
458  // if(m_lrRoundTripError.length() > sensitivityScale) result |= LOWER_RIGHT_SPLIT_FLAG;
459  // if(m_llRoundTripError.length() > sensitivityScale) result |= LOWER_LEFT_SPLIT_FLAG;
460  // std::cout << result << " == " << SPLIT_ALL << "\n";
461 
462  if((result!=SPLIT_ALL)&&!canBilinearInterpolate(bias))
463  {
464  // std::cout << "TESTING BILINEAR!!!!\n";
465  result = SPLIT_ALL;
466 
467  }
468  else
469  {
470  // std::cout << "CAN BILINEAR!!!!\n";
471  }
472  }
473 
474  return result;
475 #else
476  ossim_uint16 result = SPLIT_NONE;
477  ossimDrect vRect = getViewRect();
478 
479  if(imageHasNans()||tooBig())
480  {
481  if(m_viewBounds->intersects(getViewRect()))
482  {
483  result = SPLIT_ALL;
484  }
485  else
486  {
487  return result;
488  }
489  }
490  /*
491  if(result != SPLIT_ALL)
492  {
493  if(m_ulRoundTripError.hasNans()&&m_urRoundTripError.hasNans()&&
494  m_lrRoundTripError.hasNans()&&m_llRoundTripError.hasNans())
495  {
496  if(m_viewBounds->intersects(getViewRect()))
497  {
498  result = SPLIT_ALL;
499  }
500  return result;
501  }
502  else if(tooBig())
503  {
504  result = SPLIT_ALL;
505  }
506  }
507 
508  if(result != SPLIT_ALL)
509  {
510  if(m_ulRoundTripError.hasNans()) result |= UPPER_LEFT_SPLIT_FLAG;
511  if(m_urRoundTripError.hasNans()) result |= UPPER_RIGHT_SPLIT_FLAG;
512  if(m_lrRoundTripError.hasNans()) result |= LOWER_RIGHT_SPLIT_FLAG;
513  if(m_llRoundTripError.hasNans()) result |= LOWER_LEFT_SPLIT_FLAG;
514  }
515 */
516  if(result != SPLIT_ALL)
517  {
518  ossim_float64 sensitivityScale = m_ImageToViewScale.length();
519  //std::cout << sensitivityScale << std::endl;
520  if(sensitivityScale < 1.0) sensitivityScale = 1.0/sensitivityScale;
521 
522 
523  // if((m_ulRoundTripError.length() > sensitivityScale)||
524  // (m_urRoundTripError.length() > sensitivityScale)||
525  // (m_lrRoundTripError.length() > sensitivityScale)||
526  // (m_llRoundTripError.length() > sensitivityScale))
527  // {
528  // std::cout << "________________\n";
529 
530  // std::cout << "Sens: " << sensitivityScale << "\n"
531  // << "View: " << getViewRect() << "\n"
532  // << "UL: " << m_ulRoundTripError.length() << "\n"
533  // << "UR: " << m_urRoundTripError.length() << "\n"
534  // << "LR: " << m_lrRoundTripError.length() << "\n"
535  // << "LL: " << m_llRoundTripError.length() << "\n";
536  // }
537  // if(m_ulRoundTripError.length() > sensitivityScale) result |= UPPER_LEFT_SPLIT_FLAG;
538  // if(m_urRoundTripError.length() > sensitivityScale) result |= UPPER_RIGHT_SPLIT_FLAG;
539  // if(m_lrRoundTripError.length() > sensitivityScale) result |= LOWER_RIGHT_SPLIT_FLAG;
540  // if(m_llRoundTripError.length() > sensitivityScale) result |= LOWER_LEFT_SPLIT_FLAG;
541  // std::cout << result << " == " << SPLIT_ALL << "\n";
542 
543  if((result!=SPLIT_ALL)&&!canBilinearInterpolate(sensitivityScale))
544  {
545  // std::cout << "TESTING BILINEAR!!!!\n";
546  result = SPLIT_ALL;
547 
548  }
549  else
550  {
551  // std::cout << "CAN BILINEAR!!!!\n";
552  }
553  }
554 
555  return result;
556 #endif
557 }
558 
560 {
561 // std::cout << "TRANSFORM VIEW TO IMAGE!!!!!!!!!!!!!!\n";
562 
563  ossimDrect vrect = getViewRect();
564  ossim_float64 w = vrect.width() - 1; // subtract 1 to prevent core dump in full-earth view rect
565  ossim_float64 h = vrect.height();
566 
567  m_transform->viewToImage(m_Vul, m_Iul);
568  m_transform->viewToImage(m_Vur, m_Iur);
569  m_transform->viewToImage(m_Vlr, m_Ilr);
570  m_transform->viewToImage(m_Vll, m_Ill);
571 
572 // m_ulRoundTripError = m_transform->getRoundTripErrorView(m_Vul);
573 // m_urRoundTripError = m_transform->getRoundTripErrorView(m_Vur);
574 // m_lrRoundTripError = m_transform->getRoundTripErrorView(m_Vlr);
575 // m_llRoundTripError = m_transform->getRoundTripErrorView(m_Vll);
576 
577 #if 1
578  m_VulScale = computeViewToImageScale(m_Vul, ossimDpt( w, h));
579  m_VurScale = computeViewToImageScale(m_Vur, ossimDpt(-w, h));
580  m_VlrScale = computeViewToImageScale(m_Vlr, ossimDpt(-w,-h));
581  m_VllScale = computeViewToImageScale(m_Vll, ossimDpt( w,-h));
582 
583  ossim_int32 n = 0;
584  m_ViewToImageScale.x = 0.0;
585  m_ViewToImageScale.y = 0.0;
586 
587  if(!m_VulScale.hasNans())
588  {
589  m_ViewToImageScale += m_VulScale;
590  ++n;
591  }
592  if(!m_VurScale.hasNans())
593  {
594  m_ViewToImageScale += m_VurScale;
595  ++n;
596  }
597  if(!m_VlrScale.hasNans())
598  {
599  m_ViewToImageScale += m_VlrScale;
600  ++n;
601  }
602  if(!m_VllScale.hasNans())
603  {
604  m_ViewToImageScale += m_VllScale;
605  ++n;
606  }
607  if(!n)
608  {
609  m_ViewToImageScale.makeNan();
610  }
611  else
612  {
613  m_ViewToImageScale.x/=n;
614  m_ViewToImageScale.y/=n;
615  }
616 
617 #else
618  {
619  m_ViewToImageScale = ossimDpt(1.0, 1.0);
620 
621  ossimDpt topDelta = m_Iur - m_Iul;
622  ossimDpt rightDelta = m_Ilr - m_Iur;
623  ossimDpt bottomDelta = m_Ill - m_Ilr;
624  ossimDpt leftDelta = m_Iul - m_Ill;
625 
626  double topLen = topDelta.length();
627  double bottomLen = bottomDelta.length();
628  double rightLen = rightDelta.length();
629  double leftLen = leftDelta.length();
630 
631  double averageHoriz = ((topLen) + (bottomLen))*.5;
632  double averageVert = ((leftLen) + (rightLen))*.5;
633 
634  ossimDpt deltaViewP1P2 = m_Vul - m_Vur;
635  ossimDpt deltaViewP1P3 = m_Vul - m_Vll;
636 
637  double lengthViewP1P2 = deltaViewP1P2.length();//+1;
638  double lengthViewP1P3 = deltaViewP1P3.length();//+1;
639 
640  if(lengthViewP1P2 > FLT_EPSILON)
641  m_ViewToImageScale.x = averageHoriz/lengthViewP1P2;
642  else
643  m_ViewToImageScale.makeNan();
644  if(lengthViewP1P3 > FLT_EPSILON)
645  m_ViewToImageScale.y = averageVert/lengthViewP1P3;
646  else
647  m_ViewToImageScale.makeNan();
648  }
649 #endif
650 
651  //std::cout << m_ViewToImageScale << std::endl;
652  if(!m_ViewToImageScale.hasNans())
653  {
654  m_ImageToViewScale.x = 1.0/m_ViewToImageScale.x;
655  m_ImageToViewScale.y = 1.0/m_ViewToImageScale.y;
656  }
657  else
658  {
659  m_ImageToViewScale.makeNan();
660  }
661 }
662 
664  const ossimDpt& delta)const
665 {
666  ossimDpt result;
667  result.makeNan();
668  if(viewPt.hasNans()) return result;
669  ossimDpt ipt;
670  m_transform->viewToImage(viewPt, ipt);
671 
672  if(!ipt.isNan())
673  {
674 // ossimDpt delta;
675 // transform->viewToImage(viewPt+ossimDpt(0.5,0.5), delta);
676 
677 // delta = delta-ipt;
678 // result.x = delta.length()/std::sqrt(2);
679  // result.y = result.x;
680 
681  ossimDpt dx;
682  ossimDpt dy;
683 
684  m_transform->viewToImage(viewPt + ossimDpt(delta.x,0.0), dx);
685  m_transform->viewToImage(viewPt + ossimDpt(0.0,delta.y), dy);
686  dx = dx-ipt;
687  dy = dy-ipt;
688 
689  result.x = dx.length()/fabs(delta.x);
690  result.y = dy.length()/fabs(delta.y);
691  }
692 
693  return result;
694 }
695 
697 {
698  ossimDpt topDelta = m_Iur - m_Iul;
699  ossimDpt rightDelta = m_Ilr - m_Iur;
700  ossimDpt bottomDelta = m_Ill - m_Ilr;
701  ossimDpt leftDelta = m_Iul - m_Ill;
702 
703  topDelta = topDelta*(1.0/topDelta.length());
704  rightDelta = rightDelta*(1.0/rightDelta.length());
705  bottomDelta = bottomDelta*(1.0/bottomDelta.length());
706  leftDelta = leftDelta*(1.0/leftDelta.length());
707 
708  m_Iul = m_Iul + ((leftDelta - topDelta)*.5);
709  m_Iur = m_Iur + ((topDelta - rightDelta)*.5);
710  m_Ilr = m_Ilr + ((rightDelta - bottomDelta)*.5);
711  m_Ill = m_Ill + ((bottomDelta - leftDelta)*.5);
712 
713  if(enableRound)
714  {
715  m_Iul = ossimIpt(ossim::round<int>(m_Iul.x),
716  ossim::round<int>(m_Iul.y));
717  m_Iur = ossimIpt(ossim::round<int>(m_Iur.x),
718  ossim::round<int>(m_Iur.y));
719  m_Ilr = ossimIpt(ossim::round<int>(m_Ilr.x),
720  ossim::round<int>(m_Ilr.y));
721  m_Ill = ossimIpt(ossim::round<int>(m_Ill.x),
722  ossim::round<int>(m_Ill.y));
723  }
724 }
725 
727 {
728 // ossimDpt deltaP1P2 = m_Iul - m_Iur;
729 // ossimDpt deltaP1P3 = m_Iul - m_Ill;
730 
731 // ossimDpt deltaViewP1P2 = m_Vul - m_Vur;
732 // ossimDpt deltaViewP1P3 = m_Vul - m_Vll;
733 
734 // bool horizontalSigns = ossimGetSign(deltaP1P2.x)==ossimGetSign(deltaViewP1P2.x);
735 // bool verticalSigns = ossimGetSign(deltaP1P3.y)==ossimGetSign(deltaViewP1P3.y);
736 
737 // // check first to see if any horizontal or vertical flipping
738 // //
739 // if(horizontalSigns && verticalSigns)
740 // {
741 // // check scales to see if they are 1
742 // if(fabs(1-m_ViewToImageScale.x) <= FLT_EPSILON &&
743 // fabs(1-m_ViewToImageScale.y) <= FLT_EPSILON)
744 // {
745 // return true;
746 // }
747 // }
748 
749  double iulDelta = (m_Iul-m_Vul).length();
750  double iurDelta = (m_Iur-m_Vur).length();
751  double ilrDelta = (m_Ilr-m_Vlr).length();
752  double illDelta = (m_Ill-m_Vll).length();
753 
754  return ((iulDelta <= FLT_EPSILON)&&
755  (iurDelta <= FLT_EPSILON)&&
756  (ilrDelta <= FLT_EPSILON)&&
757  (illDelta <= FLT_EPSILON));
758 }
759 
760 
762 {
763  bool result = false;
764 
765  // now check point placement
766  ossimDpt imageToViewScale = getAbsValueImageToViewScales();
767 
768  double testScale = imageToViewScale.length();
769 
770  // ossimDpt errorUl = transform->getRoundTripErrorView(m_Vul);
771  // ossimDpt errorUr = transform->getRoundTripErrorView(m_Vur);
772  // ossimDpt errorLr = transform->getRoundTripErrorView(m_Vlr);
773  // ossimDpt errorLl = transform->getRoundTripErrorView(m_Vll);
774 
775  // if((errorUl.length() > 2 )||
776  // (errorUr.length() > 2 )||
777  // (errorLr.length() > 2 )||
778  // (errorLl.length() > 2))
779  // {
780  // return result;
781  // }
782  // std::cout << "_______________________\n"
783  // << "errorUl: " << errorUl << "\n"
784  // << "errorUr: " << errorUr << "\n"
785  // << "errorLr: " << errorLr << "\n"
786  // << "errorLl: " << errorLl << "\n";
787 
788  // if there is a large shrink or expansion then just return true.
789  // You are probably not worried about error in bilinear interpolation
790  //
791  if ((testScale > 256) ||
792  (testScale < 1.0 / 256.0))
793  {
794  return true;
795  }
796 
797  if (m_VulScale.hasNans() ||
798  m_VurScale.hasNans() ||
799  m_VlrScale.hasNans() ||
800  m_VllScale.hasNans())
801  {
802  return result;
803  }
804 
805  // std::cout << "ulScale: " << m_VulScale << "\n"
806  // << "urScale: " << m_VurScale << "\n"
807  // << "lrScale: " << m_VlrScale << "\n"
808  // << "llScale: " << m_VllScale << "\n";
809 
810  // check overage power of 2 variance
811  // If there is a variance of 1 resolution level
812  // then we must split further
813  //
814  ossim_float64 averageUlScale = m_VulScale.length();
815  ossim_float64 averageUrScale = m_VurScale.length();
816  ossim_float64 averageLrScale = m_VlrScale.length();
817  ossim_float64 averageLlScale = m_VllScale.length();
818 
819  // std::cout << "_________________________\n";
820  // std::cout << log(averageUlScale)/(log(2)) << "\n";
821  // std::cout << log(averageUrScale)/(log(2)) << "\n";
822  // std::cout << log(averageLrScale)/(log(2)) << "\n";
823  // std::cout << log(averageLlScale)/(log(2)) << "\n";
824 
825  ossim_float64 ratio1 = averageUlScale / averageUrScale;
826  ossim_float64 ratio2 = averageUlScale / averageLrScale;
827  ossim_float64 ratio3 = averageUlScale / averageLlScale;
828 
829  // std::cout << "_________________________\n";
830  // std::cout << "ratio1: " << ratio1 << "\n";
831  // std::cout << "ratio2: " << ratio2 << "\n";
832  // std::cout << "ratio3: " << ratio3 << "\n";
833 
834  // make sure all are within a power of 2 shrink or expand
835  // which means the range of each ratio should be
836  // between .5 and 2
837  result = (((ratio1 < 2) && (ratio1 > 0.5)) &&
838  ((ratio2 < 2) && (ratio2 > 0.5)) &&
839  ((ratio3 < 2) && (ratio3 > 0.5)));
840 
841  //result = ((diff1<=2)&&(diff2<=2)&&(diff3<=2));
842  //std::cout << "DIFF1: " << diff1 << std::endl;
843  //std::cout << "DIFF2: " << diff2 << std::endl;
844  //std::cout << "DIFF3: " << diff3 << std::endl;
845 
846  if (result)
847  {
848 #if 1
849  ossimDpt vUpper, vRight, vBottom, vLeft, vCenter;
850  ossimDpt iUpper, iRight, iBottom, iLeft, iCenter;
851  ossimDpt testUpper, testRight, testBottom, testLeft, testCenter;
852 
853  getViewMids(vUpper, vRight, vBottom, vLeft, vCenter);
854  getImageMids(iUpper, iRight, iBottom, iLeft, iCenter);
855 
856  // get the model centers for the mid upper left right bottom
857  m_transform->viewToImage(vCenter, testCenter);
858 
859  if (testCenter.hasNans())
860  {
861  return false;
862  }
863 
864  m_transform->viewToImage(vUpper, testUpper);
865  if (testCenter.hasNans())
866  {
867  return false;
868  }
869  m_transform->viewToImage(vRight, testRight);
870  if (testRight.hasNans())
871  {
872  return false;
873  }
874  m_transform->viewToImage(vBottom, testBottom);
875  if (testBottom.hasNans())
876  {
877  return false;
878  }
879  m_transform->viewToImage(vLeft, testLeft);
880  if (testLeft.hasNans())
881  {
882  return false;
883  }
884 
885  // now get the model error to bilinear estimate of those points
886  double errorCheck1 = (testCenter - iCenter).length();
887  double errorCheck2 = (testUpper - iUpper).length();
888  double errorCheck3 = (testRight - iRight).length();
889  double errorCheck4 = (testBottom - iBottom).length();
890  double errorCheck5 = (testLeft - iLeft).length();
891  result = ((errorCheck1 < error) &&
892  (errorCheck2 < error) &&
893  (errorCheck3 < error) &&
894  (errorCheck4 < error) &&
895  (errorCheck5 < error));
896  // std::cout <<"__________________________\n"
897  // << "ERROR1:" <<errorCheck1 << "\n"
898  // << "ERROR2:" <<errorCheck2 << "\n"
899  // << "ERROR3:" <<errorCheck3 << "\n"
900  // << "ERROR4:" <<errorCheck4 << "\n"
901  // << "ERROR5:" <<errorCheck5 << "\n"
902  // << "SENS: " << error << "\n";
903 
904 #else
905  ossimDpt vUpper, vRight, vBottom, vLeft, vCenter;
906  ossimDpt iUpper, iRight, iBottom, iLeft, iCenter;
907 
908  ossimDpt testCenter;
909  getViewMids(vUpper, vRight, vBottom, vLeft, vCenter);
910  getImageMids(iUpper, iRight, iBottom, iLeft, iCenter);
911 
912  ossimDpt iFullRes(iCenter.x * imageToViewScale.x,
913  iCenter.y * imageToViewScale.y);
914 
915  m_transform->viewToImage(vCenter, testCenter);
916 
917  if (testCenter.hasNans())
918  {
919  return false;
920  }
921  ossimDpt testFullRes(testCenter.x * imageToViewScale.x,
922  testCenter.y * imageToViewScale.y);
923 
924  double errorCheck1 = (testFullRes - iFullRes).length();
925 
926  iFullRes = ossimDpt(iUpper.x * imageToViewScale.x,
927  iUpper.y * imageToViewScale.y);
928 
929  m_transform->viewToImage(vUpper, testCenter);
930  if (testCenter.hasNans())
931  {
932  return false;
933  }
934  testFullRes = ossimDpt(testCenter.x * imageToViewScale.x,
935  testCenter.y * imageToViewScale.y);
936  double errorCheck2 = (testFullRes - iFullRes).length();
937 
938  iFullRes = ossimDpt(iRight.x * imageToViewScale.x,
939  iRight.y * imageToViewScale.y);
940 
941  m_transform->viewToImage(vRight, testCenter);
942  if (testCenter.hasNans())
943  {
944  return false;
945  }
946  testFullRes = ossimDpt(testCenter.x * imageToViewScale.x,
947  testCenter.y * imageToViewScale.y);
948  double errorCheck3 = (testFullRes - iFullRes).length();
949 
950  iFullRes = ossimDpt(iBottom.x * imageToViewScale.x,
951  iBottom.y * imageToViewScale.y);
952 
953  m_transform->viewToImage(vBottom, testCenter);
954  if (testCenter.hasNans())
955  {
956  return false;
957  }
958  testFullRes = ossimDpt(testCenter.x * imageToViewScale.x,
959  testCenter.y * imageToViewScale.y);
960  double errorCheck4 = (testFullRes - iFullRes).length();
961 
962  iFullRes = ossimDpt(iLeft.x * imageToViewScale.x,
963  iLeft.y * imageToViewScale.y);
964 
965  m_transform->viewToImage(vLeft, testCenter);
966  testFullRes = ossimDpt(testCenter.x * imageToViewScale.x,
967  testCenter.y * imageToViewScale.y);
968  double errorCheck5 = (testFullRes - iFullRes).length();
969 
970  std::cout << "__________________________\n"
971  << "ERROR1:" << errorCheck1 << "\n"
972  << "ERROR2:" << errorCheck2 << "\n"
973  << "ERROR3:" << errorCheck3 << "\n"
974  << "ERROR4:" << errorCheck4 << "\n"
975  << "ERROR5:" << errorCheck5 << "\n"
976  << "SENS: " << error << "\n";
977 
978  result = ((errorCheck1 < error) &&
979  (errorCheck2 < error) &&
980  (errorCheck3 < error) &&
981  (errorCheck4 < error) &&
982  (errorCheck5 < error));
983  // std::cout << "CAN INTERPOLATE? " << result <<"\n";
984 #endif
985  }
986  return result;
987 }
988 
990  ossimDpt& rightMid,
991  ossimDpt& bottomMid,
992  ossimDpt& leftMid,
993  ossimDpt& center)const
994 {
995 
996  upperMid = (m_Vul + m_Vur)*.5;
997  rightMid = (m_Vur + m_Vlr)*.5;
998  bottomMid = (m_Vlr + m_Vll)*.5;
999  leftMid = (m_Vul + m_Vll)*.5;
1000  center = (m_Vul + m_Vur + m_Vlr + m_Vll)*.25;
1001 }
1002 
1004  ossimDpt& rightMid,
1005  ossimDpt& bottomMid,
1006  ossimDpt& leftMid,
1007  ossimDpt& center)const
1008 {
1009  if(imageHasNans())
1010  {
1011  upperMid.makeNan();
1012  rightMid.makeNan();
1013  bottomMid.makeNan();
1014  leftMid.makeNan();
1015  center.makeNan();
1016  }
1017  else
1018  {
1019  upperMid = (m_Iul + m_Iur)*.5;
1020  rightMid = (m_Iur + m_Ilr)*.5;
1021  bottomMid = (m_Ilr + m_Ill)*.5;
1022  leftMid = (m_Iul + m_Ill)*.5;
1023  center = (m_Iul + m_Iur + m_Ilr + m_Ill)*.25;
1024  }
1025 }
1026 
1028  const ossimDpt& lr, const ossimDpt& ll)const
1029 {
1030  ossimDpt top = ur - ul;
1031  ossimDpt bottom = lr - ll;
1032 
1033  ossimDpt centerTop = ul + top * .5;
1034  ossimDpt centerBottom = ll + bottom * .5;
1035 
1036  return centerBottom + (centerBottom - centerTop)*.5;
1037 }
1038 
1040 :
1043 m_Resampler(0),
1044 m_BlankTile(0),
1045 m_Tile(0),
1049 m_inputR0Rect(),
1050 m_viewRect(),
1054 m_MaxLevelsToCompute(999999) // something large so it will always compute
1055 {
1059 }
1060 
1062  ossimImageViewTransform* imageViewTrans)
1063  : ossimImageSourceFilter(inputSource),
1064  ossimViewInterface(0),
1065  m_Resampler(0),
1066  m_BlankTile(0),
1067  m_Tile(0),
1068  m_TemporaryBuffer(0),
1069  m_StartingResLevel(0),
1070  m_ImageViewTransform(imageViewTrans),
1071  m_inputR0Rect(),
1072  m_viewRect(),
1073  m_rectsDirty(true),
1074  m_MaxRecursionLevel(5),
1075  m_AutoUpdateInputTransform(true),
1076  m_MaxLevelsToCompute(999999) // something large so it will always compute
1077 {
1081  {
1083  }
1084 }
1085 
1087 {
1089 
1090  if(m_Resampler)
1091  {
1092  delete m_Resampler;
1093  m_Resampler = 0;
1094  }
1095 }
1096 
1098  const ossimIrect& tileRect,
1099  ossim_uint32 resLevel)
1100 {
1101  // std::cout << "_________________________\n";
1102  static const char MODULE[] = "ossimImageRenderer::getTile";
1103  if(traceDebug())
1104  {
1106  << MODULE << " Requesting view rect = "
1107  << tileRect << endl;
1108  }
1109  // long w = tileRect.width();
1110  // long h = tileRect.height();
1111  // ossimIpt origin = tileRect.ul();
1112 
1113  if( !m_BlankTile.valid() || !m_Tile.valid() )
1114  {
1115  allocate();
1116  if ( !m_BlankTile.valid() || !m_Tile.valid() )
1117  {
1118  if(traceDebug())
1119  {
1121  << "ossimImageRenderer::getTile tile allocation failure!\n"
1122  << endl;
1123  }
1124  return ossimImageSourceFilter::getTile(tileRect, resLevel);
1125  }
1126  }
1127 
1128  m_BlankTile->setImageRectangle(tileRect);
1129 
1130  if(!theInputConnection)
1131  {
1132  return m_BlankTile;
1133  }
1134 
1137  {
1138  // This tile source bypassed, return the input tile source.
1139  return theInputConnection->getTile(tileRect, resLevel);
1140  }
1141 
1142  if( m_rectsDirty )
1143  {
1145 
1146  // We can't go on without these...
1147  if ( m_rectsDirty )
1148  {
1149  return m_BlankTile;
1150  }
1151  }
1152 
1153  if(m_viewRect.width() < 4 && m_viewRect.height() < 4)
1154  {
1155  return m_BlankTile;
1156  }
1157 
1158  if( !theInputConnection ||
1159  !m_viewRect.intersects(tileRect) ||
1160  !m_viewArea.intersects(tileRect) )
1161  {
1162  if(traceDebug())
1163  {
1165  << MODULE << "No intersection, Returning...." << endl;
1166  }
1167  return m_BlankTile;
1168  }
1169 
1170  // drb - handled above...
1171  // if(!m_Tile)
1172  // {
1173  // return theInputConnection->getTile(tileRect, resLevel);
1174  // }
1175 
1176  // Check for identity transform:
1178  {
1179  return theInputConnection->getTile(tileRect, resLevel);
1180  }
1181 
1182  // long tw = m_Tile->getWidth();
1183  // long th = m_Tile->getHeight();
1184 
1185  m_Tile->setImageRectangle(tileRect);
1186  m_Tile->makeBlank();
1187 
1188 
1189  //if(!(m_viewArea.intersects(ossimPolyArea2d(tileRect))))
1190  //{
1191  // return m_BlankTile;
1192  //}
1193 
1194 #if 0
1195  // expand a small patch just to alleviate errors in the size of the rect when resampling
1196  // ossimIrect viewRectClip = tileRect.clipToRect(ossimIrect(m_viewRect.ul() + ossimIpt(-8,-8),
1197  // m_viewRect.lr() + ossimIpt(8,8)));
1198  ossimIrect viewRectClip = tileRect.clipToRect(m_viewRect);
1199  std::cout << "_____________________" << std::endl;
1200  std::cout << "viewRectClip = " << viewRectClip << std::endl;
1201 // std::cout << "tileRect = " << tileRect << std::endl;
1202 // std::cout << "m_viewRect = " << m_viewRect << std::endl;
1203  ossimRendererSubRectInfo subRectInfo(viewRectClip.ul(),
1204  viewRectClip.ur(),
1205  viewRectClip.lr(),
1206  viewRectClip.ll());
1207 #else
1209  tileRect.ul(),
1210  tileRect.ur(),
1211  tileRect.lr(),
1212  tileRect.ll());
1213 
1214 
1215 #endif
1216  subRectInfo.m_viewBounds = &m_viewArea;
1217  subRectInfo.transformViewToImage();
1218 
1219  if((!m_viewArea.intersects(subRectInfo.getViewRect())))
1220 // if((!m_viewRect.intersects(subRectInfo.getViewRect())))
1221  {
1222  return m_BlankTile;
1223  }
1224  if(traceDebug())
1225  {
1227  << MODULE << " image rect = " << subRectInfo.getImageRect() << std::endl;
1228  }
1229 
1230  // If the image rect is completely outside of the valid image, there is no need to resample:
1231  // (OLK 11/18)
1232 // if ((!subRectInfo.imageHasNans())&&!m_inputR0Rect.intersects(subRectInfo.getImageRect()))
1233 // {
1234 // return m_Tile;
1235 // }
1236  recursiveResample(m_Tile, subRectInfo, 1);
1237 
1238  if(m_Tile.valid())
1239  {
1240  m_Tile->validate();
1241  }
1242  if(traceDebug())
1243  {
1245  << MODULE << "Returning...." << endl;
1246  }
1247  return m_Tile;
1248 }
1249 
1251  const ossimRendererSubRectInfo& rectInfo,
1252  ossim_uint32 /* level */)
1253 {
1254  // Removed recursion and just use the std::stack.
1255  //
1256  std::stack<ossimRendererSubRectInfo> rectStack;
1257  rectStack.push(rectInfo);
1258 
1259  while(!rectStack.empty())
1260  {
1261  ossimRendererSubRectInfo currentRectInfo = rectStack.top();
1262  ossimIrect tempViewRect = currentRectInfo.getViewRect();
1263  rectStack.pop();
1264  if(m_viewArea.intersects(tempViewRect))
1265  {
1266  if(tempViewRect.width() <2 ||
1267  tempViewRect.height() <2)
1268  {
1269  if(!currentRectInfo.imageHasNans())
1270  {
1271  fillTile(outputData,
1272  currentRectInfo);
1273  }
1274  }
1275  else
1276  {
1277  ossim_uint32 idx = 0;
1278  std::vector<ossimRendererSubRectInfo> splitRects;
1279  currentRectInfo.splitView(splitRects);
1280  if(!splitRects.empty())
1281  {
1282  for(idx = 0; idx < splitRects.size();++idx)
1283  {
1284  if(m_viewArea.intersects(splitRects[idx].getViewRect()))
1285  {
1286  rectStack.push(splitRects[idx]);
1287  }
1288  // recursiveResample(outputData,
1289  // splitRects[idx],
1290  // level + 1);
1291  }
1292  }
1293  else
1294  {
1295  if(!currentRectInfo.imageHasNans())
1296  {
1297  fillTile(outputData,
1298  currentRectInfo);
1299  }
1300  }
1301  }
1302 
1303  }
1304  }
1305  #if 0
1306  ossimIrect tempViewRect = rectInfo.getViewRect();
1307  if(rectInfo.imageIsNan())
1308  {
1309  return;
1310  }
1311 
1312  if(tempViewRect.width() <2 ||
1313  tempViewRect.height() <2)
1314  {
1315  if(!rectInfo.imageHasNans())
1316  {
1317  fillTile(outputData,
1318  rectInfo);
1319  }
1320  return;
1321  }
1322  //
1323  std::vector<ossimRendererSubRectInfo> splitRects;
1324  rectInfo.splitView(splitRects);
1325 
1326 //std::cout << "SHOULD BE SPLITTING: " << splitRects.size() <<"\n";
1327  ossim_uint32 idx = 0;
1328  if(!splitRects.empty())
1329  {
1330  // std::cout << "SPLITTING " << level << ", " << tempViewRect << "\n";
1331  for(idx = 0; idx < splitRects.size();++idx)
1332  {
1333  recursiveResample(outputData,
1334  splitRects[idx],
1335  level + 1);
1336  }
1337  }
1338  else if(!rectInfo.imageHasNans())
1339  {
1340  fillTile(outputData,
1341  rectInfo);
1342  }
1343  #endif
1344 }
1345 
1346 #define RSET_SEARCH_THRESHHOLD 0.1
1347 
1349  const ossimRendererSubRectInfo& rectInfo)
1350 {
1351  if(!outputData.valid() || !outputData->getBuf() || rectInfo.imageHasNans())
1352  {
1353  return;
1354  }
1355  ossimDrect vrect = rectInfo.getViewRect();
1356 
1357  ossimDpt imageToViewScale = rectInfo.getAbsValueImageToViewScales();
1358 
1359  if(imageToViewScale.hasNans()) return;
1360 
1361  ossimDpt tile_size = ossimDpt(vrect.width(), vrect.height());
1362  double kernelSupportX, kernelSupportY;
1363 
1364  double resLevelX = log( 1.0 / imageToViewScale.x )/ log( 2.0 );
1365  double resLevelY = log( 1.0 / imageToViewScale.y )/ log( 2.0 );
1366  double resLevel0 = resLevelX < resLevelY ? resLevelX : resLevelY;
1367  long closestFitResLevel = (long)floor( resLevel0 );
1368 
1369  //double averageScale = (imageToViewScale.x + imageToViewScale.y) / 2.0;
1370  //long closestFitResLevel = (long)floor( log( 1.0 / averageScale )/ log( 2.0 ) );
1371 
1372  ossim_uint32 resLevel = closestFitResLevel<0 ? 0:closestFitResLevel;
1373  resLevel += m_StartingResLevel;
1374 
1375  //---
1376  // ESH 02/2009: If requested resLevel is too high, let's lower it to one
1377  // that is ok.
1378  //---
1379 #if 0
1381  if ( (NUM_LEVELS > 0) && (resLevel >= NUM_LEVELS) )
1382  {
1383  resLevel = NUM_LEVELS - 1;
1384  }
1385 #endif
1386  //---
1387  // ESH 11/2008: Check the rset at the calculated resLevel to see
1388  // if it has the expected decimation factor. It it does, we can
1389  // use this rset and assume it is at resLevel.
1390  //---
1391  ossimDpt decimation;
1392  decimation.makeNan(); // initialize to nan.
1393  theInputConnection->getDecimationFactor(resLevel, decimation);
1394  double requestScale = 1.0 / (1<<resLevel);
1395  double closestScale = decimation.hasNans() ? requestScale : decimation.x;
1396 
1397 #if 0
1398  double differenceTest = 0.0;
1399  if (closestScale != 0.0)
1400  {
1401  differenceTest = (1.0/closestScale) - (1.0/requestScale);
1402  }
1403 
1404  //---
1405  // ESH 11/2008: Add in threshold test so search only happens when
1406  // necessary.
1407  // We do an rset search if 1 of 2 conditions is met: either
1408  // 1) the rset is really different in size from the requested size, or
1409  // 2) they're similar in size, and the actual rset is smaller than
1410  // the requested size.
1411  //---
1412  if ( (fabs(differenceTest) > RSET_SEARCH_THRESHHOLD) ||
1413  ((fabs(differenceTest) < RSET_SEARCH_THRESHHOLD) &&
1414  (differenceTest < 0.0) ) )
1415  {
1416  //---
1417  // ESH 11/2008: We test for the best rset. We assume
1418  // that decimation level always decreases as resLevel increases, so
1419  // the search can end before testing all rsets.
1420  //---
1421  ossim_uint32 savedResLevel = resLevel;
1422  closestScale = 1.0; // resLevel 0
1423  resLevel = 0;
1424  ossim_uint32 i;
1425  for( i=1; i<NUM_LEVELS; ++i )
1426  {
1427  theInputConnection->getDecimationFactor(i, decimation);
1428  if(decimation.hasNans() == false )
1429  {
1430  double testDiscrepancy = decimation.x - requestScale;
1431  if ( testDiscrepancy < 0.0 ) // we're done
1432  {
1433  break;
1434  }
1435  else
1436  {
1437  closestScale = decimation.x;
1438  resLevel = i;
1439  }
1440  }
1441  else // use the default value
1442  {
1443  closestScale = requestScale;
1444  resLevel = savedResLevel;
1445  break;
1446  }
1447  }
1448  }
1449 #endif
1450  ossimDpt nul(rectInfo.m_Iul.x*closestScale,
1451  rectInfo.m_Iul.y*closestScale);
1452  ossimDpt nll(rectInfo.m_Ill.x*closestScale,
1453  rectInfo.m_Ill.y*closestScale);
1454  ossimDpt nlr(rectInfo.m_Ilr.x*closestScale,
1455  rectInfo.m_Ilr.y*closestScale);
1456  ossimDpt nur(rectInfo.m_Iur.x*closestScale,
1457  rectInfo.m_Iur.y*closestScale);
1458 
1459  m_Resampler->getKernelSupport( kernelSupportX, kernelSupportY );
1460 
1461  ossimDrect boundingRect = ossimDrect( nul, nll, nlr, nur );
1462 
1463 
1464  boundingRect = ossimIrect((ossim_int32)floor(boundingRect.ul().x - (kernelSupportX)-.5),
1465  (ossim_int32)floor(boundingRect.ul().y - (kernelSupportY)-.5),
1466  (ossim_int32)ceil (boundingRect.lr().x + (kernelSupportX)+.5),
1467  (ossim_int32)ceil (boundingRect.lr().y + (kernelSupportY)+.5));
1468 
1469  ossimDrect requestRect = boundingRect;
1470 
1471  ossimRefPtr<ossimImageData> data = getTileAtResLevel(requestRect, resLevel);
1472 
1474  if( data.valid() )
1475  {
1476  status = data->getDataObjectStatus();
1477  }
1478  if( (status == OSSIM_NULL) || (status == OSSIM_EMPTY) )
1479  {
1480  return;
1481  }
1482 
1483  if((boundingRect.width() <2)&&(boundingRect.height()<2))
1484  {
1485 
1486 // return;
1487  }// std::cout << "SMALL RECT!!!!!!\n";
1488  else
1489  {
1490  ossimDrect inputRect = m_inputR0Rect;
1491  inputRect = inputRect*ossimDpt(closestScale, closestScale);
1492  m_Resampler->setBoundingInputRect(inputRect);
1493 
1494  double denominatorY = 1.0;
1495  if(tile_size.y > 2)
1496  {
1497  denominatorY = tile_size.y-1.0;
1498  }
1499 
1500  ossimDpt newScale( imageToViewScale.x / closestScale,
1501  imageToViewScale.y / closestScale );
1502  m_Resampler->setScaleFactor(newScale);
1503 
1504 
1505  //std::cout << "SPLIT VIEW RECT: " << vrect << std::endl;
1506  //std::cout << "VIEW RECT: " << outputData->getImageRectangle() << std::endl;
1507 
1508 
1509  m_Resampler->resample(data,
1510  outputData,
1511  vrect,
1512  nul,
1513  nur,
1514  ossimDpt( ( (nll.x - nul.x)/denominatorY ),
1515  ( (nll.y - nul.y)/denominatorY ) ),
1516  ossimDpt( ( (nlr.x - nur.x)/denominatorY ),
1517  ( (nlr.y - nur.y)/denominatorY ) ),
1518  tile_size);
1519  }
1520 
1521 }
1522 
1523 long ossimImageRenderer::computeClosestResLevel(const std::vector<ossimDpt>& decimationFactors,
1524  double scale)const
1525 {
1526  long result = 0;
1527  long upper = (long)decimationFactors.size();
1528  bool done = false;
1529 
1530  if(upper > 1)
1531  {
1532  while((result < upper)&&!done)
1533  {
1534  if(scale < decimationFactors[result].x)
1535  {
1536  ++result;
1537  }
1538  else
1539  {
1540  done = true;
1541  }
1542  }
1543 
1544  // now use the higher res level and resample down
1545  //
1546  if(result)
1547  {
1548  --result;
1549  }
1550  }
1551  return result;
1552 }
1553 
1555 {
1556  //---
1557  // 01 November 2011:
1558  // Backed out expand code as the ossimImageViewProjectionTransform::getImageToViewBounds
1559  // does not handle image on the edge of international date line. D. Burken
1560  //---
1561 
1562  // The input bounding rect as returned here corresponds to "pixel-is-point", i.e., the center
1563  // of the pixel area for the corners and not the edges which extend 1/2 pixel in all
1564  // directions. Because the view is probably a different GSD, first expand the input
1565  // bounding rect to the edge before transforming to a view rect. Then shrink the view rect by
1566  // 1/2 pixel to get it to the pixel center (OSSIM convention for bounding rect -- this may
1567  // need to be revisited in light of the need to match edges, not pixel centers, OLK 09/11).
1568 
1569  // Code functionality moved to below method. (drb - 08 Nov. 2011)
1570 
1571  ossimIrect result;
1572  getBoundingRect( result, resLevel );
1573  return result;
1574 }
1575 
1577 {
1578  if ( isSourceEnabled() )
1579  {
1580  rect = m_viewRect;
1581  }
1582  else if ( theInputConnection )
1583  {
1584  rect = theInputConnection->getBoundingRect(resLevel);
1585  }
1586  else
1587  {
1588  rect.makeNan();
1589  }
1590 #if 0 /* Please leave for debug. */
1591  if(traceDebug())
1592  {
1594  << "ossimImageRenderer::getBoundingRect(rect, resLevel) debug:\nbounds = "
1595  << rect << "\n";
1596  }
1597 #endif
1598 }
1599 
1601 {
1602  m_rectsDirty = true;
1607  if (!m_inputR0Rect.hasNans() )
1608  {
1609  if(ivpt&&ivpt->getImageGeometry()&&ivpt->getViewGeometry())
1610  {
1611  // Little complicated but instead of always setting the edge walk
1612  // to a high number like 50 points per edge
1613  // we will look at the image to view scale change
1614  // and use that as a factor. So as the image zooms out we
1615  // need fewer points to estimate the edge.
1616  //
1617  // ossim_uint32 idx;
1618  std::vector<ossimDrect> boundList;
1619  ossimImageGeometry* igeom = ivpt->getImageGeometry(); // look at projected meters
1620  ossimImageGeometry* vgeom = ivpt->getViewGeometry(); // look at projected meters
1621  ossimDrect testRect;
1622  igeom->getBoundingRect(testRect);
1623  ossimDpt mpp = igeom->getMetersPerPixel();
1624  ossimDpt vmpp = vgeom->getMetersPerPixel();
1625  ossim_float64 scale = 1.0;
1626  ossim_uint32 maxLen = ossim::max(testRect.width(), testRect.height());
1627 
1628  // (GP March 2, 2017) determine goodMatch : test if we have either enough samples to closely match the post spacing
1629  // or if we have at least half the number of pixels along the edge of an image
1630  //
1631  // This is hopefully to help avoid when using the polygon for intersection to not have
1632  // bad intersection tests when zooming. We might have to rethink it and implement
1633  // this as a windowed edge walker. So when zooming we create a polygon that
1634  // is denser for only what the view can see and not the entire image. Basically interatively
1635  // tesselate the input image model based on bounding volumes and then create a dense edge walker
1636  // for what lies in the view at the given scale. Too much to implement right now so we will cheet
1637  // and take an easy way out for now.
1638  //
1639 
1640  if(!mpp.hasNans()&&!vmpp.hasNans())
1641  {
1642  scale = mpp.y/vmpp.y;
1643  if(scale > 1.0) scale = 1.0;
1644  }
1645  ossim_float64 mppTest = mpp.y;
1646  ossim_float64 divisor = mppTest; // default to 30 meter elevation
1647  if(mppTest < 500 )
1648  {
1649  if(mppTest >= 45 )
1650  {
1651  divisor = 90; // 90 meters
1652  }
1653  }
1654  else
1655  {
1656  divisor = 1000; // 1 kilometer
1657  }
1658  if(divisor < 30) divisor = 30.0;
1659 
1660 
1661  // now test to see if our edge walk is close to matching enough
1662  // points for a good match.
1663  //
1664  ossim_uint32 maxEdgeSample = ossim::min(static_cast<ossim_uint32>(50), maxLen);
1665  if(maxEdgeSample < 1) maxEdgeSample = 1;
1666  ossim_uint32 testEdgeSample = ossim::round<ossim_uint32>((maxLen*scale*mpp.y)/divisor);
1667 
1668  bool goodMatch = (testEdgeSample<=maxEdgeSample)||(testEdgeSample>=(maxLen>>1));
1669  ossim_float64 steps = ossim::min(testEdgeSample, maxEdgeSample);
1670 
1671  ossim_uint32 finalSteps = ossim::round<ossim_uint32>(steps);
1672  if(finalSteps<1) finalSteps=1;
1673  if(igeom->getCrossesDateline())
1674  {
1675  if(finalSteps < maxEdgeSample) finalSteps = maxEdgeSample;
1676  }
1677 
1678  ivpt->getViewSegments(boundList, m_viewArea, finalSteps);
1679  if(boundList.size())
1680  {
1681  m_viewRect = boundList[0];
1682  ossim_uint32 idx = 0;
1683 
1684  if(goodMatch)
1685  {
1686  m_viewArea = boundList[idx];
1687  }
1688  else
1689  {
1691  }
1692  for(idx=1;idx<boundList.size();++idx)
1693  {
1694  ossimIrect rectBounds = ossimIrect(boundList[idx]);
1695  m_viewRect = m_viewRect.combine(rectBounds);
1696  if(goodMatch)
1697  {
1698  m_viewArea.add(ossimPolygon(boundList[idx]));
1699  }
1700  else
1701  {
1702  m_viewArea.add(rectBounds);
1703  }
1704  } //
1705  if(!m_viewRect.hasNans())
1706  {
1707  m_rectsDirty = false;
1708  }
1709  } //END if boundList.size()
1710  }
1711  else if(m_ImageViewTransform.valid())
1712  {
1714 
1715  if(!m_viewRect.hasNans())
1716  {
1717  m_rectsDirty = false;
1718  }
1719 
1721  }
1722  }
1723  if ( m_rectsDirty )
1724  {
1725  m_viewRect.makeNan();
1726  }
1727 #if 0 /* Please leave for debug. */
1729  << "ossimImageRenderer::initializeBoundingRects() debug:\n"
1730  << "\ninput rect: " << m_inputR0Rect
1731  << "\nview rect: " << m_viewRect << endl;
1732 #endif
1733 }
1734 
1736 {
1737  // Call the base class initialize.
1738  // Note: This will reset "theInputConnection" if it changed...
1740 
1741  deallocate();
1742 
1743  m_rectsDirty = true;
1744 
1745  // we will only do this if we are enabled for this could be expensive
1747  {
1748  checkIVT(); // This can initialize bounding rects and clear dirty flag.
1749  }
1750 
1751  if ( m_rectsDirty )
1752  {
1754  }
1755 }
1756 
1758 {
1759  m_Tile = 0;
1760  m_BlankTile = 0;
1761  m_TemporaryBuffer = 0;
1762 }
1763 
1765 {
1766  deallocate();
1767 
1768  if(theInputConnection)
1769  {
1772 
1773  m_Tile->initialize();
1774  }
1775 }
1776 
1778  const char* prefix)const
1779 {
1781  {
1782  ossimString newPrefix = ossimString(prefix) + ossimString("image_view_trans.");
1783 
1784  m_ImageViewTransform->saveState(kwl, newPrefix.c_str());
1785  }
1786  if(m_Resampler)
1787  {
1788  m_Resampler->saveState(kwl,
1789  (ossimString(prefix)+"resampler.").c_str());
1790  }
1791  kwl.add(prefix,
1792  "max_levels_to_compute",
1794 
1795  return ossimImageSource::saveState(kwl, prefix);
1796 }
1797 
1799  const char* prefix)
1800 {
1801  if (traceDebug())
1802  {
1804  << "ossimImageRenderer::loadState entered..." << endl;
1805 
1806 #ifdef OSSIM_ID_ENABLED
1808  << "OSSIM_ID: " << OSSIM_ID << endl;
1809 #endif
1810  }
1811 
1812  ossimString newPrefix = ossimString(prefix) + ossimString("image_view_trans.");
1813  bool result = ossimImageSourceFilter::loadState(kwl, prefix);
1814 
1815  if(m_Resampler)
1816  {
1817  m_Resampler->loadState(kwl,
1818  (ossimString(prefix)+"resampler.").c_str());
1819  }
1823  {
1825  }
1826  const char* maxLevelsToCompute = kwl.find(prefix,
1827  "max_levels_to_compute");
1828  if(maxLevelsToCompute)
1829  {
1830  m_MaxLevelsToCompute = ossimString(maxLevelsToCompute).toUInt32();
1831  }
1832 
1833  return result;
1834 }
1835 
1837 {
1838  m_ImageViewTransform = ivt;
1839 
1840  m_rectsDirty = true; // Want to recompute bounding rects.
1841 
1843  {
1844  checkIVT(); // This can initialize bounding rects and clear dirty flag.
1845  }
1846 
1847  if ( m_rectsDirty )
1848  {
1850  }
1851 }
1852 
1854 {
1855  bool new_view_set = false;
1857  {
1858  new_view_set = m_ImageViewTransform->setView(baseObject);
1859 
1860  // If view changes reset the bounding rects.
1862  }
1863  return new_view_set;
1864 }
1865 
1867 {
1869  {
1870  return m_ImageViewTransform->getView();
1871  }
1872  return 0;
1873 }
1874 
1876 {
1878  {
1879  return m_ImageViewTransform->getView();
1880  }
1881  return 0;
1882 }
1883 
1884 void ossimImageRenderer::getValidImageVertices(vector<ossimIpt>& validVertices,
1885  ossimVertexOrdering ordering,
1886  ossim_uint32 resLevel)const
1887 {
1889  {
1890  theInputConnection->getValidImageVertices(validVertices, ordering, resLevel);
1891  if(isSourceEnabled())
1892  {
1893  ossim_uint32 inputSize = (ossim_uint32)validVertices.size();
1894  if(inputSize)
1895  {
1896  ossimDpt viewPt;
1897  ossim_uint32 idx = 0;
1898  // transform each point to the view
1899  for(idx = 0; idx < inputSize; ++idx)
1900  {
1901  m_ImageViewTransform->imageToView(validVertices[idx], viewPt);
1902 
1903  // round it to the nearest pixel
1904  //
1905  validVertices[idx] = ossimIpt(viewPt);
1906  }
1907  }
1908  }
1909  }
1910 }
1911 
1912 //*************************************************************************************************
1913 // Returns the geometry associated with the image being served out of the renderer. This
1914 // corresponds to the view geometry defined in theIVT.
1915 //*************************************************************************************************
1917 {
1919  if (isSourceEnabled())
1920  {
1921  // Make sure the IVT was properly initialized
1923  checkIVT();
1924 
1927  if (ivpt)
1928  {
1929  // we need to return the right side since the geometry changed to a view geometry
1930  geom = ivpt->getViewGeometry();
1931  }
1932  }
1933  else if (theInputConnection)
1934  {
1936  }
1937  return geom;
1938 }
1939 
1941 {
1945 
1946  checkIVT();
1947  initialize();
1948 }
1949 
1951 {
1954  if(ivpt)
1955  ivpt->setImageGeometry(0);
1956 
1957  theInputConnection = 0;
1958 }
1959 
1961 {
1962  checkIVT();
1963  initialize();
1964 }
1965 
1967 {
1968  ossimString tempName = property->getName();
1969 
1970  if((tempName == "Filter type")||
1971  (tempName == "filter_type"))
1972  {
1973  if(m_Resampler)
1974  {
1975  m_Resampler->setFilterType(property->valueToString());
1976  }
1977  }
1978  // else if(tempName == "Blur factor")
1979  // {
1980  // if(m_Resampler)
1981  // {
1982  // m_Resampler->setBlurFactor(property->valueToString().toDouble());
1983  // }
1984  // }
1985  else
1986  {
1988  }
1989 }
1990 
1992 {
1993  ossimString tempName = name;
1994 
1995  if((tempName == "Filter type")||
1996  (tempName == "filter_type"))
1997  {
1998  std::vector<ossimString> filterNames;
1999  m_Resampler->getFilterTypes(filterNames);
2000 
2001  ossimStringProperty* stringProp = new ossimStringProperty("filter_type",
2003  false,
2004  filterNames);
2005  stringProp->clearChangeType();
2006  stringProp->setReadOnlyFlag(false);
2007  stringProp->setCacheRefreshBit();
2008 
2009  return stringProp;
2010  }
2011 // else if(tempName == "Blur factor")
2012 // {
2013 // ossimNumericProperty* numericProperty = new ossimNumericProperty("Blur factor",
2014 // ossimString::toString((double)m_Resampler->getBlurFactor()));
2015 
2016 // numericProperty->setConstraints(0.0, 50.0);
2017 // numericProperty->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64);
2018 // numericProperty->setCacheRefreshBit();
2019 
2020 // return numericProperty;
2021 // }
2022 
2024 }
2025 
2026 void ossimImageRenderer::getPropertyNames(std::vector<ossimString>& propertyNames)const
2027 {
2029 
2030  propertyNames.push_back("Filter type");
2031 // propertyNames.push_back("Blur factor");
2032 }
2033 
2034 //*************************************************************************************************
2035 // Insures that a proper IVT is established.
2036 //*************************************************************************************************
2038 {
2039  if(!isSourceEnabled())
2040  return;
2041 
2042  // Check validity of the IVT:
2044  return;
2045 
2046  // Detected uninitialized IVT. We are only concerned with projection IVTs (IVPTs) so
2047  // make sure that's what we're working with:
2051 
2052  if(!ivpt || !inputSrc)
2053  return; // nothing to do here yet.
2054 
2055  // Fetch the input image geometry from the IVPT to see if one needs to be established:
2057  if ( !inputGeom )
2058  {
2059  // Ask the input source for a geometry:
2060  inputGeom = inputSrc->getImageGeometry();
2061  if ( !inputGeom )
2062  {
2063  if(traceDebug())
2064  {
2065  ossimNotify(ossimNotifyLevel_WARN)<<"ossimImageRenderer::checkTransform() -- "
2066  "No input image geometry could be established for this renderer."<<endl;
2067  }
2068  return;
2069  }
2070  ivpt->setImageGeometry( inputGeom.get() );
2071  m_rectsDirty = true;
2072  }
2073 
2074  // Now check the output view geometry:
2075  ossimRefPtr<ossimImageGeometry> outputGeom = ivpt->getViewGeometry();
2076  if (!outputGeom)
2077  {
2079 
2080  //---
2081  // If the input geometry sports a map projection instead of a 3D
2082  // projector, use the same map projection for the view.
2083  //
2084  // Note: Don't use map projections with model transforms as they don't
2085  // allow for changing resolution.
2086  //---
2087  const ossimProjection* inputProj = inputGeom->getProjection();
2088  const ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, inputProj);
2089  if (mapProj && !mapProj->hasModelTransform() )
2090  {
2091  ossimProjection* my_proj = PTR_CAST(ossimProjection, mapProj->dup());
2092  myOutGeom->setProjection(my_proj);
2093  }
2094  else
2095  {
2096  // The input geometry uses a 3D projection, so let's default here to a
2097  // ossimEquDistCylProjection for the view:
2099  ossimDpt meters = inputGeom->getMetersPerPixel();
2100  double GSD = (meters.x + meters.y)/2.0;
2101  meters.x = GSD;
2102  meters.y = GSD;
2103  if(inputProj)
2104  {
2105  //---
2106  // Update the map projection. Since ossimMapProjection::setOrigin calls
2107  // ossimMapProjection::update we do that before setUlTiePoints as it in
2108  // turn calls setUlEastingNorthing(forward(gpt)) which depends on the orgin.
2109  //---
2110  myMapProj->setOrigin(inputProj->origin());
2111  myMapProj->setUlTiePoints( inputProj->origin() );
2112 
2113  }
2114  myMapProj->setMetersPerPixel(meters);
2115  myOutGeom->setProjection(myMapProj);
2116  }
2117 
2118  // Set up our IVT with the new output geometry:
2119  ivpt->setViewGeometry(myOutGeom.get());
2120 
2121  // Must reinitialize bounding rects before calling ossimImageGeometry::setImageSize().
2123 
2124  // Set the size on the ossimImageGeometry.
2125  ossimIrect rect;
2126  getBoundingRect(rect, 0);
2127  myOutGeom->setImageSize( rect.size() );
2128  }
2129 
2130  if ( m_rectsDirty )
2131  {
2133  }
2134 }
2135 
2137  ossimDpt& result)const
2138 {
2139  if(isSourceEnabled())
2140  {
2141  result = ossimDpt(1,1);
2142  }
2143  else
2144  {
2146  result);
2147  }
2148 }
2149 
2150 void ossimImageRenderer::getDecimationFactors(vector<ossimDpt>& decimations)const
2151 {
2152  if(isSourceEnabled())
2153  {
2154  decimations.push_back(ossimDpt(1,1));
2155  }
2156  else
2157  {
2159  }
2160 }
2161 
2163 {
2164  if(isSourceEnabled())
2165  {
2166  return 1;
2167  }
2168 
2170 }
2171 
2173  ossimDpt& ul,
2174  ossimDpt& ur,
2175  ossimDpt& lr,
2176  ossimDpt& ll)
2177 {
2178  ossimDpt upper = ur - ul;
2179  ossimDpt right = lr - ur;
2180  ossimDpt bottom = ll - lr;
2181  ossimDpt left = ul - ll;
2182 
2183  upper = (upper*(1.0 / upper.length()));
2184  upper.x *= amount.x;
2185  upper.y *= amount.y;
2186  right = (right*(1.0 / right.length()));
2187  right.x *= amount.x;
2188  right.y *= amount.y;
2189  bottom = (bottom*(1.0 / bottom.length()));
2190  bottom.x *= amount.x;
2191  bottom.y *= amount.y;
2192  left = (left*(1.0 / left.length()));
2193  left.x *= amount.x;
2194  left.y *= amount.y;
2195 
2196 
2197  ul = ul - upper + left;
2198  ur = ur + upper - right;
2199  lr = lr + left - bottom;
2200  ll = ll - left + bottom;
2201 }
2202 
2204  ossim_uint32 resLevel)
2205 {
2206  if(!theInputConnection)
2207  {
2208  m_BlankTile->setImageRectangle(boundingRect);
2209 
2210  return m_BlankTile;
2211  }
2212 
2214 
2215  // ossim_uint32 maxValue = (ossim_uint32)ossim::max((ossim_uint32)m_BoundingRect.width(),
2216  // (ossim_uint32)m_BoundingRect.height());
2217  if(resLevel == 0)
2218  {
2219  return theInputConnection->getTile(boundingRect);
2220  }
2221  if(resLevel < levels)
2222  {
2223  if(theInputConnection)
2224  {
2225  return theInputConnection->getTile(boundingRect,
2226  resLevel);
2227  }
2228  else
2229  {
2230  return m_BlankTile;
2231  }
2232  }
2233  else if((resLevel - levels) < m_MaxLevelsToCompute)
2234  {
2235  // check to see how many decimations we must achiev for the
2236  // request
2237  //
2238  int decimations = (resLevel - (levels-1));
2241 
2242  ossim_int32 multiplier = (1 << decimations);
2243 
2244  ossim_int32 xIndex = 0;
2245  ossim_int32 yIndex = 0;
2246 
2247  // adjust the tilesize so it at least will cover the multiplier
2248  // We will probably come up with something better later but for now
2249  // this will do.
2250  if(multiplier > tileSize.x)
2251  {
2252  tileSize.x = multiplier;
2253  }
2254  if(multiplier > tileSize.y)
2255  {
2256  tileSize.y = multiplier;
2257  }
2258 
2259  // set the rect that covers the requested RLevel to the valid RLevel.
2260  // the valid RLevel is what is available on the input side.
2261  //
2262  ossimIrect requestedRectAtValidRLevel = boundingRect;
2263  requestedRectAtValidRLevel.stretchToTileBoundary(tileSize);
2264  ossimIrect mappedRequestedRect = requestedRectAtValidRLevel;
2265  requestedRectAtValidRLevel = requestedRectAtValidRLevel*((double)multiplier);
2266 
2267  if(!m_TemporaryBuffer)
2268  {
2270  m_TemporaryBuffer->setImageRectangle(mappedRequestedRect);
2272  }
2273  else
2274  {
2275  m_TemporaryBuffer->setImageRectangle(mappedRequestedRect);
2277  }
2278 
2279  // ossim_uint32 totalCount = ((requestedRectAtValidRLevel.lr().y-requestedRectAtValidRLevel.ul().y)*
2280  // (requestedRectAtValidRLevel.lr().x-requestedRectAtValidRLevel.ul().x));
2281  ossim_uint32 currentCount = 0;
2282  ossimIrect boundingRect = theInputConnection->getBoundingRect(levels-1);
2283  for(yIndex = requestedRectAtValidRLevel.ul().y;yIndex < requestedRectAtValidRLevel.lr().y; yIndex += tileSize.y)
2284  {
2285  for(xIndex = requestedRectAtValidRLevel.ul().x; xIndex < requestedRectAtValidRLevel.lr().x; xIndex+=tileSize.x)
2286  {
2287  ossimIrect request(xIndex,
2288  yIndex,
2289  xIndex + (tileSize.x-1),
2290  yIndex + (tileSize.y-1));
2291  ossimRefPtr<ossimImageData> data = theInputConnection->getTile(request, levels-1);
2292 
2293  if(data.valid() && (data->getDataObjectStatus()!=OSSIM_EMPTY)&&
2294  data->getBuf()&&
2295  boundingRect.intersects(request))
2296  {
2297  switch(data->getScalarType())
2298  {
2299  case OSSIM_UINT8:
2300  {
2303  data,
2304  multiplier);
2305  break;
2306  }
2307  case OSSIM_SINT16:
2308  {
2311  data,
2312  multiplier);
2313  break;
2314  }
2315  case OSSIM_UINT16:
2316  case OSSIM_USHORT11:
2317  case OSSIM_USHORT12:
2318  case OSSIM_USHORT13:
2319  case OSSIM_USHORT14:
2320  case OSSIM_USHORT15:
2321  {
2324  data,
2325  multiplier);
2326  break;
2327  }
2328  case OSSIM_FLOAT32:
2330  {
2333  data,
2334  multiplier);
2335  break;
2336  }
2337  case OSSIM_FLOAT64:
2339  {
2342  data,
2343  multiplier);
2344  break;
2345  }
2346  case OSSIM_SCALAR_UNKNOWN:
2347  default:
2348  {
2349  break;
2350  }
2351  }
2352  }
2353  ++currentCount;
2354  }
2355  }
2357  return m_TemporaryBuffer;
2358  }
2359 
2360  return 0;
2361 }
2362 
2364 {
2365  m_MaxLevelsToCompute = maxLevels;
2366 }
2367 
2369 {
2370  return m_MaxLevelsToCompute;
2371 }
2372 
2373 template <class T>
2377  ossim_uint32 multiplier)
2378 {
2379  if(tile->getDataObjectStatus() == OSSIM_EMPTY ||
2380  !tile->getBuf())
2381  {
2382  return;
2383  }
2384 
2385  ossim_int32 maxX = (ossim_int32)tile->getWidth();
2386  ossim_int32 maxY = (ossim_int32)tile->getHeight();
2387  ossim_int32 resultHeight = result->getHeight();
2388  ossim_int32* offsetX = new ossim_int32[maxX];
2389  ossim_int32* offsetY = new ossim_int32[maxY];
2390  ossim_int32 i = 0;
2391  ossim_int32 resultWidth = (ossim_int32)result->getWidth();
2392  ossimIpt tileOrigin = tile->getOrigin();
2393  ossimIpt resultOrigin = result->getOrigin();
2394 
2395  // create a lookup table. that maps the tile to the result
2396  for(i = 0; i < maxX; ++i)
2397  {
2398  offsetX[i] = (i+tileOrigin.x)/(ossim_int32)multiplier - resultOrigin.x;
2399  if(offsetX[i] < 0 )
2400  {
2401  offsetX[i] = 0;
2402  }
2403  else if(offsetX[i] >= resultWidth)
2404  {
2405  offsetX[i] = resultWidth-1;
2406  }
2407  }
2408  for(i = 0; i < maxY; ++i)
2409  {
2410  offsetY[i] = ( ((i+tileOrigin.y)/(ossim_int32)multiplier) - resultOrigin.y);
2411  if(offsetY[i] < 0 )
2412  {
2413  offsetY[i] = 0;
2414  }
2415  else if(offsetY[i] >= resultHeight)
2416  {
2417  offsetY[i] = resultHeight-1;
2418  }
2419  offsetY[i] *= resultWidth;
2420  }
2421 
2422  if(tile->getDataObjectStatus() == OSSIM_FULL)
2423  {
2424  ossim_int32 numberOfBands = (ossim_int32)std::min(result->getNumberOfBands(),
2425  tile->getNumberOfBands());
2426  ossim_int32 band = 0;
2427  for(band = 0; band < numberOfBands; ++band)
2428  {
2429  T* tileBuf = static_cast<T*>(tile->getBuf(band));
2430  T* resultBuf = static_cast<T*>(result->getBuf(band));
2431  ossim_int32 dx = 0;
2432  ossim_int32 dy = 0;
2433  ossim_int32 boxAverageX = 0;
2434  ossim_int32 boxAverageY = 0;
2435  for(dy = 0; dy < maxY; dy+=multiplier)
2436  {
2437  for(dx = 0; dx < maxX; dx+=multiplier)
2438  {
2439  double sum = 0.0;
2440  for(boxAverageY = 0;
2441  ((boxAverageY < (ossim_int32)multiplier)&&
2442  ((boxAverageY+dy)<maxY)); ++boxAverageY)
2443  {
2444  for(boxAverageX = 0;
2445  ((boxAverageX < (ossim_int32)multiplier)&&
2446  ((boxAverageX+dx)<maxX)); ++boxAverageX)
2447  {
2448  sum += tileBuf[((boxAverageY+dy)*maxX + boxAverageX + dx)];
2449  }
2450  }
2451  sum /= (double)(multiplier*multiplier);
2452  resultBuf[ offsetX[dx] + offsetY[dy] ] = (T)sum;
2453  }
2454  }
2455  }
2456  }
2457  else
2458  {
2459  ossim_int32 numberOfBands = (ossim_int32)std::min(result->getNumberOfBands(),
2460  tile->getNumberOfBands());
2461  ossim_int32 band = 0;
2462  for(band = 0; band < numberOfBands; ++band)
2463  {
2464  T* tileBuf = static_cast<T*>(tile->getBuf(band));
2465  T* resultBuf = static_cast<T*>(result->getBuf(band));
2466  T tileBufNp = static_cast<T>(tile->getNullPix(band));
2467  ossim_int32 dx = 0;
2468  ossim_int32 dy = 0;
2469  ossim_int32 boxAverageX = 0;
2470  ossim_int32 boxAverageY = 0;
2471  for(dy = 0; dy < maxY; dy+=multiplier)
2472  {
2473  for(dx = 0; dx < maxX; dx+=multiplier)
2474  {
2475  double sum = 0.0;
2476  if(tileBuf[((dy+(multiplier>>1))*maxX + dx+(multiplier>>1))] != tileBufNp)
2477  {
2478  ossim_uint32 nullCount = 0;
2479  for(boxAverageY = 0;
2480  ((boxAverageY < (ossim_int32)multiplier)&&
2481  ((boxAverageY+dy)<maxY)); ++boxAverageY)
2482  {
2483  for(boxAverageX = 0;
2484  ((boxAverageX < (ossim_int32)multiplier)&&
2485  ((boxAverageX+dx)<maxX)); ++boxAverageX)
2486  {
2487  T value = tileBuf[((boxAverageY+dy)*maxX + boxAverageX + dx)];
2488  if(value != tileBufNp)
2489  {
2490  sum += value;
2491  }
2492  else
2493  {
2494  ++nullCount;
2495  }
2496  }
2497  }
2498  ossim_uint32 area = multiplier*multiplier;
2499  sum /= (double)(area);
2500  if(nullCount!= area)
2501  {
2502  resultBuf[ offsetX[dx] + offsetY[dy] ] = (T)sum;
2503  }
2504  }
2505  }
2506  }
2507  }
2508 
2509  }
2510 
2511  delete [] offsetX;
2512  delete [] offsetY;
2513 }
2514 
2516 {
2517  return ossimString("Image Renderer");
2518 }
2519 
2521 {
2522  return ossimString("Image Renderer");
2523 }
2524 
2526 {
2528  ossimImageSourceFilter::initialize(); // init connections
2529  if((event.getObject()!=this)&&
2531  {
2534  if(inputGeom)
2535  {
2538  if(ivpt)
2539  {
2540  ivpt->setImageGeometry(inputGeom.get());
2541  }
2542  }
2543  }
2544  initialize();
2545 }
2546 
2548 {
2549  if ( isSourceEnabled() == false )
2550  {
2551  setEnableFlag( true );
2552  }
2553 }
2554 
2556 {
2557  if ( isSourceEnabled() )
2558  {
2559  setEnableFlag( false );
2560  }
2561 }
2562 
2564 {
2565  if ( getEnableFlag() != flag )
2566  {
2568  checkIVT();
2569  initialize();
2570  }
2571 }
16 bit unsigned integer (15 bits used)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual void valueToString(ossimString &valueResult) const =0
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
ossimObject * theObject
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
This will return the bounding rect of the source.
void splitVertical(std::vector< ossimRendererSubRectInfo > &result) const
virtual ossimObject * dup() const =0
virtual ossimObject * getView()
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
m_Resampler will adjust the rect to whatever the view is.
ossimRefPtr< ossimImageViewTransform > m_transform
void setProjection(ossimProjection *projection)
Sets the projection to be used for local-to-world coordinate transformation.
virtual void getFilterTypes(std::vector< ossimString > &filterTypes) const
T max(T a, T b)
Definition: ossimCommon.h:236
virtual ossim_uint32 getNumberOfBands() const
ossimRefPtr< ossimImageData > m_Tile
64 bit floating point
virtual void setImageRectangle(const ossimIrect &rect)
ossim_float64 width() const
Definition: ossimDrect.h:522
16 bit unsigned integer
void stretchQuadOut(const ossimDpt &amount, ossimDpt &ul, ossimDpt &ur, ossimDpt &lr, ossimDpt &ll)
static ossimImageViewTransformFactory * instance()
ossimString getMinifyFilterTypeAsString() const
Represents serializable keyword/value map.
void splitView(std::vector< ossimRendererSubRectInfo > &result) const
void setMaxLevelsToCompute(ossim_uint32 maxLevels)
bool valid() const
Definition: ossimRefPtr.h:75
long computeClosestResLevel(const std::vector< ossimDpt > &decimationFactors, double scale) const
const char * find(const char *key) const
float ossim_float32
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns instance to the input image geometry.
void getBoundingRect(ossimIrect &bounding_rect) const
Get the bounding rect of (0, 0) to (imageSize.x-1, imageSize.y-1).
const ossimDpt & ul() const
Definition: ossimDrect.h:339
double y
Definition: ossimDpt.h:165
virtual void setOrigin(const ossimGpt &origin)
Sets theOrigin to origin.
ossim_uint32 height() const
Definition: ossimIrect.h:487
virtual ossim_uint32 getTileHeight() const
Returns the default processing tile height.
void checkIVT()
this is called on a property event and on input connection changes.
ossimPolyArea2d m_viewArea
bool intersects(const ossimPolyArea2d &rhs) const
void splitHorizontal(std::vector< ossimRendererSubRectInfo > &result) const
16 bit signed integer
void setScaleFactor(const ossimDpt &scale)
virtual void getDecimationFactor(ossim_uint32 resLevel, ossimDpt &result) const
Will return the decimation factor for the given resolution level.
const ossimIpt & ul() const
Definition: ossimIrect.h:274
ossim_uint32 m_StartingResLevel
This is going to allow us to chain multiple renderers together.
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
ossim_uint32 toUInt32() const
16 bit unsigned integer (13 bits used)
virtual ossim_uint32 getNumberOfDecimationLevels() const
Will return the number of resolution levels.
virtual void setReadOnlyFlag(bool flag)
bool isNan() const
Definition: ossimDpt.h:72
32 bit floating point
void getImageMids(ossimDpt &upperMid, ossimDpt &rightMid, ossimDpt &bottomMid, ossimDpt &leftMid, ossimDpt &center) const
bool intersects(const ossimIrect &rect) const
Definition: ossimIrect.cpp:183
unsigned short ossim_uint16
void recursiveResample(ossimRefPtr< ossimImageData > outputData, const ossimRendererSubRectInfo &rectInfo, ossim_uint32 level)
void setImageSize(const ossimIpt &size)
void setViewGeometry(ossimImageGeometry *g)
Assigns the geometry to use for output view. This object does NOT own the geometry.
const ossimIpt & ll() const
Definition: ossimIrect.h:277
void propertyEvent(ossimPropertyEvent &event)
ossimIpt size() const
Definition: ossimIrect.h:510
double length() const
Definition: ossimDpt.h:81
virtual ossimString getShortName() const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &origin, ossim_uint32 resLevel=0)
the resampler will need the tile request to come from the view.
virtual void initialize()
Initialize the data buffer.
void setImageViewTransform(ossimImageViewTransform *transform)
void setFilterType(ossimFilterResamplerType filterType)
virtual ossim_uint32 getTileWidth() const
Returns the default processing tile width.
ossim_uint32 getMaxLevelsToCompute() const
virtual void setMetersPerPixel(const ossimDpt &gsd)
virtual ossimObject * dup() const
virtual bool getEnableFlag() const
Definition: ossimSource.cpp:94
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
ossimFilterResampler * m_Resampler
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
void setBoundingInputRect(const ossimIrect &rect)
void clearChangeType()
static ossimImageDataFactory * instance()
virtual void refreshEvent(ossimRefreshEvent &event)
const ossimObject * getObject() const
This is the originating object that originally produced the event.
Definition: ossimEvent.cpp:64
virtual void getValidImageVertices(vector< ossimIpt > &validVertices, ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, ossim_uint32 resLevel=0) const
ordering specifies how the vertices should be arranged.
void disconnectInputEvent(ossimConnectionEvent &event)
ossimRefPtr< ossimImageData > m_BlankTile
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
bool hasModelTransform() const
ossimRefPtr< ossimImageData > m_TemporaryBuffer
ossimVertexOrdering
virtual ossimDrect getImageToViewBounds(const ossimDrect &imageRect) const
Computes the bounding rect in view space of the quad formed by the transformed image points of the in...
virtual ossimDataObjectStatus validate() const
virtual ossim_uint32 getNumberOfDecimationLevels() const
Will return the number of resolution levels.
signed short ossim_sint16
virtual void disableSource()
Disables source.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
os2<< "> n<< " > nendobj n
#define FLT_EPSILON
virtual void getValidImageVertices(std::vector< ossimIpt > &validVertices, ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, ossim_uint32 resLevel=0) const
ordering specifies how the vertices should be arranged.
ossimImageSource * theInputConnection
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
32 bit normalized floating point
ossimDpt getMetersPerPixel() const
Returns the GSD associated with this image in the active projection.
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
ossimRefPtr< ossimImageData > getTileAtResLevel(const ossimIrect &boundingRect, ossim_uint32 resLevel)
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
ossim_uint32 m_MaxLevelsToCompute
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
void resampleTileToDecimation(T dummyVariable, ossimRefPtr< ossimImageData > result, ossimRefPtr< ossimImageData > tile, ossim_uint32 multiplier)
void getViewMids(ossimDpt &upperMid, ossimDpt &rightMid, ossimDpt &bottomMid, ossimDpt &leftMid, ossimDpt &center) const
T min(T a, T b)
Definition: ossimCommon.h:203
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
bool hasNans() const
Definition: ossimDpt.h:67
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
void add(const ossimPolyArea2d &rhs)
ossim_float64 height() const
Definition: ossimDrect.h:517
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if not defined...
virtual void setEnableFlag(bool flag)
Definition: ossimSource.cpp:99
virtual void getViewSegments(std::vector< ossimDrect > &viewBounds, ossimPolyArea2d &polyArea, ossim_uint32 numberOfEdgePoints=25) const
Because of the fact we can have dateline crossings there exist on the view plane both positive and ne...
const ossimIpt & ur() const
Definition: ossimIrect.h:275
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
virtual bool isIdentity() const =0
RTTI_DEF2(ossimImageRenderer, "ossimImageRenderer", ossimImageSourceFilter, ossimViewInterface)
void deallocate()
Deletes all allocated tiles.
return status
virtual void getKernelSupport(double &x, double &y) const
ossimDpt getParametricCenter(const ossimDpt &ul, const ossimDpt &ur, const ossimDpt &lr, const ossimDpt &ll) const
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
64 bit normalized floating point
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
16 bit unsigned integer (11 bits used)
void splitAll(std::vector< ossimRendererSubRectInfo > &result) const
virtual ossimGpt origin() const =0
ossim_int32 y
Definition: ossimIpt.h:142
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
void makeNan()
Definition: ossimIrect.h:329
virtual const void * getBuf() const
virtual ossimImageViewTransform * createTransform(const ossimKeywordlist &kwl, const char *prefix=0)
virtual bool setView(ossimObject *baseObject)=0
void fillTile(ossimRefPtr< ossimImageData > outputData, const ossimRendererSubRectInfo &rectInfo)
virtual ossimString getLongName() const
double x
Definition: ossimDpt.h:164
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void getDecimationFactors(vector< ossimDpt > &decimations) const
#define RSET_SEARCH_THRESHHOLD
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
void stretchToTileBoundary(const ossimIpt &tileWidthHeight)
Definition: ossimIrect.cpp:212
virtual void resample(const ossimRefPtr< ossimImageData > &input, ossimRefPtr< ossimImageData > &output, const ossimDpt &ul, const ossimDpt &ur, const ossimDpt &deltaUl, const ossimDpt &deltaUr, const ossimDpt &length)
virtual void imageToView(const ossimDpt &imagePoint, ossimDpt &viewPoint) const
bool hasNans() const
Definition: ossimIrect.h:337
ossimDpt computeViewToImageScale(const ossimDpt &viewPt, const ossimDpt &delta=ossimDpt(1.0, 1.0)) const
virtual void setUlTiePoints(const ossimGpt &gpt)
void initializeBoundingRects()
Initializes m_inputR0Rect and m_viewBoundingRect and sets m_rectsDirty appropriately.
ossim_int32 x
Definition: ossimIpt.h:141
virtual ossimObject * getView()=0
8 bit unsigned integer
ossimRefPtr< ossimImageViewTransform > m_ImageViewTransform
virtual bool isValid() const =0
ossimDataObjectStatus
Definitions for data object status.
virtual void setEnableFlag(bool flag)
Sets the enable flag.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual void refreshEvent(ossimRefreshEvent &event)
void connectInputEvent(ossimConnectionEvent &event)
const ossimDpt & lr() const
Definition: ossimDrect.h:341
virtual void getDecimationFactor(ossim_uint32 resLevel, ossimDpt &result) const
Will return the decimation factor for the given resolution level.
ossimIrect combine(const ossimIrect &rect) const
Definition: ossimIrect.cpp:543
void allocate()
Called on first getTile, will initialize all data needed.
RefreshType getRefreshType() const
virtual const ossimIpt & getOrigin() const
virtual bool setView(ossimObject *baseObject)
virtual void enableSource()
Enables source.
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
ossim_uint32 m_MaxRecursionLevel
void setCacheRefreshBit()
virtual void getDecimationFactors(std::vector< ossimDpt > &decimations) const
Will return an array of all decimations for each resolution level.
void setImageGeometry(ossimImageGeometry *g)
Assigns the geometry to use for input image. This object does NOT own the geometry.
#define min(a, b)
Definition: auxiliary.h:75
int ossim_int32
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)