mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-23 00:02:38 -05:00
* MDAL 0.5.90 : support for custom Logger and 1D meshes * [FEATURE] [MESH] Support rendering of 1D meshes, see https://github.com/qgis/QGIS-Enhancement-Proposals/issues/164 1D mesh consist of edges (edge is straight line segment with 2 vertices) and the data that is defined on either vertices or edges. Such data can be loaded by MDAL and rendered as mesh layer in QGIS.
352 lines
11 KiB
C++
352 lines
11 KiB
C++
/*
|
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
|
Copyright (C) 2019 Vincent Cloarec (vcloarec at gmail dot com)
|
|
*/
|
|
#include "mdal_datetime.hpp"
|
|
#include "mdal_utils.hpp"
|
|
|
|
|
|
constexpr double MILLISECONDS_IN_SECOND = 1000;
|
|
constexpr double MILLISECONDS_IN_MINUTE = 1000 * 60;
|
|
constexpr double MILLISECONDS_IN_HOUR = 1000 * 60 * 60;
|
|
constexpr double MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
|
|
constexpr double MILLISECONDS_IN_WEEK = 1000 * 60 * 60 * 24 * 7;
|
|
|
|
//https://www.unidata.ucar.edu/software/netcdf-java/current/CDM/CalendarDateTime.html
|
|
constexpr double MILLISECONDS_IN_EXACT_YEAR = 3.15569259747e10; //CF Compliant
|
|
constexpr double MILLISECONDS_IN_MONTH_CF = MILLISECONDS_IN_EXACT_YEAR / 12.0; //CF Compliant
|
|
|
|
MDAL::DateTime::DateTime() = default;
|
|
|
|
MDAL::DateTime::DateTime( int year, int month, int day, int hours, int minutes, double seconds, MDAL::DateTime::Calendar calendar )
|
|
{
|
|
DateTimeValues value{year, month, day, hours, minutes, seconds};
|
|
|
|
switch ( calendar )
|
|
{
|
|
case MDAL::DateTime::Gregorian:
|
|
setWithGregorianJulianCalendarDate( value );
|
|
break;
|
|
case MDAL::DateTime::ProlepticGregorian:
|
|
setWithGregorianCalendarDate( value );
|
|
break;
|
|
case MDAL::DateTime::Julian:
|
|
setWithJulianCalendarDate( value );
|
|
break;
|
|
}
|
|
}
|
|
|
|
MDAL::DateTime::DateTime( double value, Epoch epoch ): mValid( true )
|
|
{
|
|
switch ( epoch )
|
|
{
|
|
case MDAL::DateTime::Unix:
|
|
mJulianTime = ( DateTime( 1970, 01, 01, 0, 0, 0, Gregorian ) + RelativeTimestamp( value, RelativeTimestamp::seconds ) ).mJulianTime;
|
|
break;
|
|
case MDAL::DateTime::JulianDay:
|
|
mJulianTime = int64_t( value * MILLISECONDS_IN_DAY + 0.5 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::string MDAL::DateTime::toStandartCalendarISO8601() const
|
|
{
|
|
if ( mValid )
|
|
{
|
|
DateTimeValues value = dateTimeGregorianProleptic();
|
|
if ( value.year > 0 )
|
|
return toString( value );
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
double MDAL::DateTime::toJulianDay() const
|
|
{
|
|
return mJulianTime / MILLISECONDS_IN_DAY;
|
|
}
|
|
|
|
std::string MDAL::DateTime::toJulianDayString() const
|
|
{
|
|
return std::to_string( toJulianDay() );
|
|
}
|
|
|
|
|
|
MDAL::DateTime MDAL::DateTime::operator+( const MDAL::RelativeTimestamp &duration ) const
|
|
{
|
|
if ( !mValid )
|
|
return DateTime();
|
|
return DateTime( mJulianTime + duration.mDuration );
|
|
}
|
|
|
|
|
|
MDAL::DateTime MDAL::DateTime::operator-( const MDAL::RelativeTimestamp &duration ) const
|
|
{
|
|
if ( !mValid )
|
|
return DateTime();
|
|
return DateTime( mJulianTime - duration.mDuration );
|
|
}
|
|
|
|
bool MDAL::DateTime::operator==( const MDAL::DateTime &other ) const
|
|
{
|
|
if ( !mValid && !other.mValid )
|
|
return true;
|
|
|
|
return ( mValid && other.mValid ) && ( mJulianTime == other.mJulianTime );
|
|
}
|
|
|
|
bool MDAL::DateTime::operator<( const MDAL::DateTime &other ) const
|
|
{
|
|
if ( !mValid && !other.mValid )
|
|
return false;
|
|
return ( mValid && other.mValid ) && ( mJulianTime < other.mJulianTime );
|
|
}
|
|
|
|
bool MDAL::DateTime::isValid() const { return mValid; }
|
|
|
|
MDAL::DateTime::DateTime( int64_t julianTime ): mJulianTime( julianTime ), mValid( true )
|
|
{}
|
|
|
|
/*
|
|
MDAL::DateTime::DateTimeValues MDAL::DateTime::dateTimeGregorianJulianCalendar() const
|
|
{
|
|
// https://fr.wikipedia.org/wiki/Jour_julien
|
|
DateTimeValues values;
|
|
int Z = int( mJulianTime / MILLISECONDS_IN_DAY + 0.5 ); // integer part of julian days count
|
|
double F = ( mJulianTime - MILLISECONDS_IN_DAY * ( Z - 0.5 ) ) / MILLISECONDS_IN_DAY; // fractional part of julian days count;
|
|
int S;
|
|
|
|
if ( Z < 2299161 )
|
|
S = Z;
|
|
else
|
|
{
|
|
int alpha = int( ( Z - 1867216.25 ) / 36524.25 );
|
|
S = Z + 1 + alpha - int( alpha / 4 );
|
|
}
|
|
|
|
int B = S + 1524;
|
|
int C = int( ( B - 122.1 ) / 365.25 );
|
|
int D = int( 365.25 * C );
|
|
int E = int( ( B - D ) / 30.6001 );
|
|
|
|
values.day = B - D - int( 30.6001 * E );
|
|
if ( E < 14 )
|
|
values.month = E - 1;
|
|
else
|
|
values.month = E - 13;
|
|
|
|
if ( values.month > 2 )
|
|
values.year = C - 4716;
|
|
else
|
|
values.year = C - 4715;
|
|
|
|
values.hours = int( F / MILLISECONDS_IN_HOUR );
|
|
F = int( F - values.hours * MILLISECONDS_IN_HOUR );
|
|
values.minutes = int( F / MILLISECONDS_IN_MINUTE );
|
|
F = int( F - values.minutes * MILLISECONDS_IN_MINUTE );
|
|
values.seconds = int( F / MILLISECONDS_IN_SECOND );
|
|
|
|
return values;
|
|
}
|
|
*/
|
|
|
|
MDAL::DateTime::DateTimeValues MDAL::DateTime::dateTimeGregorianProleptic() const
|
|
{
|
|
// https://fr.wikipedia.org/wiki/Jour_julien
|
|
DateTimeValues values;
|
|
int Z = int( mJulianTime / MILLISECONDS_IN_DAY + 0.5 ); // integer part of julian days count
|
|
int F = int( mJulianTime - MILLISECONDS_IN_DAY * ( Z - 0.5 ) ) ; // fractional part of julian days count in ms;
|
|
|
|
int alpha = int( ( Z - 1867216.25 ) / 36524.25 );
|
|
int S = Z + 1 + alpha - int( alpha / 4 );
|
|
|
|
int B = S + 1524;
|
|
int C = int( ( B - 122.1 ) / 365.25 );
|
|
int D = int( 365.25 * C );
|
|
int E = int( ( B - D ) / 30.6001 );
|
|
|
|
values.day = B - D - int( 30.6001 * E );
|
|
if ( E < 14 )
|
|
values.month = E - 1;
|
|
else
|
|
values.month = E - 13;
|
|
|
|
if ( values.month > 2 )
|
|
values.year = C - 4716;
|
|
else
|
|
values.year = C - 4715;
|
|
|
|
values.hours = int( F / MILLISECONDS_IN_HOUR );
|
|
F = int( F - values.hours * MILLISECONDS_IN_HOUR );
|
|
values.minutes = int( F / MILLISECONDS_IN_MINUTE );
|
|
F = int( F - values.minutes * MILLISECONDS_IN_MINUTE );
|
|
values.seconds = int( F / MILLISECONDS_IN_SECOND );
|
|
|
|
return values;
|
|
}
|
|
|
|
|
|
void MDAL::DateTime::setWithGregorianCalendarDate( MDAL::DateTime::DateTimeValues values )
|
|
{
|
|
// https://quasar.as.utexas.edu/BillInfo/JulianDatesG.html
|
|
if ( values.month <= 2 )
|
|
{
|
|
values.year--;
|
|
values.month += 12;
|
|
}
|
|
|
|
int A = values.year / 100;
|
|
int B = A / 4;
|
|
int C = 2 - A + B;
|
|
int E = int( 365.25 * ( values.year + 4716 ) );
|
|
int F = int( 30.6001 * ( values.month + 1 ) );
|
|
double julianDay = C + values.day + E + F - 1524.5;
|
|
|
|
mValid = true;
|
|
mJulianTime = int64_t( julianDay * MILLISECONDS_IN_DAY +
|
|
( values.hours ) * MILLISECONDS_IN_HOUR +
|
|
values.minutes * MILLISECONDS_IN_MINUTE +
|
|
values.seconds * MILLISECONDS_IN_SECOND );
|
|
}
|
|
|
|
void MDAL::DateTime::setWithJulianCalendarDate( MDAL::DateTime::DateTimeValues values )
|
|
{
|
|
// https://quasar.as.utexas.edu/BillInfo/JulianDatesG.html
|
|
if ( values.month <= 2 )
|
|
{
|
|
values.year--;
|
|
values.month += 12;
|
|
}
|
|
|
|
int E = int( 365.25 * ( values.year + 4716 ) );
|
|
int F = int( 30.6001 * ( values.month + 1 ) );
|
|
double julianDay = values.day + E + F - 1524.5;
|
|
|
|
mValid = true;
|
|
mJulianTime = int64_t( julianDay * MILLISECONDS_IN_DAY +
|
|
( values.hours ) * MILLISECONDS_IN_HOUR +
|
|
values.minutes * MILLISECONDS_IN_MINUTE +
|
|
values.seconds * MILLISECONDS_IN_SECOND );
|
|
}
|
|
|
|
void MDAL::DateTime::setWithGregorianJulianCalendarDate( MDAL::DateTime::DateTimeValues values )
|
|
{
|
|
// https://quasar.as.utexas.edu/BillInfo/JulianDatesG.html
|
|
|
|
mValid = true;
|
|
|
|
if ( values.year > 1582 ||
|
|
( values.year == 1582 && ( values.month > 10 || ( values.month == 10 && values.day >= 15 ) ) ) ) // gregorian calendar
|
|
{
|
|
setWithGregorianCalendarDate( values );
|
|
}
|
|
else
|
|
setWithJulianCalendarDate( values );
|
|
}
|
|
|
|
std::string MDAL::DateTime::toString( MDAL::DateTime::DateTimeValues values ) const
|
|
{
|
|
int miliseconds = int( ( values.seconds - int( values.seconds ) ) * 1000 + 0.5 );
|
|
std::string msStr;
|
|
if ( miliseconds > 0 )
|
|
{
|
|
if ( miliseconds < 10 )
|
|
msStr = prependZero( std::to_string( miliseconds ), 3 );
|
|
else if ( miliseconds < 100 )
|
|
msStr = prependZero( std::to_string( miliseconds ), 2 );
|
|
else if ( miliseconds < 1000 )
|
|
msStr = std::to_string( miliseconds );
|
|
|
|
msStr = std::string( "," ).append( msStr );
|
|
}
|
|
|
|
std::string strDateTime = prependZero( std::to_string( values.year ), 4 ) + "-" +
|
|
prependZero( std::to_string( values.month ), 2 ) + "-" +
|
|
prependZero( std::to_string( values.day ), 2 ) + "T" +
|
|
prependZero( std::to_string( values.hours ), 2 ) + ":" +
|
|
prependZero( std::to_string( values.minutes ), 2 ) + ":" +
|
|
prependZero( std::to_string( int( values.seconds ) ), 2 ) +
|
|
msStr;
|
|
|
|
return strDateTime;
|
|
}
|
|
|
|
MDAL::RelativeTimestamp MDAL::DateTime::operator-( const MDAL::DateTime &other ) const
|
|
{
|
|
if ( !mValid || !other.mValid )
|
|
return RelativeTimestamp();
|
|
return RelativeTimestamp( mJulianTime - other.mJulianTime );
|
|
}
|
|
|
|
|
|
MDAL::RelativeTimestamp::RelativeTimestamp() = default;
|
|
|
|
MDAL::RelativeTimestamp::RelativeTimestamp( double duration, MDAL::RelativeTimestamp::Unit unit )
|
|
{
|
|
switch ( unit )
|
|
{
|
|
case MDAL::RelativeTimestamp::milliseconds:
|
|
mDuration = int64_t( duration );
|
|
break;
|
|
case MDAL::RelativeTimestamp::seconds:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_SECOND + 0.5 );
|
|
break;
|
|
case MDAL::RelativeTimestamp::minutes:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_MINUTE + 0.5 );
|
|
break;
|
|
case MDAL::RelativeTimestamp::hours:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_HOUR + 0.5 );
|
|
break;
|
|
case MDAL::RelativeTimestamp::days:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_DAY + 0.5 );
|
|
break;
|
|
case MDAL::RelativeTimestamp::weeks:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_WEEK + 0.5 );
|
|
break;
|
|
case MDAL::RelativeTimestamp::months_CF:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_MONTH_CF + 0.5 );
|
|
break;
|
|
case MDAL::RelativeTimestamp::exact_years:
|
|
mDuration = int64_t( duration * MILLISECONDS_IN_EXACT_YEAR + 0.5 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
double MDAL::RelativeTimestamp::value( MDAL::RelativeTimestamp::Unit unit ) const
|
|
{
|
|
switch ( unit )
|
|
{
|
|
case MDAL::RelativeTimestamp::milliseconds:
|
|
return double( mDuration );
|
|
case MDAL::RelativeTimestamp::seconds:
|
|
return mDuration / MILLISECONDS_IN_SECOND;
|
|
case MDAL::RelativeTimestamp::minutes:
|
|
return mDuration / MILLISECONDS_IN_MINUTE;
|
|
case MDAL::RelativeTimestamp::hours:
|
|
return mDuration / MILLISECONDS_IN_HOUR;
|
|
case MDAL::RelativeTimestamp::days:
|
|
return double( mDuration ) / MILLISECONDS_IN_DAY;
|
|
case MDAL::RelativeTimestamp::weeks:
|
|
return double( mDuration ) / MILLISECONDS_IN_WEEK;
|
|
case MDAL::RelativeTimestamp::months_CF:
|
|
return double( mDuration ) / MILLISECONDS_IN_MONTH_CF;
|
|
case MDAL::RelativeTimestamp::exact_years:
|
|
return double( mDuration ) / MILLISECONDS_IN_EXACT_YEAR;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool MDAL::RelativeTimestamp::operator==( const MDAL::RelativeTimestamp &other ) const
|
|
{
|
|
return mDuration == other.mDuration;
|
|
}
|
|
|
|
bool MDAL::RelativeTimestamp::operator<( const MDAL::RelativeTimestamp &other ) const
|
|
{
|
|
return mDuration < other.mDuration;
|
|
}
|
|
|
|
MDAL::RelativeTimestamp::RelativeTimestamp( int64_t ms ): mDuration( ms )
|
|
{}
|