-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathCelestialBody.swift
110 lines (94 loc) · 4.58 KB
/
CelestialBody.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//
// CelestialBody.swift
// Orbits
//
// Created by Ben Lu on 1/28/17.
// Copyright © 2017 Ben Lu. All rights reserved.
//
import Foundation
import MathUtil
import OrderedSet
open class CelestialBody: Body, BoundedByGravity, CustomStringConvertible, Comparable {
/// radius in m
public let radius: Double
/// rotation period in hr
public let rotationPeriod: Double
public let obliquity: DegreeAngle
public let gravParam: Double
public let hillSphereRadiusRespectToRadius: Double?
public var hillSphere: Double? {
if let radRp = hillSphereRadiusRespectToRadius {
return radRp * radius
}
return nil
}
/// mass in kg
public var mass: Double {
return gravParam / gravConstant * 10e8
}
public var satellites = OrderedSet<Body>()
public var description: String {
return "CelestialBody: { naif: \(naifId), name: \(name), radius(m): \(radius), rotationPeriod(s): \(rotationPeriod), obliquity(radians): \(obliquity), gm: \(gravParam), hillSphere(m): \(String(describing: hillSphere))}"
}
public init(naifId: Int, name: String, gravParam: Double, radius: Double, rotationPeriod: Double = 0, obliquity: DegreeAngle = DegreeAngle(0), centerBodyNaifId: Int? = nil, hillSphereRadRp: Double? = nil) {
self.gravParam = gravParam
self.radius = radius
self.rotationPeriod = rotationPeriod
self.obliquity = obliquity
self.hillSphereRadiusRespectToRadius = hillSphereRadRp
super.init(naif: Naif(naifId: naifId), name: name, centerBodyNaifId: centerBodyNaifId)
}
public convenience init(naifId: Int, name: String, mass: Double, radius: Double, rotationPeriod: Double = 0, obliquity: DegreeAngle = DegreeAngle(0), centerBodyNaifId: Int? = nil, hillSphereRadRp: Double? = nil) {
self.init(naifId: naifId, name: name, gravParam: mass * gravConstant, radius: radius, rotationPeriod: rotationPeriod, obliquity: obliquity, centerBodyNaifId: centerBodyNaifId, hillSphereRadRp: hillSphereRadRp)
}
public convenience init(naifId: Int, mass: Double, radius: Double, rotationPeriod: Double = 0, obliquity: DegreeAngle = DegreeAngle(0), centerBodyNaifId: Int? = nil, hillSphereRadRp: Double? = nil) {
let name = NaifCatalog.name(forNaif: naifId)!
self.init(naifId: naifId, name: name, mass: mass, radius: radius, rotationPeriod: rotationPeriod, obliquity: obliquity, centerBodyNaifId: centerBodyNaifId, hillSphereRadRp: hillSphereRadRp)
}
public convenience init(naifId: Int, gravParam: Double, radius: Double, rotationPeriod: Double = 0, obliquity: DegreeAngle = DegreeAngle(0), centerBodyNaifId: Int? = nil, hillSphereRadRp: Double? = nil) {
let name = NaifCatalog.name(forNaif: naifId)!
self.init(naifId: naifId, name: name, gravParam: gravParam, radius: radius, rotationPeriod: rotationPeriod, obliquity: obliquity, centerBodyNaifId: centerBodyNaifId, hillSphereRadRp: hillSphereRadRp)
}
public func addSatellite(satellite: Body) {
satellites.append(satellite)
satellite.setCenter(naifId: naifId)
}
public subscript(subId: Int) -> Body? {
let targets = satellites.filter { $0.naifId == subId }
if targets.isEmpty == false {
return targets[0]
}
for satellite in satellites {
guard let orbitable = satellite as? BoundedByGravity else {
continue
}
if let target = orbitable[subId] {
return target
}
}
return nil
}
public static func ==(lhs: CelestialBody, rhs: CelestialBody) -> Bool {
return lhs.naif == rhs.naif
}
public static func <(lhs: CelestialBody, rhs: CelestialBody) -> Bool {
return lhs.naif < rhs.naif
}
// MARK: - NSCopying
public func copy(with zone: NSZone? = nil) -> Any {
let copy = CelestialBody(naifId: naifId, name: name, gravParam: gravParam, radius: radius, rotationPeriod: rotationPeriod, obliquity: obliquity, centerBodyNaifId: centerBody?.naifId, hillSphereRadRp: hillSphereRadiusRespectToRadius)
copy.motion = motion?.copy() as? OrbitalMotion
let children = satellites.filter { $0 is CelestialBody } as! [CelestialBody]
children.forEach { (child) in
let copiedChild = child.copy() as! CelestialBody
copy.addSatellite(satellite: copiedChild)
copiedChild.centerBody = copy
}
return copy
}
}
public class Sun: CelestialBody {
public static var sol: Sun {
return Sun(naifId: 10, name: "Sun", mass: 1.988544e30, radius: 6.955e8)
}
}