void MissionSelector::startMission(unsigned num) { Entry missionEntry; if(mCurrentCampaign == NULL) { // FIXME: we should fall back to station school in case a first timer plays missionEntry = mMissions[0]; } else { if(num < 0 || num >= static_cast<int>(mCurrentMissions.size())) return; mMissionNum = num; missionEntry = mCurrentMissions[num]; } Mission* oldMission = rMain()->getMission(); Orbit* orbitScreen = static_cast<Orbit*>(rMain()->getScreenManager().getState(Main::ORBIT_SCREEN)); orbitScreen->enterReadyState(); DataFile* dataFile = new DataFile(); Mission* mission = new Mission(dataFile); dataFile->setRootItem(mission); rMain()->setMission(mission); mission->initScriptFile(missionEntry.script); if(oldMission != NULL) { if (oldMission == ConfigManager::getPlayer()->getHomeBase()) { ConfigManager::getSingleton().savePlayer(); } else { delete oldMission->getDataFile(); } } }
void MissionSelector::loadMission(string fileName) { if(fileName == "") return; Mission* oldMission = rMain()->getMission(); Orbit* orbitScreen = static_cast<Orbit*>(rMain()->getScreenManager().getState(Main::ORBIT_SCREEN)); orbitScreen->enterReadyState(); DataFile* dataFile = new DataFile(stringToWString(fileName)); if(dataFile->getRootItem() != NULL) { Mission* mission = dataFile->getRootItem()->castToClass<Mission>(); if(mission != NULL) { rMain()->setMission(mission); if(oldMission != NULL) { if (oldMission == ConfigManager::getPlayer()->getHomeBase()) { ConfigManager::getSingleton().savePlayer(); } else { delete oldMission->getDataFile(); } } } } }
static bool createRotation(ParserContext* ctx, const xmlChar** att) { double period = 0.0; double obliquity = 0.0; double axisLongitude = 0.0; double offset = 0.0; double epoch = astro::J2000; if (att != NULL) { for (int i = 0; att[i] != NULL; i += 2) { if (matchName(att[i], "period")) { if (matchName(att[i + 1], "sync")) period = 0.0; else parseTime(att[i + 1], period, "h"); } else if (matchName(att[i], "obliquity")) parseAngle(att[i + 1], obliquity); else if (matchName(att[i], "axis-longitude")) parseAngle(att[i + 1], axisLongitude); else if (matchName(att[i], "offset")) parseAngle(att[i + 1], offset); else if (matchName(att[i], "epoch")) parseEpoch(att[i + 1], epoch); } } assert(ctx->body != NULL); RotationElements re; // A period of 0 means that the object is in synchronous rotation, so // we'll set its rotation period equal to its orbital period. The catch // is that we require that the orbit was specified before the rotation // elements within the XML file. Orbit* orbit = ctx->body->getOrbit(); if (orbit == NULL) return false; if (period == 0.0) re.period = (float) orbit->getPeriod(); else re.period = (float) period / 24.0f; re.obliquity = (float) degToRad(obliquity); re.axisLongitude = (float) degToRad(axisLongitude); re.offset = (float) degToRad(offset); re.epoch = epoch; ctx->body->setRotationElements(re); return true; }
void MixedOrbit::sample(double t0, double t1, int nSamples, OrbitSampleProc& proc) const { Orbit* o; if (t0 < begin) o = beforeApprox; else if (t0 < end) o = primary; else o = afterApprox; o->sample(t0, t1, nSamples, proc); }
void Orbit::test() { Orbit o; o.load("Orbits/orbits0.710.dat"); vector<double> t; for(double tt=-10; tt <= 10; tt += 0.01) t.push_back(tt); vector<double> y = o.evaluate(t, 1.); for(size_t i=0; i<y.size(); i++) cout<<t[i]<<' '<<y[i]<<endl; }
void SystemView::PutBody(const SystemBody *b, const vector3d &offset, const matrix4x4f &trans) { if (b->type == SystemBody::TYPE_STARPORT_SURFACE) return; if (b->type != SystemBody::TYPE_GRAVPOINT) { if (!m_bodyIcon) { m_bodyIcon.reset(new Graphics::Drawables::Disk(m_renderer, Color::WHITE, 1.0f)); } const double radius = b->GetRadius() * m_zoom; matrix4x4f invRot = trans; invRot.ClearToRotOnly(); invRot = invRot.InverseOf(); matrix4x4f bodyTrans = trans; bodyTrans.Translate(vector3f(offset)); bodyTrans.Scale(radius); m_renderer->SetTransform(bodyTrans * invRot); m_bodyIcon->Draw(m_renderer); m_renderer->SetTransform(trans); PutLabel(b, offset); } Frame *frame = Pi::player->GetFrame(); if(frame->IsRotFrame()) frame = frame->GetNonRotFrame(); if(frame->GetSystemBody() == b && frame->GetSystemBody()->GetMass() > 0) { const double t0 = Pi::game->GetTime(); Orbit playerOrbit = Pi::player->ComputeOrbit(); PutOrbit(&playerOrbit, offset, Color::RED, b->GetRadius()); PutSelectionBox(offset + playerOrbit.OrbitalPosAtTime(m_time - t0)* double(m_zoom), Color::RED); } if (b->children.size()) { for(std::vector<SystemBody*>::const_iterator kid = b->children.begin(); kid != b->children.end(); ++kid) { if (is_zero_general((*kid)->orbit.GetSemiMajorAxis())) continue; if ((*kid)->orbit.GetSemiMajorAxis() * m_zoom < ROUGH_SIZE_OF_TURD) { PutOrbit(&((*kid)->orbit), offset, Color(0, 255, 0, 255)); } // not using current time yet vector3d pos = (*kid)->orbit.OrbitalPosAtTime(m_time); pos *= double(m_zoom); PutBody(*kid, offset + pos, trans); } } }
void TransferPlanner::AddStartTime(double timeStep) { if(std::fabs(m_startTime) < 1.) m_startTime = Pi::game->GetTime(); m_startTime += m_factor * timeStep; double deltaT = m_startTime - Pi::game->GetTime(); if(deltaT > 0.) { Frame *frame = Pi::player->GetFrame()->GetNonRotFrame(); Orbit playerOrbit = Orbit::FromBodyState(Pi::player->GetPositionRelTo(frame), Pi::player->GetVelocityRelTo(frame), frame->GetSystemBody()->GetMass()); m_position = playerOrbit.OrbitalPosAtTime(deltaT); m_velocity = playerOrbit.OrbitalVelocityAtTime(frame->GetSystemBody()->GetMass(), deltaT); } else ResetStartTime(); }
double Orbit::calcDeviance(Orbit &other) { if ( !m_bValid ) return 0.0; // special case: if one orbit's apogee is smaller than the other orbit's // perigee, the first orbit is completely contained within the second. if ( m_apogee < other.m_perigee ) { // we are completely contained within other return other.m_orbitArea - m_orbitArea; } if ( other.m_apogee < m_perigee ) { // other is completely contained within us return m_orbitArea - other.m_orbitArea; } // do a lap around and note the difference between the r values double thetaStep = TWOPI/1440.0; // one fourth of a degree per step. Arbitrarily chosen. double deviance = 0.0; for ( double theta=0.0 ; theta<TWOPI ; theta+=thetaStep ) { // note the distances at this location double rThis = getR(theta); double rOther = other.getR(theta); // make them in to volumes. Each is a stepFraction chunk of a circle // good old r^2*dTheta/2 double areaThis = rThis*rThis*thetaStep*0.5; double areaOther = rOther*rOther*thetaStep*0.5; double diff = fabs(areaThis - areaOther); deviance += diff; } return deviance; }
void SolarSystemCreator::makeOrbit(Orbit& orbit) { int d = SSGX::d6(); if (d == 3) orbit.setEccentricity( (double)SSGX::dn(2000) / 10000.0); else orbit.setEccentricity( (double)SSGX::dn(200) / 10000.0); if (d == 4) orbit.setInclination( (double)(SSGX::d100() -50)/2.5); else orbit.setInclination( (double)(SSGX::d100() -50)/20); if (d == 6) orbit.setObliquity( (double)(SSGX::d100() -50)/2.5); else orbit.setObliquity( (double)(SSGX::d100() -50)/10); }
static void CalculateOsculatingElements(const Orbit& orbit, double t, double dt, OrbitalElements* elements) { double sdt = dt; // If the trajectory is finite, make sure we sample // it inside the valid time interval. if (!orbit.isPeriodic()) { double beginTime = 0.0; double endTime = 0.0; orbit.getValidRange(beginTime, endTime); clog << "t+dt: " << t + dt << ", endTime: " << endTime << endl; if (t + dt > endTime) { clog << "REVERSE\n"; sdt = -dt; } } Point3d p0 = orbit.positionAtTime(t); Point3d p1 = orbit.positionAtTime(t + sdt); Vec3d v0 = orbit.velocityAtTime(t); Vec3d v1 = orbit.velocityAtTime(t + sdt); double accel = ((v1 - v0) / sdt).length(); Vec3d r = p0 - Point3d(0.0, 0.0, 0.0); double GM = accel * (r * r); clog << "vel: " << v0.length() / 86400.0 << endl; clog << "vel (est): " << (p1 - p0).length() / sdt / 86400 << endl; clog << "osc: " << t << ", " << dt << ", " << accel << ", GM=" << GM << endl; StateVectorToElements(p0, v0, GM, elements); }
Planet SolarSystemCreator::createPlanet( double currentDistance, bool isSatellite, Planet& planetTop, double *prevDistance) { Planet planet; Orbit orbit; int d = SSGX::d6(); if (d == 3) orbit.setEccentricity( (double)SSGX::dn(1000) / 10000.0); else orbit.setEccentricity( (double)SSGX::dn(300) / 10000.0); if (d == 4) orbit.setInclination( (double)(SSGX::d100() -50)/30); else orbit.setInclination( (double)(SSGX::d100() -50)/5); if (d == 4) orbit.setObliquity( (double)(SSGX::d100() -50)/2); else orbit.setInclination( (double)(SSGX::d100() -50)); d = SSGX::d6(); if (currentDistance > _star->outerLifeZone()) { if (d < 5) { planet.setCoreType(NSPlanet::ctIcy); planet.setDensity( ((double)(SSGX::dn(400)))/1000*5520.0); if (!isSatellite) planet.setDiameter(SSGX::icyDiameter()); else planet.setDiameter(SSGX::satDiameter()); } else { if (!isSatellite) planet.setDiameter(SSGX::rockyDiameter()); else planet.setDiameter(SSGX::satDiameter()); planet.setDensity( ((double)(400+SSGX::dn(600)))/1000*5520.0); } } else { if (!isSatellite) planet.setDiameter(SSGX::rockyDiameter()); else planet.setDiameter(SSGX::satDiameter()); planet.setDensity( ((double)(400+SSGX::dn(900)))/1000*5520.0); } while (isSatellite && planet.diameter() > planetTop.diameter() / 3) planet.setDiameter(planet.diameter()/2); double dTemp = 255 / sqrt(( currentDistance / sqrt (_star->luminosity()))); planet.setTemperature(dTemp); double dmmwr = (0.02783 * dTemp) / ( pow(planet.gravEarth(),2) ); planet.setMmwr(dmmwr); if (dmmwr < 120) planet.setAtmosphere(atVeryThin); if (dmmwr < 80) planet.setAtmosphere(atThin); if (dmmwr < 40) planet.setAtmosphere(atStandard); if (dmmwr < 20) planet.setAtmosphere(atDense); if (dmmwr < 5) { if (planet.diameter() > 20000 ) planet.setAtmosphere(atMassive); else planet.setAtmosphere(atDense); } this->setPlanetType(planet,currentDistance); if (!isSatellite) { this->setPlanetModifiers(planet); planet.setPlanetFlag(); } else { planet.setSatelliteFlag(); //qDebug() << "Satellite flag set: " << planet.isSatellite(); } if (!isSatellite) { orbit.setDistance(currentDistance); orbit.setYear(_star->mass()); } else { double sSatDist = *prevDistance; if (sSatDist <= 0) sSatDist = 35000+(double)((SSGX::dn(90)+30) * planet.diameter()); else sSatDist += (double)((SSGX::dn(70)+10) * planet.diameter()); *prevDistance = sSatDist; orbit.setDistance(sSatDist); //in km double d1 = orbit.distance() / 40000.0; d1 = (pow(d1,3) * 793.64) / (planetTop.massEarth() + planet.massEarth()); double dYear = sqrt(d1); orbit.setFixedYear(dYear); } planet.setOrbit(orbit); int w = rand() % 10; switch (w) { case 1: planet.setName(_onomastikon->fakeNomen()); break; case 2: planet.setName(_onomastikon->fakeNomen()); break; case 3: planet.setName(_onomastikon->nomen()); break; case 4: planet.setName(_onomastikon->nomen()); break; case 5: planet.setName(_onomastikon->sigla()); break; default: planet.setName(_onomastikon->pseudoNomen()); break; } return planet; }
static bool CreateTimeline(Body* body, PlanetarySystem* system, Universe& universe, Hash* planetData, const string& path, Disposition disposition, BodyType bodyType) { FrameTree* parentFrameTree = NULL; Selection parentObject = GetParentObject(system); bool orbitsPlanet = false; if (parentObject.body()) { parentFrameTree = parentObject.body()->getOrCreateFrameTree(); orbitsPlanet = true; } else if (parentObject.star()) { SolarSystem* solarSystem = universe.getSolarSystem(parentObject.star()); if (solarSystem == NULL) solarSystem = universe.createSolarSystem(parentObject.star()); parentFrameTree = solarSystem->getFrameTree(); } else { // Bad orbit barycenter specified return false; } ReferenceFrame* defaultOrbitFrame = NULL; ReferenceFrame* defaultBodyFrame = NULL; if (bodyType == SurfaceObject) { defaultOrbitFrame = new BodyFixedFrame(parentObject, parentObject); defaultBodyFrame = CreateTopocentricFrame(parentObject, parentObject, Selection(body)); defaultOrbitFrame->addRef(); defaultBodyFrame->addRef(); } else { defaultOrbitFrame = parentFrameTree->getDefaultReferenceFrame(); defaultBodyFrame = parentFrameTree->getDefaultReferenceFrame(); } // If there's an explicit timeline definition, parse that. Otherwise, we'll do // things the old way. Value* value = planetData->getValue("Timeline"); if (value != NULL) { if (value->getType() != Value::ArrayType) { clog << "Error: Timeline must be an array\n"; return false; } Timeline* timeline = CreateTimelineFromArray(body, universe, value->getArray(), path, defaultOrbitFrame, defaultBodyFrame); if (timeline == NULL) { return false; } else { body->setTimeline(timeline); return true; } } // Information required for the object timeline. ReferenceFrame* orbitFrame = NULL; ReferenceFrame* bodyFrame = NULL; Orbit* orbit = NULL; RotationModel* rotationModel = NULL; double beginning = -numeric_limits<double>::infinity(); double ending = numeric_limits<double>::infinity(); // If any new timeline values are specified, we need to overrideOldTimeline will // be set to true. bool overrideOldTimeline = false; // The interaction of Modify with timelines is slightly complicated. If the timeline // is specified by putting the OrbitFrame, Orbit, BodyFrame, or RotationModel directly // in the object definition (i.e. not inside a Timeline structure), it will completely // replace the previous timeline if it contained more than one phase. Otherwise, the // properties of the single phase will be modified individually, for compatibility with // Celestia versions 1.5.0 and earlier. if (disposition == ModifyObject) { const Timeline* timeline = body->getTimeline(); if (timeline->phaseCount() == 1) { const TimelinePhase* phase = timeline->getPhase(0); orbitFrame = phase->orbitFrame(); bodyFrame = phase->bodyFrame(); orbit = phase->orbit(); rotationModel = phase->rotationModel(); beginning = phase->startTime(); ending = phase->endTime(); } } // Get the object's orbit reference frame. bool newOrbitFrame = false; Value* frameValue = planetData->getValue("OrbitFrame"); if (frameValue != NULL) { ReferenceFrame* frame = CreateReferenceFrame(universe, frameValue, parentObject, body); if (frame != NULL) { orbitFrame = frame; newOrbitFrame = true; overrideOldTimeline = true; } } // Get the object's body frame. bool newBodyFrame = false; Value* bodyFrameValue = planetData->getValue("BodyFrame"); if (bodyFrameValue != NULL) { ReferenceFrame* frame = CreateReferenceFrame(universe, bodyFrameValue, parentObject, body); if (frame != NULL) { bodyFrame = frame; newBodyFrame = true; overrideOldTimeline = true; } } // If no orbit or body frame was specified, use the default ones if (orbitFrame == NULL) orbitFrame = defaultOrbitFrame; if (bodyFrame == NULL) bodyFrame = defaultBodyFrame; // If the center of the is a star, orbital element units are // in AU; otherwise, use kilometers. if (orbitFrame->getCenter().star() != NULL) orbitsPlanet = false; else orbitsPlanet = true; Orbit* newOrbit = CreateOrbit(orbitFrame->getCenter(), planetData, path, !orbitsPlanet); if (newOrbit == NULL && orbit == NULL) { if (body->getTimeline() && disposition == ModifyObject) { // The object definition is modifying an existing object with a multiple phase // timeline, but no orbit definition was given. This can happen for completely // sensible reasons, such a Modify definition that just changes visual properties. // Or, the definition may try to change other timeline phase properties such as // the orbit frame, but without providing an orbit. In both cases, we'll just // leave the original timeline alone. return true; } else { clog << "No valid orbit specified for object '" << body->getName() << "'. Skipping.\n"; return false; } } // If a new orbit was given, override any old orbit if (newOrbit != NULL) { orbit = newOrbit; overrideOldTimeline = true; } // Get the rotation model for this body double syncRotationPeriod = orbit->getPeriod(); RotationModel* newRotationModel = CreateRotationModel(planetData, path, syncRotationPeriod); // If a new rotation model was given, override the old one if (newRotationModel != NULL) { rotationModel = newRotationModel; overrideOldTimeline = true; } // If there was no rotation model specified, nor a previous rotation model to // override, create the default one. if (rotationModel == NULL) { // If no rotation model is provided, use a default rotation model-- // a uniform rotation that's synchronous with the orbit (appropriate // for nearly all natural satellites in the solar system.) rotationModel = CreateDefaultRotationModel(syncRotationPeriod); } if (ParseDate(planetData, "Beginning", beginning)) overrideOldTimeline = true; if (ParseDate(planetData, "Ending", ending)) overrideOldTimeline = true; // Something went wrong if the disposition isn't modify and no timeline // is to be created. assert(disposition == ModifyObject || overrideOldTimeline); if (overrideOldTimeline) { if (beginning >= ending) { clog << "Beginning time must be before Ending time.\n"; return false; } // We finally have an orbit, rotation model, frames, and time range. Create // the object timeline. TimelinePhase* phase = TimelinePhase::CreateTimelinePhase(universe, body, beginning, ending, *orbitFrame, *orbit, *bodyFrame, *rotationModel); // We've already checked that beginning < ending; nothing else should go // wrong during the creation of a TimelinePhase. assert(phase != NULL); if (phase == NULL) { clog << "Internal error creating TimelinePhase.\n"; return false; } Timeline* timeline = new Timeline(); timeline->appendPhase(phase); body->setTimeline(timeline); // Check for circular references in frames; this can only be done once the timeline // has actually been set. // TIMELINE-TODO: This check is not comprehensive; it won't find recursion in // multiphase timelines. if (newOrbitFrame && isFrameCircular(*body->getOrbitFrame(0.0), ReferenceFrame::PositionFrame)) { clog << "Orbit frame for " << body->getName() << " is nested too deep (probably circular)\n"; return false; } if (newBodyFrame && isFrameCircular(*body->getBodyFrame(0.0), ReferenceFrame::OrientationFrame)) { clog << "Body frame for " << body->getName() << " is nested too deep (probably circular)\n"; return false; } } return true; }
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; }
// ============================================================================================================================================== // bool SyncMFD::InterpolateClosestPassage(OBJHANDLE ref, Orbit *src, double lon,double lat,double orbit,double *diff,double *tim,double *head,double *tr) { VECTOR3 Rot,Off; Orbit LEO; int i; double obli = 0.0; double trans = 0.0; double per = 0.0; double offset = 0.0; double size = 0.0; double time = 0.0; // Rotation elements obli = oapiGetPlanetObliquity(ref); trans = oapiGetPlanetTheta(ref); per = oapiGetPlanetPeriod(ref); offset = oapiGetPlanetCurrentRotation(ref); size = oapiGetSize(ref); LEO.LEO(ref); double step = PI2/16.01; double start = orbit; double end = orbit+PI2+(step/2.0); double trl, dst2; double dot,old_dot=0; VECTOR3 pos = _V(0,0,0); VECTOR3 vel = _V(0,0,0); VECTOR3 gpv = _V(0,0,0); VECTOR3 spd = _V(0,0,0); VECTOR3 relv = _V(0,0,0); VECTOR3 relp = _V(0,0,0); bool no_intercept=true; bool first=true; for (trl=start;trl<end;trl+=step) { // Caluclate time to a location time=Trl2Time(trl,src)/86400.0; // Caluclate Planets Rotation offset at that time PlanetAxis(obli,trans,offset,per,time,&Rot,&Off); // Calculate Ship's position vector and distance^2 pos = src->Position(trl); dst2 = dotp(pos,pos); // Reset the distance to correspond a surface position. pos = set_length(pos,size); // Compute ship's surface velocity vector direction vel = crossp(src->norv,pos); // Compute ship's surface velocity vector magnitude vel = set_length(vel,src->ang*size/dst2); // Compute base's position vector gpv = VectorByLonLat(Rot,Off,lon,lat)*size; // Compute speed of the base spd = GroundSpeedVector(ref,time,lon,lat); // Copmute relative position to the base relv = (vel-spd); relp = (pos-gpv); dot = dotp(relv,relp); if (old_dot<0 && dot>0 && !first) { if (angle(pos,gpv)<PI05) { start=trl-step; no_intercept=false; break; } } first=false; old_dot=dot; } // Return N/A if no passage points found if (no_intercept) { if (head) *head = 0; if (diff) *diff = 0; if (tim) *tim = 0; if (tr) *tr = start+PI2-PI05; return false; } trl=start; old_dot=-1; // We are approaching the base double trll=0; no_intercept=true; for (i=0;i<24;i++) { step/=2.0; // Caluclate time to a location time=Trl2Time(trl,src)/86400.0; // Caluclate Planets Rotation offset at that time PlanetAxis(obli,trans,offset,per,time,&Rot,&Off); // Calculate Ship's position vector and distance^2 pos = src->Position(trl); dst2 = dotp(pos,pos); // Reset the distance to correspond a surface position. pos = set_length(pos,size); // Compute ship's surface velocity vector direction vel = crossp(src->norv,pos); // Compute ship's surface velocity vector magnitude vel = set_length(vel,src->ang*size/dst2); // Compute base's position vector gpv = VectorByLonLat(Rot,Off,lon,lat)*size; // Compute speed of the base spd = GroundSpeedVector(ref,time,lon,lat); // Copmute relative position to the base relv = (vel-spd); relp = (pos-gpv); dot = dotp(relv,relp); trll=trl; if (dot==0) { no_intercept=false; break; // closest position archived, break } if (dot>0) { // base is behind of us, step back trl=trl-step; no_intercept=false; // Verify, We have a base passage. } else trl=trl+step; // base is front of us, cuntinue stepping } double dif=angle(pos, gpv); VECTOR3 zero=crossp(pos,spd); if (head) *head = nangle(relp,zero,pos); if (diff) *diff = dif; if (tim) *tim = time*86400.0; if (tr) *tr = trll; return true; }
void SystemView::PutBody(const SystemBody *b, const vector3d &offset, const matrix4x4f &trans) { if (b->GetType() == SystemBody::TYPE_STARPORT_SURFACE) return; if (b->GetType() != SystemBody::TYPE_GRAVPOINT) { if (!m_bodyIcon) { Graphics::RenderStateDesc rsd; auto solidState = m_renderer->CreateRenderState(rsd); m_bodyIcon.reset(new Graphics::Drawables::Disk(m_renderer, solidState, Color::WHITE, 1.0f)); } const double radius = b->GetRadius() * m_zoom; matrix4x4f invRot = trans; invRot.ClearToRotOnly(); invRot = invRot.Inverse(); matrix4x4f bodyTrans = trans; bodyTrans.Translate(vector3f(offset)); bodyTrans.Scale(radius); m_renderer->SetTransform(bodyTrans * invRot); m_bodyIcon->Draw(m_renderer); m_renderer->SetTransform(trans); PutLabel(b, offset); } Frame *frame = Pi::player->GetFrame(); if(frame->IsRotFrame()) frame = frame->GetNonRotFrame(); // display the players orbit(?) if(frame->GetSystemBody() == b && frame->GetSystemBody()->GetMass() > 0) { const double t0 = m_game->GetTime(); Orbit playerOrbit = Pi::player->ComputeOrbit(); PutOrbit(&playerOrbit, offset, Color::RED, b->GetRadius()); const double plannerStartTime = m_planner->GetStartTime(); if(!m_planner->GetPosition().ExactlyEqual(vector3d(0,0,0))) { Orbit plannedOrbit = Orbit::FromBodyState(m_planner->GetPosition(), m_planner->GetVel(), frame->GetSystemBody()->GetMass()); PutOrbit(&plannedOrbit, offset, Color::STEELBLUE, b->GetRadius()); if(std::fabs(m_time - t0) > 1. && (m_time - plannerStartTime) > 0.) PutSelectionBox(offset + plannedOrbit.OrbitalPosAtTime(m_time - plannerStartTime) * static_cast<double>(m_zoom), Color::STEELBLUE); else PutSelectionBox(offset + m_planner->GetPosition() * static_cast<double>(m_zoom), Color::STEELBLUE); } PutSelectionBox(offset + playerOrbit.OrbitalPosAtTime(m_time - t0)* double(m_zoom), Color::RED); } // display all child bodies and their orbits if (b->HasChildren()) { for(const SystemBody* kid : b->GetChildren()) { if (is_zero_general(kid->GetOrbit().GetSemiMajorAxis())) continue; const double axisZoom = kid->GetOrbit().GetSemiMajorAxis() * m_zoom; if (axisZoom < DEFAULT_VIEW_DISTANCE) { const SystemBody::BodySuperType bst = kid->GetSuperType(); const bool showLagrange = (bst == SystemBody::SUPERTYPE_ROCKY_PLANET || bst == SystemBody::SUPERTYPE_GAS_GIANT); PutOrbit(&(kid->GetOrbit()), offset, Color::GREEN, 0.0, showLagrange); } // not using current time yet const vector3d pos = kid->GetOrbit().OrbitalPosAtTime(m_time) * double(m_zoom); PutBody(kid, offset + pos, trans); } } }
Planet SolarSystemCreator::createPlanet( double currentDistance, bool isSatellite, Planet& planetTop, double *prevDistance) { Planet planet; if (isSatellite) planet.setParent(&planetTop); Orbit orbit; makeOrbit(orbit); makeDiameterAndDensity(isSatellite, planet, currentDistance, planetTop); double dTemp = 255 / sqrt(( currentDistance / sqrt (_star->luminosity()))); planet.setTemperature(dTemp); double dmmwr = (0.02783 * dTemp) / ( pow(planet.gravEarth(),2) ); planet.setMmwr(dmmwr); if (dmmwr < 120) planet.setAtmosphere(atVeryThin); if (dmmwr < 80) planet.setAtmosphere(atThin); if (dmmwr < 40) planet.setAtmosphere(atStandard); if (dmmwr < 20) planet.setAtmosphere(atDense); if (dmmwr < 5) { if (planet.diameter() > 20000 ) planet.setAtmosphere(atMassive); else planet.setAtmosphere(atDense); } this->setPlanetType(planet,currentDistance); if (!isSatellite) { this->setPlanetModifiers(planet); planet.setPlanetFlag(); } else { planet.setSatelliteFlag(); //qDebug() << "Satellite flag set: " << planet.isSatellite(); } if (!isSatellite) { orbit.setDistance(currentDistance); orbit.setYear(_star->mass()); } else { double sSatDist = *prevDistance; if (sSatDist <= 0) if (planetTop.planetType() != ptGasGiant) sSatDist = 105000+(double)((SSGX::dn(20)+10) * planetTop.diameter()); else sSatDist = 105000+(double)((SSGX::floatRand()*1.8+2.0) * planetTop.diameter()); else sSatDist += 80000.0+(double)((SSGX::dn(50)+25) * planet.diameter()); *prevDistance = sSatDist; orbit.setDistance(sSatDist); //in km double d1 = orbit.distance() / 40000.0; d1 = (pow(d1,3) * 793.64) / (planetTop.massEarth() + planet.massEarth()); double dYear = sqrt(d1); orbit.setFixedYear(dYear); } planet.setOrbit(orbit); int w = rand() % 10; switch (w) { case 1: planet.setName(_onomastikon->fakeNomen()); break; case 2: planet.setName(_onomastikon->fakeNomen()); break; case 3: planet.setName(_onomastikon->nomen()); break; case 4: planet.setName(_onomastikon->nomen()); break; case 5: planet.setName(_onomastikon->sigla()); break; default: planet.setName(_onomastikon->pseudoNomen()); break; } return planet; }
int main() { using namespace std; //This is the maximum error allowed when keplers_eqn() is used to solve for the //orbit's eccentric anomaly E. Shrink this number to increase numerical accuracy. double max_error = 1.0e-15; //Solve Kepler's equation N times. int N = 10000000; //Save a subset of the N solutions, for plotting and testing purposes. int Nsave = 100000; //The remaining quanties used below. double* e = new double[N]; double* M = new double[N]; double* E = new double[N]; int* iterations = new int[N]; double x, xtime_sec, rn; clock_t t0, t1; double pi = Orbit().get_pi(); Orbit orb; //Solve kepler's equation N times. Each orbit is randomly generated with //mean anomly M uniformly distributed between -Pi<M<Pi and eccentricity //logarithmically distributed so that log10(x) is uniformly distributed over //-6<log10(x)<0 where x=1-e so that e ranges over 10^(-6)<e<0.999999. srand(1); t0 = clock(); for (int i=0; i<N; i++){ //Get random number between 0<rn<1, calculate x=1-e and e=1-x. rn = (double)rand()/(double)RAND_MAX; x = pow(10.0, -6.0*rn); e[i] = 1.0 - x; //Random mean anomaly M. rn = (double)rand()/(double)RAND_MAX; M[i] = pi*(2.0*rn - 1.0); //Construct the orbit. orb = Orbit(1.0, e[i], 0.0, 0.0, 0.0, M[i]); //Calculate eccentric anomaly and track number of iterations used by keplers_eqn(). E[i] = orb.keplers_eqn(max_error); iterations[i] = orb.i_ke; } //Execution time consumed by the main loop. t1 = clock(); xtime_sec = (double)(t1 - t0)/CLOCKS_PER_SEC; cout << "execution time (sec) = " << xtime_sec << endl; //Store Nsave results in file keplers_eqn.dat. ofstream out("keplers_eqn.dat", ios::binary); out.write((char *)&xtime_sec, sizeof(xtime_sec)); out.write((char *)&Nsave, sizeof(Nsave)); out.write((char *)e, sizeof(e)*Nsave); out.write((char *)M, sizeof(M)*Nsave); out.write((char *)E, sizeof(E)*Nsave); out.write((char *)iterations, sizeof(iterations)*Nsave); out.close(); //Delete large arrays. delete[] e; delete[] E; delete[] M; }