TimelinePhase* CreateTimelinePhase(Body* body, Universe& universe, Hash* phaseData, const string& path, ReferenceFrame* defaultOrbitFrame, ReferenceFrame* defaultBodyFrame, bool isFirstPhase, bool isLastPhase, double previousPhaseEnd) { double beginning = previousPhaseEnd; double ending = numeric_limits<double>::infinity(); // Beginning is optional for the first phase of a timeline, and not // allowed for the other phases, where beginning is always the ending // of the previous phase. bool hasBeginning = ParseDate(phaseData, "Beginning", beginning); if (!isFirstPhase && hasBeginning) { clog << "Error: Beginning can only be specified for initial phase of timeline.\n"; return NULL; } // Ending is required for all phases except for the final one. bool hasEnding = ParseDate(phaseData, "Ending", ending); if (!isLastPhase && !hasEnding) { clog << "Error: Ending is required for all timeline phases other than the final one.\n"; return NULL; } // Get the orbit reference frame. ReferenceFrame* orbitFrame; Value* frameValue = phaseData->getValue("OrbitFrame"); if (frameValue != NULL) { orbitFrame = CreateReferenceFrame(universe, frameValue, defaultOrbitFrame->getCenter(), body); if (orbitFrame == NULL) { return NULL; } } else { // No orbit frame specified; use the default frame. orbitFrame = defaultOrbitFrame; } orbitFrame->addRef(); // Get the body reference frame ReferenceFrame* bodyFrame; Value* bodyFrameValue = phaseData->getValue("BodyFrame"); if (bodyFrameValue != NULL) { bodyFrame = CreateReferenceFrame(universe, bodyFrameValue, defaultBodyFrame->getCenter(), body); if (bodyFrame == NULL) { orbitFrame->release(); return NULL; } } else { // No body frame specified; use the default frame. bodyFrame = defaultBodyFrame; } bodyFrame->addRef(); // Use planet units (AU for semimajor axis) if the center of the orbit // reference frame is a star. bool usePlanetUnits = orbitFrame->getCenter().star() != NULL; // Get the orbit Orbit* orbit = CreateOrbit(orbitFrame->getCenter(), phaseData, path, usePlanetUnits); if (!orbit) { clog << "Error: missing orbit in timeline phase.\n"; bodyFrame->release(); orbitFrame->release(); return NULL; } // Get the rotation model // TIMELINE-TODO: default rotation model is UniformRotation with a period // equal to the orbital period. Should we do something else? RotationModel* rotationModel = CreateRotationModel(phaseData, path, orbit->getPeriod()); if (!rotationModel) { // TODO: Should distinguish between a missing rotation model (where it's // appropriate to use a default one) and a bad rotation model (where // we should report an error.) rotationModel = new ConstantOrientation(Quaterniond::Identity()); } TimelinePhase* phase = TimelinePhase::CreateTimelinePhase(universe, body, beginning, ending, *orbitFrame, *orbit, *bodyFrame, *rotationModel); // Frame ownership transfered to phase; release local references orbitFrame->release(); bodyFrame->release(); return phase; }