OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimImageGeometry.cpp
Go to the documentation of this file.
1 //**************************************************************************************************
2 //
3 // License: MIT
4 //
5 // Author: Oscar Kramer
6 //
7 // Description: Class implementation of ossimImageGeometry. See .h file for class documentation.
8 //
9 //**************************************************************************************************
10 // $Id$
11 
13 #include <ossim/base/ossimCommon.h>
14 #include <ossim/base/ossimDrect.h>
15 #include <ossim/base/ossimIrect.h>
16 #include <ossim/base/ossimGrect.h>
24 #include <cmath>
25 
26 RTTI_DEF1(ossimImageGeometry, "ossimImageGeometry", ossimObject);
27 
28 //**************************************************************************************************
29 // Default constructor defaults to unity transform with no projection
30 //**************************************************************************************************
32 :
33 m_transform (0),
34 m_projection(0),
35 m_decimationFactors(0),
36 m_imageSize(),
37 m_targetRrds(0)
38 {
40 }
41 
42 //**************************************************************************************************
43 // Copy constructor -- performs a deep copy. This is needed when an imageSource in the chain
44 // needs to modify the image geometry at that point in the chain. The image geometry to the left
45 // of that imageSource must remain unchanged. This constructor permits that imageSource to
46 // maintain its own geometry based on the input geometry. All objects in the chain and to the right
47 // would see this alternate geometry. See ossimScaleFilter for an example of this case.
48 //**************************************************************************************************
50 :
51 ossimObject(copy_this),
52 m_transform(copy_this.m_transform.valid()?(ossim2dTo2dTransform*)copy_this.m_transform->dup():((ossim2dTo2dTransform*)0)),
53 m_projection(copy_this.m_projection.valid()?(ossimProjection*)copy_this.m_projection->dup():(ossimProjection*)0),
54 m_decimationFactors(copy_this.m_decimationFactors),
55 m_imageSize(copy_this.m_imageSize),
56 m_targetRrds(copy_this.m_targetRrds)
57 {
58 }
59 
60 //**************************************************************************************************
63 //**************************************************************************************************
65 :
66 ossimObject(),
67 m_transform(transform),
68 m_projection(proj),
69 m_decimationFactors(0),
70 m_imageSize(),
71 m_targetRrds(0)
72 {
74 }
75 
76 //**************************************************************************************************
77 // Destructor is hidden. Only accessible via ossimRefPtr centrally managed
78 //**************************************************************************************************
80 {
81  // Nothing to do
82 }
83 
85 {
87  if (!handler.valid())
88  return false;
89 
91  if (!geom.valid())
92  return false;
93 
94  *this = *geom;
95  return true;
96 }
97 
98 void ossimImageGeometry::rnToRn(const ossimDpt& inRnPt, ossim_uint32 inResolutionLevel,
99  ossim_uint32 outResolutionLevel, ossimDpt& outRnPt) const
100 {
101  if (inResolutionLevel != outResolutionLevel)
102  {
103  // Back out the decimation.
104  ossimDpt pt;
105  undecimatePoint(inRnPt, inResolutionLevel, pt);
106 
107  // Decimate to new level.
108  decimatePoint(pt, outResolutionLevel, outRnPt);
109  }
110  else
111  {
112  outRnPt = inRnPt; // No transform required.
113  }
114 }
115 
117  ossim_uint32 resolutionLevel,
118  ossimDpt& fullPt) const
119 {
120  // Back out the decimation.
121  ossimDpt localPt;
122  undecimatePoint(rnPt, resolutionLevel, localPt);
123 
124  // Remove any shift/rotation.
125  if ( m_transform.valid() && !localPt.hasNans() )
126  {
127  m_transform->forward(localPt, fullPt);
128  }
129  else
130  {
131  fullPt = localPt; // No transform (shift/rotation)
132  }
133 }
134 
136  ossim_uint32 resolutionLevel,
137  ossimDpt& rnPt) const
138 {
139  // Apply shift/rotation.
140  ossimDpt localPt;
141  if (m_transform.valid())
142  {
143  m_transform->inverse(fullPt, localPt);
144  }
145  else
146  {
147  localPt = fullPt; // No transform (shift/rotation)
148  }
149 
150  // Apply the decimation.
151  decimatePoint(localPt, resolutionLevel, rnPt);
152 }
153 
155  ossim_uint32 resolutionLevel,
156  ossimGpt& wpt) const
157 {
158  ossimDpt localPt;
159  rnToRn(rnPt, resolutionLevel, m_targetRrds, localPt);
160  localToWorld(localPt, wpt);
161 }
162 
164  ossim_uint32 resolutionLevel,
165  ossimDpt& rnPt) const
166 {
167  ossimDpt localPt;
168  worldToLocal(wpt, localPt);
169  rnToRn(localPt, m_targetRrds, resolutionLevel, rnPt);
170 }
171 
172 //**************************************************************************************************
177 //**************************************************************************************************
178 bool ossimImageGeometry::localToWorld(const ossimDpt& local_pt, ossimGpt& world_pt) const
179 {
181  if (!m_projection.valid())
182  {
183  world_pt.makeNan();
184  return false;
185  }
186 
187  // First transform local pixel to full-image pixel:
188  ossimDpt full_image_pt;
189  rnToFull(local_pt, m_targetRrds, full_image_pt);
190 
191  // Perform projection to world coordinates:
192  m_projection->lineSampleToWorld(full_image_pt, world_pt);
193 
194 
195  // Put longitude between -180 and +180 and latitude between -90 and +90 if not so.
196  // world_pt.wrap();
197 
198  return true;
199 }
200 
201 bool ossimImageGeometry::localToWorld(const ossimDrect& local_rect, ossimGrect& world_rect) const
202 {
203  ossimGpt gp1, gp2, gp3, gp4;
204  if ( localToWorld(local_rect.ul(), gp1) && localToWorld(local_rect.ur(), gp2) &&
205  localToWorld(local_rect.lr(), gp3) && localToWorld(local_rect.ll(), gp4))
206  {
207  world_rect = ossimGrect(gp1, gp2, gp3, gp4);
208  return true;
209  }
210  return false;
211 }
212 
213 //**************************************************************************************************
217 //**************************************************************************************************
219  const double& h_ellipsoid,
220  ossimGpt& world_pt) const
221 {
223  if (!m_projection.valid())
224  {
225  world_pt.makeNan();
226  return false;
227  }
228 
229  // First transform local pixel to full-image pixel:
230  ossimDpt full_image_pt;
231  rnToFull(local_pt, m_targetRrds, full_image_pt);
232 
233  // Perform projection to world coordinates:
234  m_projection->lineSampleHeightToWorld(full_image_pt, h_ellipsoid, world_pt);
235 
236  // Put longitude between -180 and +180 and latitude between -90 and +90 if not so.
237  world_pt.wrap();
238 
239  return true;
240 }
241 
242 //**************************************************************************************************
246 //**************************************************************************************************
247 bool ossimImageGeometry::worldToLocal(const ossimGpt& world_pt, ossimDpt& local_pt) const
248 {
249  bool result = true;
250 
251  if ( m_projection.valid() )
252  {
253  //const ossimEquDistCylProjection* eqProj =
254  // dynamic_cast<const ossimEquDistCylProjection*>( m_projection.get() );
255 
256  ossimDpt full_image_pt;
257 
258  //***** GCP
259  // I am having major problems with the call and is messing up on Image that are edge to edge -180 to 180.
260  // It appears to wrap and think that the image is onl 1 pixel wide. I am commenting out for now
261  // until a better solution can be done for points that wrap. We need a general implementation that will work
262  // with any projector
263  //
264 
265  //if ( eqProj && (m_imageSize.hasNans() == false) )
266  // {
267  // Call specialized method to handle wrapping...
268  // eqProj->worldToLineSample( world_pt, m_imageSize, full_image_pt );
269  // }
270  // else if( isAffectedByElevation() )
271  if( isAffectedByElevation() )
272  {
273  ossimGpt copyPt( world_pt );
274  if(world_pt.isHgtNan())
275  {
277  }
278 
279  // Perform projection from world coordinates to full-image space:
280  m_projection->worldToLineSample(copyPt, full_image_pt);
281  }
282  else
283  {
284  // Perform projection from world coordinates to full-image space:
285  m_projection->worldToLineSample(world_pt, full_image_pt);
286  }
287 
288  // Transform to local space:
289  fullToRn(full_image_pt, m_targetRrds, local_pt);
290  }
291  else // No projection set:
292  {
293  local_pt.makeNan();
294  result = false;
295  }
296 
297  return result;
298 
299 } // End: ossimImageGeometry::worldToLocal(const ossimGpt&, ossimDpt&)
300 
301 bool ossimImageGeometry::worldToLocal(const ossimGrect& world_rect, ossimDrect& local_rect) const
302 {
303  ossimDpt dp1, dp2, dp3, dp4;
304  if ( worldToLocal(world_rect.ul(), dp1) && worldToLocal(world_rect.ur(), dp2) &&
305  worldToLocal(world_rect.lr(), dp3) && worldToLocal(world_rect.ll(), dp4))
306  {
307  local_rect = ossimDrect(dp1, dp2, dp3, dp4);
308  return true;
309  }
310  return false;
311 }
312 
313 //**************************************************************************************************
315 //**************************************************************************************************
317 {
318  m_transform = transform;
319 }
320 
321 //**************************************************************************************************
323 //**************************************************************************************************
325 {
326  m_projection = projection;
327 }
328 
329 //**************************************************************************************************
331 //**************************************************************************************************
333 {
334  if (m_projection.valid())
336  return false;
337 }
338 
339 //*************************************************************************************************
342 //*************************************************************************************************
344 {
345  ossimDpt gsd;
346  getMetersPerPixel(gsd);
347  return gsd;
348 }
349 
350 //*************************************************************************************************
353 //*************************************************************************************************
355 {
356  if (m_projection.valid() && !m_transform.valid())
357  {
358  // No transform present, so simply query the projection for GSD:
360  }
361  else if (m_projection.valid() && (m_imageSize.hasNans() == false))
362  {
363  // A transform is involved, so need to use localToWorld call below:
364  ossimDpt pL0 (m_imageSize/2);
365  ossimDpt pLx (pL0.x+1, pL0.y);
366  ossimDpt pLy (pL0.x, pL0.y+1);
367  ossimGpt g0, gx, gy;
368 
369  localToWorld(pL0, g0);
370  localToWorld(pLx, g0.height(), gx);
371  localToWorld(pLy, g0.height(), gy);
372 
373  // Compute horizontal distance for one pixel:
374  gsd.x = g0.distanceTo(gx);
375  gsd.y = g0.distanceTo(gy);
376  }
377  else
378  {
379  // This object is not fully initialized:
380  gsd.makeNan();
381  }
382 }
383 
384 //*************************************************************************************************
385 // Returns the resolution of this image in degrees/pixel. Note that this only
386 // makes sense if there is a projection associated with the image. Returns NaNs if no
387 // projection defined.
388 //*************************************************************************************************
390 {
391  ossimDpt dpp;
392  getDegreesPerPixel(dpp);
393  return dpp;
394 }
395 
396 //*************************************************************************************************
397 // Computes the resolution of this image in degrees/pixel. Note that this only
398 // makes sense if there is a projection associated with the image. Returns NaNs if no
399 // projection defined.
400 //*************************************************************************************************
402 {
403  const ossimMapProjection *map_proj = dynamic_cast<const ossimMapProjection *>(m_projection.get());
404  if (map_proj && !m_transform.valid())
405  {
406  // No transform present, so simply query the projection for resolution:
407  dpp = map_proj->getDecimalDegreesPerPixel();
408  }
409  else if (m_projection.valid() && (m_imageSize.hasNans() == false))
410  {
411  // A transform is involved, so need to use localToWorld call below:
412  ossimDpt pL0 (m_imageSize/2);
413  ossimDpt pLx (pL0.x+1, pL0.y);
414  ossimDpt pLy (pL0.x, pL0.y+1);
415  ossimGpt g0, gx, gy;
416 
417  localToWorld(pL0, g0);
418  localToWorld(pLx, g0.height(), gx);
419  localToWorld(pLy, g0.height(), gy);
420 
421  // Compute horizontal distance for one pixel:
422  double dlatx = std::fabs(g0.lat - gx.lat);
423  double dlaty = std::fabs(g0.lat - gy.lat);
424  double dlonx = std::fabs(g0.lon - gx.lon);
425  double dlony = std::fabs(g0.lon - gy.lon);
426  dpp.lat = sqrt(dlatx*dlatx + dlaty*dlaty);
427  dpp.lon = sqrt(dlonx*dlonx + dlony*dlony);
428  }
429  else
430  {
431  // This object is not fully initialized:
432  dpp.makeNan();
433  }
434 }
435 
436 //**************************************************************************************************
438 //**************************************************************************************************
440 {
441  out << "type: ossimImageGeometry" << std::endl;
442  if(m_transform.valid())
443  {
444  out << " m_transform: ";
445  m_transform->print(out);
446  }
447  else
448  {
449  out << " No transform defined. Using identity transform.\n";
450  }
451 
452  if(m_projection.valid())
453  {
454  out << " m_projection: ";
455  m_projection->print(out);
456  }
457  else
458  {
459  out << " No projection defined. ";
460  }
461 
462  for ( std::vector<ossimDpt>::size_type i = 0; i < m_decimationFactors.size(); ++i )
463  {
464  cout << "m_decimationFactors[" << i << "]: " << m_decimationFactors[i] << "\n";
465  }
466 
467  out << "m_imageSize: " << m_imageSize
468  << "\nm_targetRrds: " << m_targetRrds << "\n";
469 
470  return out;
471 }
472 
473 //**************************************************************************************************
476 //**************************************************************************************************
478 {
479  return ((m_transform == other.m_transform) && (m_projection == other.m_projection) &&
480  (decimationFactor(0) == other.decimationFactor(0)) );
481 }
482 
483 //**************************************************************************************************
488 //**************************************************************************************************
490 {
492  if (size)
493  {
494  if (r_index < size)
495  {
496  return m_decimationFactors[r_index];
497  }
498 
499  // Return the last defined decimation if the index requested exceeds list size:
500  return m_decimationFactors[size-1];
501  }
502 
503  // Compute the decimation factor:
504  ossim_float64 factor = 1.0/(ossim_float64)(1 << r_index);
505 
506  return ossimDpt(factor, factor);
507 }
508 
510  ossimDpt& result) const
511 {
512  const ossim_uint32 SIZE = (ossim_uint32)m_decimationFactors.size();
513  if (SIZE)
514  {
515  if (r_index < SIZE)
516  {
517  result = m_decimationFactors[r_index];
518  }
519  else
520  {
521  //---
522  // Return the last defined decimation if the index requested
523  // exceeds list size:
524  //---
525  result = m_decimationFactors[SIZE-1];
526  }
527  }
528  else
529  {
530  // Compute the decimation factor:
531  ossim_float64 factor = 1.0/(ossim_float64)(1 << r_index);
532  result.x = factor;
533  result.y = factor;
534  }
535 }
536 
538  std::vector<ossimDpt>& decimations) const
539 {
540  decimations = m_decimationFactors;
541 }
542 
543 //*****************************************************************************
546 //*****************************************************************************
548  const char* prefix)
549 {
550  const char* lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
551  if (lookup)
552  {
554  {
555  ossimObject::loadState(kwl, prefix);
556 
557  // m_transform
558  ossimString transformPrefix = ossimString(prefix) + "transform.";
560  createNativeObjectFromRegistry(kwl, transformPrefix.c_str());
561  if( transform.valid() )
562  {
563  m_transform = transform;
564  }
565 
566  // m_projection:
567  ossimString projectionPrefix = ossimString(prefix) + "projection.";
569  createProjection(kwl, projectionPrefix.c_str());
570  if( projection.valid() )
571  {
572  m_projection = projection;
573  }
574 
575  // m_decimationFactors:
576  ossimString decimations = kwl.find(prefix, "decimations");
577  if( decimations.size() )
578  {
579  m_decimationFactors.clear();
580  ossim::toVector(m_decimationFactors, decimations);
581  }
582 
583  // m_imageSize:
584  ossimString imageSize = kwl.find(prefix, "image_size");
585  if( imageSize.size() )
586  {
587  m_imageSize.toPoint(imageSize);
588  }
589 
590  // m_targetRrds:
591  ossimString targetRrds = kwl.find(prefix, "target_rrds");
592  if ( targetRrds.size() )
593  {
594  m_targetRrds = ossimString(targetRrds).toUInt32();
595  }
596  }
597  else
598  {
599  // Now look for projection spec (for backwards compatibility):
601  createProjection(kwl, prefix);
602  if (projection)
603  {
604  setProjection(projection);
605  }
606  }
607  }
608  else
609  {
610  //---
611  // Old geometry file with no type keyword:
612  //---
614  createProjection(kwl, prefix);
615  if (projection)
616  {
617  setProjection(projection);
618  }
619  }
620 
621  return true;
622 }
623 
624 //**************************************************************************************************
626 //**************************************************************************************************
627 bool ossimImageGeometry::saveState(ossimKeywordlist& kwl, const char* prefix) const
628 {
629  bool good_save = true;
630 
631  // m_transform:
632  if (m_transform.valid())
633  {
634  ossimString transformPrefix = ossimString(prefix) + "transform.";
635  good_save = m_transform->saveState(kwl, transformPrefix.c_str());
636  }
637 
638  // m_projection:
639  if (m_projection.valid())
640  {
641  ossimString projectionPrefix = ossimString(prefix) + "projection.";
642  good_save &= m_projection->saveState(kwl, projectionPrefix.c_str());
643  }
644 
645  // m_gsd:
646  ossimDpt gsd;
647  getMetersPerPixel(gsd);
648  kwl.add(prefix, "gsd", gsd.toString(), true);
649 
650  // m_decimationFactors:
651  if(m_decimationFactors.size())
652  {
653  ossimString resultPoints;
655  kwl.add(prefix, "decimations", resultPoints, true);
656  }
657  else
658  {
659  kwl.add(prefix, "decimations", "", true);
660  }
661 
662  // m_imageSize:
663  kwl.add(prefix, "image_size", m_imageSize.toString(), true);
664 
665  // m_targetRrds;
666  kwl.add(prefix, "target_rrds", m_targetRrds, true);
667 
668  // Base class:
669  good_save &= ossimObject::saveState(kwl, prefix);
670 
671  return good_save;
672 }
673 
675 {
676  m_targetRrds = rrds;
677 }
678 
680 {
681  return m_targetRrds;
682 }
683 
684 //**************************************************************************************************
686 //**************************************************************************************************
688 {
689  if (this != &copy_this)
690  {
691  // Get deep copy of 2D transform if one exists:
692  if (copy_this.m_transform.valid())
693  {
695  }
696 
697  // Now establish a deep copy of the projection, if any:
698  if (copy_this.m_projection.valid())
699  {
700  m_projection = (ossimProjection*) copy_this.m_projection->dup();
701  }
702 
703  // the Gsd should already be solved from the source we are copying from
704  m_imageSize = copy_this.m_imageSize;
706  m_targetRrds = copy_this.m_targetRrds;
707  }
708  return *this;
709 }
710 
711 //**************************************************************************************************
713 //**************************************************************************************************
715  ossimGpt& glr, ossimGpt& gll) const
716 {
717  ossimDpt iul (0,0);
718  ossimDpt iur (m_imageSize.x-1, 0);
719  ossimDpt ilr (m_imageSize.x-1, m_imageSize.y-1);
720  ossimDpt ill (0, m_imageSize.y-1);
721 
722  bool status = true;
723 
724  status &= localToWorld(iul, gul);
725  status &= localToWorld(iur, gur);
726  status &= localToWorld(ilr, glr);
727  status &= localToWorld(ill, gll);
728 
729  return status;
730 }
731 
732 void ossimImageGeometry::getTiePoint(ossimGpt& tie, bool edge) const
733 {
734  ossimGrect grect;
735  getBoundingGroundRect(grect);
736  if ( m_projection.valid() && (m_imageSize.hasNans() == false) )
737  {
738  // Use the easting/northing version of this method if underlying projection is meters:
739  const ossimMapProjection* map_proj =
740  dynamic_cast<const ossimMapProjection*>(m_projection.get());
741  if (map_proj)
742  {
743  if(!map_proj->isGeographic())
744  {
745  ossimDpt enTie;
746  getTiePoint(enTie, edge);
747  if (!enTie.hasNans())
748  tie = m_projection->inverse(enTie);
749  else
750  tie.makeNan();
751  }
752  else
753  {
754  tie = grect.ul();
755  if(edge)
756  {
757  ossimDpt half_pixel_shift = map_proj->getDecimalDegreesPerPixel() * 0.5;
758  tie.lat += half_pixel_shift.y;
759  tie.lon -= half_pixel_shift.x;
760  }
761  }
762  }
763  else
764  {
765 
766  // must be a sensor model so we will set to the upper left bounds of the image
767  tie = grect.ul();
768 // std::cout << "GRECT ======= " << grect << "\n";
769 // std::cout << m_projection->getClassName() << std::endl;
770 // ossimDpt pt = m_projection->forward( tie );
771 // std::cout << "FORWARD:" <<pt << std::endl;
772  }
773  }
774 
775 
776 #if 0
777  // std::cout << "GRECT ======= " << grect << "\n";
778  if ( m_projection.valid() && (m_imageSize.hasNans() == false) )
779  {
780  // Use the easting/northing version of this method if underlying projection is meters:
781  const ossimMapProjection* map_proj =
782  dynamic_cast<const ossimMapProjection*>(m_projection.get());
783  if (map_proj && !map_proj->isGeographic())
784  {
785  ossimDpt enTie;
786  getTiePoint(enTie, edge);
787  if (!enTie.hasNans())
788  tie = m_projection->inverse(enTie);
789  else
790  tie.makeNan();
791  return; // return here only because it bugs Dave
792  }
793 
794  // Use projection to ground to establish UL extreme of image:
795  ossimDpt iul (0,0);
796  ossimDpt iur (m_imageSize.x-1, 0);
797  ossimDpt ilr (m_imageSize.x-1, m_imageSize.y-1);
798  ossimDpt ill (0, m_imageSize.y-1);
799  ossimDpt iRight(1, 0);
800  ossimDpt iDown(0, 1);
801 
802  ossimGpt gul;
803  ossimGpt gur;
804  ossimGpt glr;
805  ossimGpt gll;
806  ossimGpt gRight;
807  ossimGpt gDown;
808 
809  localToWorld(iul, gul);
810  localToWorld(iur, gur);
811  localToWorld(ilr, glr);
812  localToWorld(ill, gll);
813  localToWorld(iRight, gRight);
814  localToWorld(iDown, gDown);
815 
816  std::cout << "gul: " << gul << "\n"
817  << "gur: " << gur << "\n"
818  << "glr: " << glr << "\n"
819  << "gll: " << gll << "\n"
820  << "gRight: " << gRight << "\n"
821  << "gDown: " << gDown << "\n";
822  // Determine the direction of the image:
823  if ( gul.lat > gDown.lat ) // oriented north up
824  {
825  if ( gul.lat >= gRight.lat ) // straight up or leaning right
826  {
827  std::cout << "ONE\n";
828  tie.lat = gul.lat;
829  tie.lon = gll.lon;
830  }
831  else // leaning left
832  {
833  std::cout << "TWO\n";
834  tie.lat = gur.lat;
835  tie.lon = gul.lon;
836  }
837  }
838  else // south or on side
839  {
840  if ( gRight.lat >= gul.lat ) // straight down or leaning right
841  {
842  std::cout << "THREE\n";
843  tie.lat = glr.lat;
844  tie.lon = gur.lon;
845  }
846  else // leaning left
847  {
848  std::cout << "FOUR\n";
849  tie.lat = gll.lat;
850  tie.lon = glr.lon;
851  }
852  }
853  std::cout << "TIE BEFORE ==== " << tie << "\n";
854 
855  if ( edge )
856  {
857  ossimDpt pt = m_projection->forward( tie );
858  ossimDpt half_pixel_shift = m_projection->getMetersPerPixel() * 0.5;
859  pt.y += half_pixel_shift.y;
860  pt.x -= half_pixel_shift.x;
861  tie = m_projection->inverse( pt );
862  }
863 
864  std::cout << "TIE ==== " << tie << "\n";
865  } // if ( (m_imageSize.hasNans() == false) && m_projection.valid() )
866  else
867  {
868  tie.lat = ossim::nan();
869  tie.lon = ossim::nan();
870  }
871 #endif
872 }
873 
874 //**************************************************************************************************
875 // Assigns tie to the UL easting northing of the image. If edge is true, the E/N will be for the
876 // pixel-is-area representation
877 //**************************************************************************************************
878 void ossimImageGeometry::getTiePoint(ossimDpt& tie, bool edge) const
879 {
881  {
882  tie.makeNan();
883  return; // return here only because it bugs Dave
884  }
885 
886  // Use the geographic version of this method if underlying projection is NOT map in meters:
887  const ossimMapProjection* map_proj = dynamic_cast<const ossimMapProjection*>(m_projection.get());
888  if (!map_proj || map_proj->isGeographic())
889  {
890  // Use the geographic version of this method to establish UL:
891  ossimGpt gTie;
892  gTie.hgt = 0.0;
893  getTiePoint(gTie, edge);
894  if (!gTie.hasNans())
895  tie = m_projection->forward( gTie );
896  else
897  tie.makeNan();
898  return; // return here only because it bugs Dave
899  }
900 
901  // The underlying projection is a proper map projection in meters. Use easting northing
902  // directly to avoid shifting the UL tiepoint because of skewed edge in geographic. Note:
903  // assume the image is North up:
904  ossimDpt iul (0,0);
905  ossimDpt ful;
906  rnToFull(iul, 0, ful);
907  map_proj->lineSampleToEastingNorthing(ful, tie);
908  if (edge && !tie.hasNans())
909  {
910  // Shift from pixel-is-point to pixel-is-area
911  ossimDpt half_pixel_shift = map_proj->getMetersPerPixel() * 0.5;
912  tie.y += half_pixel_shift.y;
913  tie.x -= half_pixel_shift.x;
914  }
915 }
916 
917 //**************************************************************************************************
919  ossim_uint32 resolutionLevel,
920  ossimDpt& outPt) const
921 {
922  // Back out the decimation.
923  ossimDpt decimation = decimationFactor(resolutionLevel);
924 
925  //---
926  // If no nans and one or both of the factors is not 1.0 decimation should
927  // be applied.
928  //---
929  if ( (decimation.x != 1.0) || (decimation.y != 1.0) )
930  {
931  if ( !decimation.hasNans() && !rnPt.hasNans() )
932  {
933  outPt.x = rnPt.x * (1.0/decimation.x);
934  outPt.y = rnPt.y * (1.0/decimation.y);
935  }
936  else
937  {
938  outPt.makeNan();
939  }
940  }
941  else
942  {
943  outPt = rnPt; // No decimation.
944  }
945 }
946 
947 //**************************************************************************************************
949  ossim_uint32 resolutionLevel,
950  ossimDpt& rnPt) const
951 {
952 
953  // Apply the decimation.
954  ossimDpt decimation = decimationFactor(resolutionLevel);
955 
956  //---
957  // If no nans and one or both of the factors is not 1.0 decimation should
958  // be applied.
959  //---
960  if ( (decimation.x != 1.0) || (decimation.y != 1.0) )
961  {
962  if ( !decimation.hasNans() && !inPt.hasNans() )
963  {
964  rnPt.x = inPt.x * decimation.x;
965  rnPt.y = inPt.y * decimation.y;
966  }
967  else
968  {
969  rnPt.makeNan();
970  }
971  }
972  else
973  {
974  rnPt = inPt; // No decimation.
975  }
976 }
977 
979 {
980  bool result = ossimObject::isEqualTo(obj, compareType);
981  const ossimImageGeometry* rhs = dynamic_cast<const ossimImageGeometry*> (&obj);
982  if(rhs&&result) // we know the types are the same
983  {
984  result = ((m_decimationFactors.size() == rhs->m_decimationFactors.size())&&
986  (m_targetRrds == rhs->m_targetRrds));
987 
988  if(result)
989  {
990  ossim_uint32 decimationIdx = 0;
991  for(decimationIdx = 0; result&&(decimationIdx < m_decimationFactors.size());++decimationIdx)
992  {
993  result = m_decimationFactors[decimationIdx].isEqualTo(rhs->m_decimationFactors[decimationIdx]);
994  }
995  }
996 
997  if(result && compareType==OSSIM_COMPARE_IMMEDIATE)
998  {
999  result = ((m_transform.get() == rhs->m_transform.get())&&
1000  (m_projection.get() == rhs->m_projection.get()));
1001 
1002  }
1003  else
1004  {
1005  if(m_transform.valid()&&rhs->m_transform.valid())
1006  {
1007  result = m_transform->isEqualTo(*rhs->m_transform.get());
1008  }
1009  else if(reinterpret_cast<ossim_uint64>(m_transform.get()) | reinterpret_cast<ossim_uint64>(rhs->m_transform.get())) // one is null
1010  {
1011  result = false;
1012  }
1013  if(m_projection.valid()&&rhs->m_projection.valid())
1014  {
1015  result = m_projection->isEqualTo(*rhs->m_projection.get());
1016  }
1017  else if(reinterpret_cast<ossim_uint64>(m_projection.get()) | reinterpret_cast<ossim_uint64>(rhs->m_projection.get())) // one is null
1018  {
1019  result = false;
1020  }
1021 
1022  }
1023  }
1024  return result;
1025 }
1026 
1028 {
1029  bool result = false;
1030  ossimIrect rect;
1031  ossimGpt ul;
1032  ossimGpt ur;
1033  ossimGpt lr;
1034  ossimGpt ll;
1035  ossimGpt center;
1036  ossimGpt wgs84;
1037 
1038  getBoundingRect(rect);
1039 
1040  localToWorld(rect.ul(), ul);
1041  localToWorld(rect.ur(), ur);
1042  localToWorld(rect.lr(), lr);
1043  localToWorld(rect.ll(), ll);
1044  localToWorld(rect.midPoint(), center);
1045 
1046  if(ul.isLonNan()||ur.isLonNan()||lr.isLonNan()||ll.isLonNan()||center.isLonNan())
1047  {
1048  return result;
1049  }
1050  else
1051  {
1052  ul.changeDatum(wgs84.datum());
1053  ur.changeDatum(wgs84.datum());
1054  lr.changeDatum(wgs84.datum());
1055  ll.changeDatum(wgs84.datum());
1056  center.changeDatum(wgs84.datum());
1057  result = ( (fabs(center.lond()-ul.lond()) > 180.0) ||
1058  (fabs(center.lond()-ur.lond()) > 180.0) ||
1059  (fabs(center.lond()-lr.lond()) > 180.0) ||
1060  (fabs(center.lond()-ll.lond()) > 180.0) ||
1061  (fabs(ul.lond()) > 180.0) ||
1062  (fabs(ur.lond()) > 180.0) ||
1063  (fabs(lr.lond()) > 180.0) ||
1064  (fabs(ll.lond()) > 180.0)
1065 
1066  );
1067  }
1068 
1069  return result;
1070 }
1071 
1072 void ossimImageGeometry::getImageEdgePoints(std::vector<ossimDpt>& result, ossim_uint32 partitions)const
1073 {
1074 
1075  ossimDrect imageRect;
1076  getBoundingRect(imageRect);
1077  if(imageRect.hasNans())
1078  {
1079  // error out
1080  return;
1081  }
1082 
1083  // Make edge to edge.
1084  imageRect.expand( ossimDpt(0.5, 0.5) );
1085 
1086  result.clear();
1087  // First get the image points we will be transforming
1088  if(partitions > 2)
1089  {
1090  ossimDpt uli = imageRect.ul();
1091  ossimDpt uri = imageRect.ur();
1092  ossimDpt lri = imageRect.lr();
1093  ossimDpt lli = imageRect.ll();
1094 
1095  ossim_float32 stepSize = partitions;
1096  ossimDpt deltaUpper = (uri-uli)*(1.0/stepSize);
1097  ossimDpt deltaRight = (lri-uri)*(1.0/stepSize);
1098  ossimDpt deltaLower = (lli-lri)*(1.0/stepSize);
1099  ossimDpt deltaLeft = (uli-lli)*(1.0/stepSize);
1100 
1101  ossimDpt p;
1102  ossim_int32 idx = 0;
1103  ossimDpt initialPoint= uli;
1104  for(idx = 0; idx < stepSize;++idx)
1105  {
1106  result.push_back(initialPoint);
1107  initialPoint.x+=deltaUpper.x;
1108  initialPoint.y+=deltaUpper.y;
1109  }
1110  initialPoint= uri;
1111  for(idx = 0; idx < stepSize;++idx)
1112  {
1113  result.push_back(initialPoint);
1114  initialPoint.x+=deltaRight.x;
1115  initialPoint.y+=deltaRight.y;
1116  }
1117 
1118  initialPoint= lri;
1119  for(idx = 0; idx < stepSize;++idx)
1120  {
1121  result.push_back(initialPoint);
1122  initialPoint.x+=deltaLower.x;
1123  initialPoint.y+=deltaLower.y;
1124  }
1125 
1126  initialPoint= lli;
1127  for(idx = 0; idx < stepSize;++idx)
1128  {
1129  result.push_back(initialPoint);
1130  initialPoint.x+=deltaLeft.x;
1131  initialPoint.y+=deltaLeft.y;
1132  }
1133  }
1134  else // If not enough partitions then we will just use the corners
1135  {
1136  result.resize(4);
1137 
1138  result[0] = imageRect.ul();
1139  result[1] = imageRect.ur();
1140  result[2] = imageRect.lr();
1141  result[3] = imageRect.ll();
1142  }
1143 
1144 }
1145 
1147 {
1148  std::vector<ossimDpt> points;
1149  std::vector<ossimGpt> gPoints;
1150  std::vector<ossimPolygon> polyList;
1151  ossimDrect imageRect;
1152  ossimGpt cg;
1153  ossimDrect worldRect(ossimDpt(-180,-90),
1154  ossimDpt(-180,90),
1155  ossimDpt(180,90),
1156  ossimDpt(180,-90));
1157  getBoundingRect(imageRect);
1158  // bool affectedByElevation = isAffectedByElevation();
1160  result.clear();
1161  if(imageRect.hasNans())
1162  {
1163  // error out
1164  return;
1165  }
1166  localToWorld(imageRect.midPoint(), cg);
1167  if(cg.isLatNan() || cg.isLonNan())
1168  {
1169  return;
1170  }
1171  ossim_int32 sgn = static_cast<ossim_int32>(
1172  ossim::sgn(cg.lond()));
1173 
1174  getImageEdgePoints(points, partitions);
1175  if(points.empty())
1176  {
1177  return;
1178  }
1179 
1180  if(crossesDateline)
1181  {
1182  for(std::vector<ossimDpt>::const_iterator iter=points.begin();
1183  iter != points.end();
1184  ++iter)
1185  {
1186  ossimGpt testGpt;
1187  localToWorld(*iter, testGpt);
1188 
1189  if(!testGpt.isLatNan()&&!testGpt.isLonNan())
1190  {
1191  bool needToShift =( (std::fabs(testGpt.lond()-cg.lond()) > 180.0)||
1192  (std::fabs(testGpt.lond()>180.0)) );
1193  if(needToShift)
1194  {
1195  testGpt.lond(testGpt.lond()+sgn*360);
1196  }
1197  gPoints.push_back(testGpt);
1198  }
1199  }
1200  // now clip the ground list to the full ground rect
1201  //
1202  ossimPolygon tempPoly(gPoints);
1203  tempPoly.clipToRect(polyList, worldRect);
1204  for(std::vector<ossimPolygon>::const_iterator iter = polyList.begin();
1205  iter!=polyList.end();++iter)
1206  {
1207  result.add(ossimPolyArea2d(*iter));
1208  }
1209  // now shift gpoints to the other side
1210  //
1211  for(std::vector<ossimGpt>::iterator iter = gPoints.begin();
1212  iter != gPoints.end();
1213  ++iter)
1214  {
1215  (*iter).lond((*iter).lond()+(-sgn*360));
1216  }
1217  tempPoly = gPoints;
1218  polyList.clear();
1219  tempPoly.clipToRect(polyList, worldRect);
1220  for(std::vector<ossimPolygon>::const_iterator iter = polyList.begin();
1221  iter!=polyList.end();++iter)
1222  {
1223  result.add(ossimPolyArea2d(*iter));
1224  }
1225  }
1226  else
1227  {
1228  for(std::vector<ossimDpt>::const_iterator iter=points.begin();
1229  iter != points.end();++iter)
1230  {
1231  ossimGpt testGpt;
1232  localToWorld(*iter, testGpt);
1233 
1234  if(!testGpt.isLatNan()&&!testGpt.isLonNan())
1235  {
1236  gPoints.push_back(testGpt);
1237  }
1238  }
1239  result.add(ossimPolygon(gPoints));
1240  }
1241  if(!result.isValid()) result.setToBufferedShape();
1242 }
1243 
1244 
1246 {
1247  if (m_imageSize.hasNans())
1248  {
1249  bounding_rect.makeNan();
1250  }
1251  else
1252  {
1253  bounding_rect.set_ulx(0);
1254  bounding_rect.set_uly(0);
1255  bounding_rect.set_lrx(m_imageSize.x-1);
1256  bounding_rect.set_lry(m_imageSize.y-1);
1257  }
1258 }
1259 
1261 {
1262  if (m_imageSize.hasNans())
1263  {
1264  bounding_rect.makeNan();
1265  }
1266  else
1267  {
1268  bounding_rect.set_ulx(0);
1269  bounding_rect.set_uly(0);
1270  bounding_rect.set_lrx(m_imageSize.x-1);
1271  bounding_rect.set_lry(m_imageSize.y-1);
1272  }
1273 }
1274 
1276 {
1277  ossimGpt ul, ur, lr, ll;
1278  getCornerGpts(ul, ur, lr, ll);
1279  bounding_grect.ul().lat = ul.lat > ur.lat ? ul.lat : ur.lat;
1280  bounding_grect.ul().lon = ul.lon < ll.lon ? ul.lon : ll.lon;
1281  bounding_grect.lr().lat = ll.lat < lr.lat ? ll.lat : lr.lat;
1282  bounding_grect.lr().lon = ur.lon > lr.lon ? ur.lon : lr.lon;
1283 }
1284 
1285 void ossimImageGeometry::applyScale(const ossimDpt& scale, bool recenterTiePoint)
1286 {
1287  if ((scale.x != 0.0) && (scale.y != 0.0))
1288  {
1289  ossimMapProjection* map_Proj = dynamic_cast<ossimMapProjection*>(m_projection.get());
1290  if ( map_Proj )
1291  {
1292  m_imageSize.x = ossim::round<ossim_int32>(m_imageSize.x / scale.x);
1293  m_imageSize.y = ossim::round<ossim_int32>(m_imageSize.y / scale.y);
1294  map_Proj->applyScale(scale, recenterTiePoint);
1295  }
1296  }
1297 }
1298 
1300 {
1302 }
1303 
1305 {
1306  return dynamic_cast<const ossimAdjustableParameterInterface*>(getProjection());
1307 
1308 }
1309 
1311  const ossimGpt& gpt,
1312  ossim_uint32 idx,
1313  ossim_float64 paramDelta)
1314 {
1315  double den = 0.5/paramDelta; // this is the same as dividing by 2*delta
1316 
1317  result = ossimDpt(0.0,0.0);
1319 
1320  if(!adjustableParamInterface) return false;
1321  if(idx >= adjustableParamInterface->getNumberOfAdjustableParameters()) return false;
1322 
1323  ossimDpt p1, p2;
1324  // double middle = adjustableParamInterface->getAdjustableParameter(idx);
1325  double middle = adjustableParamInterface->getParameterCenter(idx);
1326 
1327  //set parm to high value
1328  // adjustableParamInterface->setAdjustableParameter(idx, middle + paramDelta, true);
1329  adjustableParamInterface->setParameterCenter(idx, middle + paramDelta, true);
1330  worldToLocal(gpt, p1);
1331 
1332  //set parm to low value and gte difference
1333  // adjustableParamInterface->setAdjustableParameter(idx, middle - paramDelta, true);
1334  adjustableParamInterface->setParameterCenter(idx, middle - paramDelta, true);
1335  worldToLocal(gpt, p2);
1336 
1337  //get partial derivative
1338  result = (p2-p1)*den;
1339 
1340  //reset param
1341  // adjustableParamInterface->setAdjustableParameter(idx, middle, true);
1342  adjustableParamInterface->setParameterCenter(idx, middle, true);
1343 
1344  return !result.hasNans();
1345 }
1346 
1348  const ossimGpt& gpt,
1349  ossim_float64 paramDelta)
1350 {
1352 
1353  ossim_uint32 nAdjustables = adjustableParamInterface->getNumberOfAdjustableParameters();
1354 
1355  ossim_uint32 idx = 0;
1356 
1357  result = NEWMAT::Matrix(nAdjustables, 2);
1358  for(;idx < nAdjustables; ++idx)
1359  {
1360  ossimDpt paramResResult;
1362  gpt,
1363  idx,
1364  paramDelta);
1365  result[idx][0] = paramResResult.x;
1366  result[idx][1] = paramResResult.y;
1367  }
1368 
1369  return true;
1370 }
1371 
1373  const ossimGpt& gpt,
1374  const DeltaParamList& deltas)
1375 {
1376 
1378 
1379  ossim_uint32 nAdjustables = adjustableParamInterface->getNumberOfAdjustableParameters();
1380 
1381  if(nAdjustables != deltas.size()) return false;
1382  ossim_uint32 idx = 0;
1383 
1384  result = NEWMAT::Matrix(nAdjustables, 2);
1385  for(;idx < nAdjustables; ++idx)
1386  {
1387  ossimDpt paramResResult;
1389  gpt,
1390  idx,
1391  deltas[idx]);
1392  // ROWxCOL
1393  result[idx][0] = paramResResult.x;
1394  result[idx][1] = paramResResult.y;
1395  }
1396 
1397  return true;
1398 }
1399 
1401  const ossimGpt& gpt,
1402  const ossimDpt3d& deltaLlh)
1403 {
1404  if(!getProjection()) return false;
1405  ossimDpt p1;
1406  ossimDpt p2;
1407 
1408  ossimDpt deltaWithRespectToLon;
1409  ossimDpt deltaWithRespectToLat;
1410  ossimDpt deltaWithRespectToH;
1411  ossim_float64 h = ossim::isnan(gpt.height())?0.0:gpt.height();
1412 
1413  // do the change in lon first for the dx, dy
1414  //
1415  worldToLocal(ossimGpt(gpt.latd(), gpt.lond()+deltaLlh.x, h, gpt.datum()), p1);
1416  worldToLocal(ossimGpt(gpt.latd(), gpt.lond()-deltaLlh.x, h, gpt.datum()), p2);
1417 
1418  double den = 0.5/deltaLlh.x; // this is the same as dividing by 2*delta
1419  deltaWithRespectToLon = (p2-p1)*den;
1420 
1421 
1422  // do the change in lat for the dx, dy
1423  //
1424  worldToLocal(ossimGpt(gpt.latd()+deltaLlh.y, gpt.lond(), h, gpt.datum()), p1);
1425  worldToLocal(ossimGpt(gpt.latd()-deltaLlh.y, gpt.lond(), h, gpt.datum()), p2);
1426 
1427  den = 0.5/deltaLlh.y; // this is the same as dividing by 2*delta
1428  deltaWithRespectToLat = (p2-p1)*den;
1429 
1430 
1431  // do the change in height first for the dx, dy
1432  //
1433  worldToLocal(ossimGpt(gpt.latd(), gpt.lond(), h+deltaLlh.z, gpt.datum()), p1);
1434  worldToLocal(ossimGpt(gpt.latd(), gpt.lond(), h-deltaLlh.z, gpt.datum()), p2);
1435 
1436  den = 0.5/deltaLlh.z; // this is the same as dividing by 2*delta
1437  deltaWithRespectToH = (p2-p1)*den;
1438 
1439 
1440  result = NEWMAT::Matrix(3,2);
1441 
1442  // set the matrix
1443  //
1444  result[1][0] = deltaWithRespectToLon.x*DEG_PER_RAD;
1445  result[1][1] = deltaWithRespectToLon.y*DEG_PER_RAD;
1446  result[0][0] = deltaWithRespectToLat.x*DEG_PER_RAD;
1447  result[0][1] = deltaWithRespectToLat.y*DEG_PER_RAD;
1448  result[2][0] = deltaWithRespectToH.x;
1449  result[2][1] = deltaWithRespectToH.y;
1450 
1451 
1452  return true;
1453 }
1454 
1456  const ossimGpt& gpt)
1457 {
1458  ossimDpt mpp = getMetersPerPixel();
1459  ossimGpt originPoint;
1460  ossim_float64 len = mpp.length();
1461 
1462  if(len > FLT_EPSILON)
1463  {
1464  ossim_float64 delta = originPoint.metersPerDegree().length();
1465 
1466  delta = len/delta;
1467 
1468  return computeGroundToImagePartials(result,
1469  gpt,
1470  ossimDpt3d(delta,
1471  delta,
1472  len));
1473  }
1474 
1475  return false;
1476 }
1477 
1478 
1480 {
1481  ossim_float64 result = ossim::nan();
1482 
1483  if ( m_projection.valid() )
1484  {
1486  {
1487  const int NUMBER_OF_SAMPLES = 9;
1488 
1489  // In meters. This is about a height of a 6 to 7 story building.
1490  const double ELEVATION_DISPLACEMENT = 20;
1491 
1492  ossimDrect bounds;
1493  getBoundingRect( bounds );
1494 
1495  if( !bounds.hasNans() )
1496  {
1497  // only need an average
1498  // so will keep the test close to the pixel location
1499  // we are sampling
1500  // let's get rid of the scale
1501  ossim_float64 widthPercent = 1;//bounds.width()*.1;
1502  ossim_float64 heightPercent = 1;//bounds.height()*.1;
1503 
1504  //---
1505  // Sanity check to make sure that taking 10 percent out on the image
1506  // gets us to at least 1 pixel away.
1507  //---
1508  // if(widthPercent < 1.0) widthPercent = 1.0;
1509  // if(heightPercent < 1.0) heightPercent = 1.0;
1510 
1511  // set up some work variables to help calculate the average partial
1512  //
1513  std::vector<ossimDpt> ipts(NUMBER_OF_SAMPLES);
1514  std::vector<ossimGpt> gpts(NUMBER_OF_SAMPLES);
1515  std::vector<ossimDpt> iptsDisplacement(NUMBER_OF_SAMPLES);
1516  std::vector<ossimDpt> partials(NUMBER_OF_SAMPLES);
1517  ossimDpt averageDelta(0.0,0.0);
1518  ossimDpt centerIpt = pt;
1519  if(centerIpt.hasNans())
1520  {
1521  centerIpt = bounds.midPoint();
1522  }
1523  //---
1524  // Lets take an average displacement about the center point (3x3 grid)
1525  // we will go 10 percent out of the width and height of the image and
1526  // look at the displacement at those points and average them we will
1527  // use the average displacement to compute the up is up rotation.
1528  //---
1529 
1530  // top row:
1531 
1532  // 45 degree left quadrant
1533  // RP - FIX POINTS IN FIRST ROW
1534  ipts[0] = centerIpt + ossimDpt(-widthPercent, -heightPercent);
1535  // 45 degree middle top
1536  ipts[1] = centerIpt + ossimDpt(0.0,heightPercent);
1537  // 45 degree right quadrant
1538  ipts[2] = centerIpt + ossimDpt(widthPercent, -heightPercent);
1539 
1540  // middle row
1541  ipts[3] = centerIpt + ossimDpt(-widthPercent, 0.0); // left middle
1542  ipts[4] = centerIpt;
1543  ipts[5] = centerIpt + ossimDpt(widthPercent, 0.0);
1544 
1545  // bottom row
1546  ipts[6] = centerIpt + ossimDpt(-widthPercent, heightPercent);
1547  ipts[7] = centerIpt + ossimDpt(0.0, heightPercent);
1548  ipts[8] = centerIpt + ossimDpt(widthPercent, heightPercent);
1549 
1550  ossim_uint32 idx = 0;
1551  for(idx = 0; idx < ipts.size(); ++idx)
1552  {
1553  double h = 0.0;
1554  localToWorld(ipts[idx], gpts[idx]);
1555  h = gpts[idx].height();
1556  if(ossim::isnan(h)) h = 0.0;
1557  gpts[idx].height(h + ELEVATION_DISPLACEMENT);
1558  worldToLocal(gpts[idx], iptsDisplacement[idx]);
1559  averageDelta = averageDelta + (iptsDisplacement[idx] - ipts[idx]);
1560  }
1561 
1562  ossim_float64 averageLength = averageDelta.length();
1563  if(averageLength < 1) return false;
1564 
1565  if(!ossim::almostEqual((double)0.0, (double)averageLength))
1566  {
1567  averageDelta = averageDelta/averageLength;
1568  }
1569  // RP - the rest of this calculation seems to be leading to less accurate results.
1570  // We already have the average image space displacement from raising the height for 9 points in the image
1571  // Just rotate based on this displacement,
1572  // scaling based on the image size distorts the direction of the up vector, leading to inaccurate results for non-square images
1573  //
1574  //ossimDpt averageLocation = (ossimDpt(averageDelta.x*bounds.width(),
1575  // averageDelta.y*bounds.height())+centerIpt) ;
1576  //ossimGpt averageLocationGpt;
1577  //ossimGpt centerGpt;
1578 
1579  //localToWorld(averageLocation, averageLocationGpt);
1580  //localToWorld(ipts[0], centerGpt);
1581 
1582  ossimDpt deltaPt = averageDelta; //averageLocation - centerIpt;
1583  ossimDpt deltaUnitPt = deltaPt;
1584  double len = deltaPt.length();
1585  if(len > FLT_EPSILON)
1586  {
1587  deltaUnitPt = deltaUnitPt/len;
1588  }
1589 
1590  // Image space model positive y is down. Let's reflect to positve y up.
1591  deltaUnitPt.y *= -1.0; // Reflect y to be right handed.
1592 
1593  result = ossim::atan2d(deltaUnitPt.x, deltaUnitPt.y);
1594 
1595  //---
1596  // We are essentially simulating camera rotation so negate the rotation
1597  // value.
1598  //---
1599  result *= -1;
1600 
1601  if(result < 0) result += 360.0;
1602 
1603  } // Matches: if( bounds.hasNans() == false )
1604  }
1605  else
1606  {
1607  result = 0;
1608  }
1609 
1610  } // Matches: if ( m_projection.valid() && m_projection->isAffectedByElevation() )
1611 
1612  return result;
1613 
1614 }
1615 
1616 
1618 {
1619  ossim_float64 result = ossim::nan();
1620 
1621  if ( m_projection.valid() )
1622  {
1624  {
1625 
1626  ossimDrect bounds;
1627  getBoundingRect( bounds );
1628 
1629  if( !bounds.hasNans() )
1630  {
1631  return upIsUpAngle(bounds.midPoint());
1632  }
1633  }
1634  else
1635  {
1636  result = 0;
1637  }
1638 
1639  } // Matches: if ( m_projection.valid() && m_projection->isAffectedByElevation() )
1640 
1641  return result;
1642 
1643 } // End: ossimImageGeometry::upIsUpAngle()
1644 
1646 {
1647  ossim_float64 result = ossim::nan();
1648 
1649  if ( m_projection.valid() )
1650  {
1651  ossimDrect bounds;
1652  getBoundingRect( bounds );
1653 
1654  if( !bounds.hasNans() )
1655  {
1656  ossimDpt centerIpt = bounds.midPoint();
1657 
1658  ossimDpt midBottomIpt( centerIpt.x, bounds.lr().y );
1659  ossimDpt midTopIpt( centerIpt.x, bounds.ul().y );
1660 
1661  ossimGpt midBottomGpt;
1662  ossimGpt midTopGpt;
1663 
1664  localToWorld( midBottomIpt, midBottomGpt );
1665  localToWorld( midTopIpt, midTopGpt );
1666 
1667  if ( !midBottomGpt.hasNans() && !midTopGpt.hasNans() )
1668  {
1669  result = midBottomGpt.azimuthTo( midTopGpt );
1670 
1671  if(result < 0) result += 360.0;
1672  }
1673  }
1674 
1675  } // Matches: if ( m_projection.valid() )
1676 
1677  return result;
1678 
1679 } // End: ossimImageGeometry::northUpAngle()
1680 
1682 {
1683  return dynamic_cast<const ossimMapProjection*>( m_projection.get() ) != 0;
1684 }
1685 
void getBoundingGroundRect(ossimGrect &bounding_grect) const
ossimString toString() const
Definition: ossimIpt.cpp:139
void set_uly(ossim_float64 y)
Definition: ossimDrect.h:718
void calculatePolyBounds(ossimPolyArea2d &result, ossim_uint32 partitions=25) const
This is the first stage implementation.
void set_uly(ossim_int32 y)
Definition: ossimIrect.h:666
void makeNan()
Definition: ossimDrect.h:388
virtual const ossimDpt & getDecimalDegreesPerPixel() const
Returns decimal degrees per pixel as an ossimDpt with "x" representing longitude and "y" representing...
bool operator==(const ossimImageGeometry &compare_this) const
Returns TRUE if argument geometry has exactly the same instances for transform and m_projection...
virtual ossimObject * dup() const =0
RTTI_DEF1(ossimImageGeometry, "ossimImageGeometry", ossimObject)
void rnToRn(const ossimDpt &inRnPt, ossim_uint32 inResolutionLevel, ossim_uint32 outResolutionLevel, ossimDpt &outRnPt) const
rnToRn is a utility method that takes a rn resolution image point and maps it to the another rn resol...
ossimRefPtr< ossim2dTo2dTransform > m_transform
Maintains local_image-to-full_image transformation.
void makeNan()
Definition: ossimIpt.h:56
void setProjection(ossimProjection *projection)
Sets the projection to be used for local-to-world coordinate transformation.
bool computeImageToGroundPartialsWRTAdjParam(ossimDpt &result, const ossimGpt &gpt, ossim_uint32 idx, ossim_float64 paramDelta=1.0)
void set_ulx(ossim_float64 x)
Definition: ossimDrect.h:709
virtual bool isEqualTo(const ossimObject &obj, ossimCompareType compareType=OSSIM_COMPARE_FULL) const
bool isAffectedByElevation() const
Returns TRUE if this geometry is sensitive to elevation.
T sgn(T x)
Definition: ossimCommon.h:339
virtual ossimImageHandler * open(const ossimFilename &fileName, bool trySuffixFirst=true, bool openOverview=true) const
open that takes a filename.
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
virtual void forward(const ossimDpt &input, ossimDpt &output) const =0
#define DEG_PER_RAD
void undecimatePoint(const ossimDpt &rnPt, ossim_uint32 resolutionLevel, ossimDpt &outPt) const
Method to back out decimation of a point.
Represents serializable keyword/value map.
bool isLonNan() const
Definition: ossimGpt.h:140
bool valid() const
Definition: ossimRefPtr.h:75
OSSIM_DLL void toStringList(ossimString &resultStringOfPoints, const std::vector< ossimDpt > &pointList, char separator=' ')
Will take a vector of ossimDpt and convert to a string list separated by spaces For example: (45...
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Attempts to initialize a transform and a projection given the KWL.
bool isValid(bool displayValidationError=false) const
const char * find(const char *key) const
float ossim_float32
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
std::ostream & print(std::ostream &out) const
Prints contents to output stream.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
void getBoundingRect(ossimIrect &bounding_rect) const
Get the bounding rect of (0, 0) to (imageSize.x-1, imageSize.y-1).
bool computeGroundToImagePartials(NEWMAT::Matrix &result, const ossimGpt &gpt, const ossimDpt3d &deltaLlh)
const ossimDpt & ul() const
Definition: ossimDrect.h:339
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Definition: ossimObject.cpp:95
void setTargetRrds(ossim_uint32 rrds)
Set m_targetRrds data member.
double y
Definition: ossimDpt.h:165
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual ossimGpt inverse(const ossimDpt &pp) const
void makeNan()
Definition: ossimGpt.h:130
virtual bool isGeographic() const
virtual bool isEqualTo(const ossimObject &obj, ossimCompareType compareType=OSSIM_COMPARE_FULL) const
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
ossim_float64 upIsUpAngle() const
ossim_uint32 m_targetRrds
Target rrds for localToWorld and worldToLocal methods.
ossim_uint32 toUInt32() const
static ossimElevManager * instance()
METHOD: instance() Implements singelton pattern.
bool getCornerGpts(ossimGpt &ul, ossimGpt &ur, ossimGpt &lr, ossimGpt &ll) const
Assigns the ossimGpts with the ground coordinates of the four corresponding image corner points...
ossimCompareType
ossimDpt getDegreesPerPixel() const
Returns the resolution of this image in degrees/pixel.
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
const ossimIpt & ll() const
Definition: ossimIrect.h:277
void wrap()
Wrap method to maintain longitude between -180 and +180 and latitude between -90 and +90...
Definition: ossimGpt.h:305
bool isLatNan() const
Definition: ossimGpt.h:139
double distanceTo(const ossimGpt &arg_gpt) const
METHOD: distanceTo(ossimGpt) Computes straight-line distance in meters between this and arg gpt: ...
Definition: ossimGpt.cpp:431
virtual void applyScale(const ossimDpt &scale, bool recenterTiePoint)
Applies scale to theDeltaLonPerPixel, theDeltaLatPerPixel and theMetersPerPixel data members (eg: the...
const ossimDrect & expand(const ossimDpt &padding)
Definition: ossimDrect.cpp:493
static const char * TYPE_KW
double length() const
Definition: ossimDpt.h:81
ossimImageGeometry()
Default constructor defaults to unity transform with no projection.
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
Definition: ossimGpt.cpp:316
bool isHgtNan() const
Definition: ossimGpt.h:143
#define STATIC_TYPE_NAME(T)
Definition: ossimRtti.h:325
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
std::vector< ossim_float64 > DeltaParamList
bool open(const ossimFilename &image)
Shortcut way of getting to an image&#39;s geometry when access to pixels is not needed.
virtual bool isEqualTo(const ossimObject &obj, ossimCompareType compareType=OSSIM_COMPARE_FULL) const
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual ossimAdjustableParameterInterface * getAdjustableParameterInterface()
void set_lry(ossim_float64 y)
Definition: ossimDrect.h:754
double z
Definition: ossimDpt3d.h:145
double lat
Definition: ossimDpt.h:165
void rnToFull(const ossimDpt &rnPt, ossim_uint32 resolutionLevel, ossimDpt &fullPt) const
rnToFull is a utility method that takes a rn resolution image point and maps it to the full image poi...
OSSIM_DLL void toVector(std::vector< ossimDpt > &result, const ossimString &stringOfPoints)
Will take a string list separated by spaces and convert to a vector of ossimDpts. ...
yy_size_t size
ossim_float64 lon
Definition: ossimGpt.h:266
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if non defined...
bool localToWorld(const ossimDpt &local_pt, ossimGpt &world_pt) const
Exposes the 3D projection from image to world coordinates.
virtual void lineSampleToEastingNorthing(const ossimDpt &liineSample, ossimDpt &eastingNorthing) const
virtual void inverse(const ossimDpt &input, ossimDpt &output) const
std::string::size_type size() const
Definition: ossimString.h:405
virtual double getHeightAboveEllipsoid(const ossimGpt &gpt)
ossimIpt midPoint() const
Definition: ossimIrect.h:750
#define FLT_EPSILON
virtual ossimDpt getMetersPerPixel() const =0
virtual void lineSampleHeightToWorld(const ossimDpt &lineSampPt, const double &heightAboveEllipsoid, ossimGpt &worldPt) const =0
unsigned int ossim_uint32
ossimDpt getMetersPerPixel() const
Returns the GSD associated with this image in the active projection.
ossimRefPtr< ossimProjection > m_projection
Maintains full_image-to-world_space transformation.
double height() const
Definition: ossimGpt.h:107
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
const ossimGpt & ul() const
Definition: ossimGrect.h:252
double atan2d(double y, double x)
Definition: ossimCommon.h:267
const ossimIpt & lr() const
Definition: ossimIrect.h:276
void rnToWorld(const ossimDpt &rnPt, ossim_uint32 resolutionLevel, ossimGpt &wpt) const
rnToWorld is a utility method that takes a rn resolution image point and maps it to the world point...
void worldToRn(const ossimGpt &wpt, ossim_uint32 resolutionLevel, ossimDpt &rnPt) const
worldToRn is a utility method that takes a world point allows one to transform all the way back to an...
ossimGpt ur() const
Definition: ossimGrect.h:257
bool hasNans() const
Definition: ossimDrect.h:396
void decimatePoint(const ossimDpt &inPt, ossim_uint32 resolutionLevel, ossimDpt &rnPt) const
Method to apply decimation of a point.
bool hasNans() const
Definition: ossimDpt.h:67
void add(const ossimPolyArea2d &rhs)
double lon
Definition: ossimDpt.h:164
void toPoint(const std::string &s)
Initializes this point from string.
Definition: ossimIpt.cpp:170
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...
bool clipToRect(vector< ossimPolygon > &result, const ossimDrect &rect) const
Uses the ossimPolyArea2d class for the intersection.
static ossimProjectionFactoryRegistry * instance()
void set_lrx(ossim_int32 x)
Definition: ossimIrect.h:693
void applyScale(const ossimDpt &scale, bool recenterTiePoint)
Changes the GSD and image size to reflect the scale provided.
return status
void decimationFactors(std::vector< ossimDpt > &decimations) const
Gets array of all decimation levels.
const ossimImageGeometry & operator=(const ossimImageGeometry &copy_this)
Replaces any existing transform and projection with those in the copy_this object.
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
bool isEqualTo(const ossimIpt &rhs, ossimCompareType compareType=OSSIM_COMPARE_FULL) const
Definition: ossimIpt.cpp:261
ossimString toString(ossim_uint32 precision=15) const
Definition: ossimDpt.cpp:160
void getTiePoint(ossimGpt &tie, bool edge) const
Get the latitude, longitude of the tie point.
void set_lry(ossim_int32 y)
Definition: ossimIrect.h:702
virtual ossimDpt forward(const ossimGpt &wp) const
ossimDpt midPoint() const
Definition: ossimDrect.h:817
bool hasNans() const
Definition: ossimGpt.h:135
ossim_int32 y
Definition: ossimIpt.h:142
void makeNan()
Definition: ossimIrect.h:329
const ossimDpt & ur() const
Definition: ossimDrect.h:340
void setTransform(ossim2dTo2dTransform *transform)
Sets the transform to be used for local-to-full-image coordinate transformation.
double x
Definition: ossimDpt.h:164
double x
Definition: ossimDpt3d.h:143
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
virtual ossimObject * dup() const
Definition: ossimObject.cpp:29
virtual bool isAffectedByElevation() const =0
Pure virtual method to query if projection is affected by elevation.
static ossim2dTo2dTransformRegistry * instance()
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
ossimPolyArea2d & setToBufferedShape(double distance=FLT_EPSILON)
bool worldToLocal(const ossimGpt &world_pt, ossimDpt &local_pt) const
Exposes the 3D world-to-local image coordinate reverse projection.
ossimDpt metersPerDegree() const
Definition: ossimGpt.cpp:498
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Saves the transform (if any) and projection (if any) states to the KWL.
static ossimImageHandlerRegistry * instance()
ossim_int32 x
Definition: ossimIpt.h:141
const ossimDpt & ll() const
Definition: ossimDrect.h:342
ossim_float64 lat
Definition: ossimGpt.h:265
double y
Definition: ossimDpt3d.h:144
virtual void lineSampleToWorld(const ossimDpt &lineSampPt, ossimGpt &worldPt) const =0
bool hasNans() const
Definition: ossimIpt.h:58
virtual ossimDpt getMetersPerPixel() const
void set_lrx(ossim_float64 x)
Definition: ossimDrect.h:745
void fullToRn(const ossimDpt &fullPt, ossim_uint32 resolutionLevel, ossimDpt &rnPt) const
fullToRn is a utility method that takes a full image point and maps it to a rn resolution image point...
void setParameterCenter(ossim_uint32 idx, double center, bool notify=false)
virtual std::ostream & print(std::ostream &out) const
Generic print method.
ossim_float64 northUpAngle() const
virtual void worldToLineSample(const ossimGpt &worldPoint, ossimDpt &lineSampPt) const =0
std::vector< ossimDpt > m_decimationFactors
List of decimation factors for R-levels.
const ossimDpt & lr() const
Definition: ossimDrect.h:341
bool crossesDateline(H5::DataSet &dataset, const ossimIrect &validRect)
Checks for dateline cross.
bool isMapProjected() const
Returns true if underlying projection is derived from ossimMapProjection.
const ossimGpt & lr() const
Definition: ossimGrect.h:269
ossimGpt ll() const
Definition: ossimGrect.h:263
void makeNan()
Definition: ossimDpt.h:65
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
ossimDpt decimationFactor(ossim_uint32 r_index) const
Returns the decimation factor from R0 for the resolution level specified.
int ossim_int32
void set_ulx(ossim_int32 x)
Definition: ossimIrect.h:657
void getImageEdgePoints(std::vector< ossimDpt > &result, ossim_uint32 partitions=25) const
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91
bool computeImageToGroundPartialsWRTAdjParams(NEWMAT::Matrix &result, const ossimGpt &gpt, ossim_float64 paramDelta=1.0)
ossim_uint32 getTargetRrds() const