//***************************************************************************** // 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(); } }
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); }
//***************************************************************************** // 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); }
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"); }
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); }
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); }
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); } }
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; }
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); }
//***************************************************************************** // 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; }
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; } }
//***************************************************************************** // 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; } }
//***************************************************************************** // 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; }
//***************************************************************************** // 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; }
//***************************************************************************** // 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; }