• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • kstars
  • tools
modcalcvizequinox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  modcalcvizequinox.cpp - description
3  -------------------
4  begin : Thu 22 Feb 2007
5  copyright : (C) 2007 by Jason Harris
6  email : kstars@30doradus.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "modcalcvizequinox.h"
19 
20 #include <cmath> //fabs()
21 
22 #include <KPlotWidget>
23 #include <KPlotAxis>
24 #include <KPlotObject>
25 #include <KPlotPoint>
26 #include <KGlobal>
27 #include <KLocale>
28 #include <kmessagebox.h>
29 
30 #include "dms.h"
31 #include "kstarsdata.h"
32 #include "kstarsdatetime.h"
33 #include "ksnumbers.h"
34 #include "skyobjects/kssun.h"
35 #include "widgets/dmsbox.h"
36 
37 
38 modCalcEquinox::modCalcEquinox(QWidget *parentSplit) :
39  QFrame(parentSplit), dSpring(), dSummer(), dAutumn(), dWinter()
40 {
41  setupUi(this);
42 
43  connect( Year, SIGNAL( valueChanged(int) ), this, SLOT( slotCompute() ) );
44  connect( InputFileBatch, SIGNAL(urlSelected(const KUrl&)), this, SLOT(slotCheckFiles()) );
45  connect( OutputFileBatch, SIGNAL(urlSelected(const KUrl&)), this, SLOT(slotCheckFiles()) );
46  connect( RunButtonBatch, SIGNAL(clicked()), this, SLOT(slotRunBatch()));
47  connect( ViewButtonBatch, SIGNAL(clicked()), this, SLOT(slotViewBatch()));
48 
49  Plot->axis(KPlotWidget::LeftAxis)->setLabel( i18n("Sun's Declination") );
50  Plot->setTopPadding( 40 );
51  //Don't draw Top & Bottom axes; custom axes drawn as plot objects
52  Plot->axis(KPlotWidget::BottomAxis)->setVisible( false );
53  Plot->axis(KPlotWidget::TopAxis)->setVisible( false );
54 
55  //This will call slotCompute():
56  Year->setValue( KStarsData::Instance()->lt().date().year() );
57 
58  RunButtonBatch->setEnabled( false );
59  ViewButtonBatch->setEnabled( false );
60 
61  show();
62 }
63 
64 modCalcEquinox::~modCalcEquinox(){
65 }
66 
67 double modCalcEquinox::dmonth(int i) {
68  Q_ASSERT( i>=0 && i<12 && "Month must be in 0 .. 11 range");
69  return DMonth[i];
70 }
71 
72 void modCalcEquinox::slotCheckFiles() {
73  RunButtonBatch->setEnabled(
74  !InputFileBatch->lineEdit()->text().isEmpty() && !OutputFileBatch->lineEdit()->text().isEmpty()
75  );
76 }
77 
78 void modCalcEquinox::slotRunBatch() {
79  QString inputFileName = InputFileBatch->url().toLocalFile();
80 
81  if ( QFile::exists(inputFileName) ) {
82  QFile f( inputFileName );
83  if ( !f.open( QIODevice::ReadOnly) ) {
84  QString message = i18n( "Could not open file %1.", f.fileName() );
85  KMessageBox::sorry( 0, message, i18n( "Could Not Open File" ) );
86  inputFileName.clear();
87  return;
88  }
89 
90  QTextStream istream(&f);
91  processLines( istream );
92 
93  ViewButtonBatch->setEnabled( true );
94 
95  f.close();
96  } else {
97  QString message = i18n( "Invalid file: %1", inputFileName );
98  KMessageBox::sorry( 0, message, i18n( "Invalid file" ) );
99  inputFileName.clear();
100  return;
101  }
102 }
103 
104 void modCalcEquinox::processLines( QTextStream &istream ) {
105  QFile fOut( OutputFileBatch->url().toLocalFile() );
106  fOut.open(QIODevice::WriteOnly);
107  QTextStream ostream(&fOut);
108  int originalYear = Year->value();
109 
110  //Write header to output file
111  ostream << i18n("# Timing of Equinoxes and Solstices\n")
112  << i18n("# computed by KStars\n#\n")
113  << i18n("# Vernal Equinox\t\tSummer Solstice\t\t\tAutumnal Equinox\t\tWinter Solstice\n#\n");
114 
115  while ( ! istream.atEnd() ) {
116  QString line = istream.readLine();
117  bool ok = false;
118  int year = line.toInt( &ok );
119 
120  //for now I will simply change the value of the Year widget to trigger
121  //computation of the Equinoxes and Solstices.
122  if ( ok ) {
123  //triggers slotCompute(), which sets values of dSpring et al.:
124  Year->setValue( year );
125 
126  //Write to output file
127  ostream <<
128  KGlobal::locale()->formatDate( dSpring.date(), KLocale::LongDate ) << "\t"
129  << KGlobal::locale()->formatDate( dSummer.date(), KLocale::LongDate ) << "\t"
130  << KGlobal::locale()->formatDate( dAutumn.date(), KLocale::LongDate ) << "\t"
131  << KGlobal::locale()->formatDate( dWinter.date(), KLocale::LongDate ) << endl;
132  }
133  }
134 
135  if ( Year->value() != originalYear )
136  Year->setValue( originalYear );
137 }
138 
139 void modCalcEquinox::slotViewBatch() {
140  QFile fOut( OutputFileBatch->url().toLocalFile() );
141  fOut.open(QIODevice::ReadOnly);
142  QTextStream istream(&fOut);
143  QStringList text;
144 
145  while ( ! istream.atEnd() )
146  text.append( istream.readLine() );
147 
148  fOut.close();
149 
150  KMessageBox::informationList( 0, i18n("Results of Sidereal time calculation"), text, OutputFileBatch->url().toLocalFile() );
151 }
152 
153 void modCalcEquinox::slotCompute()
154 {
155  KStarsData* data = KStarsData::Instance();
156  KSSun Sun;
157  int year0 = Year->value();
158 
159  KStarsDateTime dt( QDate(year0, 1, 1), QTime(0,0,0) );
160  long double jd0 = dt.djd(); //save JD on Jan 1st
161  for ( int imonth=0; imonth < 12; imonth++ ) {
162  KStarsDateTime kdt( QDate(year0, imonth+1, 1), QTime(0,0,0) );
163  DMonth[imonth] = kdt.djd() - jd0;
164  }
165 
166  Plot->removeAllPlotObjects();
167 
168  //Add the celestial equator, just a single line bisecting the plot horizontally
169  KPlotObject *ce = new KPlotObject( data->colorScheme()->colorNamed( "EqColor" ), KPlotObject::Lines, 2.0 );
170  ce->addPoint( 0.0, 0.0 );
171  ce->addPoint( 366.0, 0.0 );
172  Plot->addPlotObject( ce );
173 
174  //Add Ecliptic. This is more complicated than simply incrementing the
175  //ecliptic longitude, because we want the x-axis to be time, not RA.
176  //For each day in the year, compute the Sun's position.
177  KPlotObject *ecl = new KPlotObject( data->colorScheme()->colorNamed( "EclColor" ), KPlotObject::Lines, 2 );
178  ecl->setLinePen( QPen( ecl->pen().color(), 4 ) );
179 
180  Plot->setLimits( 1.0, double(dt.date().daysInYear()), -30.0, 30.0 );
181 
182  //Add top and bottom axis lines, and custom tickmarks at each month
183  addDateAxes();
184 
185  for ( int i=1; i<=dt.date().daysInYear(); i++ ) {
186  KSNumbers num( dt.djd() );
187  Sun.findPosition( &num );
188  ecl->addPoint( double(i), Sun.dec().Degrees() );
189 
190  dt = dt.addDays( 1 );
191  }
192  Plot->addPlotObject( ecl );
193 
194  dSpring = findEquinox( Year->value(), true, ecl );
195  dSummer = findSolstice( Year->value(), true );
196  dAutumn = findEquinox( Year->value(), false, ecl );
197  dWinter = findSolstice( Year->value(), false );
198 
199  //Display the Date/Time of each event in the text fields
200  VEquinox->setText( KGlobal::locale()->formatDateTime( dSpring, KLocale::LongDate ) );
201  SSolstice->setText( KGlobal::locale()->formatDateTime( dSummer, KLocale::LongDate ) );
202  AEquinox->setText( KGlobal::locale()->formatDateTime( dAutumn, KLocale::LongDate ) );
203  WSolstice->setText( KGlobal::locale()->formatDateTime( dWinter, KLocale::LongDate ) );
204 
205  //Add vertical dotted lines at times of the equinoxes and solstices
206  KPlotObject *poSpring = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
207  poSpring->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) );
208  poSpring->addPoint( dSpring.djd()-jd0, Plot->dataRect().top() );
209  poSpring->addPoint( dSpring.djd()-jd0, Plot->dataRect().bottom() );
210  Plot->addPlotObject( poSpring );
211  KPlotObject *poSummer = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
212  poSummer->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) );
213  poSummer->addPoint( dSummer.djd()-jd0, Plot->dataRect().top() );
214  poSummer->addPoint( dSummer.djd()-jd0, Plot->dataRect().bottom() );
215  Plot->addPlotObject( poSummer );
216  KPlotObject *poAutumn = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
217  poAutumn->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) );
218  poAutumn->addPoint( dAutumn.djd()-jd0, Plot->dataRect().top() );
219  poAutumn->addPoint( dAutumn.djd()-jd0, Plot->dataRect().bottom() );
220  Plot->addPlotObject( poAutumn );
221  KPlotObject *poWinter = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
222  poWinter->setLinePen( QPen( Qt::white, 1.0, Qt::DotLine ) );
223  poWinter->addPoint( dWinter.djd()-jd0, Plot->dataRect().top() );
224  poWinter->addPoint( dWinter.djd()-jd0, Plot->dataRect().bottom() );
225  Plot->addPlotObject( poWinter );
226 }
227 
228 //Add custom top/bottom axes with tickmarks for each month
229 void modCalcEquinox::addDateAxes() {
230  KPlotObject *poTopAxis = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
231  poTopAxis->addPoint( 0.0, Plot->dataRect().bottom() ); //y-axis is reversed!
232  poTopAxis->addPoint( 366.0, Plot->dataRect().bottom() );
233  Plot->addPlotObject( poTopAxis );
234 
235  KPlotObject *poBottomAxis = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
236  poBottomAxis->addPoint( 0.0, Plot->dataRect().top() + 0.02 );
237  poBottomAxis->addPoint( 366.0, Plot->dataRect().top() + 0.02 );
238  Plot->addPlotObject( poBottomAxis );
239 
240  //Tick mark for each month
241  for ( int imonth=0; imonth<12; imonth++ ) {
242  KPlotObject *poMonth = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
243  poMonth->addPoint( dmonth(imonth), Plot->dataRect().top() );
244  poMonth->addPoint( dmonth(imonth), Plot->dataRect().top() + 1.4 );
245  Plot->addPlotObject( poMonth );
246  poMonth = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
247  poMonth->addPoint( dmonth(imonth), Plot->dataRect().bottom() );
248  poMonth->addPoint( dmonth(imonth), Plot->dataRect().bottom() - 1.4 );
249  Plot->addPlotObject( poMonth );
250  }
251 }
252 
253 KStarsDateTime modCalcEquinox::findEquinox( int year, bool Spring, KPlotObject *ecl ) {
254  // Interpolate to find the moment when the Sun crosses the equator
255  // Set initial guess in February or August to be sure that this
256  // point is before equinox.
257  const int month = Spring ? 2 : 8;
258  int i = QDate( year, month, 1 ).dayOfYear();
259  double dec1, dec2;
260  dec2 = ecl->points()[i]->y();
261  do {
262  ++i;
263  dec1 = dec2;
264  dec2 = ecl->points()[i]->y();
265  } while ( dec1*dec2 > 0.0 ); //when dec1*dec2<0.0, we bracket the zero
266 
267  double x1 = ecl->points()[i-1]->x();
268  double x2 = ecl->points()[i]->x();
269  double d = fabs(dec2 - dec1);
270  double f = 1.0 - fabs(dec2)/d; //fractional distance of the zero, from point1 to point2
271 
272  KStarsDateTime dt0( QDate( year, 1, 1 ), QTime(0,0,0) );
273  KStarsDateTime dt = dt0.addSecs( 86400.0*(x1-1 + f*(x2-x1)) );
274  return dt;
275 }
276 
277 KStarsDateTime modCalcEquinox::findSolstice( int year, bool Summer ) {
278  //Find the moment when the Sun reaches maximum declination
279  //First find three points which bracket the maximum (i.e., x2 > x1,x3)
280  //Start at June 16th, which will always be approaching the solstice
281 
282  long double jd1,jd2,jd3,jd4;
283  double y2(0.0),y3(0.0), y4(0.0);
284  int month = 6;
285  if ( ! Summer ) month = 12;
286 
287  jd3 = KStarsDateTime( QDate( year, month, 16 ), QTime(0,0,0) ).djd();
288  KSNumbers num( jd3 );
289  KSSun Sun;
290  Sun.findPosition( &num );
291  y3 = Sun.dec().Degrees();
292 
293  int sgn = 1;
294  if ( ! Summer ) sgn = -1; //find minimum if the winter solstice is sought
295 
296  do {
297  jd3 += 1.0;
298  num.updateValues( jd3 );
299  Sun.findPosition( &num );
300  y2 = y3;
301  Sun.findPosition( &num );
302  y3 = Sun.dec().Degrees();
303  } while ( y3*sgn > y2*sgn );
304 
305  //Ok, now y2 is larger(smaller) than both y3 and y1.
306  jd2 = jd3 - 1.0;
307  jd1 = jd3 - 2.0;
308 
309  //Choose a new starting jd2 that follows the golden ratio:
310  // a/b = 1.618; a+b = 2...a = 0.76394
311  jd2 = jd1 + 0.76394;
312  num.updateValues( jd2 );
313  Sun.findPosition( &num );
314  y2 = Sun.dec().Degrees();
315 
316  while ( jd3 - jd1 > 0.0005 ) { //sub-minute pecision
317  jd4 = jd1 + jd3 - jd2;
318 
319  num.updateValues( jd4 );
320  Sun.findPosition( &num );
321  y4 = Sun.dec().Degrees();
322 
323  if ( y4*sgn > y2*sgn ) { //make jd4 the new center
324  if ( jd4 > jd2 ) {
325  jd1 = jd2;
326  jd2 = jd4;
327  y2 = y4;
328  } else {
329  jd3 = jd2;
330  y3 = y2;
331  jd2 = jd4;
332  y2 = y4;
333  }
334  } else { //make jd4 a new endpoint
335  if ( jd4 > jd2 ) {
336  jd3 = jd4;
337  y3 = y4;
338  } else {
339  jd1 = jd4;
340  }
341  }
342  }
343 
344  return KStarsDateTime( jd2 );
345 }
346 
347 #include "modcalcvizequinox.moc"
KSPlanetBase::findPosition
void findPosition(const KSNumbers *num, const dms *lat=0, const dms *LST=0, const KSPlanetBase *Earth=0)
Find position, including correction for Figure-of-the-Earth.
Definition: ksplanetbase.cpp:122
modCalcEquinox::modCalcEquinox
modCalcEquinox(QWidget *p)
Definition: modcalcvizequinox.cpp:38
KStarsData
KStarsData is the backbone of KStars.
Definition: kstarsdata.h:66
KSSun
Child class of KSPlanetBase; encapsulates information about the Sun.
Definition: kssun.h:31
KStarsData::colorScheme
ColorScheme * colorScheme()
Definition: kstarsdata.h:149
QWidget
KStarsData::Instance
static KStarsData * Instance()
Definition: kstarsdata.h:92
dms::Degrees
const double & Degrees() const
Definition: dms.h:98
ColorScheme::colorNamed
QColor colorNamed(const QString &name) const
Retrieve a color by name.
Definition: colorscheme.cpp:97
dms.h
NaN::f
const float f
Definition: nan.h:36
modcalcvizequinox.h
KStarsDateTime::djd
long double djd() const
Definition: kstarsdatetime.h:145
KStarsDateTime::addSecs
KStarsDateTime addSecs(double s) const
Definition: kstarsdatetime.cpp:127
KStarsDateTime
Extension of KDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day...
Definition: kstarsdatetime.h:45
ksnumbers.h
modCalcEquinox::dmonth
double dmonth(int imonth)
Definition: modcalcvizequinox.cpp:67
SkyPoint::dec
const dms & dec() const
Definition: skypoint.h:174
modCalcEquinox::~modCalcEquinox
~modCalcEquinox()
Definition: modcalcvizequinox.cpp:64
QTextStream
KSNumbers
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition: ksnumbers.h:43
kssun.h
NaN::d
const double d
Definition: nan.h:35
kstarsdatetime.h
kstarsdata.h
dmsbox.h
QFrame
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:20 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal