OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimQuadTreeWarp.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: See top level LICENSE.txt file.
5 //
6 // Author: Garrett Potts
7 //
8 //*************************************************************************
9 // $Id: ossimQuadTreeWarp.cpp 23324 2015-05-27 12:57:14Z dburken $
10 
12 #include <algorithm>
13 #include <stack>
14 #include <iostream>
15 
16 #include <ossim/base/ossimTrace.h>
18 
19 static ossimTrace traceExec ("ossimQuadTreeWarp:exec");
20 static ossimTrace traceDebug ("ossimQuadTreeWarp:debug");
21 
22 RTTI_DEF1(ossimQuadTreeWarp, "ossimQuadTreeWarp", ossim2dTo2dTransform);
23 
25  const ossimDpt& position, const ossimDpt& delta)
26  :thePosition(position),
27  theDelta(delta),
28  theLockedFlag(false)
29 {
30 }
31 
33 {
34  for(ossim_uint32 i = 0;i< theSharedNodeList.size();++i)
35  {
36  theSharedNodeList[i]->removeVertex(this);
37  }
38 
39 }
40 
42 {
43  thePosition = position;
44 }
45 
47 {
48  theDelta = delta;
49 }
50 
52 {
53  return theDelta;
54 }
55 
57 {
58  return thePosition;
59 }
60 
62 {
63  if(node)
64  {
65  theSharedNodeList.push_back(node);
66  }
67 }
68 
70 {
71  std::vector<ossimQuadTreeWarpNode*>::iterator iter = theSharedNodeList.begin();
72  bool found = false;
73  ossimQuadTreeWarpNode* removedNode = NULL;
74  while((iter != theSharedNodeList.end())&&!found)
75  {
76  if(*iter == node)
77  {
78  removedNode = *iter;
79  iter = theSharedNodeList.erase(iter);
80  found = true;
81  }
82  else
83  {
84  ++iter;
85  }
86  }
87 
88  if(removedNode)
89  {
90  removedNode->removeVertex(this);
91  }
92 }
93 
95 {
96  return (theSharedNodeList.size() > 0);
97 }
98 
100  const char* prefix)const
101 {
102  kwl.add(prefix,
103  "x",
104  thePosition.x,
105  true);
106  kwl.add(prefix,
107  "y",
108  thePosition.y,
109  true);
110  kwl.add(prefix,
111  "dx",
112  theDelta.x,
113  true);
114  kwl.add(prefix,
115  "dy",
116  theDelta.y,
117  true);
118  kwl.add(prefix,
119  "lock_flag",
120  (int)theLockedFlag,
121  true);
122 
123  return true;
124 }
125 
127  const char* prefix)
128 {
129  const char* x = kwl.find(prefix,
130  "x");
131  const char* y = kwl.find(prefix,
132  "y");
133  const char* dx = kwl.find(prefix,
134  "dx");
135  const char* dy = kwl.find(prefix,
136  "dy");
137  const char* lockedFlag = kwl.find(prefix,
138  "lock_flag");
139  if(x&&y&&dx&&dy&&lockedFlag)
140  {
143  theDelta.x = ossimString(dx).toDouble();
144  theDelta.y = ossimString(dy).toDouble();
145  theLockedFlag = ossimString(lockedFlag).toBool();
146 
147  return true;
148  }
149 
150  return false;
151 }
152 
154  :
155  theUlVertex(NULL),
156  theUrVertex(NULL),
157  theLrVertex(NULL),
158  theLlVertex(NULL),
159  theParent(NULL)
160 {
162 }
163 
165  const ossimDrect& bounds,
166  ossimQuadTreeWarpNode* parent,
167  ossimQuadTreeWarpVertex* ulVertex,
168  ossimQuadTreeWarpVertex* urVertex,
169  ossimQuadTreeWarpVertex* lrVertex,
170  ossimQuadTreeWarpVertex* llVertex)
171  :
172  theBoundingRect(bounds),
173  theUlVertex(ulVertex),
174  theUrVertex(urVertex),
175  theLrVertex(lrVertex),
176  theLlVertex(llVertex),
177  theParent(parent)
178 {
179 }
180 
182 {
183  removeVertices();
184 
185  theUlVertex = NULL;
186  theUrVertex = NULL;
187  theLrVertex = NULL;
188  theLlVertex = NULL;
189 
190 }
191 
193 {
195 }
196 
198 {
199  if(!v) return;
200 
201  if(theUlVertex == v)
202  {
203  theUlVertex = NULL;
204  v->removeNode(this);
205  }
206  if(theUrVertex == v)
207  {
208  theUrVertex = NULL;
209  v->removeNode(this);
210  }
211  if(theLrVertex == v)
212  {
213  theLrVertex = NULL;
214  v->removeNode(this);
215  }
216  if(theLlVertex == v)
217  {
218  theLlVertex = NULL;
219  v->removeNode(this);
220  }
221 }
223 {
228 }
229 
231 {
232  return (theChildren.size() == 0);
233 }
234 
236 {
238  theChildren.clear();
239  theParent = NULL;
244 }
245 
247 {
248  std::vector<ossimQuadTreeWarpNode*>::iterator iter = theChildren.begin();
249 
250  while(iter != theChildren.end())
251  {
252  if(*iter == node)
253  {
254  theChildren.erase(iter);
255  return;
256  }
257  ++iter;
258  }
259 }
260 
262  const char* prefix)const
263 {
264  kwl.add(prefix,
266  theBoundingRect.ul().x,
267  true);
268  kwl.add(prefix,
270  theBoundingRect.ul().y,
271  true);
272  kwl.add(prefix,
274  theBoundingRect.lr().x,
275  true);
276  kwl.add(prefix,
278  theBoundingRect.lr().y,
279  true);
280 
281  return true;
282 }
283 
285  const char* prefix)
286 {
287  const char* ul_x = kwl.find(prefix, ossimKeywordNames::UL_X_KW);
288  const char* ul_y = kwl.find(prefix, ossimKeywordNames::UL_Y_KW);
289  const char* lr_x = kwl.find(prefix, ossimKeywordNames::LR_X_KW);
290  const char* lr_y = kwl.find(prefix, ossimKeywordNames::LR_Y_KW);
291 
292  if(ul_x&&ul_y&&lr_x&&lr_y)
293  {
294  theBoundingRect = ossimDrect(ossimString(ul_x).toDouble(),
295  ossimString(ul_y).toDouble(),
296  ossimString(lr_x).toDouble(),
297  ossimString(lr_y).toDouble());
298  return true;
299  }
300 
301  return false;
302 }
303 
304 
306  :theTree(NULL)
307 {
308 }
309 
311  const ossimDpt& ulShift,
312  const ossimDpt& urShift,
313  const ossimDpt& lrShift,
314  const ossimDpt& llShift)
315  :theTree(NULL)
316 {
317  create(boundingRect, ulShift, urShift, lrShift, llShift);
318 }
319 
322  theWarpEnabledFlag(true),
323  theTree(NULL)
324 {
325  ossimKeywordlist kwl;
326 
327  rhs.saveState(kwl);
328 
329  loadState(kwl);
330 }
331 
333 {
334  return new ossimQuadTreeWarp(*this);
335 }
336 
338 {
339  clear();
340 }
341 
343 {
344  if(!isEmpty())
345  {
347  {
348  return theTree->theBoundingRect.midPoint();
349  }
350 
351  }
352 
353  return ossimDpt(0,0);
354 }
355 
356 void ossimQuadTreeWarp::create(const ossimDrect& boundingRect,
357  const ossimDpt& ulShift,
358  const ossimDpt& urShift,
359  const ossimDpt& lrShift,
360  const ossimDpt& llShift)
361 {
362  clear();
363 
364  theTree = new ossimQuadTreeWarpNode(boundingRect);
365 
366  ossimQuadTreeWarpVertex* ul = new ossimQuadTreeWarpVertex(boundingRect.ul(),
367  ulShift);
368  ossimQuadTreeWarpVertex* ur = new ossimQuadTreeWarpVertex(boundingRect.ur(),
369  urShift);
370  ossimQuadTreeWarpVertex* lr = new ossimQuadTreeWarpVertex(boundingRect.lr(),
371  lrShift);
372  ossimQuadTreeWarpVertex* ll = new ossimQuadTreeWarpVertex(boundingRect.ll(),
373  llShift);
374  ul->addSharedNode(theTree);
375  ur->addSharedNode(theTree);
376  lr->addSharedNode(theTree);
377  ll->addSharedNode(theTree);
378 
379  theVertexList.push_back(ul);
380  theVertexList.push_back(ur);
381  theVertexList.push_back(lr);
382  theVertexList.push_back(ll);
383 
384  theTree->theUlVertex = ul;
385  theTree->theUrVertex = ur;
386  theTree->theLrVertex = lr;
387  theTree->theLlVertex = ll;
388 
389 }
390 
392 {
393  for(ossim_uint32 i = 0; i < theVertexList.size();++i)
394  {
395  out << *theVertexList[i] << "\n";
396  }
397 }
398 
400 {
401  return theTree;
402 }
403 
405 {
406  return theTree;
407 }
408 
410 {
411  return (theTree==NULL);
412 }
413 
415 {
416  if(!isEmpty())
417  {
418  out << "___________VERTEX LIST____________________\n";
419  printVertices(out);
420  out << "___________TREE LIST____________________\n";
421 
422  recursivePrint(out, theTree);
423  }
424  else
425  {
426  out << "<empty tree>\n";
427  }
428  return out;
429 }
430 
432 {
433  if(position.hasNans()) return (ossimQuadTreeWarpVertex*)NULL;
434 
435  double dist = 1.0/DBL_EPSILON;
437  for(ossim_uint32 i = 0; i < theVertexList.size(); ++i)
438  {
439  double d = (position-theVertexList[i]->thePosition).length();
440  if( d < dist)
441  {
442  result = theVertexList[i];
443  dist = d;
444  }
445  }
446 
447  return result;
448 // ossimQuadTreeWarpNode* node = findNode(position);
449 
450 // if(node&&node->hasValidVertices())
451 // {
452 // double ulDist = (position-node->theUlVertex->thePosition).length();
453 // double urDist = (position-node->theUrVertex->thePosition).length();
454 // double lrDist = (position-node->theLrVertex->thePosition).length();
455 // double llDist = (position-node->theLlVertex->thePosition).length();
456 
457 // double minDist = std::min(ulDist, std::min(urDist, std::min(lrDist, llDist)));
458 
459 // if(minDist == ulDist)
460 // {
461 // return node->theUlVertex;
462 // }
463 // else if(minDist == urDist)
464 // {
465 // return node->theUrVertex;
466 // }
467 // else if(minDist == lrDist)
468 // {
469 // return node->theLrVertex;
470 // }
471 // else if(minDist == llDist)
472 // {
473 // return node->theLlVertex;
474 // }
475 // }
476 
477 // return ((ossimQuadTreeWarpVertex*)NULL);
478 }
479 
480 
482 {
483  ossim_uint32 i = 0;
485  ossimQuadTreeWarpNode* currentNode = theTree;
486 
487  if((currentNode)&&
488  (currentNode->theBoundingRect.pointWithin(position)))
489  {
490  while((currentNode)&&
491  (!currentNode->isLeaf()))
492  {
493  for(i = 0; i < currentNode->theChildren.size(); ++i)
494  {
495  if(currentNode->theChildren[i]->theBoundingRect.pointWithin(position))
496  {
497  currentNode = currentNode->theChildren[i];
498  break;
499  }
500  }
501  }
502 
503  if(currentNode&&currentNode->hasValidVertices())
504  {
505  if(currentNode->theUlVertex->thePosition == position)
506  {
507  result = currentNode->theUlVertex;
508  }
509  else if(currentNode->theUrVertex->thePosition == position)
510  {
511  result = currentNode->theUrVertex;
512  }
513  else if(currentNode->theLrVertex->thePosition == position)
514  {
515  result = currentNode->theLrVertex;
516  }
517  else if(currentNode->theLlVertex->thePosition == position)
518  {
519  result = currentNode->theLlVertex;
520  }
521  }
522 
523  }
524 
525  return result;
526 }
527 
529 {
530  std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin();
531 
532  while(iter != theVertexList.end())
533  {
534  if(position == (*iter)->getPosition())
535  {
536  return (*iter);
537  }
538  ++iter;
539  }
540 
541  return (ossimQuadTreeWarpVertex*)NULL;
542 }
543 
545 {
546  if(theTree)
547  {
549  theTree = NULL;
550  }
551 
552  for(ossim_uint32 i = 0; i < theVertexList.size(); ++i)
553  {
554  delete theVertexList[i];
555  }
556 
557  theVertexList.clear();
558 }
559 
561  ossimDpt& result)const
562 {
564  {
565  ossimDpt shift;
566 
567  getShift(shift,
568  pt);
569 
570  result = pt + shift;
571  }
572  else
573  {
574  result = pt;
575  }
576 }
577 
579 {
581  {
582  ossimDpt shift;
583 
584  getShift(shift,
585  pt);
586 
587  pt += shift;
588  }
589 }
590 
592  const ossimDpt& pt)const
593 {
594  getShift(result,
595  findNode(pt),
596  pt);
597 }
598 
600  double splitHoriCoefficient,
601  double splitVertCoefficient)
602 {
603  ossimQuadTreeWarpNode* node = findNode(point);
604 
605  if(node)
606  {
607  if(splitHoriCoefficient == 0.0)
608  {
609  splitHoriCoefficient = (point.x - node->theBoundingRect.ul().x)/
610  node->theBoundingRect.width();
611  }
612  if(splitVertCoefficient == 0.0)
613  {
614  splitVertCoefficient = (point.y - node->theBoundingRect.ul().y)/
615  node->theBoundingRect.height();
616  }
617  split(node,
618  splitHoriCoefficient,
619  splitVertCoefficient);
620  }
621 }
622 
623 
625  double splitHoriCoefficient,
626  double splitVertCoefficient)
627 {
628  if(!node) return;
629 
630  splitHoriCoefficient = splitHoriCoefficient>1?1:splitHoriCoefficient;
631  splitHoriCoefficient = splitHoriCoefficient<0?0:splitHoriCoefficient;
632  splitVertCoefficient = splitVertCoefficient>1?1:splitVertCoefficient;
633  splitVertCoefficient = splitVertCoefficient<0?0:splitVertCoefficient;
634 
635  if( ((splitHoriCoefficient == 0)&&(splitVertCoefficient == 0)) ||
636  ((splitHoriCoefficient == 1)&&(splitVertCoefficient == 1)))
637  {
638  return;
639  }
640 
641  if(node->isLeaf())
642  {
643  if(node->theBoundingRect.hasNans())
644  {
645  ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << "ossimQuadTreeWarp::split, Node has nans for the rect and can't split\n";
646  }
647  else
648  {
649  ossimDpt ul = node->theBoundingRect.ul();
650  ossimDpt ur = node->theBoundingRect.ur();
651  ossimDpt lr = node->theBoundingRect.lr();
652  ossimDpt ll = node->theBoundingRect.lr();
653 
654 
655  double xmid = ul.x + (ur.x - ul.x)*splitHoriCoefficient;
656  double ymid = ul.y + (ll.y - ul.y)*splitVertCoefficient;
657 
658  ossimDpt left(ul.x, ymid);
659 
660  ossimDpt right(ur.x,
661  ymid);
662 
663  ossimDpt top(xmid,
664  ul.y);
665 
666  ossimDpt bottom(xmid,
667  lr.y);
668 
669 
670  ossimDrect ulRect(ul.x,
671  ul.y,
672  xmid,
673  ymid);
674 
675  ossimDrect urRect(top.x,
676  top.y,
677  right.x,
678  right.y);
679 
680  ossimDrect lrRect(xmid,
681  ymid,
682  lr.x,
683  lr.y);
684 
685  ossimDrect llRect(left.x,
686  left.y,
687  bottom.x,
688  bottom.y);
689 
694 
695  getNewQuads(node,
696  ulRect,
697  urRect,
698  lrRect,
699  llRect,
700  ulNode,
701  urNode,
702  lrNode,
703  llNode);
704 
705  if(ulNode&&urNode&&lrNode&&llNode)
706  {
707  node->theChildren.push_back(ulNode);
708  node->theChildren.push_back(urNode);
709  node->theChildren.push_back(lrNode);
710  node->theChildren.push_back(llNode);
711 
712  // it's no longer a leaf so remove the vertices
713  // from the list
714  node->removeVertex(node->theUlVertex);
715  node->removeVertex(node->theUrVertex);
716  node->removeVertex(node->theLrVertex);
717  node->removeVertex(node->theLlVertex);
718  }
719  }
720  }
721  else
722  {
723  ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << "ossimQuadTreeWarp::split, can only split leaf nodes\n";
724  }
725 
727 }
728 
730  const ossimDrect& ul,
731  const ossimDrect& ur,
732  const ossimDrect& lr,
733  const ossimDrect& ll,
734  ossimQuadTreeWarpNode*& ulNode,
735  ossimQuadTreeWarpNode*& urNode,
736  ossimQuadTreeWarpNode*& lrNode,
737  ossimQuadTreeWarpNode*& llNode)
738 {
739  ossimDpt midShift;
740  getShift(midShift, parent, ul.lr());
741 
743  midShift);
744 
745  ulNode = new ossimQuadTreeWarpNode(ul, parent);
746  urNode = new ossimQuadTreeWarpNode(ur, parent);
747  lrNode = new ossimQuadTreeWarpNode(lr, parent);
748  llNode = new ossimQuadTreeWarpNode(ll, parent);
749 
750  midV->addSharedNode(ulNode);
751  midV->addSharedNode(urNode);
752  midV->addSharedNode(lrNode);
753  midV->addSharedNode(llNode);
754 
755  // get the shared vertices first. We will add ourself
756  // to the pointer list. when we construct
757  // the quad nodes. Note the mid point will be shared
758  // by all quads and will be marked as adjustable
759  //
760  ossimQuadTreeWarpVertex* ulSharedV = getVertex(ul.ul());
761  ossimQuadTreeWarpVertex* urSharedV = getVertex(ur.ur());
762  ossimQuadTreeWarpVertex* lrSharedV = getVertex(lr.lr());
763  ossimQuadTreeWarpVertex* llSharedV = getVertex(ll.ll());
764 
765  if( !ulSharedV || !urSharedV|| !lrSharedV || !llSharedV )
766  {
767  delete ulNode;
768  delete urNode;
769  delete lrNode;
770  delete llNode;
771  ulNode = 0;
772  urNode = 0;
773  lrNode = 0;
774  llNode = 0;
775  delete midV;
776  midV = 0;
777 
779  << "FATAL: ossimQuadTreeWarp::split, can't locating shared vertices. This Shouldn't happen!!!\n";
780  return;
781  }
782 
783  // we know that the midpoint is new and is shared by all quads
784  // so we have 2 more to check
785  ossimQuadTreeWarpVertex* topSharedV = getVertex(ul.ur());
786  ossimQuadTreeWarpVertex* bottomSharedV = getVertex(lr.ll());
787 
788  ossimQuadTreeWarpVertex* leftSharedV = getVertex(ul.ll());
789  ossimQuadTreeWarpVertex* rightSharedV = getVertex(ur.lr());
790 
791  ossimDpt tempShift;
792 
793  if(!topSharedV)
794  {
795  getShift(tempShift, parent, ul.ur());
796  topSharedV = new ossimQuadTreeWarpVertex(ul.ur(),
797  tempShift);
798  theVertexList.push_back(topSharedV);
799  }
800  if(!bottomSharedV)
801  {
802  getShift(tempShift, parent, ll.lr());
803  bottomSharedV = new ossimQuadTreeWarpVertex(ll.lr(),
804  tempShift);
805 
806  theVertexList.push_back(bottomSharedV);
807  }
808  if(!leftSharedV)
809  {
810  getShift(tempShift, parent, ul.ll());
811  leftSharedV = new ossimQuadTreeWarpVertex(ul.ll(),
812  tempShift);
813  theVertexList.push_back(leftSharedV);
814  }
815  if(!rightSharedV)
816  {
817  getShift(tempShift, parent, ur.lr());
818  rightSharedV = new ossimQuadTreeWarpVertex(ur.lr(),
819  tempShift);
820  theVertexList.push_back(rightSharedV);
821  }
822  theVertexList.push_back(midV);
823 
824  topSharedV->addSharedNode(ulNode);
825  topSharedV->addSharedNode(urNode);
826 
827  bottomSharedV->addSharedNode(llNode);
828  bottomSharedV->addSharedNode(lrNode);
829  leftSharedV->addSharedNode(ulNode);
830  leftSharedV->addSharedNode(llNode);
831  rightSharedV->addSharedNode(urNode);
832  rightSharedV->addSharedNode(lrNode);
833 
834  ulSharedV->addSharedNode(ulNode);
835  urSharedV->addSharedNode(urNode);
836  lrSharedV->addSharedNode(lrNode);
837  llSharedV->addSharedNode(llNode);
838 
839  ulNode->theUlVertex = ulSharedV;
840  ulNode->theUrVertex = topSharedV;
841  ulNode->theLrVertex = midV;
842  ulNode->theLlVertex = leftSharedV;
843 
844  urNode->theUlVertex = topSharedV;
845  urNode->theUrVertex = urSharedV;
846  urNode->theLrVertex = rightSharedV;
847  urNode->theLlVertex = midV;
848 
849  lrNode->theUlVertex = midV;
850  lrNode->theUrVertex = rightSharedV;
851  lrNode->theLrVertex = lrSharedV;
852  lrNode->theLlVertex = bottomSharedV;
853 
854  llNode->theUlVertex = leftSharedV;
855  llNode->theUrVertex = midV;
856  llNode->theLrVertex = bottomSharedV;
857  llNode->theLlVertex = llSharedV;
858 }
859 
861  const ossimQuadTreeWarpNode* node,
862  const ossimDpt& pt)const
863 {
864  result.x = 0.0;
865  result.y = 0.0;
866 
867  if(!node)
868  {
869  return;
870  }
871  if(!node->isLeaf())
872  {
873  return;
874  }
875 
876  if(node->hasValidVertices())
877  {
878  ossimDpt ulShift = node->theUlVertex->getDelta();
879  ossimDpt urShift = node->theUrVertex->getDelta();
880  ossimDpt lrShift = node->theLrVertex->getDelta();
881  ossimDpt llShift = node->theLlVertex->getDelta();
882 
883  ossimDpt ul = node->theBoundingRect.ul();
884  ossimDpt ur = node->theBoundingRect.ur();
885  ossimDpt ll = node->theBoundingRect.ll();
886 
887  double horizontalPercent = fabs((pt.x-ul.x))/
888  (ur.x-ul.x);
889 
890  double verticalPercent = fabs((pt.y - ul.y))/
891  (ll.y-ul.y);
892 
893  ossimDpt upper = ulShift + (urShift - ulShift)*horizontalPercent;
894  ossimDpt lower = llShift + (lrShift - llShift)*horizontalPercent;
895 
896  result = upper + (lower - upper)*verticalPercent;
897  }
898  else
899  {
900  ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimQuadTreeWarp::getShift, " << "Node does not have valid vertices in ossimQuadTreeWarp::getShift\n";
901  }
902 }
903 
905 {
906  if(node&&
907  !node->isLeaf())
908  {
913 
914  recursivePruneTree(node);
915 
916  if(ulV&&urV&&lrV&&llV)
917  {
918  node->theUlVertex = ulV;
919  node->theUrVertex = urV;
920  node->theLrVertex = lrV;
921  node->theLlVertex = llV;
922 
923  ulV->addSharedNode(node);
924  urV->addSharedNode(node);
925  lrV->addSharedNode(node);
926  llV->addSharedNode(node);
927  }
928  else
929  {
930  ossimNotify(ossimNotifyLevel_WARN) << "WARNING: ossimQuadTreeWarp::pruneTree, invlaid vertex find\n";
931  }
934  }
935 }
936 
938 {
939  if(!node||node->isLeaf()) return;
940 
941  for(ossim_uint32 i = 0; i < node->theChildren.size(); ++i)
942  {
944  delete node->theChildren[i];
945  node->theChildren[i] = NULL;
946  }
947  node->theChildren.clear();
948 }
949 
950 
952 {
953  if((!pt.hasNans())&&(!isEmpty()))
954  {
956  {
957  return findNode(theTree,
958  pt);
959  }
960  }
961 
962  return (ossimQuadTreeWarpNode*)NULL;
963 }
964 
966 {
967  ossimDpt result;
968 
969  getShift(result, pt);
970 
971  return result;
972 }
973 
975 {
976  if((!pt.hasNans())&&(!isEmpty()))
977  {
979  {
980  return findNode(theTree,
981  pt);
982  }
983  }
984 
985  return (const ossimQuadTreeWarpNode*)NULL;
986 }
987 
989  const ossimDpt& pt)
990 {
992 
993  if(!node)
994  {
995  return result;
996  }
997  if(node->isLeaf())
998  {
999  result = node;
1000  }
1001  else
1002  {
1003  bool found = false;
1004  for(ossim_uint32 i = 0; (i < node->theChildren.size())&&(!found); ++i)
1005  {
1006  if(node->theChildren[i]->theBoundingRect.pointWithin(pt))
1007  {
1008  result = findNode(node->theChildren[i],
1009  pt);
1010  found = true;
1011  }
1012  }
1013  }
1014 
1015  return result;
1016 }
1017 
1018 void ossimQuadTreeWarp::findAllNodes(std::vector<ossimQuadTreeWarpNode*>& result,
1019  const ossimDpt& pt)
1020 {
1021  if((!pt.hasNans())&&(!isEmpty()))
1022  {
1024  {
1025  findAllNodes(result,
1026  theTree,
1027  pt);
1028  }
1029  }
1030 
1031 }
1032 
1033 void ossimQuadTreeWarp::findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result,
1034  const ossimDpt& pt)const
1035 {
1036  if(!pt.hasNans()&&(!isEmpty()))
1037  {
1039  {
1040  findAllNodes(result,
1041  theTree,
1042  pt);
1043  }
1044  }
1045 
1046 }
1047 
1049  const ossimDpt& pt)const
1050 {
1051  const ossimQuadTreeWarpNode* result = (const ossimQuadTreeWarpNode*)NULL;
1052 
1053  if(!node)
1054  {
1055  return result;
1056  }
1057  if(node->isLeaf())
1058  {
1059  result = node;
1060  }
1061  else
1062  {
1063  bool found = false;
1064  for(ossim_uint32 i = 0; (i < node->theChildren.size())&&(!found); ++i)
1065  {
1066  if(node->theChildren[i]->theBoundingRect.pointWithin(pt))
1067  {
1068  result = findNode(node->theChildren[i],
1069  pt);
1070  found = true;
1071  }
1072  }
1073  }
1074 
1075  return result;
1076 }
1077 
1078 void ossimQuadTreeWarp::findAllNodes(std::vector<ossimQuadTreeWarpNode*>& result,
1079  ossimQuadTreeWarpNode* node,
1080  const ossimDpt& pt)
1081 {
1082  if(node->isLeaf())
1083  {
1084  result.push_back(node);
1085  }
1086  else
1087  {
1088  for(ossim_uint32 i = 0;
1089  i < node->theChildren.size();
1090  ++i)
1091  {
1092  if(node->theChildren[i]->theBoundingRect.pointWithin(pt))
1093  {
1094  findAllNodes(result,
1095  node->theChildren[i],
1096  pt);
1097  }
1098  }
1099  }
1100 }
1101 
1102 void ossimQuadTreeWarp::findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result,
1103  ossimQuadTreeWarpNode* node,
1104  const ossimDpt& pt)const
1105 {
1106  if(!node) return;
1107  if(node->isLeaf())
1108  {
1109  result.push_back(node);
1110  }
1111  else
1112  {
1113  for(ossim_uint32 i = 0;
1114  i < node->theChildren.size();
1115  ++i)
1116  {
1117  if(node->theChildren[i]->theBoundingRect.pointWithin(pt))
1118  {
1119  findAllNodes(result,
1120  node->theChildren[i],
1121  pt);
1122  }
1123  }
1124  }
1125 }
1127 {
1128  std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin();
1129 
1130  while(iter != theVertexList.end())
1131  {
1132  if( !(*iter)->isShared())
1133  {
1134  delete (*iter);
1135  iter = theVertexList.erase(iter);
1136  }
1137  else
1138  {
1139  ++iter;
1140  }
1141  }
1142 }
1143 
1145 {
1146  std::vector<ossimQuadTreeWarpVertex*>::iterator iter = std::find(theVertexList.begin(),
1147  theVertexList.end(),
1148  v);
1149  if(iter != theVertexList.end())
1150  {
1151  delete (*iter);
1152  iter = theVertexList.erase(iter);
1153  }
1154 }
1155 
1156 
1158  ossimQuadTreeWarpNode* node)const
1159 {
1160  if(node)
1161  {
1162  out << (*node) << "\n";
1163  }
1164 
1165  if(!node->isLeaf())
1166  {
1167  for(ossim_uint32 i =0; i < node->theChildren.size();++i)
1168  {
1169  recursivePrint(out, node->theChildren[i]);
1170  }
1171  }
1172 }
1173 
1175 {
1176  if(node->isLeaf())
1177  {
1178  delete node;
1179  }
1180  else
1181  {
1182  for(ossim_uint32 i = 0; i < node->theChildren.size(); ++ i)
1183  {
1184  recursiveDelete(node->theChildren[i]);
1185  }
1186 
1187  delete node;
1188  }
1189 }
1190 
1192  const ossimDpt& point)const
1193 {
1194  if(!node) return false;
1195 
1196  if(node->theBoundingRect.pointWithin(point))
1197  {
1198  double minx, maxx;
1199  double miny, maxy;
1200  node->theBoundingRect.getBounds(minx, miny, maxx, maxy);
1201 
1202  return ( (point.x == minx) ||
1203  (point.x == miny) ||
1204  (point.y == miny) ||
1205  (point.y == maxy) );
1206  }
1207 
1208  return false;
1209 }
1210 
1212  const ossimDpt& point)const
1213 {
1214  if(!node) return false;
1215 
1216  return ( (point == node->theBoundingRect.ul())||
1217  (point == node->theBoundingRect.ur())||
1218  (point == node->theBoundingRect.lr())||
1219  (point == node->theBoundingRect.ll()) );
1220 }
1221 
1223 {
1224  std::vector<ossimQuadTreeWarpNode*> nodeList;
1225 
1226  findAllNodes(nodeList,
1227  v->getPosition());
1228 
1229  if(nodeList.size() != v->theSharedNodeList.size())
1230  {
1231  if(isOnEdge(theTree, v->getPosition()))
1232  {
1233  v->theLockedFlag = false;
1234  }
1235  else
1236  {
1237  v->theLockedFlag = true;
1238  }
1239  }
1240  else
1241  {
1242  v->theLockedFlag = false;
1243  }
1244 
1245  // if the original was not locked
1246  // then we need to make sure we change the delta
1247  // along the locked edge so to produce no artifacts
1248  //
1249  if(v->theLockedFlag)
1250  {
1251  updateDelta(v);
1252  }
1253 }
1254 
1256 {
1257  ossimQuadTreeWarpVertex* top = NULL;
1258  ossimQuadTreeWarpVertex* bottom = NULL;
1259  ossimQuadTreeWarpVertex* left = NULL;
1260  ossimQuadTreeWarpVertex* right = NULL;
1261 
1262  std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin();
1263 
1264  while(iter != theVertexList.end())
1265  {
1266  ossimQuadTreeWarpVertex* testV = (*iter);
1267 
1268  // test along the vertical
1269  if( (testV->thePosition.x == v->thePosition.x)&&
1270  (testV->thePosition.y != v->thePosition.y)&&
1271  (!testV->theLockedFlag))
1272  {
1273  if(testV->thePosition.y > v->thePosition.y)
1274  {
1275  if(bottom)
1276  {
1277  if(bottom->thePosition.y > testV->thePosition.y)
1278  {
1279  bottom = testV;
1280  }
1281  }
1282  else
1283  {
1284  bottom = testV;
1285  }
1286  }
1287  else
1288  {
1289  if(top)
1290  {
1291  if(top->thePosition.y < testV->thePosition.y)
1292  {
1293  top = testV;
1294  }
1295  }
1296  else
1297  {
1298  top = testV;
1299  }
1300  }
1301  }
1302 
1303  if( (testV->thePosition.y == v->thePosition.y)&&
1304  (testV->thePosition.x != v->thePosition.x)&&
1305  (!testV->theLockedFlag))
1306  {
1307  if(testV->thePosition.x > v->thePosition.x)
1308  {
1309  if(right)
1310  {
1311  if(right->thePosition.x > testV->thePosition.x)
1312  {
1313  right = testV;
1314  }
1315  }
1316  else
1317  {
1318  right = testV;
1319  }
1320  }
1321  else
1322  {
1323  if(left)
1324  {
1325  if(left->thePosition.x < testV->thePosition.x)
1326  {
1327  left = testV;
1328  }
1329  }
1330  else
1331  {
1332  left = testV;
1333  }
1334  }
1335  }
1336 
1337  ++iter;
1338  }
1339  ossimDpt topBottomDelta;
1340  ossimDpt leftRightDelta;
1341 
1342  topBottomDelta.makeNan();
1343  leftRightDelta.makeNan();
1344 
1345  if(top&&bottom)
1346  {
1347  double t = (v->thePosition.y - top->thePosition.y)/
1348  (bottom->thePosition.y - top->thePosition.y);
1349 
1350  topBottomDelta = top->theDelta + (bottom->theDelta-top->theDelta)*t;
1351  v->theDelta = topBottomDelta;
1352 
1353  }
1354  if(left&&right)
1355  {
1356  double t = (v->thePosition.x - left->thePosition.x)/
1357  (right->thePosition.x - left->thePosition.x);
1358 
1359  leftRightDelta = left->theDelta + (right->theDelta-left->theDelta)*t;
1360  v->theDelta = leftRightDelta;
1361  }
1362 
1363  if(top&&bottom&&left&&right)
1364  {
1365  v->theDelta = (topBottomDelta+leftRightDelta)*.5;
1366  }
1367 }
1368 
1370 {
1371  std::vector<ossimQuadTreeWarpVertex*>::iterator iter = theVertexList.begin();
1372 
1373  while(iter != theVertexList.end())
1374  {
1375  if(*iter)
1376  {
1377  updateLockFlag(*iter);
1378  }
1379 
1380  ++iter;
1381  }
1382 }
1383 
1384 const std::vector<ossimQuadTreeWarpVertex*>& ossimQuadTreeWarp::getVertices()const
1385 {
1386  return theVertexList;
1387 }
1388 
1390 {
1391  theWarpEnabledFlag = flag;
1392 }
1393 
1395 {
1396  for(ossim_uint32 i = 0; i < theVertexList.size(); ++i)
1397  {
1398  theVertexList[i]->theDelta = ossimDpt(0,0);
1399  }
1400 }
1401 
1403  const char* prefix)const
1404 {
1405  for(ossim_uint32 i = 0; i < theVertexList.size(); ++i)
1406  {
1407  ossimString newPrefix = ossimString(prefix)+ "v" + ossimString::toString(i) +".";
1408 
1409  theVertexList[i]->saveState(kwl, newPrefix.c_str());
1410  }
1411 
1412  recursiveSave(theTree, kwl, prefix);
1413 
1414  return ossim2dTo2dTransform::saveState(kwl, prefix);
1415 }
1416 
1418  const char* prefix)
1419 {
1420  clear();
1421  ossimString newPrefix = ossimString(prefix);
1422 
1423  // load the vertices first
1424  //
1425  ossimString regExpression = ossimString("^(") + newPrefix + "v[0-9]+\\.)";
1426 
1427  ossim_uint32 result = kwl.getNumberOfSubstringKeys(regExpression);
1428 
1429  ossim_uint32 numberOfMatches = 0;
1430  ossim_uint32 count = 0;
1431  while(numberOfMatches < result)
1432  {
1433  ossimString newPrefix = ossimString(prefix)+ossimString("v") + ossimString::toString(count) +".";
1434 
1436 
1437  if(!vert->loadState(kwl, newPrefix.c_str()))
1438  {
1439  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: "<< " ossimQuadTreeWarp::loadState, invalid load on vertex\n";
1440  delete vert;
1441  clear();
1442 
1443  return false;
1444  }
1445  else
1446  {
1447  ++numberOfMatches;
1448  theVertexList.push_back(vert);
1449  }
1450 
1451  ++count;
1452  }
1453 
1455 
1456  if(!theTree->loadState(kwl, prefix))
1457  {
1458  clear();
1459  return false;
1460  }
1461  if(!recursiveLoad(theTree, kwl, prefix))
1462  {
1463  clear();
1464  return false;
1465  }
1466 
1467  if(!ossim2dTo2dTransform::loadState(kwl, prefix))
1468  {
1469  clear();
1470  return false;
1471  }
1472 
1473  return true;
1474 }
1475 
1477  ossimKeywordlist& kwl,
1478  const char* prefix)const
1479 {
1480  if(!node) return false;
1481 
1482  if(!node->saveState(kwl,
1483  prefix))
1484  {
1485  return false;
1486  }
1487 
1488  if(node->isLeaf())
1489  {
1490  return true;
1491  }
1492  else
1493  {
1494  for(ossim_uint32 i = 0; i < node->theChildren.size(); ++ i)
1495  {
1496  ossimString newPrefix = ossimString(prefix) + ossimString::toString(i) + ".";
1497 
1498  if(!recursiveSave(node->theChildren[i],
1499  kwl,
1500  newPrefix.c_str()))
1501  {
1502  return false;
1503  }
1504  }
1505  }
1506 
1507  return true;
1508 }
1509 
1511  const ossimKeywordlist& kwl,
1512  const char* prefix)
1513 {
1514  if(!node) return false;
1515  ossimString copyPrefix = prefix;
1516 
1521 
1522  ossimString ulPre = copyPrefix + "0.";
1523  ossimString urPre = copyPrefix + "1.";
1524  ossimString lrPre = copyPrefix + "2.";
1525  ossimString llPre = copyPrefix + "3.";
1526 
1527  if(ul->loadState(kwl,
1528  ulPre.c_str()))
1529  {
1530  ul->theParent = node;
1531  node->theChildren.push_back(ul);
1532  recursiveLoad(ul,
1533  kwl,
1534  ulPre.c_str());
1535  }
1536  else
1537  {
1538  delete ul;
1539  ul = NULL;
1540  }
1541 
1542  if(ur->loadState(kwl,
1543  urPre.c_str()))
1544  {
1545  ur->theParent = node;
1546  node->theChildren.push_back(ur);
1547  recursiveLoad(ur,
1548  kwl,
1549  urPre.c_str());
1550  }
1551  else
1552  {
1553  delete ur;
1554  ur = NULL;
1555  }
1556 
1557  if(lr->loadState(kwl,
1558  lrPre.c_str()))
1559  {
1560  lr->theParent = node;
1561  node->theChildren.push_back(lr);
1562  recursiveLoad(lr,
1563  kwl,
1564  lrPre.c_str());
1565  }
1566  else
1567  {
1568  delete lr;
1569  lr = NULL;
1570  }
1571 
1572  if(ll->loadState(kwl,
1573  llPre.c_str()))
1574  {
1575  ll->theParent = node;
1576  node->theChildren.push_back(ll);
1577  recursiveLoad(ll,
1578  kwl,
1579  llPre.c_str());
1580  }
1581  else
1582  {
1583  delete ll;
1584  ll = NULL;
1585  }
1586 
1587  if(node->isLeaf())
1588  {
1589  node->theUlVertex = getVertex(node->theBoundingRect.ul());
1590  node->theUrVertex = getVertex(node->theBoundingRect.ur());
1591  node->theLrVertex = getVertex(node->theBoundingRect.lr());
1592  node->theLlVertex = getVertex(node->theBoundingRect.ll());
1593 
1594  if(node->hasValidVertices())
1595  {
1596  node->theUlVertex->addSharedNode(node);
1597  node->theUrVertex->addSharedNode(node);
1598  node->theLrVertex->addSharedNode(node);
1599  node->theLlVertex->addSharedNode(node);
1600  }
1601  else
1602  {
1603  return false;
1604  }
1605  }
1606 
1607  return true;
1608 }
1609 
1611 {
1612  out << "Position: " << rhs.thePosition
1613  << "\nDelta: " << rhs.theDelta
1614  << "\nLocked flag: " << rhs.theLockedFlag
1615  << "\nShared nodes: " << rhs.theSharedNodeList.size() << std::endl;
1616 
1617  return out;
1618 }
1619 
1621  const ossimQuadTreeWarpNode& rhs)
1622 {
1623  out << "Bounding rect: " << rhs.theBoundingRect << std::endl;
1624 
1625  if(rhs.theUlVertex)
1626  {
1627  out << "ulVertex:\n" << *rhs.theUlVertex<< std::endl;
1628  }
1629  if(rhs.theUrVertex)
1630  {
1631  out << "urVertex:\n" << *rhs.theUrVertex<< std::endl;
1632  }
1633  if(rhs.theLrVertex)
1634  {
1635  out << "lrVertex:\n" << *rhs.theLrVertex<< std::endl;
1636  }
1637  if(rhs.theLlVertex)
1638  {
1639  out << "llVertex:\n" << *rhs.theLlVertex;
1640  }
1641 
1642  return out;
1643 }
1644 
1646 {
1647  rhs.print(out);
1648 
1649  return out;
1650 }
1651 
void removeNode(ossimQuadTreeWarpNode *node)
void makeNan()
Definition: ossimDrect.h:388
ossim_uint32 x
virtual std::ostream & print(std::ostream &out) const
Generic print method.
ossimQuadTreeWarpNode * theParent
bool pointWithin(const ossimDpt &pt, double epsilon=0.0) const
Definition: ossimDrect.h:781
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
std::ostream & operator<<(std::ostream &out, const ossimQuadTreeWarpVertex &rhs)
ossimQuadTreeWarpVertex * findClosestVertex(ossimDpt &position)
ossim_uint32 getNumberOfSubstringKeys(const ossimString &regularExpression) const
bool isOnEdge(ossimQuadTreeWarpNode *node, const ossimDpt &point) const
ossim_float64 width() const
Definition: ossimDrect.h:522
ossimQuadTreeWarpNode * theTree
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Represents serializable keyword/value map.
void removeChild(ossimQuadTreeWarpNode *node)
static const char * LR_X_KW
ossim_uint32 y
const char * find(const char *key) const
bool saveState(ossimKeywordlist &kwl, const char *prefix) const
const ossimDpt & ul() const
Definition: ossimDrect.h:339
bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
double y
Definition: ossimDpt.h:165
static ossimString toString(bool aValue)
Numeric to string methods.
void updateDelta(ossimQuadTreeWarpVertex *v)
ossimQuadTreeWarpVertex * theLrVertex
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual void forward(const ossimDpt &pt, ossimDpt &result) const
void findAllNodes(std::vector< ossimQuadTreeWarpNode *> &result, const ossimDpt &pt)
void getShift(ossimDpt &result, const ossimDpt &pt) const
void split(const ossimDpt &point, double splitHoriCoefficient=0.0, double splitVertCoefficient=0.0)
const ossimDpt & getPosition() const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
void recursivePrint(std::ostream &out, ossimQuadTreeWarpNode *node) const
void setDelta(const ossimDpt &delta)
void pruneTree(ossimQuadTreeWarpNode *node)
bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
bool recursiveLoad(ossimQuadTreeWarpNode *node, const ossimKeywordlist &kwl, const char *prefix)
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
static const char * LR_Y_KW
static const char * UL_X_KW
void recursivePruneTree(ossimQuadTreeWarpNode *node)
bool toBool() const
String to numeric methods.
const ossimDpt & getDelta() const
unsigned int ossim_uint32
virtual ossimObject * dup() const
std::vector< ossimQuadTreeWarpNode * > theChildren
void removeVertex(ossimQuadTreeWarpVertex *v)
double toDouble() const
ossimQuadTreeWarpVertex * theUlVertex
const std::vector< ossimQuadTreeWarpVertex * > & getVertices() const
bool recursiveSave(ossimQuadTreeWarpNode *node, ossimKeywordlist &kwl, const char *prefix) const
static const char * UL_Y_KW
bool hasNans() const
Definition: ossimDrect.h:396
ossimQuadTreeWarpNode * findNode(const ossimDpt &pt)
ossimQuadTreeWarpVertex * theLlVertex
void getNewQuads(ossimQuadTreeWarpNode *parent, const ossimDrect &ul, const ossimDrect &ur, const ossimDrect &lr, const ossimDrect &ll, ossimQuadTreeWarpNode *&ulNode, ossimQuadTreeWarpNode *&urNode, ossimQuadTreeWarpNode *&lrNode, ossimQuadTreeWarpNode *&llNode)
#define DBL_EPSILON
ossimQuadTreeWarpVertex * getVertex(const ossimDpt &position)
ossimQuadTreeWarpVertex * theUrVertex
bool hasNans() const
Definition: ossimDpt.h:67
ossim_float64 height() const
Definition: ossimDrect.h:517
bool isOnPoint(ossimQuadTreeWarpNode *node, const ossimDpt &point) const
void create(const ossimDrect &boundingRect, const ossimDpt &ulShift=ossimDpt(0, 0), const ossimDpt &urShift=ossimDpt(0, 0), const ossimDpt &lrShift=ossimDpt(0, 0), const ossimDpt &llShift=ossimDpt(0, 0))
void recursiveDelete(ossimQuadTreeWarpNode *node)
ossimQuadTreeWarpVertex(const ossimDpt &position=ossimDpt(0, 0), const ossimDpt &delta=ossimDpt(0, 0))
bool loadState(const ossimKeywordlist &kwl, const char *prefix)
ossimDpt midPoint() const
Definition: ossimDrect.h:817
virtual ossimDpt getOrigin() const
void addSharedNode(ossimQuadTreeWarpNode *node)
const ossimDpt & ur() const
Definition: ossimDrect.h:340
ossimQuadTreeWarpVertex * findVertex(const ossimDpt &position)
double x
Definition: ossimDpt.h:164
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 removeSharedVertex(ossimQuadTreeWarpVertex *v)
ossimQuadTreeWarpNode * getRoot()
const ossimDpt & ll() const
Definition: ossimDrect.h:342
std::vector< ossimQuadTreeWarpVertex * > theVertexList
void getBounds(double &minx, double &miny, double &maxx, double &maxy) const
Definition: ossimDrect.h:372
RTTI_DEF1(ossimQuadTreeWarp, "ossimQuadTreeWarp", ossim2dTo2dTransform)
std::vector< ossimQuadTreeWarpNode * > theSharedNodeList
const ossimDpt & lr() const
Definition: ossimDrect.h:341
void setPosition(const ossimDpt &position)
void updateLockFlag(ossimQuadTreeWarpVertex *v)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
void setWarpEnabledFlag(bool flag)
virtual void printVertices(std::ostream &out) const