gdal/frmts/msg/reflectancecalculator.cpp

167 строки
5.8 KiB
C++

/******************************************************************************
*
* Purpose: Implementation of ReflectanceCalculator class. Calculate
* reflectance values from radiance, for visual bands.
* Author: Bas Retsios, retsios@itc.nl
*
******************************************************************************
* Copyright (c) 2004, ITC
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
******************************************************************************/
#include "cpl_port.h" // Must be first.
#include "reflectancecalculator.h"
#include <cmath>
#include <cstdlib>
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ReflectanceCalculator::ReflectanceCalculator(std::string sTimeStamp,
double rRTOA)
: m_rRTOA(rRTOA)
{
std::string sYear(sTimeStamp.substr(0, 4));
std::string sMonth(sTimeStamp.substr(4, 2));
std::string sDay(sTimeStamp.substr(6, 2));
std::string sHours(sTimeStamp.substr(8, 2));
std::string sMins(sTimeStamp.substr(10, 2));
m_iYear = atoi(sYear.c_str());
int iMonth = atoi(sMonth.c_str());
m_iDay = atoi(sDay.c_str());
for (int i = 1; i < iMonth; ++i)
m_iDay += iDaysInMonth(i, m_iYear);
int iHours = atoi(sHours.c_str());
int iMins = atoi(sMins.c_str());
m_rHours = iHours + iMins / 60.0;
}
ReflectanceCalculator::~ReflectanceCalculator()
{
}
double ReflectanceCalculator::rGetReflectance(double rRadiance, double rLat,
double rLon) const
{
double phi = rLat * M_PI / 180;
// double lam = rLon * M_PI / 180;
double rSunDist = rSunDistance();
double ReflectanceNumerator = rRadiance * rSunDist * rSunDist;
double zenithAngle = rZenithAngle(phi, rDeclination(), rHourAngle(rLon));
double ReflectanceDenominator = m_rRTOA * cos(zenithAngle * M_PI / 180);
double Reflectance = ReflectanceNumerator / ReflectanceDenominator;
return Reflectance;
}
double ReflectanceCalculator::rZenithAngle(double phi, double rDeclin,
double l_rHourAngle)
{
double rCosZen =
(sin(phi) * sin(rDeclin) + cos(phi) * cos(rDeclin) * cos(l_rHourAngle));
double zenithAngle = acos(rCosZen) * 180 / M_PI;
return zenithAngle;
}
double ReflectanceCalculator::rDeclination() const
{
double rJulianDay = m_iDay - 1;
double yearFraction = (rJulianDay + m_rHours / 24) / iDaysInYear(m_iYear);
double T = 2 * M_PI * yearFraction;
double declin = 0.006918 - 0.399912 * cos(T) + 0.070257 * sin(T) -
0.006758 * cos(2 * T) + 0.000907 * sin(2 * T) -
0.002697 * cos(3 * T) + 0.00148 * sin(3 * T);
return declin;
}
double ReflectanceCalculator::rHourAngle(double rLon) const
{
// In: rLon (in degrees)
// Out: hourAngle (in radians)
double rJulianDay = m_iDay - 1;
double yearFraction = (rJulianDay + m_rHours / 24) / iDaysInYear(m_iYear);
double T = 2 * M_PI * yearFraction;
double EOT2 = 229.18 * (0.000075 + 0.001868 * cos(T) - 0.032077 * sin(T));
double EOT3 = 229.18 * (-0.014615 * cos(2 * T) - 0.040849 * sin(2 * T));
double EOT = EOT2 + EOT3;
double TimeOffset = EOT + (4. * rLon);
// True solar time in minutes:
double TrueSolarTime = m_rHours * 60 + TimeOffset;
// Solar hour angle in degrees and in radians:
double HaDegr = (TrueSolarTime / 4. - 180.);
double hourAngle = HaDegr * M_PI / 180;
return hourAngle;
}
double ReflectanceCalculator::rSunDistance() const
{
int iJulianDay = m_iDay - 1;
double theta = 2 * M_PI * (iJulianDay - 3) / 365.25;
// rE0 is the inverse of the square of the sun-distance ratio
double rE0 = 1.000110 + 0.034221 * cos(theta) + 0.00128 * sin(theta) +
0.000719 * cos(2 * theta) + 0.000077 * sin(2 * theta);
// The calculated distance is expressed as a factor of the "average
// sun-distance" (on 1 Jan approx. 0.98, on 1 Jul approx. 1.01)
return 1 / sqrt(rE0);
}
int ReflectanceCalculator::iDaysInYear(int iYear)
{
bool fLeapYear = iDaysInMonth(2, iYear) == 29;
if (fLeapYear)
return 366;
else
return 365;
}
int ReflectanceCalculator::iDaysInMonth(int iMonth, int iYear)
{
int iDays;
if ((iMonth == 4) || (iMonth == 6) || (iMonth == 9) || (iMonth == 11))
iDays = 30;
else if (iMonth == 2)
{
iDays = 28;
if (iYear % 100 == 0) // century year
{
if (iYear % 400 == 0) // century leap year
++iDays;
}
else
{
if (iYear % 4 == 0) // normal leap year
++iDays;
}
}
else
iDays = 31;
return iDays;
}