⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 darkcal.cpp

📁 This is a pgm can be used for astronomy
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------------------
 * DarkCal - calculates the darkest hours for a given month and year.
 *
 * Created by Mark Huss <mark@mhuss.com>
 *
 * This is a generic console program and has been built and run on both
 * win32 and "unix-like" systems.
 *
 * Developed and built using the mingw32 gcc compiler 2.95.2
 *
 * THIS SOFTWARE IS NOT COPYRIGHTED
 *
 * This source code is offered for use in the public domain. You may
 * use, modify or distribute it freely.
 *
 * This code is distributed in the hope that it will be useful but
 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
 * DISCLAMED. This includes but is not limited to warranties of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Astro library based on Bill Gray's open-source code at projectpluto.com
 *
 * created August 2000
 */
//---------------------------------------------------------------------------

#include "AstroOps.h"
#include "PlanetData.h"
#include "DateOps.h"

#include "RiseSet.h"

#include "ConfigFile.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//----------------------------------------------------------------------------

#define TP_START a
#define TP_END b
#define TP_RISE a
#define TP_SET b

#define DEBUG 1
#undef PROGRESS_BAR

static const char* CFG_EXT = ".cfg";

static const int DAYS=33;     // 31 max plus one on either side

static const char* monthNames[] = {
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"
};

enum DST { DST_NONE, DST_START, DST_END };

// Struct to hold date & location
struct CalData {
  CalData() : month(1), year(2000) {}

  int month;
  int year;
  ObsInfo loc;
};

// file globals
static bool g_tabDelimited = false; // true means produce tab-delimited output
static bool g_ignoreDst = false;    // true means ignore DST
static bool g_html = false;         // true means produce HTML output
static FILE* g_fp = stdout;         // file to use for tab-d or HTML

//----------------------------------------------------------------------------
// print heading
//
void printHeading(CalData& cd) {
  const char* pUtc = ( cd.loc.timeZone() < 0 ) ? "UTC" : "UTC+";
  char title[256];
  sprintf( title,
      "%s, %d at latitude %5.2f, longitude %5.2f, tz %s%d",
       monthNames[ cd.month-1 ], cd.year, cd.loc.degLatitude(),
       cd.loc.degLongitude(), pUtc, cd.loc.timeZone() );

  if ( g_tabDelimited ) {
    fprintf( g_fp, "\n%s\n\n", title );
    fputs( "Day\tDarkest Hours\tEvent\tMoon Rises\tMoon Sets\t"
            "Sunset\tAstronomical Twilight Ends\tNext Day\t"
            "Astronomical Twilight Starts\tSunrise\n", g_fp );
  }
  else if (g_html)
    fprintf( g_fp, "<HTML>\n"
          "<HEAD>\n"
          "  <TITLE>Darkest Hours</TITLE>\n"
          "</HEAD>\n<BODY>\n"
          "<STYLE type=\"text/css\">\n<!--\n"
          "  TH, TD { font-size:12px }\n"
          "  .bar { background:silver }\n"
          "-->\n</STYLE>\n"
          "<H2>Darkest Hours</H2>\n"
          "<TABLE CELLSPACING=0 BORDER=0 WIDTH=\"100%%\">\n"
          "<TR CLASS=\"bar\"><TH COLSPAN=10 ALIGN=\"center\">%s</TH></TR>\n"
          "<TR>\n"
          "  <TH>Day</TH>\n  <TH>Darkest<BR>Hours</TH>\n  <TH>Event</TH>\n"
          "  <TH>Moon<BR>Rises</TH>\n  <TH>Moon<BR>Sets</TH>\n"
          "  <TH>Sunset</TH>\n  <TH>AstTwi<BR>Ends</TH>\n  <TH>Next<BR>Day</TH>\n"
          "  <TH>AstTwi<BR>Starts</TH>\n  <TH>Sunrise</TH>\n"
          "</TR>\n", title );
  else {
    printf( "\n%s\n\n"
            "Day Darkest                  Moon   Moon   Sunset AstTwi Next AstTwi Sunrise\n"
            "    Hours          Events    Rises  Sets          Ends   Day  Starts\n"
            "--  -------------  --------  -----  -----  -----  -----  --   -----  -----\n",
             title );
  }
}

//----------------------------------------------------------------------------
static char* nextColumn( char* p, int sp, bool empty=false )
{
  if (g_tabDelimited)
    *p++ = '\t';
  else if (g_html) {
    if (empty)
      strcpy(p,"&nbsp;</TD>\n  <TD>");
    else
      strcpy(p,"</TD>\n  <TD>");
    p += strlen(p);
  }
  else {
    while (sp--)
      *p++ = ' ';
  }
  return p;
}

//----------------------------------------------------------------------------
// print a (double) time as hh:mm
//
// a time < 0 is printed as '--:--'
//
static char* printTime( char* p, double t, bool ws=true )
{
   if( t < 0.)
      sprintf( p, "--:--" );
   else {
      // round up to nearest minute
      long minutes = long(t * 24. * 60. + .5);
      sprintf( p, "%02d:%02d", int(minutes / 60), int(minutes % 60) );
   }
   return ws ? nextColumn( p+5, 2) : p+5;
}

//----------------------------------------------------------------------------
// print a pair of (double) times as hh:mm
//
static char* printTimes( char* p, TimePair& tp ) {
   p = printTime( p, tp.a, false );
   *p++ = ' ';
   *p++ = '-';
   *p++ = ' ';
   return printTime( p, tp.b );
}

//----------------------------------------------------------------------------
// print the day, substituting 'Su' on Sundays
//
// d = 1..31
//
static char* printDay( char* p, long jd, int d, bool eom ) {
  if( (jd+d) % 7 == 6)        /* Sunday */
    strcpy( p, "Su" );
  else {
    int nextDay = eom ? 1 : d+1;
    sprintf( p, "%2d", nextDay );
  }
  return nextColumn(p+2,2);
}

//----------------------------------------------------------------------------
// figure out darkest hours & print to buffer
//
char* printDarkness( char* p, int i, const TimePair* const astTwi, const TimePair* const moonRSOrg )
{
  TimePair dark = { astTwi[i].TP_END, astTwi[i+1].TP_START };

  // first time in, create a local copy that we can munge
  static TimePair moonRS[DAYS];
  if ( 0 == i )
    memcpy( moonRS, moonRSOrg, sizeof(TimePair)*DAYS);

  // define day + time vars to deal with 'yesterday' and 'tomorrow'
  double darkStart = astTwi[i].TP_END + i;
  double darkEnd = astTwi[i+1].TP_START + (i+1);

  double moonRise;
  if ( moonRS[i].TP_RISE < 0. || moonRS[i].TP_SET > moonRS[i].TP_RISE) {
      moonRise = moonRS[i+1].TP_RISE + (i+1);
      moonRS[i].TP_RISE = moonRS[i+1].TP_RISE;
  }
  else
      moonRise = moonRS[i].TP_RISE + i;

  double moonSet;
  if ( moonRS[i].TP_SET < 0. || moonRS[i].TP_RISE > moonRS[i].TP_SET ) {
    moonSet = moonRS[i+1].TP_SET + (i+1);
    moonRS[i].TP_SET = moonRS[i+1].TP_SET;
  }
  else
    moonSet = moonRS[i].TP_SET + i;

  // check moon rise & set
  if (moonSet > darkStart && moonSet < darkEnd) {
    darkStart = moonSet;
    dark.TP_START = moonRS[i].TP_SET;
  }
  if (moonRise > darkStart && moonRise < darkEnd ) {
    darkEnd = moonRise;
    dark.TP_END = moonRS[i].TP_RISE;
  }

  bool noDarkness = (moonRise < darkStart && moonSet > darkEnd );

  // print out darkness range or 'none'
  if ( noDarkness ) {
    strcpy(p, " -- none -- " );
    p = nextColumn(p+12, 3);
  }
  else
    p = printTimes( p, dark );

  return p;
}

//----------------------------------------------------------------------------
// helper fn for printEvents
inline char* append(char* pTo, const char* pFrom, int len)
{
  memcpy( pTo, pFrom, len );
  return pTo + len;
}

//----------------------------------------------------------------------------
// check for lunar and solar quarters & print if found
//

char* printEvents( char*p, int i, double* jd, ObsInfo& oi, DST dstDay )
{
  char* pStart = p;

  static PlanetData pd;
  double lunarLon[2], solarLon[2];

  // get ecliptic longitude for earth & moon
  //
  for( int j=0; j<2; j++ ) {
    pd.calc( EARTH, jd[i] + double(j), oi );
    solarLon[j] = pd.eclipticLon();

    pd.calc( LUNA, jd[i] + double(j), oi );
    lunarLon[j] = pd.eclipticLon();
  }

  // We don't bother finding the exact instant of the following events.
  // The code just checks for a quadrant change and reports the  event.

  // check for lunar quarters
  //
  int quad1 = RiseSet::quadrant( lunarLon[1] - solarLon[1] );
  int quad0 = RiseSet::quadrant( lunarLon[0] - solarLon[0] );
  if( quad1 != quad0 ) {
      static const char* strings[4] = { "1Q ", "FM ", "3Q ", "NM " };
      p = append( p, strings[quad0], 3);
  }

  // check for solar quarters
  //
  quad1 = RiseSet::quadrant( solarLon[1] );
  quad0 = RiseSet::quadrant( solarLon[0] );
  if( quad1 != quad0 ) {
      static const char* strings[4] =
          { "SumSol ", "Aut Eq  ", "WinSol ", "Ver Eq " };

      p = append( p, strings[quad0], 7 );
  }

  // handle DST indicator
  if ( DST_START == dstDay )
    p = append( p, "DSTime", 6 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -