Exemple #1
0
//*****************************************************************************
//  METHOD: ossimRpcModel::lineSampleToWorld()
//
//  Overrides base class implementation. Performs DEM intersection.
//*****************************************************************************
void  ossimRpcModel::lineSampleToWorld(const ossimDpt& imagePoint,
                                       ossimGpt&       worldPoint) const
{

//---
// Under debate... (drb 20130610)
// this seems to be more accurate for the round trip
//---
#if 0
    if(!imagePoint.hasNans())
    {

        lineSampleHeightToWorld(imagePoint,
                                worldPoint.height(),
                                worldPoint);
    }
    else
    {
        worldPoint.makeNan();
    }
#else
    if(!imagePoint.hasNans())
    {
        ossimEcefRay ray;
        imagingRay(imagePoint, ray);
        ossimElevManager::instance()->intersectRay(ray, worldPoint);
    }
    else
    {
        worldPoint.makeNan();
    }
#endif
}
ossim_int32 ossimUtmProjection::computeZone(const ossimGpt& ground)
{
   ossim_int32 result = 0;

   double longitude = ground.lonr();
   double lat_Degrees  = (ossim_int32)( (ground.latd()) + 0.00000005);
   double long_Degrees = (ossim_int32)( (ground.lond()) + 0.00000005);
   
   if (longitude < M_PI)
      result = (ossim_int32)( (31 + ((180 * longitude) / (6 * M_PI)) ) + 0.00000005);
   else
      result = (ossim_int32)( (((180 * longitude) / (6 * M_PI)) - 29) + 0.00000005);
   if (result > 60)
      result = 1;
    /* UTM special cases */
   if ((lat_Degrees > 55) && (lat_Degrees < 64) && (long_Degrees > -1)
       && (long_Degrees < 3))
      result = 31;
   if ((lat_Degrees > 55) && (lat_Degrees < 64) && (long_Degrees > 2)
       && (long_Degrees < 12))
      result = 32;
   if ((lat_Degrees > 71) && (long_Degrees > -1) && (long_Degrees < 9))
      result = 31;
   if ((lat_Degrees > 71) && (long_Degrees > 8) && (long_Degrees < 21))
      result = 33;
   if ((lat_Degrees > 71) && (long_Degrees > 20) && (long_Degrees < 33))
      result = 35;
   if ((lat_Degrees > 71) && (long_Degrees > 32) && (long_Degrees < 42))
      result = 37;

   return result;
}
//*****************************************************************************
//  METHOD: ossimRpcProjection::worldToLineSample()
//  
//  Overrides base class implementation. Directly computes line-sample from
//  the polynomials.
//*****************************************************************************
void ossimRpcProjection::worldToLineSample(const ossimGpt& ground_point,
                                      ossimDpt&       imgPt) const
{
   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): entering..." << std::endl;

   if(ground_point.isLatNan() ||
      ground_point.isLonNan() )
     {
       imgPt.makeNan();
       return;
     }
         
   //*
   // Normalize the lat, lon, hgt:
   //*
   double nlat = (ground_point.lat - theLatOffset) / theLatScale;
   double nlon = (ground_point.lon - theLonOffset) / theLonScale;
   double nhgt;

   if(ossim::isnan(ground_point.hgt))
   {
      nhgt = (theHgtScale - theHgtOffset) / theHgtScale;
   }
   else
   {
      nhgt = (ground_point.hgt - theHgtOffset) / theHgtScale;
   }

   
   //***
   // Compute the adjusted, normalized line (U) and sample (V):
   //***
   double Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
   double Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
   double Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
   double Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
   double U_rot  = Pu / Qu;
   double V_rot  = Pv / Qv;

   //***
   // U, V are normalized quantities. Need now to establish the image file
   // line and sample. First, back out the adjustable parameter effects
   // starting with rotation:
   //***
   double U = U_rot*theCosMapRot + V_rot*theSinMapRot;
   double V = V_rot*theCosMapRot - U_rot*theSinMapRot;

   //***
   // Now back out skew, scale, and offset adjustments:
   //***
   imgPt.line = U*(theLineScale+theIntrackScale) + theLineOffset + theIntrackOffset;
   imgPt.samp = V*(theSampScale+theCrtrackScale) + theSampOffset + theCrtrackOffset;


   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): returning..." << std::endl;

   return;
}
void  ossimRpcProjection::lineSampleToWorld(const ossimDpt& imagePoint,
                                            ossimGpt&       worldPoint) const
{
   if(!imagePoint.hasNans())
   {
      
      lineSampleHeightToWorld(imagePoint,
                              worldPoint.height(),
                              worldPoint);
   }
   else
   {
      worldPoint.makeNan();
   }
}
Exemple #5
0
void ossimBuckeyeSensor::lineSampleToWorld(const ossimDpt& image_point,
	ossimGpt&       gpt) const
{
	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::lineSampleToWorld:entering..." << std::endl;

	if(image_point.hasNans())
	{
		gpt.makeNan();
		return;
	}

	//***
	// Determine imaging ray and invoke elevation source object's services to
	// intersect ray with terrain model:
	//***

	ossimEcefRay ray;
	imagingRay(image_point, ray);
	ossimElevManager::instance()->intersectRay(ray, gpt);

	if (traceDebug())
	{
		ossimNotify(ossimNotifyLevel_DEBUG) << "image_point = " << image_point << std::endl;
		ossimNotify(ossimNotifyLevel_DEBUG) << "ray = " << ray << std::endl;
		ossimNotify(ossimNotifyLevel_DEBUG) << "gpt = " << gpt << std::endl;
	}

	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::lineSampleToWorld: returning..." << std::endl;
	return;
}
ossimGpt ossimThreeParamDatum::shift(const ossimGpt &aPt)const
{
   const ossimDatum *aDatum = aPt.datum();

   if( code() == aDatum->code())
   {
      return ossimGpt(aPt.latd(), aPt.lond(), aPt.height(), this);
   }
   
   if(aDatum)
   {
      return shiftFromWgs84(aDatum->shiftToWgs84(aPt));
   }

   return aPt;
}
void ossimIvtGeomXform::imageToGround(const ossimDpt& ipt, ossimGpt& gpt)
{
  gpt.makeNan();
  if(m_geom.valid())
  {
    m_geom->localToWorld(ipt, gpt);
  }
}
ossimGpt ossimThreeParamDatum::shiftToWgs84(const ossimGpt &aPt)const
{
   
   if(ossim::almostEqual(param1(),  0.0)&&
      ossim::almostEqual(param2(), 0.0)&&
      ossim::almostEqual(param3(), 0.0))
   {
      return ossimGpt(aPt.latd(),
                      aPt.lond(),
                      aPt.latd(),
                      ossimGpt().datum());
   }
      
   ossimEcefPoint p1 = aPt;
   ossimEcefPoint p2;
 
   
   if(withinMolodenskyRange(aPt.latd()))
   {
      ossimWgs84Datum wgs84;
      double latin, lonin, hgtin;
      double latout, lonout, hgtout;
      
      double da = wgs84.ellipsoid()->getA() - ellipsoid()->getA();
      double df = wgs84.ellipsoid()->getFlattening() - ellipsoid()->getFlattening();

      latin = aPt.latr();
      lonin = aPt.lonr();
      hgtin = aPt.height();

      if(aPt.isHgtNan())
      {
         hgtin = 0.0;
      }
      molodenskyShift(ellipsoid()->getA(), da, ellipsoid()->getFlattening(), df, param1(), param2(), param3(),
                      latin, lonin, hgtin,
                      latout, lonout, hgtout);
      ossimGpt g;

      g.latr(latout);
      g.lonr(lonout);
      g.height(hgtout);
      g.datum(this);
      return g;
   }
   else
     {
       p2 = ossimEcefPoint(p1.x() + theParam1,
			   p1.y() + theParam2,
			   p1.z() + theParam3);
     }
   
   return ossimGpt(p2); // defaults to WGS84
}
void ossimIvtGeomXform::viewToGround(const ossimDpt& viewPt, ossimGpt& gpt)
{
  ossimDpt ipt;
  gpt.makeNan();
  viewToImage(viewPt, ipt);
  if(!ipt.hasNans())
  {
    imageToGround(ipt, gpt);
  }
}
void ossimUtmProjection::setOrigin(const ossimGpt& origin)
{
   setZone(origin);
   // NOTE: We will not set the hemisphere if the origin latitude is 0.0.
   if (origin.latd() != 0.0)
   {
      setHemisphere(origin);
   }
   ossimMapProjection::setOrigin(origin);
}
Exemple #11
0
//*****************************************************************************
//  METHOD: ossimRpcModel::lineSampleToWorld()
//  
//  Overrides base class implementation. Performs DEM intersection.
//*****************************************************************************
void  ossimRpcModel::lineSampleToWorld(const ossimDpt& imagePoint,
                                       ossimGpt&       worldPoint) const
{

	//lineSampleHeightToWorld(imagePoint, theHgtOffset, worldPoint);
	//worldPoint.hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(worldPoint);
	//if(!worldPoint.hasNans()) return;

   if(!imagePoint.hasNans())
   {
      ossimEcefRay ray;
	  imagingRay(imagePoint, ray);
	  if (m_proj) worldPoint.datum(m_proj->getDatum());	//loong
      ossimElevManager::instance()->intersectRay(ray, worldPoint);
   }
   else
   {
      worldPoint.makeNan();
   }
}
void ossimDtedElevationDatabase::createRelativePath(ossimFilename& file, const ossimGpt& gpt)const
{
   ossimFilename lon, lat;
   int ilon = static_cast<int>(floor(gpt.lond()));
   
   if (ilon < 0)
   {
      lon = "w";
   }
   else
   {
      lon = "e";
   }
   
   ilon = abs(ilon);
   std::ostringstream  s1;
   s1 << std::setfill('0') << std::setw(3)<< ilon;
   
   lon += s1.str().c_str();//ossimString::toString(ilon);
   
   int ilat =  static_cast<int>(floor(gpt.latd()));
   if (ilat < 0)
   {
      lat += "s";
   }
   else
   {
      lat += "n";
   }
   
   ilat = abs(ilat);
   std::ostringstream  s2;
   
   s2<< std::setfill('0') << std::setw(2)<< ilat;
   
   lat += s2.str().c_str();
   
   file = lon.dirCat(lat+m_extension);
}
Exemple #13
0
   void ossimTileMapModel::worldToLineSample(const ossimGpt& ground_point,
                                             ossimDpt&       img_pt) const
   {
      // if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::worldToLineSample(): entering..." << std::endl;

      if(ground_point.isLatNan() || ground_point.isLonNan() )
      {
         img_pt.makeNan();
         return;
      }

      double x = (180.0 + ground_point.lon) / 360.0;
      double y = - ground_point.lat * M_PI / 180; // convert to radians
      y = 0.5 * log((1+sin(y)) / (1 - sin(y)));
      y *= 1.0/(2 * M_PI); // scale factor from radians to normalized
      y += 0.5; // and make y range from 0 - 1

      img_pt.samp = floor(x*pow(2.,static_cast<double>(qDepth))*256);

      img_pt.line = floor(y*pow(2.,static_cast<double>(qDepth))*256);

      return;
   }
void ossimSrtmElevationDatabase::createRelativePath(ossimFilename& file, const ossimGpt& gpt)const
{
   int ilat =  static_cast<int>(floor(gpt.latd()));
   if (ilat < 0)
   {
      file = "S";
   }
   else
   {
      file = "N";
   }
   
   ilat = abs(ilat);
   std::ostringstream  os1;
   
   os1 << std::setfill('0') << std::setw(2) <<ilat;
   
   file += os1.str().c_str();
   
   int ilon = static_cast<int>(floor(gpt.lond()));
   
   if (ilon < 0)
   {
      file += "W";
   }
   else
   {
      file += "E";
   }
   
   ilon = abs(ilon);
   std::ostringstream  os2;
   os2 << std::setfill('0') << std::setw(3) << ilon;
   
   file += os2.str().c_str();
   file.setExtension("hgt");
}
Exemple #15
0
std::string oms::WktUtility::toWktGeometryGivenCenterRadius(const ossimGpt& center, 
                                                            double radius,
                                                            ossimUnitType radialUnit,
                                                            unsigned int numberOfSamples,
                                                            int          directionalSign)const
{
   std::string result = "";
   if(ossim::almostEqual(radius, 0.0))
   {
      result = "POINT(" + ossimString::toString(center.lond()).string() + " " + ossimString::toString(center.latd()).string() + ")";
   }
   else 
   {
      double headingStepSizeInDegrees = (360.0/static_cast<double>(numberOfSamples))*
      directionalSign;
      ossim_uint32 step = 0;
      double degreesDistance = ossimUnitConversionTool(radius, radialUnit).getValue(OSSIM_DEGREES);
      ossimDpt centerGpt(center);
      ossimDpt newPoint;
      ossimDpt firstPoint;
      if(numberOfSamples > 0)
      {
         result = "POLYGON((";
      }
      for(step = 0; step < numberOfSamples; ++step)
      {
         double x = ossim::degreesToRadians(headingStepSizeInDegrees*step);// - 90.0));
         double dy = sin(x);
         double dx = cos(x);
         newPoint.lat = dy*degreesDistance;
         newPoint.lon = dx*degreesDistance;
         newPoint = centerGpt + newPoint;
         if(step == 0)
         {
            firstPoint = newPoint;
         }
         result += (ossimString::toString(ossim::clamp(newPoint.lon, -180.0, 180.0)).string()+" "
                    +ossimString::toString(ossim::clamp(newPoint.lat, -90.0, 90.0)).string()+",");
      }
      if(numberOfSamples > 0)
      {
         result += (ossimString::toString(firstPoint.lon ).string() + " " +
                    ossimString::toString(firstPoint.lat ).string() );
         result += "))";
      }
   }

   return result;
}
void ossimCsmSensorModel::lineSampleToWorld(const ossimDpt& image_point,
                                            ossimGpt&       gpt) const
{
   if(image_point.hasNans())
   {
      gpt.makeNan();
      return;
   }
   //***
   // Determine imaging ray and invoke elevation source object's services to
   // intersect ray with terrain model:
   //***
   ossimEcefRay ray;
   imagingRay(image_point, ray);
   ossimElevManager::instance()->intersectRay(ray, gpt);   
}
Exemple #17
0
 void ossimTileMapModel::lineSampleHeightToWorld(const ossimDpt& image_point,
                                                 const double&   /* height */,
                                                 ossimGpt&       gpt) const
 {
    if(!image_point.hasNans())
    {
       gpt.lon = static_cast<double>(image_point.samp)/(1 << qDepth)/256 *360.0-180.0;
       double y = static_cast<double>(image_point.line)/(1 << qDepth)/256;
       double ex = exp(4*M_PI*(y-0.5));
       gpt.lat = -180.0/M_PI*asin((ex-1)/(ex+1));
    }
    else
    {
       gpt.makeNan();
    }
    return;
 }
ossimGpt ossimNadconNarDatum::shift(const ossimGpt    &aPt)const
{
  const ossimDatum* datum = aPt.datum();
  ossimString code = datum->code();
  ossimString subCode(code.begin(),
		      code.begin() + 3);
  if(subCode == "NAR")
  {
     return aPt;
  }
  else
  {
     if(subCode == "NAS")
     {
	checkGrid(aPt);
	if(!theLatGrid.getFileOkFlag()||
	   !theLonGrid.getFileOkFlag())
        {
           return ossimThreeParamDatum::shift(aPt);
        }
	
        double shiftLat = theLatGrid.getShiftAtLatLon(aPt.latd(), aPt.lond());
        double shiftLon = theLonGrid.getShiftAtLatLon(aPt.latd(), aPt.lond());
        
        if( (ossim::isnan(shiftLat)) || (ossim::isnan(shiftLon)) )
        {
           return ossimThreeParamDatum::shift(aPt);
        }
        else
        {
           // Note the shifts are stored in the file
           // as seconds.
           //
           // convert the seconds into decimal degrees.  
           //
           shiftLat /= 3600.0;
           shiftLon /= 3600.0;
           return ossimGpt(aPt.latd() + shiftLat,
                           aPt.lond() - shiftLon,
                           aPt.height(),
                           this);
        }
     }
     else
     {
        return ossimThreeParamDatum::shift(aPt);
     }
  }
  
  return ossimThreeParamDatum::shift(aPt);
}
ossimDpt ossimVanDerGrintenProjection::forward(const ossimGpt &latLon)const
{
   double easting  = 0.0;
   double northing = 0.0;
   ossimGpt gpt = latLon;
   
   if (theDatum)
   {
      if (theDatum->code() != latLon.datum()->code())
      {
         gpt.changeDatum(theDatum); // Shift to our datum.
      }
   }

   Convert_Geodetic_To_Van_der_Grinten(gpt.latr(),
                                       gpt.lonr(),
                                       &easting,
                                       &northing);
   return ossimDpt(easting, northing);
}
Exemple #20
0
void ossimApplanixUtmModel::lineSampleHeightToWorld(const ossimDpt& image_point,
                                                 const double&   heightEllipsoid,
                                                 ossimGpt&       worldPoint) const
{
   if (!insideImage(image_point))
   {
      worldPoint.makeNan();
//       worldPoint = extrapolate(image_point, heightEllipsoid);
   }
   else
   {
      //***
      // First establish imaging ray from image point:
      //***
      ossimEcefRay ray;
      imagingRay(image_point, ray);
      ossimEcefPoint Pecf (ray.intersectAboveEarthEllipsoid(heightEllipsoid));
      worldPoint = ossimGpt(Pecf);
   }
}
Exemple #21
0
void ossimBuckeyeSensor::lineSampleHeightToWorld(const ossimDpt& image_point,
	const double&   heightEllipsoid,
	ossimGpt&       worldPoint) const
{
	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::lineSampleHeightToWorld: entering..." << std::endl;
	if (!insideImage(image_point))
	{
		worldPoint.makeNan();
	}
	else
	{
		//***
		// First establish imaging ray from image point:
		//***
		ossimEcefRay ray;
		imagingRay(image_point, ray);
		ossimEcefPoint Pecf (ray.intersectAboveEarthEllipsoid(heightEllipsoid));
		worldPoint = ossimGpt(Pecf);
	}
	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::lineSampleHeightToWorld: returning..." << std::endl;
}
ossimDpt ossimTransCylEquAreaProjection::forward(const ossimGpt &latLon)const
{
   double easting  = 0.0;
   double northing = 0.0;
   ossimGpt gpt = latLon;
   
   if (theDatum)
   {
      if (theDatum->code() != latLon.datum()->code())
      {
         gpt.changeDatum(theDatum); // Shift to our datum.
      }
   }

   Convert_Geodetic_To_Trans_Cyl_Eq_Area(gpt.latr(),
                                         gpt.lonr(),
                                         &easting,
                                         &northing);
   
   return ossimDpt(easting, northing);
}
void ossimSpectraboticsRedEdgeModel::lineSampleToWorld(const ossimDpt& image_point,
                                               ossimGpt&       gpt) const
{
   if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSpectraboticsRedEdgeModel::lineSampleToWorld:entering..." << std::endl;
   
   if(image_point.hasNans())
   {
      gpt.makeNan();
      return;
   }
   //***
   // Extrapolate if image point is outside image:
   //***
//   if (!insideImage(image_point))
//   {
//      gpt.makeNan();
//       gpt = extrapolate(image_point);
//      return;
//   }

   //***
   // Determine imaging ray and invoke elevation source object's services to
   // intersect ray with terrain model:
   //***
   ossimEcefRay ray;
   imagingRay(image_point, ray);
   ossimElevManager::instance()->intersectRay(ray, gpt);

   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG) << "image_point = " << image_point << std::endl;
      ossimNotify(ossimNotifyLevel_DEBUG) << "ray = " << ray << std::endl;
      ossimNotify(ossimNotifyLevel_DEBUG) << "gpt = " << gpt << std::endl;
   }

   if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModel::lineSampleToWorld: returning..." << std::endl;
   return;
}
Exemple #24
0
ossimUsgsQuad::ossimUsgsQuad(const ossimGpt& lrGpt)
   :
      theQuadLowerRightCorner(0.0, 0.0, 0.0, lrGpt.datum()),
      theQuarterQuadLowerRightCorner(0.0, 0.0, 0.0, lrGpt.datum())
//      thePaddingInDegrees(0.0, 0.0),

{
   const char* MODULE = "ImgOutput::quadBasename";

   //***
   // NOTE:
   // This method computes a file name from the lower right corner of the
   // image.  The format is derived from USGS Digital Raster Graphic(DRG)
   // program for standardized data set names for DRG products.  Due to
   // customer  requirements there is one deviation:  The first digit of the
   // name is converted to a letter with 1 being = A, 2 being = B,
   // 3 being = C, ....
   // This was done to allow the name to be used on a pc.
   //***

   const double QUAD_SIZE_IN_DEGREES = 0.125;

   ossimString          baseString;
   int                  tmpInt;
   double               tmpDbl;
   char quadChar        = 'A';
   char quadNum         = '1';

   ostringstream           os;
   os << setiosflags(ios::right)
      << setiosflags(ios::fixed)
      << setfill('0');

   tmpInt = static_cast<int>(abs(lrGpt.lat)); // Cast away the fractional part.
   os << tmpInt; // latitude

   //***
   // Get the quadrant charactor in the latitude direction. (A - H)
   //***
   tmpDbl = fabs(lrGpt.lat) - (double)tmpInt;
   quadChar += static_cast<int>(tmpDbl / QUAD_SIZE_IN_DEGREES);

   tmpInt = static_cast<int>(abs(lrGpt.lon)); // longitude
   os << setw(3) << tmpInt;

   tmpDbl = fabs(lrGpt.lon) - (double)tmpInt;

   quadNum += static_cast<char>(tmpDbl / QUAD_SIZE_IN_DEGREES);

   os << quadChar << quadNum;

   double latFraction = (lrGpt.lat / QUAD_SIZE_IN_DEGREES) -
                        ossim::round<int>((lrGpt.lat) / QUAD_SIZE_IN_DEGREES);
   double lonFraction = (lrGpt.lon / QUAD_SIZE_IN_DEGREES) -
                        ossim::round<int>((lrGpt.lon) / QUAD_SIZE_IN_DEGREES);

   // Black & White
//   if(theRectsStandardFlag && 
//      theChipSource->radiometry().numberOfBands() == 1)
//   {
//       char quarterQuadChar = '4';
//       if (latFraction && lonFraction)
//       {
//          quarterQuadChar = '1';
//       }
//       else if (latFraction && !lonFraction)
//       {
//          quarterQuadChar = '2';
//       }
//       else if (!latFraction && lonFraction)
//       {
//          quarterQuadChar = '3';
//       }   
//       os << quarterQuadChar << ends;
//    }
//    // Color 
//    else if(theRectsStandardFlag &&
//            theChipSource->radiometry().numberOfBands() > 1)
//    {
//       char quarterQuadChar = '8';
//       if (latFraction && lonFraction)
//       {
//          quarterQuadChar = '5';
//       }
//       else if (latFraction && !lonFraction)
//       {
//          quarterQuadChar = '6';
//       }
//       else if (!latFraction && lonFraction)
//       {
//          quarterQuadChar = '7';
//       }   
//       os << quarterQuadChar << ends;
//    }
//    else
//    {
      char quarterQuadChar = 'D';
      if (latFraction && lonFraction)
      {
         quarterQuadChar = 'A';
      }
      else if (latFraction && !lonFraction)
      {
         quarterQuadChar = 'B';
      }
      else if (!latFraction && lonFraction)
      {
         quarterQuadChar = 'C';
      }   
      os << quarterQuadChar << ends;
//   }

   
   baseString = os.str().c_str();

   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << " DEBUG: " << MODULE  
         << "\nbaseString:  " << baseString << std::endl;
   }
   
   setQuadName(baseString);
}
Exemple #25
0
//*****************************************************************************
//  METHOD: ossimHgtRef::getLocalTerrainNormal()
//
//  Get get local terrain normal unit vector.
//
//*****************************************************************************
ossimColumnVector3d ossimHgtRef::getLocalTerrainNormal(const ossimGpt& pg) const
{
    ossimColumnVector3d tNorm;
    const ossim_float64 delta = 100.0;

    switch (theCurrentHeightRefType)
    {
    case AT_HGT:
        // Use ellipsoid tangent plane mormal
        tNorm = tNorm.zAligned();
        break;

    case AT_DEM:
    {
        // Use local 3X3 grid around point to get mean slope
        NEWMAT::Matrix h(3,3);
        ossimDpt mpd;
        mpd = pg.metersPerDegree();
        ossim_float64 dLon = delta/mpd.x;
        ossim_float64 dLat = delta/mpd.y;


        for (ossim_int32 lon=-1; lon<=1; ++lon)
        {
            ossim_float64 clon = pg.lond()+lon*dLon;
            for (ossim_int32 lat=-1; lat<=1; ++lat)
            {
                ossim_float64 clat = pg.latd()+lat*dLat;
                ossimGpt p(clat, clon, pg.height());
                h(2-lat,lon+2) =
                    ossimElevManager::instance()->getHeightAboveEllipsoid(p);
            }
        }

        if (traceDebug())
        {
            ossimNotify(ossimNotifyLevel_DEBUG)
                    <<"DEBUG: getLocalTerrainNormal...  3X3 grid"<<endl;
            for (ossim_int32 lat=-1; lat<=1; ++lat)
            {
                for (ossim_int32 lon=-1; lon<=1; ++lon)
                    ossimNotify(ossimNotifyLevel_DEBUG)<<"  "<<h(lat+2,lon+2);
                ossimNotify(ossimNotifyLevel_DEBUG)<<endl;
            }
        }

        ossim_float64 dz_dlon =
            ((h(1,3)+2*h(2,3)+h(3,3))-(h(1,1)+2*h(2,1)+h(3,1)))/(8*delta);
        ossim_float64 dz_dlat =
            ((h(1,1)+2*h(1,2)+h(1,3))-(h(3,1)+2*h(3,2)+h(3,3)))/(8*delta);
        tNorm[0] = -dz_dlon;
        tNorm[1] = -dz_dlat;
        tNorm[2] = 1.0 - sqrt(dz_dlon*dz_dlon+dz_dlat*dz_dlat);
    }

        // If error condition, return z-aligned vector to allow continuation
    if (ossim::isnan(tNorm[0]) ||
            ossim::isnan(tNorm[1]) ||
            ossim::isnan(tNorm[2]))
    {
        tNorm = tNorm.zAligned();
        if(traceDebug())
        {
            ossimNotify(ossimNotifyLevel_WARN)
                    << "WARNING: ossimHgtRef::getLocalTerrainNormal(): "
                    << "\n   error... terrain normal set to vertical..."
                    << std::endl;

        }
    }
    break;

    default:
        tNorm = tNorm.zAligned();
        break;
    }

    return tNorm;
}
Exemple #26
0
ossimDpt ossimRpcModel::getForwardDeriv(int derivMode,
                                        const ossimGpt& pos,
                                        double h)
{
   if (derivMode >= 0)
   {
      return ossimSensorModel::getForwardDeriv(derivMode, pos, h);
   }
   
   else
   {
      ossimDpt returnData;
      if (derivMode==OBS_INIT)
      {
         ossimDpt obs;
         obs.samp = pos.latd();
         obs.line = pos.lond();
         theObs = obs;
      }
      else if (derivMode==EVALUATE)
      {
         double nlat = (pos.lat - theLatOffset) / theLatScale;
         double nlon = (pos.lon - theLonOffset) / theLonScale;
         double nhgt;
         if( ossim::isnan(pos.hgt) )
         {
            nhgt = (theHgtScale - theHgtOffset) / theHgtScale;
         }
         else
         {
            nhgt = (pos.hgt - theHgtOffset) / theHgtScale;
         }
         
         double Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
         double Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
         double Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
         double Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
         double Un  = Pu / Qu;
         double Vn  = Pv / Qv;
         
         double U  = Un*theLineScale + theLineOffset;
         double V  = Vn*theSampScale + theSampOffset;
         double dPu_dLat, dQu_dLat, dPv_dLat, dQv_dLat;
         double dPu_dLon, dQu_dLon, dPv_dLon, dQv_dLon;
         double dPu_dHgt, dQu_dHgt, dPv_dHgt, dQv_dHgt;
         dPu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineNumCoef);
         dQu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineDenCoef);
         dPv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampNumCoef);
         dQv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampDenCoef);
         dPu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineNumCoef);
         dQu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineDenCoef);
         dPv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampNumCoef);
         dQv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampDenCoef);
         dPu_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theLineNumCoef);
         dQu_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theLineDenCoef);
         dPv_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theSampNumCoef);
         dQv_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theSampDenCoef);
         
         double dU_dLat, dU_dLon, dU_dHgt, dV_dLat, dV_dLon, dV_dHgt;
         dU_dLat = (Qu*dPu_dLat - Pu*dQu_dLat)/(Qu*Qu);
         dU_dLon = (Qu*dPu_dLon - Pu*dQu_dLon)/(Qu*Qu);
         dU_dHgt = (Qu*dPu_dHgt - Pu*dQu_dHgt)/(Qu*Qu);
         dV_dLat = (Qv*dPv_dLat - Pv*dQv_dLat)/(Qv*Qv);
         dV_dLon = (Qv*dPv_dLon - Pv*dQv_dLon)/(Qv*Qv);
         dV_dHgt = (Qv*dPv_dHgt - Pv*dQv_dHgt)/(Qv*Qv);
         
        dU_dLat *= theLineScale/theLatScale;
        dU_dLon *= theLineScale/theLonScale;
        dU_dHgt *= theLineScale/theHgtScale;
        dV_dLat *= theSampScale/theLatScale;
        dV_dLon *= theSampScale/theLonScale;
        dV_dHgt *= theSampScale/theHgtScale;
        dU_dLat *= DEG_PER_RAD;
        dU_dLon *= DEG_PER_RAD;
        dV_dLat *= DEG_PER_RAD;
        dV_dLon *= DEG_PER_RAD;
         ossimEcefPoint location(pos);
         NEWMAT::Matrix jMat(3,3);
         pos.datum()->ellipsoid()->jacobianWrtEcef(location, jMat);
         theParWRTx.u = dU_dLat*jMat(1,1)+dU_dLon*jMat(2,1)+dU_dHgt*jMat(3,1);
         theParWRTy.u = dU_dLat*jMat(1,2)+dU_dLon*jMat(2,2)+dU_dHgt*jMat(3,2);
         theParWRTz.u = dU_dLat*jMat(1,3)+dU_dLon*jMat(2,3)+dU_dHgt*jMat(3,3);
         theParWRTx.v = dV_dLat*jMat(1,1)+dV_dLon*jMat(2,1)+dV_dHgt*jMat(3,1);
         theParWRTy.v = dV_dLat*jMat(1,2)+dV_dLon*jMat(2,2)+dV_dHgt*jMat(3,2);
         theParWRTz.v = dV_dLat*jMat(1,3)+dV_dLon*jMat(2,3)+dV_dHgt*jMat(3,3);
         ossimDpt resid(theObs.samp-V, theObs.line-U);
         returnData = resid;
      }
      else if (derivMode==P_WRT_X)
      {
         returnData = theParWRTx;
      }
      else if (derivMode==P_WRT_Y)
      {
         returnData = theParWRTy;
      }
      else
      {
         returnData = theParWRTz;
      }
      return returnData;
   }
}
Exemple #27
0
//*****************************************************************************
//  METHOD: ossimSarModel::getForwardDeriv()
//
//  Compute partials of samp/line WRT to ground.
//
//*****************************************************************************
ossimDpt ossimRpcModel::getForwardDeriv(int derivMode,
                                        const ossimGpt& pos,
                                        double h)
{
    // If derivMode (parmIdx) >= 0 call base class version
    // for "adjustable parameters"
    if (derivMode >= 0)
    {
        return ossimSensorModel::getForwardDeriv(derivMode, pos, h);
    }

    // Use alternative derivMode definitions
    else
    {
        ossimDpt returnData;

        //******************************************
        // OBS_INIT mode
        //    [1]
        //    [2]
        //  Note: In this mode, pos is used to pass
        //  in the (s,l) observations.
        //******************************************
        if (derivMode==OBS_INIT)
        {
            // Image coordinates
            ossimDpt obs;
            obs.samp = pos.latd();
            obs.line = pos.lond();
            theObs = obs;
        }

        //******************************************
        // EVALUATE mode
        //   [1] evaluate & save partials, residuals
        //   [2] return residuals
        //******************************************
        else if (derivMode==EVALUATE)
        {
            //***
            // Normalize the lat, lon, hgt:
            //***
            double nlat = (pos.lat - theLatOffset) / theLatScale;
            double nlon = (pos.lon - theLonOffset) / theLonScale;
            double nhgt;

            if( ossim::isnan(pos.hgt) )
            {
                nhgt = (theHgtScale - theHgtOffset) / theHgtScale;
            }
            else
            {
                nhgt = (pos.hgt - theHgtOffset) / theHgtScale;
            }

            //***
            // Compute the normalized line (Un) and sample (Vn):
            //***
            double Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
            double Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
            double Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
            double Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
            double Un  = Pu / Qu;
            double Vn  = Pv / Qv;

            //***
            // Compute the actual line (U) and sample (V):
            //***
            double U  = Un*theLineScale + theLineOffset;
            double V  = Vn*theSampScale + theSampOffset;

            //***
            // Compute the partials of each polynomial wrt lat, lon, hgt
            //***
            double dPu_dLat, dQu_dLat, dPv_dLat, dQv_dLat;
            double dPu_dLon, dQu_dLon, dPv_dLon, dQv_dLon;
            double dPu_dHgt, dQu_dHgt, dPv_dHgt, dQv_dHgt;
            dPu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineNumCoef);
            dQu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineDenCoef);
            dPv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampNumCoef);
            dQv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampDenCoef);
            dPu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineNumCoef);
            dQu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineDenCoef);
            dPv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampNumCoef);
            dQv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampDenCoef);
            dPu_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theLineNumCoef);
            dQu_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theLineDenCoef);
            dPv_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theSampNumCoef);
            dQv_dHgt = dPoly_dHgt(nlat, nlon, nhgt, theSampDenCoef);

            //***
            // Compute partials of quotients U and V wrt lat, lon, hgt
            //***
            double dU_dLat, dU_dLon, dU_dHgt, dV_dLat, dV_dLon, dV_dHgt;
            dU_dLat = (Qu*dPu_dLat - Pu*dQu_dLat)/(Qu*Qu);
            dU_dLon = (Qu*dPu_dLon - Pu*dQu_dLon)/(Qu*Qu);
            dU_dHgt = (Qu*dPu_dHgt - Pu*dQu_dHgt)/(Qu*Qu);
            dV_dLat = (Qv*dPv_dLat - Pv*dQv_dLat)/(Qv*Qv);
            dV_dLon = (Qv*dPv_dLon - Pv*dQv_dLon)/(Qv*Qv);
            dV_dHgt = (Qv*dPv_dHgt - Pv*dQv_dHgt)/(Qv*Qv);

            //***
            // Apply necessary scale factors
            //***
            dU_dLat *= theLineScale/theLatScale;
            dU_dLon *= theLineScale/theLonScale;
            dU_dHgt *= theLineScale/theHgtScale;
            dV_dLat *= theSampScale/theLatScale;
            dV_dLon *= theSampScale/theLonScale;
            dV_dHgt *= theSampScale/theHgtScale;

            dU_dLat *= DEG_PER_RAD;
            dU_dLon *= DEG_PER_RAD;
            dV_dLat *= DEG_PER_RAD;
            dV_dLon *= DEG_PER_RAD;

            // Save the partials referenced to ECF
            ossimEcefPoint location(pos);
            NEWMAT::Matrix jMat(3,3);
            pos.datum()->ellipsoid()->jacobianWrtEcef(location, jMat);
            //  Line
            theParWRTx.u = dU_dLat*jMat(1,1)+dU_dLon*jMat(2,1)+dU_dHgt*jMat(3,1);
            theParWRTy.u = dU_dLat*jMat(1,2)+dU_dLon*jMat(2,2)+dU_dHgt*jMat(3,2);
            theParWRTz.u = dU_dLat*jMat(1,3)+dU_dLon*jMat(2,3)+dU_dHgt*jMat(3,3);
            //  Samp
            theParWRTx.v = dV_dLat*jMat(1,1)+dV_dLon*jMat(2,1)+dV_dHgt*jMat(3,1);
            theParWRTy.v = dV_dLat*jMat(1,2)+dV_dLon*jMat(2,2)+dV_dHgt*jMat(3,2);
            theParWRTz.v = dV_dLat*jMat(1,3)+dV_dLon*jMat(2,3)+dV_dHgt*jMat(3,3);

            // Residuals
            ossimDpt resid(theObs.samp-V, theObs.line-U);
            returnData = resid;
        }

        //******************************************
        // P_WRT_X, P_WRT_Y, P_WRT_Z modes
        //   [1] 3 separate calls required
        //   [2] return 3 sets of partials
        //******************************************
        else if (derivMode==P_WRT_X)
        {
            returnData = theParWRTx;
        }

        else if (derivMode==P_WRT_Y)
        {
            returnData = theParWRTy;
        }

        else
        {
            returnData = theParWRTz;
        }

        return returnData;
    }
}
Exemple #28
0
//*****************************************************************************
//  METHOD: ossimRpcModel::worldToLineSample()
//
//  Overrides base class implementation. Directly computes line-sample from
//  the polynomials.
//*****************************************************************************
void ossimRpcModel::worldToLineSample(const ossimGpt& ground_point,
                                      ossimDpt&       img_pt) const
{
    // if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcModel::worldToLineSample(): entering..." << std::endl;

    if(ground_point.isLatNan() || ground_point.isLonNan() )
    {
        img_pt.makeNan();
        return;
    }

    //***
    // First check if the world point is inside bounding rectangle:
    //***
    //ossimDpt wdp (ground_point);
    //if (!(theBoundGndPolygon.pointWithin(ground_point)))
    // {
    //img_pt = extrapolate(ground_point);
    //if (traceExec())  CLOG << "returning..." << endl;
    //   img_pt.makeNan();
    //    return;
    // }

    //***
    // Normalize the lat, lon, hgt:
    //***
    double nlat = (ground_point.lat - theLatOffset) / theLatScale;
    double nlon = (ground_point.lon - theLonOffset) / theLonScale;
    double nhgt;

    if( ground_point.isHgtNan() )
    {
        // nhgt = (theHgtScale - theHgtOffset) / theHgtScale;
        nhgt = ( - theHgtOffset) / theHgtScale;
    }
    else
    {
        nhgt = (ground_point.hgt - theHgtOffset) / theHgtScale;
    }

    //***
    // Compute the adjusted, normalized line (U) and sample (V):
    //***
    double Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
    double Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
    double Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
    double Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
    double U_rot  = Pu / Qu;
    double V_rot  = Pv / Qv;

    //***
    // U, V are normalized quantities. Need now to establish the image file
    // line and sample. First, back out the adjustable parameter effects
    // starting with rotation:
    //***
    double U = U_rot*theCosMapRot + V_rot*theSinMapRot;
    double V = V_rot*theCosMapRot - U_rot*theSinMapRot;

    //***
    // Now back out skew, scale, and offset adjustments:
    //***
    img_pt.line = U*(theLineScale+theIntrackScale) + theLineOffset + theIntrackOffset;

    img_pt.samp = V*(theSampScale+theCrtrackScale) + theSampOffset + theCrtrackOffset;

    // if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcModel::worldToLineSample(): returning..." << std::endl;
    return;
}
Exemple #29
0
//*****************************************************************************
//  METHOD: intersectRay()
//
//  Service method for intersecting a ray with the elevation surface to
//  arrive at a ground point. The ray is expected to originate ABOVE the
//  surface and pointing down.
//
//  NOTE: the gpt argument is expected to be initialized with the desired
//  datum, including ellipsoid, for the proper intersection point to be
//  computed.
//
//  LIMITATION: This release supports only single valued solutions, i.e., it
//  is possible a ray passing through one side of a mountain and out the other
//  will return an intersection with the far side. Eventually, a more robust
//  algorithm will be employed.
//
//*****************************************************************************
bool ossimElevSource::intersectRay(const ossimEcefRay& ray, ossimGpt& gpt, double defaultElevValue)
{
    if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimElevSource::intersectRay: entering..." << std::endl;

    static const double CONVERGENCE_THRESHOLD = 0.001; // meters
    static const int    MAX_NUM_ITERATIONS    = 50;

    double          h_ellips; // height above ellipsoid
    bool            intersected;
    ossimEcefPoint  prev_intersect_pt (ray.origin());
    ossimEcefPoint  new_intersect_pt;
    double          distance;
    bool            done = false;
    int             iteration_count = 0;

    if(ray.hasNans())
    {
        gpt.makeNan();
        return false;
    }
    //***
    // Set the initial guess for horizontal intersect position as the ray's
    // origin, and establish the datum and ellipsoid:
    //***
    const ossimDatum*     datum     = gpt.datum();
    const ossimEllipsoid* ellipsoid = datum->ellipsoid();
//    double lat, lon, h;

//    ellipsoid->XYZToLatLonHeight(ray.origin().x(),
//                                 ray.origin().y(),
//                                 ray.origin().z(),
//                                 lat, lon, h);
//    ossimGpt nadirGpt(lat, lon, h);

//    std::cout << "nadir pt = " << nadirGpt << std::endl;

    gpt = ossimGpt(prev_intersect_pt, datum);

    //
    // Loop to iterate on ray intersection with variable elevation surface:
    //
    do
    {
        //
        // Intersect ray with ellipsoid inflated by h_ellips:
        //
        h_ellips = getHeightAboveEllipsoid(gpt);
        if ( ossim::isnan(h_ellips) ) h_ellips = defaultElevValue;

        intersected = ellipsoid->nearestIntersection(ray,
                      h_ellips,
                      new_intersect_pt);
        if (!intersected)
        {
            //
            // No intersection (looking over the horizon), so set ground point
            // to NaNs:
            //
            gpt.makeNan();
            done = true;
        }
        else
        {
            //
            // Assign the ground point to the latest iteration's intersection
            // point:
            //
            gpt = ossimGpt(new_intersect_pt, datum);

            //
            // Determine if convergence achieved:
            //
            distance = (new_intersect_pt - prev_intersect_pt).magnitude();
            if (distance < CONVERGENCE_THRESHOLD)
                done = true;
            else
            {
                prev_intersect_pt = new_intersect_pt;
            }
        }

        iteration_count++;

    } while ((!done) && (iteration_count < MAX_NUM_ITERATIONS));

    if (iteration_count == MAX_NUM_ITERATIONS)
    {
        if(traceDebug())
        {
            ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimElevSource::intersectRay: Max number of iterations reached solving for ground "
                                               << "point. Result is probably inaccurate." << std::endl;
        }
    }

    if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimElevSource::intersectRay: returning..." << std::endl;
    return intersected;
}
Exemple #30
0
//*****************************************************************************
//  METHOD: ossimRpcModel::lineSampleHeightToWorld()
//
//  Performs reverse projection of image line/sample to ground point.
//  The imaging ray is intersected with a level plane at height = elev.
//
//  NOTE: U = line, V = sample -- this differs from the convention.
//
//*****************************************************************************
void ossimRpcModel::lineSampleHeightToWorld(const ossimDpt& image_point,
        const double&   ellHeight,
        ossimGpt&       gpt) const
{
    // if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcModel::lineSampleHeightToWorld: entering..." << std::endl;

    //***
    // Extrapolate if point is outside image:
    //***
    if (!insideImage(image_point))
    {
//       gpt = extrapolate(image_point, ellHeight);
//       if (traceExec())  CLOG << "returning..." << endl;
        gpt.makeNan();
        return;
    }

    //***
    // Constants for convergence tests:
    //***
    static const int    MAX_NUM_ITERATIONS  = 10;
    static const double CONVERGENCE_EPSILON = 0.1;  // pixels

    //***
    // The image point must be adjusted by the adjustable parameters as well
    // as the scale and offsets given as part of the RPC param normalization.
    //
    //      NOTE: U = line, V = sample
    //***
    double U    = (image_point.y-theLineOffset - theIntrackOffset) / (theLineScale+theIntrackScale);
    double V    = (image_point.x-theSampOffset - theCrtrackOffset) / (theSampScale+theCrtrackScale);

    //***
    // Rotate the normalized U, V by the map rotation error (adjustable param):
    //***
    double U_rot = theCosMapRot*U - theSinMapRot*V;
    double V_rot = theSinMapRot*U + theCosMapRot*V;
    U = U_rot;
    V = V_rot;


    // now apply adjust intrack and cross track
    //***
    // Initialize quantities to be used in the iteration for ground point:
    //***
    double nlat      = 0.0;  // normalized latitude
    double nlon      = 0.0;  // normalized longitude

    double nhgt;

    if(ossim::isnan(ellHeight))
    {
        nhgt = (theHgtScale - theHgtOffset) / theHgtScale;  // norm height
    }
    else
    {
        nhgt = (ellHeight - theHgtOffset) / theHgtScale;  // norm height
    }

    double epsilonU = CONVERGENCE_EPSILON/(theLineScale+theIntrackScale);
    double epsilonV = CONVERGENCE_EPSILON/(theSampScale+theCrtrackScale);
    int    iteration = 0;

    //***
    // Declare variables only once outside the loop. These include:
    // * polynomials (numerators Pu, Pv, and denominators Qu, Qv),
    // * partial derivatives of polynomials wrt X, Y,
    // * computed normalized image point: Uc, Vc,
    // * residuals of normalized image point: deltaU, deltaV,
    // * partial derivatives of Uc and Vc wrt X, Y,
    // * corrections to normalized lat, lon: deltaLat, deltaLon.
    //***
    double Pu, Qu, Pv, Qv;
    double dPu_dLat, dQu_dLat, dPv_dLat, dQv_dLat;
    double dPu_dLon, dQu_dLon, dPv_dLon, dQv_dLon;
    double Uc, Vc;
    double deltaU, deltaV;
    double dU_dLat, dU_dLon, dV_dLat, dV_dLon, W;
    double deltaLat, deltaLon;

    //***
    // Now iterate until the computed Uc, Vc is within epsilon of the desired
    // image point U, V:
    //***
    do
    {
        //***
        // Calculate the normalized line and sample Uc, Vc as ratio of
        // polynomials Pu, Qu and Pv, Qv:
        //***
        Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
        Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
        Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
        Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
        Uc = Pu/Qu;
        Vc = Pv/Qv;

        //***
        // Compute residuals between desired and computed line, sample:
        //***
        deltaU = U - Uc;
        deltaV = V - Vc;

        //***
        // Check for convergence and skip re-linearization if converged:
        //***
        if ((fabs(deltaU) > epsilonU) || (fabs(deltaV) > epsilonV))
        {
            //***
            // Analytically compute the partials of each polynomial wrt lat, lon:
            //***
            dPu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineNumCoef);
            dQu_dLat = dPoly_dLat(nlat, nlon, nhgt, theLineDenCoef);
            dPv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampNumCoef);
            dQv_dLat = dPoly_dLat(nlat, nlon, nhgt, theSampDenCoef);
            dPu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineNumCoef);
            dQu_dLon = dPoly_dLon(nlat, nlon, nhgt, theLineDenCoef);
            dPv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampNumCoef);
            dQv_dLon = dPoly_dLon(nlat, nlon, nhgt, theSampDenCoef);

            //***
            // Analytically compute partials of quotients U and V wrt lat, lon:
            //***
            dU_dLat = (Qu*dPu_dLat - Pu*dQu_dLat)/(Qu*Qu);
            dU_dLon = (Qu*dPu_dLon - Pu*dQu_dLon)/(Qu*Qu);
            dV_dLat = (Qv*dPv_dLat - Pv*dQv_dLat)/(Qv*Qv);
            dV_dLon = (Qv*dPv_dLon - Pv*dQv_dLon)/(Qv*Qv);

            W = dU_dLon*dV_dLat - dU_dLat*dV_dLon;

            //***
            // Now compute the corrections to normalized lat, lon:
            //***
            deltaLat = (dU_dLon*deltaV - dV_dLon*deltaU) / W;
            deltaLon = (dV_dLat*deltaU - dU_dLat*deltaV) / W;
            nlat += deltaLat;
            nlon += deltaLon;
        }

        //double h = ossimElevManager::instance()->getHeightAboveEllipsoid(ossimGpt(nlat, nlon));
        // if(!ossim::isnan(h))
        // {
        //   nhgt = h;
        // }

        iteration++;

    } while (((fabs(deltaU)>epsilonU) || (fabs(deltaV)>epsilonV))
             && (iteration < MAX_NUM_ITERATIONS));

    //***
    // Test for exceeding allowed number of iterations. Flag error if so:
    //***
    if (iteration == MAX_NUM_ITERATIONS)
    {
        ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimRpcModel::lineSampleHeightToWorld: \nMax number of iterations reached in ground point "
                                           << "solution. Results are inaccurate." << endl;
    }

    //***
    // Now un-normalize the ground point lat, lon and establish return quantity:
    //***
    gpt.lat = nlat*theLatScale + theLatOffset;
    gpt.lon = nlon*theLonScale + theLonOffset;
    gpt.hgt = ellHeight;

}