This Stellarium script will find the next time two celestial objects are closest together. It is useful for finding when two planets conjunct or when a planet is close to a celestial object. If two planets are selected, and one of them starts retrograding before their conjunction, that will be the point of closest separation.
// ******************************************************************************************
// Stellarium script to find the next nearest time two objects are closest to each other.
// The time can be in the past or future, depending on whether they are initially moving
// away from each other.
//
// Created by David O'Neil, Aug, 2019. Released to the public domain, for anyone interested.
// Just leave this 'created by' (or 'originally created by') verbage in the derived work.
//
// To use:
// * Set the 'obj1' and 'obj2' variables to whatever you want.
// * Set the date via Stellarium's user interface close to a time you are looking for them
// to come together.
// (The date must be 1/2 year or so of a conjunction, to overcome the difficulty of
// taking retrograde motions into account.)
// * Run the script. It will find the next point of nearness that is closest to that date,
// whether that is in the future or the past.
// ******************************************************************************************
pi = Math.PI;
degToRad = pi/180;
obj1 = "Jupiter";
obj2 = "Saturn";
core.selectObjectByName(obj1, true);
StelMovementMgr.setFlagTracking(true);
justFindSeparation = false;
if (justFindSeparation) {
d = getRadiansBetweenObjects();
d = d/degToRad;
core.debug(d);
degrees = Math.floor(d);
minutes = d - degrees;
minutes = minutes * 60;
seconds = minutes - Math.floor(minutes);
core.debug(degrees + " " + Math.floor(minutes) + " " + seconds*60);
}
else findClosestConjunction();
core.debug(d / degToRad);
function findClosestConjunction() {
core.selectObjectByName("obj1", true);
core.setTimeRate(0); //Lock the sky in place, so we can see it unmoving!
//Get the initial 2 points:
a1 = getRadiansBetweenObjects();
//Do initial iteration in 1-day increment:
a2 = getTheAngleAfter("+1 days");
direction = "+";
if (a2 < a1) {
direction = "+";
}
else {
direction = "-";
a2 = getTheAngleAfter("-1 days");
a2 = getTheAngleAfter("-1 days"); //Don't know why can't use "-2 days" reliably!
}
timeStepString = direction + "1 days";
//Iterate:
while (a2 < a1) {
a1 = a2;
a2 = getTheAngleAfter(timeStepString);
}
//Assume we've gone through several days, and have passed the last good one,
//so step back (or forward) a day to fix the overstep:
if (direction == "+") {
a1 = getTheAngleAfter("-1 days");
}
else {
a1 = getTheAngleAfter("+1 days");
}
//Now we are doing it by the hours. As before, we must check whether we need to
//go back or forward.
//Now determine whether to go forward or back:
a2 = getTheAngleAfter("+1 hour");
if (a2 < a1) {
direction = "+";
}
else {
direction = "-";
a2 = getTheAngleAfter("-1 hours");
a2 = getTheAngleAfter("-1 hours"); //As before, don't know why can't just -2 this.
}
timeStepString = direction + "1 hour";
while (a2 < a1) {
a1 = a2;
a2 = getTheAngleAfter(timeStepString);
}
//Assume we've gone through several hours, and have passed the last good one,
//so step back (or forward) an hour to fix the overstep:
if (direction == "+") {
a1 = getTheAngleAfter("-1 hours");
}
else {
a1 = getTheAngleAfter("+1 hours");
}
//And finally, for the minutes:
//First, set a1 to a2, as a2 was last measurement taken at current time:
a1 = a2;
a2 = getTheAngleAfter("+1 minute");
if (a2 < a1) {
direction = "+";
}
else {
direction = "-";
a2 = getTheAngleAfter("-1 minutes");
a2 = getTheAngleAfter("-1 minutes");
}
timeStepString = direction + "1 minute";
while (a2 < a1) {
a1 = a2;
a2 = getTheAngleAfter(timeStepString);
}
core.debug("Finished! Separation = " + a1 + ", " + a2);
core.setTimeRate(0); //Lock the sky in place, so we can see it unmoving!
}
function getTheAngleAfter(timeStep) {
obj2Azi = core.getObjectInfo(obj2).azimuth;
core.setDate(timeStep);
//The following was an attempt to leave the wait time at 0.01, and loop wait until
//Stellarium got things caught up, but it never worked, and I had to change the
//wait time to 0.05 many times, instead of 0.03.
while (core.getObjectInfo(obj2).azimuth == obj2Azi) {
core.wait(0.01);
}
angleDiff = getRadiansBetweenObjects();
return angleDiff;
}
function getRadiansBetweenObjects() {
obj2Azi = core.getObjectInfo(obj2).elong;
obj2Azi = obj2Azi * degToRad;
obj2Alt = core.getObjectInfo(obj2).elat;
obj2Alt = obj2Alt * degToRad;
obj1Azi = core.getObjectInfo(obj1).elong;
obj1Azi = obj1Azi * degToRad;
obj1Alt = core.getObjectInfo(obj1).elat;
obj1Alt = obj1Alt * degToRad;
d = Math.acos(Math.sin(obj2Alt)*Math.sin(obj1Alt)+Math.cos(obj2Alt)*Math.cos(obj1Alt)*Math.cos(obj2Azi-obj1Azi));
//The following formula is for when the objects are very close together, or very close to 180 degrees apart:
//I may have Azi and Alt mixed up.
// delAzi = obj1Azi - obj2Azi;
// delAlt = obj1Alt - obj2Alt;
//d = sqrt ( (cos(aziA-aziB) * (altA-altB)) ^2 + (aziA-aziB)^2 )
//d = Math.sqrt ( Math.cos(delAzi)*(delAlt) * Math.cos(delAzi)*(delAlt) + (delAzi)*(delAzi) );
return d; //In radians
}