wineclipses.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:17k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // wineclipses.cpp by Kendrix <kendrix@wanadoo.fr>
  2. // modified by Chris Laurel
  3. // 
  4. // Compute Solar Eclipses for our Solar System planets
  5. //
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. #include <string>
  11. #include <sstream>
  12. #include <algorithm>
  13. #include <set>
  14. #include <cassert>
  15. #include <windows.h>
  16. #include <commctrl.h>
  17. #include "eclipsefinder.h"
  18. #include "wineclipses.h"
  19. #include "res/resource.h"
  20. #include "celmath/mathlib.h"
  21. #include "celmath/ray.h"
  22. #include "celmath/distance.h"
  23. #include "celutil/util.h"
  24. #include "celutil/winutil.h"
  25. using namespace std;
  26. WNDPROC oldListViewProc;
  27. static vector<Eclipse> eclipseList;
  28. extern void SetMouseCursor(LPCTSTR lpCursor);
  29. char* MonthNames[12] =
  30. {
  31.     "Jan", "Feb", "Mar", "Apr",
  32.     "May", "Jun", "Jul", "Aug",
  33.     "Sep", "Oct", "Nov", "Dec"
  34. };
  35. bool InitEclipseFinderColumns(HWND listView)
  36. {
  37.     LVCOLUMN lvc;
  38.     LVCOLUMN columns[5];
  39.     lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  40.     lvc.fmt = LVCFMT_CENTER;
  41.     lvc.pszText = "";
  42.     int nColumns = sizeof(columns) / sizeof(columns[0]);
  43.     int i;
  44.     for (i = 0; i < nColumns; i++)
  45.         columns[i] = lvc;
  46.     bind_textdomain_codeset("celestia", CurrentCP());
  47.     columns[0].pszText = _("Planet");
  48.     columns[0].cx = 50;
  49.     columns[1].pszText = _("Satellite");
  50.     columns[1].cx = 65;
  51.     columns[2].pszText = _("Date");
  52.     columns[2].cx = 80;
  53.     columns[3].pszText = _("Start");
  54.     columns[3].cx = 55;
  55.     columns[4].pszText = _("Duration");
  56.     columns[4].cx = 55;
  57.     bind_textdomain_codeset("celestia", "UTF8");
  58.     for (i = 0; i < nColumns; i++)
  59.     {
  60.         columns[i].iSubItem = i;
  61.         if (ListView_InsertColumn(listView, i, &columns[i]) == -1)
  62.             return false;
  63.     }
  64.     return true;
  65. }
  66. bool InitEclipseFinderItems(HWND listView, const vector<Eclipse>& eclipses)
  67. {
  68.     LVITEM lvi;
  69.     lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  70.     lvi.state = 0;
  71.     lvi.stateMask = 0;
  72.     lvi.pszText = LPSTR_TEXTCALLBACK;
  73.     for (unsigned int i = 0; i < eclipses.size(); i++)
  74.     {
  75.         lvi.iItem = i;
  76.         lvi.iSubItem = 0;
  77.         lvi.lParam = (LPARAM) &(eclipses[i]);
  78.         ListView_InsertItem(listView, &lvi);
  79.     }
  80.     return true;
  81. }
  82. static char callbackScratch[256];
  83. void EclipseFinderDisplayItem(LPNMLVDISPINFOA nm)
  84. {
  85.     Eclipse* eclipse = reinterpret_cast<Eclipse*>(nm->item.lParam);
  86.     if (eclipse == NULL)
  87.     {
  88.         nm->item.pszText = "";
  89.         return;
  90.     }
  91.     switch (nm->item.iSubItem)
  92.     {
  93.     case 0:
  94.         {
  95.             strncpy(callbackScratch, UTF8ToCurrentCP(_(eclipse->planete.c_str())).c_str(), sizeof(callbackScratch) - 1);
  96.             nm->item.pszText = callbackScratch;
  97.         }
  98.         break;
  99.             
  100.     case 1:
  101.         {
  102.             if (!strcmp(eclipse->planete.c_str(),"None")) 
  103.             {
  104.                 sprintf(callbackScratch,"");
  105.                 nm->item.pszText = callbackScratch;
  106.             }
  107.             else
  108.             {
  109.                 strncpy(callbackScratch, UTF8ToCurrentCP(_(eclipse->sattelite.c_str())).c_str(), sizeof(callbackScratch) - 1);
  110.                 nm->item.pszText = callbackScratch;
  111.             }
  112.         }
  113.         break;
  114.     case 2:
  115.         {
  116.             bind_textdomain_codeset("celestia", CurrentCP());
  117.             astro::Date startDate(eclipse->startTime);
  118.             if (!strcmp(eclipse->planete.c_str(),"None"))
  119.                 sprintf(callbackScratch,"");
  120.             else
  121.                 sprintf(callbackScratch, "%2d %s %4d",
  122.                         startDate.day,
  123.                         _(MonthNames[startDate.month - 1]),
  124.                         startDate.year);
  125.             nm->item.pszText = callbackScratch;
  126.             bind_textdomain_codeset("celestia", "UTF8");
  127.         }
  128.         break;
  129.             
  130.     case 3:
  131.         {
  132.             astro::Date startDate(eclipse->startTime);
  133.             if (!strcmp(eclipse->planete.c_str(),"None"))
  134.                 sprintf(callbackScratch,"");
  135.             else
  136.             {
  137.                 sprintf(callbackScratch, "%02d:%02d",
  138.                         startDate.hour, startDate.minute);
  139.             }
  140.             nm->item.pszText = callbackScratch;
  141.         }
  142.         break;
  143.     case 4:
  144.         {
  145.             if (!strcmp(eclipse->planete.c_str(),"None")) 
  146.             {
  147.                 sprintf(callbackScratch,"");
  148.                 nm->item.pszText = callbackScratch;
  149.             }
  150.             else
  151.             {
  152.                 int minutes = (int) ((eclipse->endTime - eclipse->startTime) *
  153.                                     24 * 60);
  154.                 sprintf(callbackScratch, "%02d:%02d", minutes / 60, minutes % 60);
  155.                 nm->item.pszText = callbackScratch;
  156.             }
  157.         }
  158.         break;
  159.     }
  160. }
  161. void InitDateControls(HWND hDlg, astro::Date& newTime, SYSTEMTIME& fromTime, SYSTEMTIME& toTime)
  162. {
  163.     HWND dateItem = NULL;
  164.     fromTime.wYear = newTime.year - 1;
  165.     fromTime.wMonth = newTime.month;
  166.     fromTime.wDay = newTime.day;
  167.     fromTime.wDayOfWeek = ((int) ((double) newTime + 0.5) + 1) % 7;
  168.     fromTime.wHour = 0;
  169.     fromTime.wMinute = 0;
  170.     fromTime.wSecond = (int) 0;
  171.     fromTime.wMilliseconds = 0;
  172.     toTime = fromTime;
  173.     toTime.wYear += 2;
  174.     dateItem = GetDlgItem(hDlg, IDC_DATEFROM);
  175.     if (dateItem != NULL)
  176.     {
  177.         DateTime_SetFormat(dateItem, "dd' 'MMM' 'yyy");
  178.         DateTime_SetSystemtime(dateItem, GDT_VALID, &fromTime);
  179.     }
  180.     dateItem = GetDlgItem(hDlg, IDC_DATETO);
  181.     if (dateItem != NULL)
  182.     {
  183.         DateTime_SetFormat(dateItem, "dd' 'MMM' 'yyy");
  184.         DateTime_SetSystemtime(dateItem, GDT_VALID, &toTime);
  185.     }
  186. }
  187. struct EclipseFinderSortInfo
  188. {
  189.     int         subItem;
  190.     string      planete;
  191.     string      sattelite;
  192.     int32       Year;
  193.     int8        Month;
  194.     int8        Day;
  195.     int8        Hour;
  196. };
  197. int CALLBACK EclipseFinderCompareFunc(LPARAM lParam0, LPARAM lParam1,
  198.                                     LPARAM lParamSort)
  199. {
  200.     EclipseFinderSortInfo* sortInfo = reinterpret_cast<EclipseFinderSortInfo*>(lParamSort);
  201.     Eclipse* eclipse0 = reinterpret_cast<Eclipse*>(lParam0);
  202.     Eclipse* eclipse1 = reinterpret_cast<Eclipse*>(lParam1);
  203.     switch (sortInfo->subItem)
  204.     {
  205.     case 1:
  206.         if (eclipse0->sattelite < eclipse1->sattelite)
  207.             return -1;
  208.         else if (eclipse1->sattelite < eclipse0->sattelite)
  209.             return 1;
  210.         else
  211.             return 0;
  212.     case 4:
  213.         {
  214.             double duration0 = eclipse0->endTime - eclipse0->startTime;
  215.             double duration1 = eclipse1->endTime - eclipse1->startTime;
  216.             if (duration0 < duration1)
  217.                 return -1;
  218.             else if (duration1 < duration0)
  219.                 return 1;
  220.             else
  221.                 return 0;
  222.         }
  223.     default:
  224.         if (eclipse0->startTime < eclipse1->startTime)
  225.             return -1;
  226.         else if (eclipse1->startTime < eclipse0->startTime)
  227.             return 1;
  228.         else
  229.             return 0;
  230.     }
  231. }
  232. BOOL APIENTRY EclipseListViewProc(HWND hWnd,
  233.                                   UINT message,
  234.                                   UINT wParam,
  235.                                   LONG lParam)
  236. {
  237.     switch(message)
  238.     {
  239.     case WM_LBUTTONDBLCLK:
  240.         {
  241.             LVHITTESTINFO lvHit;
  242.             lvHit.pt.x = LOWORD(lParam);
  243.             lvHit.pt.y = HIWORD(lParam);
  244.             int listIndex = ListView_HitTest(hWnd, &lvHit);
  245.             if (listIndex >= 0)
  246.             {
  247.                 SendMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(IDSETDATEANDGO, 0), NULL);
  248.             }
  249.         }
  250.         break;
  251.     }
  252.     return CallWindowProc(oldListViewProc, hWnd, message, wParam, lParam);
  253. }
  254. BOOL APIENTRY EclipseFinderProc(HWND hDlg,
  255.                                 UINT message,
  256.                                 UINT wParam,
  257.                                 LONG lParam)
  258. {
  259.     EclipseFinderDialog* eclipseFinderDlg = reinterpret_cast<EclipseFinderDialog*>(GetWindowLong(hDlg, DWL_USER));
  260.     switch (message)
  261.     {
  262.     case WM_INITDIALOG:
  263.         {
  264.             EclipseFinderDialog* efd = reinterpret_cast<EclipseFinderDialog*>(lParam);
  265.             if (efd == NULL)
  266.                 return EndDialog(hDlg, 0);
  267.             SetWindowLong(hDlg, DWL_USER, lParam);
  268.             HWND hwnd = GetDlgItem(hDlg, IDC_ECLIPSES_LIST);
  269.             InitEclipseFinderColumns(hwnd);
  270.             SendDlgItemMessage(hDlg, IDC_ECLIPSES_LIST, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  271.             bind_textdomain_codeset("celestia", CurrentCP());
  272.             CheckRadioButton(hDlg, IDC_SOLARECLIPSE, IDC_LUNARECLIPSE, IDC_SOLARECLIPSE);
  273.             efd->bSolar = true;
  274.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)_("Earth"));
  275.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)_("Jupiter"));
  276.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)_("Saturn"));
  277.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)_("Uranus"));
  278.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)_("Neptune"));
  279.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_ADDSTRING, 0, (LPARAM)_("Pluto"));
  280.             SendDlgItemMessage(hDlg, IDC_ECLIPSETARGET, CB_SETCURSEL, 0, 0);
  281.             efd->strPlaneteToFindOn = "Earth";
  282.             bind_textdomain_codeset("celestia", "UTF8");
  283.             InitDateControls(hDlg, astro::Date(efd->appCore->getSimulation()->getTime()), efd->fromTime, efd->toTime);
  284.             // Subclass the ListView to intercept WM_LBUTTONUP messages
  285.             HWND hCtrl;
  286.             if (hCtrl = GetDlgItem(hDlg, IDC_ECLIPSES_LIST))
  287.                 oldListViewProc = (WNDPROC) SetWindowLong(hCtrl, GWL_WNDPROC, (DWORD) EclipseListViewProc);
  288.         }
  289.         return(TRUE);
  290.     case WM_DESTROY:
  291.         if (eclipseFinderDlg != NULL && eclipseFinderDlg->parent != NULL)
  292.         {
  293.             SendMessage(eclipseFinderDlg->parent, WM_COMMAND, IDCLOSE,
  294.                         reinterpret_cast<LPARAM>(eclipseFinderDlg));
  295.         }
  296.         break;
  297.     case WM_CLOSE:
  298.         DestroyWindow(hDlg);
  299.         return TRUE;
  300.     case WM_COMMAND:
  301.         switch (LOWORD(wParam))
  302.         {
  303.         case IDCOMPUTE:
  304.             {
  305.                 HWND hwnd = GetDlgItem(hDlg, IDC_ECLIPSES_LIST);
  306.                 ListView_DeleteAllItems(hwnd);
  307.                 if (eclipseFinderDlg->strPlaneteToFindOn.empty())
  308.                     eclipseFinderDlg->strPlaneteToFindOn = "Earth";
  309.                 SetMouseCursor(IDC_WAIT);
  310.                 astro::Date from(eclipseFinderDlg->fromTime.wYear,
  311.                                  eclipseFinderDlg->fromTime.wMonth,
  312.                                  eclipseFinderDlg->fromTime.wDay);
  313.                 astro::Date to(eclipseFinderDlg->toTime.wYear,
  314.                                eclipseFinderDlg->toTime.wMonth,
  315.                                eclipseFinderDlg->toTime.wDay);
  316.                 EclipseFinder ef(eclipseFinderDlg->appCore,
  317.                                  eclipseFinderDlg->strPlaneteToFindOn,
  318.                                  eclipseFinderDlg->bSolar ? Eclipse::Solar : Eclipse::Moon,
  319.                                  (double) from,
  320.                                  (double) to);
  321.                 eclipseList = ef.getEclipses();
  322.                 InitEclipseFinderItems(hwnd, eclipseList);
  323.                 SetMouseCursor(IDC_ARROW);
  324.                 break;
  325.             }
  326.         case IDCLOSE:
  327.             {
  328.                 if (eclipseFinderDlg != NULL && eclipseFinderDlg->parent != NULL)
  329.                 {
  330.                     SendMessage(eclipseFinderDlg->parent, WM_COMMAND, IDCLOSE,
  331.                                 reinterpret_cast<LPARAM>(eclipseFinderDlg));
  332.                 }
  333.                 EndDialog(hDlg, 0);
  334.                 break;
  335.             }
  336.         case IDSETDATEANDGO:
  337.             if (eclipseFinderDlg->BodytoSet_)
  338.             {
  339.                 Simulation* sim = eclipseFinderDlg->appCore->getSimulation();
  340.                 sim->setTime(eclipseFinderDlg->TimetoSet_);
  341.                 Selection target(eclipseFinderDlg->BodytoSet_);
  342.                 Selection ref(eclipseFinderDlg->BodytoSet_->getSystem()->getStar());
  343.                 // Use the phase lock coordinate system to set a position
  344.                 // on the line between the sun and the body where the eclipse
  345.                 // is occurring.
  346.                 sim->setFrame(ObserverFrame::PhaseLock, target, ref);
  347.                 sim->update(0.0);
  348.                 double distance = astro::kilometersToMicroLightYears(target.radius() * 4.0);
  349.                 sim->gotoLocation(Point3d(distance, 0, 0), Quatd::yrotation(-PI / 2) * Quatd::xrotation(-PI / 2), 2.5);
  350.             }
  351.             break;
  352.         case IDC_SOLARECLIPSE:
  353.                 eclipseFinderDlg->bSolar = true;
  354.             break;
  355.         case IDC_LUNARECLIPSE:
  356.                 eclipseFinderDlg->bSolar = false;
  357.             break;
  358.         case IDC_ECLIPSETARGET:
  359.             if(HIWORD(wParam) == CBN_SELCHANGE)
  360.             {
  361.                 switch(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0))
  362.                 {
  363.                 case 0:
  364.                     eclipseFinderDlg->strPlaneteToFindOn = "Earth";
  365.                     break;
  366.                 case 1:
  367.                     eclipseFinderDlg->strPlaneteToFindOn = "Jupiter";
  368.                     break;
  369.                 case 2:
  370.                     eclipseFinderDlg->strPlaneteToFindOn = "Saturn";
  371.                     break;
  372.                 case 3:
  373.                     eclipseFinderDlg->strPlaneteToFindOn = "Uranus";
  374.                     break;
  375.                 case 4:
  376.                     eclipseFinderDlg->strPlaneteToFindOn = "Neptune";
  377.                     break;
  378.                 case 5:
  379.                     eclipseFinderDlg->strPlaneteToFindOn = "Pluto";
  380.                     break;
  381.                 }
  382.             }
  383.         }
  384.         return TRUE;
  385.     case WM_NOTIFY:
  386.         {
  387.             LPNMHDR hdr = (LPNMHDR) lParam;
  388.             if(hdr->idFrom == IDC_ECLIPSES_LIST)
  389.             {
  390.                 switch(hdr->code)
  391.                 {
  392.                 case LVN_GETDISPINFO:
  393.                     EclipseFinderDisplayItem((LPNMLVDISPINFOA) lParam);
  394.                     break;
  395.                 case LVN_ITEMCHANGED:
  396.                     {
  397.                         LPNMLISTVIEW nm = (LPNMLISTVIEW) lParam;
  398.                         if ((nm->uNewState & LVIS_SELECTED) != 0)
  399.                         {
  400.                             Eclipse* eclipse = reinterpret_cast<Eclipse*>(nm->lParam);
  401.                             if (eclipse != NULL)
  402.                             {
  403.                                 eclipseFinderDlg->TimetoSet_ = 
  404.                                     (eclipse->startTime + eclipse->endTime) / 2.0f;
  405.                                 eclipseFinderDlg->BodytoSet_ = eclipse->body;
  406.                             }
  407.                         }
  408.                         break;
  409.                     }
  410.                 case LVN_COLUMNCLICK:
  411.                     {
  412.                         HWND hwnd = GetDlgItem(hDlg, IDC_ECLIPSES_LIST);
  413.                         if (hwnd != 0)
  414.                         {
  415.                             LPNMLISTVIEW nm = (LPNMLISTVIEW) lParam;
  416.                             EclipseFinderSortInfo sortInfo;
  417.                             sortInfo.subItem = nm->iSubItem;
  418. //                            sortInfo.sattelite = ;
  419. //                            sortInfo.pos = eclipseFinderDlg->pos;
  420.                             ListView_SortItems(hwnd, EclipseFinderCompareFunc,
  421.                                                reinterpret_cast<LPARAM>(&sortInfo));
  422.                         }
  423.                     }
  424.                 }
  425.             }
  426.             if (hdr->code == DTN_DATETIMECHANGE)
  427.             {
  428.                 LPNMDATETIMECHANGE change = (LPNMDATETIMECHANGE) lParam;
  429.                 if (change->dwFlags == GDT_VALID)
  430.                 {
  431.                     if (wParam == IDC_DATEFROM)
  432.                     {
  433.                         eclipseFinderDlg->fromTime.wYear = change->st.wYear;
  434.                         eclipseFinderDlg->fromTime.wMonth = change->st.wMonth;
  435.                         eclipseFinderDlg->fromTime.wDay = change->st.wDay;
  436.                     }
  437.                     else if (wParam == IDC_DATETO)
  438.                     {
  439.                         eclipseFinderDlg->toTime.wYear = change->st.wYear;
  440.                         eclipseFinderDlg->toTime.wMonth = change->st.wMonth;
  441.                         eclipseFinderDlg->toTime.wDay = change->st.wDay;
  442.                     }
  443.                 }
  444.             }
  445.         }
  446.         break;
  447.     }
  448.     return FALSE;
  449. }
  450. EclipseFinderDialog::EclipseFinderDialog(HINSTANCE appInstance,
  451.                                          HWND _parent,
  452.                                          CelestiaCore* _appCore) :
  453.     appCore(_appCore),
  454.     parent(_parent),
  455.     BodytoSet_(NULL)
  456. {
  457.     hwnd = CreateDialogParam(appInstance,
  458.                              MAKEINTRESOURCE(IDD_ECLIPSEFINDER),
  459.                              parent,
  460.                              EclipseFinderProc,
  461.                              reinterpret_cast<LONG>(this));
  462. }