Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

wineclipses.cpp

Go to the documentation of this file.
00001 // wineclipses.cpp by Kendrix <kendrix@wanadoo.fr>
00002 // modified by Chris Laurel
00003 // 
00004 // Compute Solar Eclipses for our Solar System planets
00005 //
00006 // This program is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU General Public License
00008 // as published by the Free Software Foundation; either version 2
00009 // of the License, or (at your option) any later version.
00010 
00011 #include <string>
00012 #include <sstream>
00013 #include <algorithm>
00014 #include <set>
00015 #include <cassert>
00016 #include <windows.h>
00017 #include <commctrl.h>
00018 #include "eclipsefinder.h"
00019 #include "wineclipses.h"
00020 #include "res/resource.h"
00021 #include "celmath/mathlib.h"
00022 #include "celmath/ray.h"
00023 #include "celmath/distance.h"
00024 
00025 using namespace std;
00026 
00027 WNDPROC oldListViewProc;
00028 
00029 static vector<Eclipse> eclipseList;
00030 
00031 extern void SetMouseCursor(LPCTSTR lpCursor);
00032 
00033 char* MonthNames[12] =
00034 {
00035     "Jan", "Feb", "Mar", "Apr",
00036     "May", "Jun", "Jul", "Aug",
00037     "Sep", "Oct", "Nov", "Dec"
00038 };
00039 
00040 bool InitEclipseFinderColumns(HWND listView)
00041 {
00042     LVCOLUMN lvc;
00043     LVCOLUMN columns[5];
00044 
00045     lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
00046     lvc.fmt = LVCFMT_CENTER;
00047     lvc.pszText = "";
00048 
00049     int nColumns = sizeof(columns) / sizeof(columns[0]);
00050     int i;
00051 
00052     for (i = 0; i < nColumns; i++)
00053         columns[i] = lvc;
00054 
00055     columns[0].pszText = "Planet";
00056     columns[0].cx = 50;
00057     columns[1].pszText = "Satellite";
00058     columns[1].cx = 65;
00059     columns[2].pszText = "Date";
00060     columns[2].cx = 80;
00061     columns[3].pszText = "Start";
00062     columns[3].cx = 55;
00063     columns[4].pszText = "Duration";
00064     columns[4].cx = 55;
00065 
00066     for (i = 0; i < nColumns; i++)
00067     {
00068         columns[i].iSubItem = i;
00069         if (ListView_InsertColumn(listView, i, &columns[i]) == -1)
00070             return false;
00071     }
00072 
00073     return true;
00074 }
00075 
00076 
00077 bool InitEclipseFinderItems(HWND listView, const vector<Eclipse>& eclipses)
00078 {
00079     LVITEM lvi;
00080 
00081     lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
00082     lvi.state = 0;
00083     lvi.stateMask = 0;
00084     lvi.pszText = LPSTR_TEXTCALLBACK;
00085 
00086     for (int i = 0; i < eclipses.size(); i++)
00087     {
00088         lvi.iItem = i;
00089         lvi.iSubItem = 0;
00090         lvi.lParam = (LPARAM) &(eclipses[i]);
00091         ListView_InsertItem(listView, &lvi);
00092     }
00093 
00094     return true;
00095 }
00096 
00097 
00098 static char callbackScratch[256];
00099 void EclipseFinderDisplayItem(LPNMLVDISPINFOA nm)
00100 {
00101     Eclipse* eclipse = reinterpret_cast<Eclipse*>(nm->item.lParam);
00102     if (eclipse == NULL)
00103     {
00104         nm->item.pszText = "";
00105         return;
00106     }
00107 
00108     switch (nm->item.iSubItem)
00109     {
00110     case 0:
00111         {
00112             nm->item.pszText = const_cast<char*>(eclipse->planete.c_str());
00113         }
00114         break;
00115             
00116     case 1:
00117         {
00118             nm->item.pszText = const_cast<char*>(eclipse->sattelite.c_str());
00119         }
00120         break;
00121 
00122     case 2:
00123         {
00124             astro::Date startDate(eclipse->startTime);
00125             if (!strcmp(eclipse->planete.c_str(),"None"))
00126                 sprintf(callbackScratch,"");
00127             else
00128                 sprintf(callbackScratch, "%2d %s %4d",
00129                         startDate.day,
00130                         MonthNames[startDate.month - 1],
00131                         startDate.year);
00132             nm->item.pszText = callbackScratch;
00133         }
00134         break;
00135             
00136     case 3:
00137         {
00138             astro::Date startDate(eclipse->startTime);
00139             if (!strcmp(eclipse->planete.c_str(),"None"))
00140                 sprintf(callbackScratch,"");
00141             else
00142             {
00143                 sprintf(callbackScratch, "%02d:%02d",
00144                         startDate.hour, startDate.minute);
00145             }
00146             nm->item.pszText = callbackScratch;
00147         }
00148         break;
00149 
00150     case 4:
00151         {
00152             int minutes = (int) ((eclipse->endTime - eclipse->startTime) *
00153                                  24 * 60);
00154             sprintf(callbackScratch, "%02d:%02d", minutes / 60, minutes % 60);
00155             nm->item.pszText = callbackScratch;
00156         }
00157         break;
00158     }
00159 }
00160 
00161 
00162 void InitDateControls(HWND hDlg, astro::Date& newTime, SYSTEMTIME& fromTime, SYSTEMTIME& toTime)
00163 {
00164     HWND dateItem = NULL;
00165 
00166     fromTime.wYear = newTime.year - 1;
00167     fromTime.wMonth = newTime.month;
00168     fromTime.wDay = newTime.day;
00169     fromTime.wDayOfWeek = ((int) ((double) newTime + 0.5) + 1) % 7;
00170     fromTime.wHour = 0;
00171     fromTime.wMinute = 0;
00172     fromTime.wSecond = (int) 0;
00173     fromTime.wMilliseconds = 0;
00174 
00175     toTime = fromTime;
00176     toTime.wYear += 2;
00177 
00178     dateItem = GetDlgItem(hDlg, IDC_DATEFROM);
00179     if (dateItem != NULL)
00180     {
00181         DateTime_SetFormat(dateItem, "dd' 'MMM' 'yyy");
00182         DateTime_SetSystemtime(dateItem, GDT_VALID, &fromTime);
00183     }
00184     dateItem = GetDlgItem(hDlg, IDC_DATETO);
00185     if (dateItem != NULL)
00186     {
00187         DateTime_SetFormat(dateItem, "dd' 'MMM' 'yyy");
00188         DateTime_SetSystemtime(dateItem, GDT_VALID, &toTime);
00189     }
00190 }
00191 
00192 
00193 struct EclipseFinderSortInfo
00194 {
00195     int         subItem;
00196     string      planete;
00197     string      sattelite;
00198     int32       Year;
00199     int8        Month;
00200     int8        Day;
00201     int8        Hour;
00202 };
00203 
00204 
00205 int CALLBACK EclipseFinderCompareFunc(LPARAM lParam0, LPARAM lParam1,
00206                                     LPARAM lParamSort)
00207 {
00208     EclipseFinderSortInfo* sortInfo = reinterpret_cast<EclipseFinderSortInfo*>(lParamSort);
00209     Eclipse* eclipse0 = reinterpret_cast<Eclipse*>(lParam0);
00210     Eclipse* eclipse1 = reinterpret_cast<Eclipse*>(lParam1);
00211 
00212     switch (sortInfo->subItem)
00213     {
00214     case 1:
00215         if (eclipse0->sattelite < eclipse1->sattelite)
00216             return -1;
00217         else
00218             return 1;
00219 
00220     case 4:
00221         if ((eclipse0->endTime - eclipse0->startTime) <
00222             (eclipse1->endTime - eclipse1->startTime))
00223             return -1;
00224         else
00225             return 1;
00226 
00227     default:
00228         if (eclipse0->startTime < eclipse1->startTime)
00229             return -1;
00230         else
00231             return 1;
00232     }
00233 }
00234 
00235 BOOL APIENTRY EclipseListViewProc(HWND hWnd,
00236                                   UINT message,
00237                                   UINT wParam,
00238                                   LONG lParam)
00239 {
00240     switch(message)
00241     {
00242     case WM_LBUTTONDBLCLK:
00243         {
00244             LVHITTESTINFO lvHit;
00245             lvHit.pt.x = LOWORD(lParam);
00246             lvHit.pt.y = HIWORD(lParam);
00247             int listIndex = ListView_HitTest(hWnd, &lvHit);
00248             if (listIndex >= 0)
00249             {
00250                 SendMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(IDSETDATEANDGO, 0), NULL);
00251             }
00252         }
00253         break;
00254     }
00255 
00256     return CallWindowProc(oldListViewProc, hWnd, message, wParam, lParam);
00257 }
00258 
00259 BOOL APIENTRY EclipseFinderProc(HWND hDlg,
00260                                 UINT message,
00261                                 UINT wParam,
00262                                 LONG lParam)
00263 {
00264     EclipseFinderDialog* eclipseFinderDlg = reinterpret_cast<EclipseFinderDialog*>(GetWindowLong(hDlg, DWL_USER));
00265 
00266     switch (message)
00267     {
00268     case WM_INITDIALOG:
00269         {
00270             EclipseFinderDialog* efd = reinterpret_cast<EclipseFinderDialog*>(lParam);
00271             if (efd == NULL)
00272                 return EndDialog(hDlg, 0);
00273             SetWindowLong(hDlg, DWL_USER, lParam);
00274             HWND hwnd = GetDlgItem(hDlg, IDC_ECLIPSES_LIST);
00275             InitEclipseFinderColumns(hwnd);
00276             SendDlgItemMessage(hDlg, IDC_ECLIPSES_LIST, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
00277 
00278             SendDlgItemMessage(hDlg, IDC_ECLIPSETYPE, CB_ADDSTRING, 0, (LPARAM)"solar");
00279             SendDlgItemMessage(hDlg, IDC_ECLIPSETYPE, CB_ADDSTRING, 0, (LPARAM)"moon");
00280             SendDlgItemMessage(hDlg, IDC_ECLIPSETYPE, CB_SETCURSEL, 0, 0);
00281             efd->bSolar = true;
00282 
00283             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)"Earth");
00284             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)"Jupiter");
00285             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)"Saturn");
00286             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)"Uranus");
00287             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)"Neptune");
00288             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)"Pluto");
00289             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_SETCURSEL, 0, 0);
00290             efd->strPlaneteToFindOn = "Earth";
00291 
00292             InitDateControls(hDlg, astro::Date(efd->appCore->getSimulation()->getTime()), efd->fromTime, efd->toTime);
00293 
00294             // Subclass the ListView to intercept WM_LBUTTONUP messages
00295             HWND hCtrl;
00296             if (hCtrl = GetDlgItem(hDlg, IDC_ECLIPSES_LIST))
00297                 oldListViewProc = (WNDPROC) SetWindowLong(hCtrl, GWL_WNDPROC, (DWORD) EclipseListViewProc);
00298         }
00299         return(TRUE);
00300 
00301     case WM_DESTROY:
00302         if (eclipseFinderDlg != NULL && eclipseFinderDlg->parent != NULL)
00303         {
00304             SendMessage(eclipseFinderDlg->parent, WM_COMMAND, IDCLOSE,
00305                         reinterpret_cast<LPARAM>(eclipseFinderDlg));
00306         }
00307         break;
00308 
00309     case WM_CLOSE:
00310         DestroyWindow(hDlg);
00311         return TRUE;
00312 
00313     case WM_COMMAND:
00314         switch (LOWORD(wParam))
00315         {
00316         case IDCOMPUTE:
00317             {
00318                 HWND hwnd = GetDlgItem(hDlg, IDC_ECLIPSES_LIST);
00319                 ListView_DeleteAllItems(hwnd);
00320                 if (eclipseFinderDlg->strPlaneteToFindOn.empty())
00321                     eclipseFinderDlg->strPlaneteToFindOn = "Earth";
00322                 SetMouseCursor(IDC_WAIT);
00323 
00324 
00325                 astro::Date from(eclipseFinderDlg->fromTime.wYear,
00326                                  eclipseFinderDlg->fromTime.wMonth,
00327                                  eclipseFinderDlg->fromTime.wDay);
00328                 astro::Date to(eclipseFinderDlg->toTime.wYear,
00329                                eclipseFinderDlg->toTime.wMonth,
00330                                eclipseFinderDlg->toTime.wDay);
00331                 EclipseFinder ef(eclipseFinderDlg->appCore,
00332                                  eclipseFinderDlg->strPlaneteToFindOn,
00333                                  eclipseFinderDlg->bSolar ? Eclipse::Solar : Eclipse::Moon,
00334                                  (double) from,
00335                                  (double) to);
00336                 eclipseList = ef.getEclipses();
00337                 InitEclipseFinderItems(hwnd, eclipseList);
00338                 SetMouseCursor(IDC_ARROW);
00339                 break;
00340             }
00341 
00342         case IDCLOSE:
00343             {
00344                 if (eclipseFinderDlg != NULL && eclipseFinderDlg->parent != NULL)
00345                 {
00346                     SendMessage(eclipseFinderDlg->parent, WM_COMMAND, IDCLOSE,
00347                                 reinterpret_cast<LPARAM>(eclipseFinderDlg));
00348                 }
00349                 EndDialog(hDlg, 0);
00350                 break;
00351             }
00352 
00353         case IDSETDATEANDGO:
00354             if (eclipseFinderDlg->BodytoSet_)
00355             {
00356                 Simulation* sim = eclipseFinderDlg->appCore->getSimulation();
00357                 sim->setTime(eclipseFinderDlg->TimetoSet_);
00358                 Selection target(eclipseFinderDlg->BodytoSet_);
00359                 Selection ref(eclipseFinderDlg->BodytoSet_->getSystem()->getStar());
00360                 // Use the phase lock coordinate system to set a position
00361                 // on the line between the sun and the body where the eclipse
00362                 // is occurring.
00363                 sim->setFrame(FrameOfReference(astro::PhaseLock, target, ref));
00364                 sim->update(0.0);
00365 
00366                 double distance = astro::kilometersToMicroLightYears(target.radius() * 4.0);
00367                 RigidTransform to;
00368                 to.rotation = Quatd::yrotation(PI);
00369                 to.translation = Point3d(0, 0, -distance);
00370                 sim->gotoLocation(to, 2.5);
00371             }
00372             break;
00373         case IDC_ECLIPSETYPE:
00374             if(HIWORD(wParam) == CBN_SELCHANGE)
00375             {
00376                 switch(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0))
00377                 {
00378                 case 0:
00379                     eclipseFinderDlg->bSolar = true;
00380                     break;
00381                 case 1:
00382                     eclipseFinderDlg->bSolar = false;
00383                     break;
00384                 }
00385             }
00386             break;
00387         case IDC_ECLIPSETARGET:
00388             if(HIWORD(wParam) == CBN_SELCHANGE)
00389             {
00390                 switch(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0))
00391                 {
00392                 case 0:
00393                     eclipseFinderDlg->strPlaneteToFindOn = "Earth";
00394                     break;
00395                 case 1:
00396                     eclipseFinderDlg->strPlaneteToFindOn = "Jupiter";
00397                     break;
00398                 case 2:
00399                     eclipseFinderDlg->strPlaneteToFindOn = "Saturn";
00400                     break;
00401                 case 3:
00402                     eclipseFinderDlg->strPlaneteToFindOn = "Uranus";
00403                     break;
00404                 case 4:
00405                     eclipseFinderDlg->strPlaneteToFindOn = "Neptune";
00406                     break;
00407                 case 5:
00408                     eclipseFinderDlg->strPlaneteToFindOn = "Pluto";
00409                     break;
00410                 }
00411             }
00412         }
00413         return TRUE;
00414 
00415     case WM_NOTIFY:
00416         {
00417             LPNMHDR hdr = (LPNMHDR) lParam;
00418 
00419             if(hdr->idFrom == IDC_ECLIPSES_LIST)
00420             {
00421                 switch(hdr->code)
00422                 {
00423                 case LVN_GETDISPINFO:
00424                     EclipseFinderDisplayItem((LPNMLVDISPINFOA) lParam);
00425                     break;
00426                 case LVN_ITEMCHANGED:
00427                     {
00428                         LPNMLISTVIEW nm = (LPNMLISTVIEW) lParam;
00429                         if ((nm->uNewState & LVIS_SELECTED) != 0)
00430                         {
00431                             Eclipse* eclipse = reinterpret_cast<Eclipse*>(nm->lParam);
00432                             if (eclipse != NULL)
00433                             {
00434                                 eclipseFinderDlg->TimetoSet_ = 
00435                                     (eclipse->startTime + eclipse->endTime) / 2.0f;
00436                                 eclipseFinderDlg->BodytoSet_ = eclipse->body;
00437                             }
00438                         }
00439                         break;
00440                     }
00441                 case LVN_COLUMNCLICK:
00442                     {
00443                         HWND hwnd = GetDlgItem(hDlg, IDC_ECLIPSES_LIST);
00444                         if (hwnd != 0)
00445                         {
00446                             LPNMLISTVIEW nm = (LPNMLISTVIEW) lParam;
00447                             EclipseFinderSortInfo sortInfo;
00448                             sortInfo.subItem = nm->iSubItem;
00449 //                            sortInfo.sattelite = ;
00450 //                            sortInfo.pos = eclipseFinderDlg->pos;
00451                             ListView_SortItems(hwnd, EclipseFinderCompareFunc,
00452                                                reinterpret_cast<LPARAM>(&sortInfo));
00453                         }
00454                     }
00455 
00456                 }
00457             }
00458             if (hdr->code == DTN_DATETIMECHANGE)
00459             {
00460                 LPNMDATETIMECHANGE change = (LPNMDATETIMECHANGE) lParam;
00461                 if (change->dwFlags == GDT_VALID)
00462                 {
00463                     if (wParam == IDC_DATEFROM)
00464                     {
00465                         eclipseFinderDlg->fromTime.wYear = change->st.wYear;
00466                         eclipseFinderDlg->fromTime.wMonth = change->st.wMonth;
00467                         eclipseFinderDlg->fromTime.wDay = change->st.wDay;
00468                     }
00469                     else if (wParam == IDC_DATETO)
00470                     {
00471                         eclipseFinderDlg->toTime.wYear = change->st.wYear;
00472                         eclipseFinderDlg->toTime.wMonth = change->st.wMonth;
00473                         eclipseFinderDlg->toTime.wDay = change->st.wDay;
00474                     }
00475                 }
00476             }
00477         }
00478         break;
00479     }
00480 
00481     return FALSE;
00482 }
00483 
00484 
00485 EclipseFinderDialog::EclipseFinderDialog(HINSTANCE appInstance,
00486                                          HWND _parent,
00487                                          CelestiaCore* _appCore) :
00488     appCore(_appCore),
00489     parent(_parent),
00490     BodytoSet_(NULL)
00491 {
00492     hwnd = CreateDialogParam(appInstance,
00493                              MAKEINTRESOURCE(IDD_ECLIPSEFINDER),
00494                              parent,
00495                              EclipseFinderProc,
00496                              reinterpret_cast<LONG>(this));
00497 }

Generated on Sat Jan 14 22:30:31 2006 for Celestia by  doxygen 1.4.1