300 lines
9.2 KiB
Plaintext
300 lines
9.2 KiB
Plaintext
//
|
|
// EclipseFinderController.mm
|
|
// celestia
|
|
//
|
|
// Created by Da Woon Jung on 2007-05-07.
|
|
// Copyright 2007 Da Woon Jung. All rights reserved.
|
|
//
|
|
|
|
#import "EclipseFinderController.h"
|
|
#import "CelestiaAppCore.h"
|
|
#import "NSString_ObjCPlusPlus.h"
|
|
#import "CelestiaBody_PrivateAPI.h"
|
|
#include "eclipsefinder.h"
|
|
#include <celutil/util.h>
|
|
|
|
@interface EclipseFinderController(Private)
|
|
- (void)getEclipses: (id)aObject;
|
|
- (void)getEclipsesDone: (id)aObject;
|
|
@end
|
|
|
|
|
|
@implementation EclipseFinderController
|
|
|
|
static NSMutableArray *eclipses;
|
|
static NSCalendarDate *startDate;
|
|
static NSCalendarDate *midDate;
|
|
static NSCalendarDate *endDate;
|
|
static string receiverName;
|
|
static Eclipse::Type eclipseType;
|
|
static CelestiaBody *eclipseBody;
|
|
|
|
- (id)init
|
|
{
|
|
self = [super initWithWindowNibName: @"EclipseFinder"];
|
|
if (self)
|
|
{
|
|
eclipses = [[NSMutableArray alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)windowDidLoad
|
|
{
|
|
[eclipseList setDoubleAction: @selector(go:)];
|
|
}
|
|
|
|
- (void)windowWillClose:(NSNotification *)aNotification
|
|
{
|
|
if ([self window] == [aNotification object])
|
|
{
|
|
keepGoing = NO;
|
|
}
|
|
}
|
|
|
|
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
|
|
{
|
|
NSDictionary *userInfo = [aNotification userInfo];
|
|
if (userInfo && NSReturnTextMovement == [[userInfo objectForKey: @"NSTextMovement"] intValue])
|
|
{
|
|
[self find: self];
|
|
}
|
|
}
|
|
|
|
- (IBAction)find: (id)sender
|
|
{
|
|
CelestiaSimulation *sim;
|
|
CelestiaSelection *sel;
|
|
Body *body;
|
|
id startDateObj = [eclipseFindStart objectValue];
|
|
id endDateObj = [eclipseFindEnd objectValue];
|
|
NSString *receiverStr = [eclipseReceiver stringValue];
|
|
keepGoing = YES;
|
|
|
|
if (0 == [receiverStr length])
|
|
{
|
|
NSRunAlertPanel(NSLocalizedString(@"No Object Name Entered",@""),
|
|
NSLocalizedString(@"Please enter an object name.",@""),
|
|
nil,nil,nil);
|
|
return;
|
|
}
|
|
|
|
if (nil == startDateObj || nil == endDateObj)
|
|
{
|
|
NSRunAlertPanel(NSLocalizedString(@"No Starting or Ending Date Entered",@""),
|
|
NSLocalizedString(@"Please enter starting and ending dates.",@""),
|
|
nil,nil,nil);
|
|
return;
|
|
}
|
|
|
|
sim = [[CelestiaAppCore sharedAppCore] simulation];
|
|
sel = [sim findObjectFromPath: receiverStr];
|
|
if (nil == sel || [sel isEmpty])
|
|
{
|
|
NSRunAlertPanel(NSLocalizedString(@"Object Not Found",@""),
|
|
NSLocalizedString(@"Please check that the object name is correct.",@""),
|
|
nil,nil,nil);
|
|
return;
|
|
}
|
|
|
|
eclipseBody = [sel body];
|
|
body = [eclipseBody body];
|
|
if (nil == body || nil == body->getSystem())
|
|
{
|
|
NSRunAlertPanel(NSLocalizedString(@"Object Not Found",@""),
|
|
NSLocalizedString(@"Please check that the object name is correct.",@""),
|
|
nil,nil,nil);
|
|
return;
|
|
}
|
|
|
|
if (body->getSystem()->getPrimaryBody())
|
|
{
|
|
// Eclipse receiver is a moon -> find lunar eclipses
|
|
eclipseType = Eclipse::Moon;
|
|
PlanetarySystem *system = body->getSystem();
|
|
if (system)
|
|
{
|
|
Body *parent = system->getPrimaryBody();
|
|
if (NULL == parent)
|
|
{
|
|
return;
|
|
}
|
|
receiverName = parent->getName();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eclipseType = Eclipse::Solar;
|
|
receiverName = body->getName();
|
|
// EclipseFinder class expects unlocalized names
|
|
}
|
|
|
|
|
|
startDate = (NSCalendarDate *)startDateObj;
|
|
endDate = (NSCalendarDate *)endDateObj;
|
|
midDate = [startDate dateByAddingYears: 0
|
|
months: 0
|
|
days: 15
|
|
hours: 0
|
|
minutes: 0
|
|
seconds: 0];
|
|
// Find eclipses in small timeslices, to give the user
|
|
// a chance to abort with the stop button
|
|
|
|
[findButton setEnabled: NO];
|
|
eclipses = [[NSMutableArray alloc] init];
|
|
[eclipseProgress startAnimation: self];
|
|
|
|
[NSThread detachNewThreadSelector: @selector(getEclipses:)
|
|
toTarget: self withObject: nil];
|
|
}
|
|
|
|
/* Go code borrowed from Windows version */
|
|
- (IBAction)go: (id)sender
|
|
{
|
|
NSInteger rowIndex = [eclipseList selectedRow];
|
|
if (rowIndex < 0) return;
|
|
|
|
CelestiaCore *appCore = (CelestiaCore*) [[CelestiaAppCore sharedAppCore] appCore];
|
|
NSDictionary *eclipse = [eclipses objectAtIndex: rowIndex];
|
|
Body *body = [(CelestiaBody *)[eclipse objectForKey: @"body"] body];
|
|
double startTime = [[eclipse objectForKey: @"start"] doubleValue];
|
|
Simulation *sim = appCore->getSimulation();
|
|
sim->setTime(startTime);
|
|
Selection target(body);
|
|
Selection ref(body->getSystem()->getStar());
|
|
sim->setFrame(ObserverFrame::PhaseLock, target, ref);
|
|
sim->update(0.0);
|
|
|
|
double distance = astro::kilometersToMicroLightYears(target.radius() * 4.0);
|
|
sim->setSelection(target);
|
|
sim->gotoLocation(Point3d(distance, 0, 0),
|
|
Quatd::yrotation(-0.5*PI)*Quatd::xrotation(-0.5*PI),
|
|
5.0);
|
|
}
|
|
|
|
- (IBAction)stopFind: (id)sender
|
|
{
|
|
keepGoing = NO;
|
|
}
|
|
|
|
|
|
- (void)getEclipses: (id)aObject
|
|
{
|
|
CelestiaCore *appCore = (CelestiaCore*) [[CelestiaAppCore sharedAppCore] appCore];
|
|
EclipseFinder *eclipseFinder;
|
|
const Eclipse *eclipse;
|
|
double jd;
|
|
double hours, minutes;
|
|
NSString *eclipseName;
|
|
NSString *duration;
|
|
NSCalendarDate *eclipseDate;
|
|
vector<Eclipse>::const_iterator iter;
|
|
|
|
while (keepGoing)
|
|
{
|
|
if (NSOrderedDescending == [midDate compare: endDate])
|
|
{
|
|
if (NSOrderedAscending == [startDate compare: endDate])
|
|
{
|
|
midDate = endDate;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
eclipseFinder =
|
|
new EclipseFinder(appCore,
|
|
receiverName,
|
|
eclipseType,
|
|
(double)astro::Date(astro::secondsToJulianDate([startDate timeIntervalSince1970])) + (double)astro::Date(1970,1,1),
|
|
(double)astro::Date(astro::secondsToJulianDate([midDate timeIntervalSince1970])) + (double)astro::Date(1970,1,1)
|
|
);
|
|
|
|
const vector<Eclipse> &freshEclipses = eclipseFinder->getEclipses();
|
|
|
|
for (iter = freshEclipses.begin();
|
|
iter != freshEclipses.end() && keepGoing;
|
|
++iter)
|
|
{
|
|
eclipse = &(*iter);
|
|
jd = astro::julianDateToSeconds((double)(*eclipse->date));
|
|
if (0 == jd && eclipse->planete == "None")
|
|
continue;
|
|
if (eclipse->body != [(CelestiaBody *)eclipseBody body])
|
|
continue;
|
|
|
|
eclipseName = [NSString stringWithStdString: (eclipseType == Eclipse::Moon ? eclipse->planete : eclipse->sattelite)];
|
|
eclipseDate = [NSCalendarDate dateWithTimeIntervalSince1970: (jd - astro::julianDateToSeconds((double)astro::Date(1970,1,1)))];
|
|
hours = astro::julianDateToSeconds(eclipse->endTime - eclipse->startTime)/3600.0;
|
|
minutes = 60.0*(hours - (int)hours);
|
|
duration = [NSString stringWithFormat: @"%02d:%02d", (int)hours, (int)minutes];
|
|
|
|
[eclipses addObject:
|
|
[NSDictionary dictionaryWithObjectsAndKeys:
|
|
[NSString stringWithUTF8String:_([eclipseName UTF8String])], @"caster",
|
|
eclipseDate, @"date",
|
|
[[CelestiaBody alloc] initWithBody: eclipse->body], @"body",
|
|
[NSNumber numberWithDouble: eclipse->startTime], @"start",
|
|
duration, @"duration",
|
|
nil]
|
|
];
|
|
}
|
|
|
|
delete eclipseFinder;
|
|
|
|
startDate = midDate;
|
|
midDate = [startDate dateByAddingYears: 0
|
|
months: 0
|
|
days: 15
|
|
hours: 0
|
|
minutes: 0
|
|
seconds: 0];
|
|
}
|
|
|
|
[self performSelectorOnMainThread: @selector(getEclipsesDone:)
|
|
withObject: nil
|
|
waitUntilDone: NO];
|
|
}
|
|
|
|
- (void)getEclipsesDone: (id)aObject
|
|
{
|
|
startDate = nil;
|
|
midDate = nil;
|
|
endDate = nil;
|
|
eclipseBody = nil;
|
|
[eclipseProgress stopAnimation: self];
|
|
[findButton setEnabled: YES];
|
|
[eclipseList reloadData];
|
|
}
|
|
|
|
|
|
- (NSInteger)numberOfRowsInTableView: (NSTableView *)aTableView
|
|
{
|
|
return [eclipses count];
|
|
}
|
|
|
|
- (id)tableView: (NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
|
|
{
|
|
id result = nil;
|
|
NSDictionary *eclipse = nil;
|
|
|
|
if ([eclipses count] > 0)
|
|
{
|
|
eclipse = [eclipses objectAtIndex: rowIndex];
|
|
if ([[aTableColumn identifier] isEqualToString: @"begin"])
|
|
{
|
|
result = [NSCalendarDate dateWithTimeIntervalSince1970: astro::julianDateToSeconds([[eclipse objectForKey: @"start"] doubleValue] - (double)astro::Date(1970,1,1))];
|
|
}
|
|
else
|
|
{
|
|
result = [eclipse objectForKey: [aTableColumn identifier]];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
@end
|