diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h
index cb0ce77afa..e01f29e51e 100644
--- a/include/openspace/util/spicemanager.h
+++ b/include/openspace/util/spicemanager.h
@@ -115,6 +115,12 @@ public:
Direction direction = Direction::Reception;
};
+ /// The possible values for the method parameter of the targetInFieldOfView method
+ enum class FieldOfViewMethod {
+ Ellipsoid = 0,
+ Point
+ };
+
/**
* Loads one or more SPICE kernels into a program. The provided path can either be a
* binary, text-kernel, or meta-kernel which gets loaded into the kernel pool. The
@@ -448,192 +454,218 @@ public:
glm::dmat3 frameTransformationMatrix(const std::string& from,
const std::string& to, double ephemerisTime) const;
+ /// Struct that is used as the return value from the #getSurfaceIntercept method
+ struct SurfaceInterceptResult {
+ /**
+ * The closest surface intercept point on the target body in Cartesian Coordinates
+ * relative to the reference frame.
+ */
+ glm::dvec3 surfaceIntercept;
+
+ /**
+ * If the aberration correction is not AberrationCorrection::Type::None, this
+ * value contains the time for which the intercept was computed. Otherwise it is
+ * the same as the ephemerisTime.
+ */
+ double interceptEpoch;
+
+ /**
+ * The vector from the observer's position to the \p surfaceIntercept position in
+ * the provided reference frame.
+ */
+ glm::dvec3 surfaceVector;
+
+ /// true if the ray intersects the body, false otherwise
+ bool interceptFound;
+ };
+
/**
- * Given an \p observer and a direction vector \p directionVector defining a ray,
- * compute the surface intercept of the ray on a \p target body at a specified
+ * Given an \p observer and a probing direction vector \p directionVector defining a
+ * ray, compute the surface intercept of the ray on a \p target body at a specified
* \p targetEpoch, optionally corrected for aberrations (\p aberrationCorrection).
- * \param target Name of target body
- * \param observer Name of observing body
+ * \param target The name of target body
+ * \param observer The name of the observer
* \param fovFrame Reference frame of the ray's direction vector
- * \param bodyFixedFrame Body-fixed, body-centered target body frame
- * \param method Computation method
- * \param aberrationCorrection Aberration correction
+ * \param referenceFrame The reference frame in which the surface intercept and the
+ * surface vector are expressed
+ * \param aberrationCorrection The aberration correction method that is applied to
+ * compute the intercept
* \param ephemerisTime Intercept time in ephemeris seconds past J2000 TDB
- * \param directionVector Ray's direction vector
+ * \param directionVector Probing ray's direction
* \param surfaceIntercept Surface intercept point on the target body
* \param surfaceVector Vector from observer to intercept point
* \param isVisible Flag indicating whether intercept was found
* \return true if not error occurred, false otherwise
- * For further details, refer to
- * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html
+ * \throws SpiceKernelException If the \p target or \p observer do not name the same
+ * NAIF object, the \p target or \p observer name the same NAIF object or are in the
+ * same location, the \p referenceFrame or \p fovFrame are not recognized,
+ * insufficient kernel information has been loaded.
+ * \pre \p target must not be empty.
+ * \pre \p observer must not be empty.
+ * \pre \p The \p target and \p observer must be different strings
+ * \pre \p fovFrame must not be empty.
+ * \pre \p referenceFrame must not be empty.
+ * \pre \p directionVector must not be the null vector
+ * \post The SurfaceInterceptResult does not contain any uninitialized values.
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html
*/
- bool getSurfaceIntercept(const std::string& target,
- const std::string& observer,
- const std::string& fovFrame,
- const std::string& bodyFixedFrame,
- AberrationCorrection aberrationCorrection,
- double ephemerisTime,
- glm::dvec3& directionVector,
- glm::dvec3& surfaceIntercept,
- glm::dvec3& surfaceVector,
- bool& isVisible
- ) const;
+ SurfaceInterceptResult getSurfaceIntercept(const std::string& target,
+ const std::string& observer, const std::string& fovFrame,
+ const std::string& referenceFrame, AberrationCorrection aberrationCorrection,
+ double ephemerisTime, const glm::dvec3& directionVector) const;
/**
- * Determine if a specified ephemeris object is within the
- * field-of-view (FOV) of a specified instrument at a given time.
- * \param instrument Name or ID code string of the instrument.
- * \param target Name or ID code string of the target.
- * \param observer Name or ID code string of the observer.
- * \param aberrationCorrection Aberration correction method.
- * \param method Type of shape model used for the target.
- * \param referenceFrame Body-fixed, body-centered frame for target body.
- * \param targetEpoch Time of the observation (seconds past J2000).
- * \param isVisible true if the target is visible
- * \return The success of the function
- * For further detail, refer to
- * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/fovtrg_c.html
+ * Determine whether a specific \p target is in the field-of-view of a specified
+ * \p instrument or an \p observer at a given time, using the reference frame
+ * \p referenceFrame.
+ * \param target The name or NAIF ID code string of the target
+ * \param observer The name or NAIF ID code string of the observer
+ * \param referenceFrame Body-fixed, body-centered frame for target body
+ * \param instrument The name or NAIF ID code string of the instrument
+ * \param method The type of shape model used for the target
+ * \param aberrationCorrection The aberration correction method
+ * \param ephemerisTime Time of the observation (seconds past J2000)
+ * \return true if the target is visible, false otherwise
+ * \throws SpiceKernelException If the \p target or \p observer do not name valid
+ * NAIF objects, the \p target or \p observer name the same NAIF object, the
+ * \p instrument does not name a valid NAIF object, or insufficient kernel information
+ * has been loaded.
+ * \pre \p target must not be empty.
+ * \pre \p observer must not be empty.
+ * \pre \p target and \p observer must not be different strings
+ * \pre \p referenceFrame must not be empty.
+ * \pre \p instrument must not be empty.
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/fovtrg_c.html
*/
- bool targetWithinFieldOfView(const std::string& instrument,
- const std::string& target,
- const std::string& observer,
- const std::string& method,
- const std::string& referenceFrame,
- const std::string& aberrationCorrection,
- double& targetEpoch,
- bool& isVisible
- ) const;
+ bool isTargetInFieldOfView(const std::string& target, const std::string& observer,
+ const std::string& referenceFrame, const std::string& instrument,
+ FieldOfViewMethod method, AberrationCorrection aberrationCorrection,
+ double& ephemerisTime) const;
+
/**
- * This method performs the same computation as the function its overloading
- * with the exception that in doing so it assumes the inertial bodyfixed frame
- * is that of 'IAU' type, allowing the client to omitt the
- * referenceFrame for planetary objects.
+ * Determine whether a specific \p target is in the field-of-view of a specified
+ * \p instrument or an \p observer at a given time. The reference frame used is
+ * derived from the \p target by converting it into an IAU inertial
+ * reference frame.
+ * \param target The name or NAIF ID code string of the target
+ * \param observer The name or NAIF ID code string of the observer
+ * \param instrument The name or NAIF ID code string of the instrument
+ * \param method The type of shape model used for the target
+ * \param aberrationCorrection The aberration correction method
+ * \param ephemerisTime Time of the observation (seconds past J2000)
+ * \return true if the target is visible, false otherwise
+ * \throws SpiceKernelException If the \p target or \p observer do not name valid
+ * NAIF objects, the \p target or \p observer name the same NAIF object, the
+ * \p instrument does not name a valid NAIF object, or insufficient kernel information
+ * has been loaded.
+ * \pre \p target must not be empty.
+ * \pre \p observer must not be empty.
+ * \pre \p target and \p observer must not be different strings
+ * \pre \p referenceFrame must not be empty.
+ * \pre \p instrument must not be empty.
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/fovtrg_c.html
*/
- bool targetWithinFieldOfView(const std::string& instrument,
- const std::string& target,
- const std::string& observer,
- const std::string& method,
- const std::string& aberrationCorrection,
- double& targetEpoch,
- bool& isVisible
- ) const;
-
+ bool isTargetInFieldOfView(const std::string& target, const std::string& observer,
+ const std::string& instrument, FieldOfViewMethod method,
+ AberrationCorrection aberrationCorrection, double& ephemerisTime) const;
+
+ /// Struct that is used as the return value from the #getTargetState method
+ struct TargetStateResult {
+ /// The target position
+ glm::dvec3 position;
+
+ /// The target velocity
+ glm::dvec3 velocity;
+
+ /// One-way light time between target and observer if
+ /// the aberration correction is enabled
+ double lightTime;
+ };
+
/**
- * Returns the state vector (position and velocity) of a
- * target body relative to an observer in a specific
- * referenceFrame, optionally corrected for light time (planetary
- * aberration) and stellar aberration (aberrationCorrection). For further
- * details, refer to
- * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkezr_c.html. For more
- * information on NAIF IDs, refer to
- * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html
+ * Returns the state vector (position and velocity) of a \p target body relative to an
+ * \p observer in a specific \p referenceFrame, optionally corrected for aberration
+ * (\p aberrationCorrection).
* \param target The target body name or the target body's NAIF ID
* \param observer The observing body name or the observing body's NAIF ID
* \param referenceFrame The reference frame of the output position vector
- * \param aberrationCorrection The aberration correction flag out of the list of
- * values (NONE, LT, LT+S, CN,
- * CN+S for the reception case or XLT, XLT+S,
- * XCN, or XCN+S for the transmission case.
+ * \param aberrationCorrection The aberration correction method
* \param ephemerisTime The time at which the position is to be queried
- * \param position The output containing the position of the target; if the method
- * fails, the position is unchanged
- * \param velocity The output containing the velocity of the target; if the method
- * fails, the velocity is unchanged
- * \param lightTime If the aberrationCorrection is different from
- * NONE, this variable will contain the one-way light time between the
- * observer and the target.If the method fails, the lightTime is unchanged
- * \return true if the function was successful, false
- * otherwise
+ * \return A TargetStateResult object that contains the position>, containing
+ * the position of the target; the velocity, containing the velocity of
+ * the target; and the lightTime, containing the one-way light time
+ * between the \p target and the \p observer. This method is only set if the
+ * \p aberrationCorrection is set to a valid different from AberrationCorrection::None
+ * \throws SpiceKernelException If the \p target or \p observer do not name a valid
+ * NAIF object, the \p referenceFrame is not a valid frame, or if there is
+ * insufficient kernel information.
+ * \pre \p target must not be empty.
+ * \pre \p observer must not be empty.
+ * \pre \p referenceFrame must not be empty.
+ * \post The resulting TargetStateResult is set to valid values; the
+ * lightTime is only set to a valid different from 0.0 if
+ * the \p aberrationCorrection is not AberrationCorrection::None.
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkezr_c.html
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html
*/
- bool getTargetState(const std::string& target,
- const std::string& observer,
- const std::string& referenceFrame,
- const std::string& aberrationCorrection,
- double ephemerisTime,
- glm::dvec3& position,
- glm::dvec3& velocity,
- double& lightTime) const;
-
- bool getTargetState(const std::string& target,
- const std::string& observer,
- const std::string& referenceFrame,
- const std::string& aberrationCorrection,
- double ephemerisTime,
- PowerScaledCoordinate& position,
- PowerScaledCoordinate& velocity,
- double& lightTime) const;
+ TargetStateResult getTargetState(const std::string& target,
+ const std::string& observer, const std::string& referenceFrame,
+ AberrationCorrection aberrationCorrection, double ephemerisTime) const;
/**
- * Returns the state transformation matrix used to convert from one frame to another
- * at a specified ephemerisTime. For further details, please refer to
- * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sxform_c.html.
+ * Returns the state transformation matrix used to convert from the \p sourceFrame to
+ * the \p destinationFrame at a specific \p ephemerisTime.
+ * \param sourceFrame The name of the source reference frame
+ * \param destinationFrame The name of the destination reference frame
+ * \param ephemerisTime The time for which the transformation matrix should be
+ * returned
+ * \return The TransformMatrix containing the transformation matrix that defines the
+ * transformation from the \p sourceFrame to the \p destinationFrame
+ * \throws SpiceKernelException If the \p sourceFrame or the \p destinationFrame is
+ * not a valid frame
+ * \pre \p sourceFrame must not be empty.
+ * \pre \p destinatoinFrame must not be empty.
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sxform_c.html
+ */
+ TransformMatrix getStateTransformMatrix(const std::string& sourceFrame,
+ const std::string& destinationFrame, double ephemerisTime) const;
+
+ /**
+ * Returns the matrix that transforms position vectors from the source reference frame
+ * \p sourceFrame to the destination reference frame \p destinationFrame at the
+ * specific \p ephemerisTime.
* \param sourceFrame The name of the source reference frame
* \param destinationFrame The name of the destination reference frame
* \param ephemerisTime The time at which the transformation matrix is to be queried
- * \param transformationMatrix The output containing the TransformMatrix containing
- * the transformation matrix that defines the transformation from the
- * sourceFrame to the destinationFrame. If the method fails
- * the transformationMatrix is unchanged
- * \return true if the function was successful, false
- * otherwise
+ * \return The transformation matrix that defines the transformation from the
+ * \p sourceFrame to the \p destinationFrame
+ * \throws SpiceKernelException If there is no coverage available for the specified
+ * \p sourceFrame, \p destinationFrame, \p ephemerisTime combination
+ * \pre \p sourceFrame must not be empty
+ * \pre \p destinationFrame must not be empty
+ * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/pxform_c.html
*/
- bool getStateTransformMatrix(const std::string& sourceFrame,
- const std::string& destinationFrame,
- double ephemerisTime,
- TransformMatrix& transformationMatrix) const;
+ glm::dmat3 getPositionTransformMatrix(const std::string& sourceFrame,
+ const std::string& destinationFrame, double ephemerisTime) const;
/**
- * Returns the matrix that transforms position vectors from one reference frame to
- * another at a specified ephemerisTime. For further details, please refer to
- * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/pxform_c.html.
+ * Returns the transformation matrix that transforms position vectors from the
+ * \p sourceFrame at the time \p ephemerisTimeFrom to the \p destinationFrame at the
+ * time \p ephemerisTimeTo.
* \param sourceFrame The name of the source reference frame
* \param destinationFrame The name of the destination reference frame
- * \param ephemerisTime The time at which the transformation matrix is to be queried
- * \param transformationMatrix The output containing the transformation matrix that
- * defines the transformation from the sourceFrame to the
- * destinationFrame. If the method fails the
- * transformationMatrix is unchanged
- * \return true if the function was successful, false
- * otherwise
+ * \param ephemerisTimeFrom The time for the source reference frame
+ * \param ephemerisTimeTo The time for the destination reference frame
+ * \return Thetransformation matrix that maps between the \p sourceFrame at time
+ * \p ephemerisTimeFrom to the \p destinationFrame at the time \p ephemerisTimeTo.
+ * \throws SpiceKernelException If there is no coverage available for the specified
+ * \p sourceFrame and \p destinationFrame
+ * \pre \p sourceFrame must not be empty.
+ * \pre \p destinationFrame must not be empty.
*/
- bool getPositionTransformMatrix(const std::string& sourceFrame,
- const std::string& destinationFrame,
- double ephemerisTime,
- glm::dmat3& transformationMatrix) const;
-
- /**
- * The following overloaded function performs similar to its default - the exception being
- * that it computes transformationMatrix with respect to local time offset
- * between an observer and its target. This allows for the accountance of light travel of
- * photons, e.g to account for instrument pointing offsets due to said phenomenon.
- * \param sourceFrame The name of the source reference frame
- * \param destinationFrame The name of the destination reference frame
- * \param ephemerisTimeFrom Recorded/observed observation time
- * \param ephemerisTimeTo Emission local target-time
- * \param transformationMatrix The output containing the transformation matrix that
- */
-
- bool getPositionTransformMatrix(const std::string& sourceFrame,
- const std::string& destinationFrame,
- double ephemerisTimeFrom,
- double ephemerisTimeTo,
- glm::dmat3& transformationMatrix) const;
-
- /**
- * If a transform matrix is requested for an uncovered time in the CK kernels,
- * this function will insert a transform matrix in positionMatrix.
- * If the coverage has not yet started, the first transform matrix will be retrieved,
- * If the coverage has ended, the last transform matrix will be retrieved
- * If time is in a coverage gap, the transform matrix will be interpolated
- * \param time, for which an estimated transform matrix is desirable
- * \param fromFrame, the transform matrix will be retrieved in relation to this frame
- * \param toFrame, the frame missing CK data for this time
- * \param positionMatrix, the estimated transform matrix of the frame, passed by reference
- * \return true if an estimated transform matrix is found
- */
- bool getEstimatedTransformMatrix(const double time, const std::string fromFrame, const std::string toFrame, glm::dmat3& positionMatrix) const;
-
-
+ glm::dmat3 getPositionTransformMatrix(const std::string& sourceFrame,
+ const std::string& destinationFrame, double ephemerisTimeFrom,
+ double ephemerisTimeTo) const;
/**
* Applies the transformationMatrix retrieved from
@@ -823,9 +855,29 @@ private:
* \post If an exception is thrown, \p lightTime will not be modified
*/
glm::dvec3 getEstimatedPosition(const std::string& target,
- const std::string& observer, const std::string& referenceFrame,
- AberrationCorrection aberrationCorrection, double ephemerisTime,
- double& lightTime) const;
+ const std::string& observer, const std::string& referenceFrame,
+ AberrationCorrection aberrationCorrection, double ephemerisTime,
+ double& lightTime) const;
+
+ /**
+ * If a transform matrix is requested for an uncovered time in the CK kernels, this
+ * function will an estimated matrix. If the coverage has not yet started, the first
+ * transform matrix will be retrieved. If the coverage has ended, the last transform
+ * matrix will be retrieved. If time is in a coverage gap, the transform
+ * matrix will be interpolated.
+ * \param fromFrame The transform matrix will be retrieved in relation to this frame
+ * \param toFrame The reference frame into which the resulting matrix will transformed
+ * \param time The time for which an estimated transform matrix is requested
+ * \return The estimated transform matrix of the frame
+ * \throws SpiceKernelException If there is no coverage available for the specified
+ * \p sourceFrame and \p destinationFrame or the reference frames do not name a valid
+ * NAIF frame.
+ * \pre \p fromFrame must not be empty
+ * \pre \p toFrame must not be empty
+ */
+ glm::dmat3 getEstimatedTransformMatrix(const std::string& fromFrame,
+ const std::string& toFrame, double time) const;
+
/// A list of all loaded kernels
std::vector _loadedKernels;
diff --git a/modules/base/ephemeris/spiceephemeris.cpp b/modules/base/ephemeris/spiceephemeris.cpp
index 85e12f474f..e687a512e2 100644
--- a/modules/base/ephemeris/spiceephemeris.cpp
+++ b/modules/base/ephemeris/spiceephemeris.cpp
@@ -82,8 +82,7 @@ void SpiceEphemeris::update(const UpdateData& data) {
return;
double lightTime = 0.0;
- glm::dvec3 position = SpiceManager::ref().targetPosition(_targetName, _originName,
- "GALACTIC", SpiceManager::AberrationCorrection(), data.time, lightTime);
+ glm::dvec3 position = SpiceManager::ref().targetPosition(_targetName, _originName, "GALACTIC", {}, data.time, lightTime);
//double interval = openspace::ImageSequencer2::ref().getIntervalLength();
//if (_ghosting == "TRUE" && interval > 60){
diff --git a/modules/base/rendering/renderableconstellationbounds.cpp b/modules/base/rendering/renderableconstellationbounds.cpp
index 52fa9785a7..558803e3ae 100644
--- a/modules/base/rendering/renderableconstellationbounds.cpp
+++ b/modules/base/rendering/renderableconstellationbounds.cpp
@@ -179,11 +179,10 @@ void RenderableConstellationBounds::update(const UpdateData& data) {
if (_program->isDirty())
_program->rebuildFromFile();
- SpiceManager::ref().getPositionTransformMatrix(
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(
_originReferenceFrame,
"GALACTIC",
- data.time,
- _stateMatrix
+ data.time
);
}
diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp
index d76787cf3b..db13df15ae 100644
--- a/modules/base/rendering/renderablemodel.cpp
+++ b/modules/base/rendering/renderablemodel.cpp
@@ -184,7 +184,7 @@ void RenderableModel::render(const RenderData& data) {
_alpha = 1.0f;
glm::dvec3 p =
- SpiceManager::ref().targetPosition(_target, "SUN", "GALACTIC", SpiceManager::AberrationCorrection(), time, lt);
+ SpiceManager::ref().targetPosition(_target, "SUN", "GALACTIC", {}, time, lt);
psc tmppos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
glm::vec3 cam_dir = glm::normalize(data.camera.position().vec3() - tmppos.vec3());
_programObject->setUniform("cam_dir", cam_dir);
@@ -242,12 +242,13 @@ void RenderableModel::update(const UpdateData& data) {
//}
// set spice-orientation in accordance to timestamp
- if (!_source.empty())
- openspace::SpiceManager::ref().getPositionTransformMatrix(_source, _destination, _time, _stateMatrix);
+ if (!_source.empty()) {
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_source, _destination, _time);
+ }
double lt;
glm::dvec3 p =
- openspace::SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", SpiceManager::AberrationCorrection(), _time, lt);
+ openspace::SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", {}, _time, lt);
_sunPosition = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
}
diff --git a/modules/base/rendering/renderablepath.cpp b/modules/base/rendering/renderablepath.cpp
index 784caa4ba2..ebefd57a2e 100644
--- a/modules/base/rendering/renderablepath.cpp
+++ b/modules/base/rendering/renderablepath.cpp
@@ -223,7 +223,7 @@ void RenderablePath::calculatePath(std::string observer) {
//float b = _lineColor[2];
for (int i = 0; i < segments; i++) {
glm::dvec3 p =
- SpiceManager::ref().targetPosition(_target, observer, _frame, SpiceManager::AberrationCorrection(), currentTime, lightTime);
+ SpiceManager::ref().targetPosition(_target, observer, _frame, {}, currentTime, lightTime);
pscPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
pscPos[3] += 3;
diff --git a/modules/base/rendering/renderableplanet.cpp b/modules/base/rendering/renderableplanet.cpp
index 7ef837325c..9f074f0365 100644
--- a/modules/base/rendering/renderableplanet.cpp
+++ b/modules/base/rendering/renderableplanet.cpp
@@ -183,7 +183,7 @@ void RenderablePlanet::render(const RenderData& data)
double lt;
glm::dvec3 p =
- SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", SpiceManager::AberrationCorrection(), _time, lt);
+ SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", {}, _time, lt);
psc sun_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
// setup the data to the shader
@@ -217,7 +217,7 @@ void RenderablePlanet::render(const RenderData& data)
void RenderablePlanet::update(const UpdateData& data){
// set spice-orientation in accordance to timestamp
- openspace::SpiceManager::ref().getPositionTransformMatrix(_frame, "GALACTIC", data.time, _stateMatrix);
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_frame, "GALACTIC", data.time);
_time = data.time;
}
diff --git a/modules/base/rendering/renderablesphericalgrid.cpp b/modules/base/rendering/renderablesphericalgrid.cpp
index a1d0bce088..ff35d37c16 100644
--- a/modules/base/rendering/renderablesphericalgrid.cpp
+++ b/modules/base/rendering/renderablesphericalgrid.cpp
@@ -227,9 +227,8 @@ void RenderableSphericalGrid::render(const RenderData& data){
_gridProgram->deactivate();
}
-void RenderableSphericalGrid::update(const UpdateData& data){
-
- openspace::SpiceManager::ref().getPositionTransformMatrix("IAU_JUPITER", "GALACTIC", data.time, _parentMatrix);
+void RenderableSphericalGrid::update(const UpdateData& data) {
+ _parentMatrix = SpiceManager::ref().getPositionTransformMatrix("IAU_JUPITER", "GALACTIC", data.time);
}
}
\ No newline at end of file
diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp
index 9ce516c87b..4bb2d5b9f8 100644
--- a/modules/base/rendering/renderabletrail.cpp
+++ b/modules/base/rendering/renderabletrail.cpp
@@ -219,11 +219,11 @@ void RenderableTrail::update(const UpdateData& data) {
glm::dvec3 p;
// Update the floating current time
if (start > data.time)
- p = SpiceManager::ref().targetPosition(_target, _observer, _frame, SpiceManager::AberrationCorrection(), start, lightTime);
+ p = SpiceManager::ref().targetPosition(_target, _observer, _frame, {}, start, lightTime);
else if (end < data.time)
- p = SpiceManager::ref().targetPosition(_target, _observer, _frame, SpiceManager::AberrationCorrection(), end, lightTime);
+ p = SpiceManager::ref().targetPosition(_target, _observer, _frame, {}, end, lightTime);
else
- p = SpiceManager::ref().targetPosition(_target, _observer, _frame, SpiceManager::AberrationCorrection(), data.time, lightTime);
+ p = SpiceManager::ref().targetPosition(_target, _observer, _frame, {}, data.time, lightTime);
psc pscPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
@@ -247,7 +247,7 @@ void RenderableTrail::update(const UpdateData& data) {
else if (end < et)
et = end;
glm::dvec3 p =
- SpiceManager::ref().targetPosition(_target, _observer, _frame, SpiceManager::AberrationCorrection(), et, lightTime);
+ SpiceManager::ref().targetPosition(_target, _observer, _frame, {}, et, lightTime);
pscPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
pscPos[3] += 3;
_vertexArray[i] = { pscPos[0], pscPos[1], pscPos[2], pscPos[3] };
@@ -300,7 +300,7 @@ void RenderableTrail::fullYearSweep(double time) {
try {
p =
- SpiceManager::ref().targetPosition(_target, _observer, _frame, SpiceManager::AberrationCorrection(), time, lightTime);
+ SpiceManager::ref().targetPosition(_target, _observer, _frame, {}, time, lightTime);
}
catch (const SpiceManager::SpiceKernelException& e) {
// This fires for PLUTO BARYCENTER and SUN and uses the only value sometimes?
diff --git a/modules/newhorizons/rendering/renderablecrawlingline.cpp b/modules/newhorizons/rendering/renderablecrawlingline.cpp
index cfe9d7d6a2..2ed7a2aa49 100644
--- a/modules/newhorizons/rendering/renderablecrawlingline.cpp
+++ b/modules/newhorizons/rendering/renderablecrawlingline.cpp
@@ -148,8 +148,7 @@ void RenderableCrawlingLine::render(const RenderData& data) {
void RenderableCrawlingLine::update(const UpdateData& data) {
if (_program->isDirty())
_program->rebuildFromFile();
- glm::dmat3 transformMatrix = glm::dmat3(1);
- openspace::SpiceManager::ref().getPositionTransformMatrix(_source, _referenceFrame, data.time, transformMatrix);
+ glm::dmat3 transformMatrix = SpiceManager::ref().getPositionTransformMatrix(_source, _referenceFrame, data.time);
glm::mat4 tmp = glm::mat4(1);
for (int i = 0; i < 3; i++) {
diff --git a/modules/newhorizons/rendering/renderablefov.cpp b/modules/newhorizons/rendering/renderablefov.cpp
index 1d0f6c5ffb..9649a5036b 100644
--- a/modules/newhorizons/rendering/renderablefov.cpp
+++ b/modules/newhorizons/rendering/renderablefov.cpp
@@ -78,8 +78,8 @@ RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary)
success = dictionary.getValue(keyInstrument, _instrumentID);
ghoul_assert(success, "");
- success = dictionary.getValue(keyInstrumentMethod, _method);
- ghoul_assert(success, "");
+// success = dictionary.getValue(keyInstrumentMethod, _method);
+// ghoul_assert(success, "");
std::string a = "NONE";
success = dictionary.getValue(keyInstrumentAberration, a);
@@ -231,11 +231,24 @@ glm::dvec3 RenderableFov::interpolate(glm::dvec3 p0, glm::dvec3 p1, float t) {
// This method is the current bottleneck.
psc RenderableFov::checkForIntercept(glm::dvec3 ray) {
- bool intercepted = false;
- openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
- _frame, _aberrationCorrection,
- _time, ray, ipoint, ivec, intercepted);
-
+ std::string bodyfixed = "IAU_";
+ bool convert = (_frame.find(bodyfixed) == std::string::npos);
+ if (convert)
+ bodyfixed = SpiceManager::ref().frameFromBody(_fovTarget);
+ else
+ bodyfixed = _frame;
+
+ SpiceManager::SurfaceInterceptResult result = SpiceManager::ref().getSurfaceIntercept(
+ _fovTarget, _spacecraft, _instrumentID, bodyfixed, _aberrationCorrection, _time, ray);
+
+ if (convert) {
+ result.surfaceVector = SpiceManager::ref().frameTransformationMatrix(bodyfixed, _frame, _time) * result.surfaceVector;
+ }
+
+ ipoint = result.surfaceIntercept;
+ ivec = result.surfaceVector;
+ bool intercepted = result.interceptFound;
+
ivec *= 0.9999;// because fov lands exactly on top of surface we need to move it out slightly
_interceptVector = PowerScaledCoordinate::CreatePowerScaledCoordinate(ivec[0], ivec[1], ivec[2]);
_interceptVector[3] += 3;
@@ -258,10 +271,26 @@ psc RenderableFov::orthogonalProjection(glm::dvec3 vecFov) {
glm::dvec3 RenderableFov::bisection(glm::dvec3 p1, glm::dvec3 p2, double tolerance) {
//check if point is on surface
glm::dvec3 half = interpolate(p1, p2, 0.5f);
- bool intercepted = false;
- openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
- _frame, _aberrationCorrection,
- _time, half, ipoint, ivec, intercepted);
+
+ std::string bodyfixed = "IAU_";
+ bool convert = (_frame.find(bodyfixed) == std::string::npos);
+ if (convert)
+ bodyfixed = SpiceManager::ref().frameFromBody(_fovTarget);
+ else
+ bodyfixed = _frame;
+
+
+ SpiceManager::SurfaceInterceptResult result = SpiceManager::ref().getSurfaceIntercept(
+ _fovTarget, _spacecraft, _instrumentID, bodyfixed, _aberrationCorrection, _time, half);
+
+ if (convert) {
+ result.surfaceVector = SpiceManager::ref().frameTransformationMatrix(bodyfixed, _frame, _time) * result.surfaceVector;
+ }
+
+ ipoint = result.surfaceIntercept;
+ ivec = result.surfaceVector;
+ bool intercepted = result.interceptFound;
+
if (glm::distance(_previousHalf, half) < tolerance){
_previousHalf = glm::dvec3(0);
return half;
@@ -301,10 +330,28 @@ void RenderableFov::fovSurfaceIntercept(bool H[], std::vector bounds
// IFF incident point is also non-interceptive BUT something is within FOV
// we need then to check if this segment makes contact with surface
glm::dvec3 half = interpolate(current, next, 0.5f);
- bool intercepted;
- openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
- _frame, _aberrationCorrection,
- _time, half, ipoint, ivec, intercepted);
+
+ std::string bodyfixed = "IAU_";
+ bool convert = (_frame.find(bodyfixed) == std::string::npos);
+ if (convert)
+ bodyfixed = SpiceManager::ref().frameFromBody(_fovTarget);
+ else
+ bodyfixed = _frame;
+
+
+ SpiceManager::SurfaceInterceptResult res =
+ SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft,
+ _instrumentID, bodyfixed, _aberrationCorrection, _time, half);
+
+ if (convert) {
+ res.surfaceVector = SpiceManager::ref().frameTransformationMatrix(bodyfixed, _frame, _time) * res.surfaceVector;
+ }
+
+ ipoint = res.surfaceIntercept;
+ ivec = res.surfaceVector;
+ bool intercepted = res.interceptFound;
+
+
if (intercepted){
// find the two outer most points of intersection
glm::dvec3 root1 = bisection(half, current, tolerance);
@@ -396,15 +443,15 @@ void RenderableFov::computeColors() {
void RenderableFov::determineTarget(){
_fovTarget = _potentialTargets[0]; //default;
for (int i = 0; i < _potentialTargets.size(); i++){
- bool success = openspace::SpiceManager::ref().targetWithinFieldOfView(
+ _withinFOV = openspace::SpiceManager::ref().isTargetInFieldOfView(
+ _potentialTargets[i], _spacecraft,
+
_instrumentID,
- _potentialTargets[i],
- _spacecraft,
- _method,
- std::string(_aberrationCorrection),
- _time,
- _withinFOV);
- if (success && _withinFOV){
+ SpiceManager::FieldOfViewMethod::Ellipsoid,
+ _aberrationCorrection,
+ _time
+ );
+ if (_withinFOV){
_fovTarget = _potentialTargets[i];
break;
}
@@ -417,9 +464,25 @@ void RenderableFov::computeIntercepts(const RenderData& data){
for (int i = 0; i <= _bounds.size(); i++){
int r = (i == _bounds.size()) ? 0 : i;
// compute surface intercept
- openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
- _frame, _aberrationCorrection,
- _time, _bounds[r], ipoint, ivec, _interceptTag[r]);
+ std::string bodyfixed = "IAU_";
+ bool convert = (_frame.find(bodyfixed) == std::string::npos);
+ if (convert)
+ bodyfixed = SpiceManager::ref().frameFromBody(_fovTarget);
+ else
+ bodyfixed = _frame;
+
+ SpiceManager::SurfaceInterceptResult res =
+ SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft,
+ _instrumentID, bodyfixed, _aberrationCorrection, _time, _bounds[r]);
+
+ if (convert) {
+ res.surfaceVector = SpiceManager::ref().frameTransformationMatrix(bodyfixed, _frame, _time) * res.surfaceVector;
+ }
+
+ ipoint = res.surfaceIntercept;
+ ivec = res.surfaceVector;
+ _interceptTag[r] = res.interceptFound;
+
// if not found, use the orthogonal projected point
if (!_interceptTag[r]) _projectionBounds[r] = orthogonalProjection(_bounds[r]);
@@ -510,7 +573,7 @@ void RenderableFov::render(const RenderData& data) {
void RenderableFov::update(const UpdateData& data) {
_time = data.time;
- openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _frame, data.time, _stateMatrix);
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _frame, data.time);
_spacecraftRotation = glm::mat4(1);
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
diff --git a/modules/newhorizons/rendering/renderablefov.h b/modules/newhorizons/rendering/renderablefov.h
index d1290351f7..2327dc6cf6 100644
--- a/modules/newhorizons/rendering/renderablefov.h
+++ b/modules/newhorizons/rendering/renderablefov.h
@@ -96,7 +96,6 @@ public:
std::string _observer;
std::string _frame;
std::string _instrumentID;
- std::string _method;
SpiceManager::AberrationCorrection _aberrationCorrection;
std::string _fovTarget;
glm::dvec3 ipoint, ivec;
diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp
index a2670285b0..d6d4eaa7a1 100644
--- a/modules/newhorizons/rendering/renderablemodelprojection.cpp
+++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp
@@ -351,12 +351,13 @@ void RenderableModelProjection::update(const UpdateData& data) {
}
// set spice-orientation in accordance to timestamp
- if (!_source.empty())
- openspace::SpiceManager::ref().getPositionTransformMatrix(_source, _destination, _time, _stateMatrix);
+ if (!_source.empty()) {
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_source, _destination, _time);
+ }
double lt;
glm::dvec3 p =
- openspace::SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", SpiceManager::AberrationCorrection(), _time, lt);
+ openspace::SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", {}, _time, lt);
_sunPosition = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
}
@@ -406,8 +407,8 @@ void RenderableModelProjection::imageProjectGPU() {
}
void RenderableModelProjection::attitudeParameters(double time) {
- openspace::SpiceManager::ref().getPositionTransformMatrix(_source, _destination, time, _stateMatrix);
- openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _destination, time, _instrumentMatrix);
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_source, _destination, time);
+ _instrumentMatrix = SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _destination, time);
_transform = glm::mat4(1);
diff --git a/modules/newhorizons/rendering/renderableplaneprojection.cpp b/modules/newhorizons/rendering/renderableplaneprojection.cpp
index 3d25ded0a4..552ad2d7b6 100644
--- a/modules/newhorizons/rendering/renderableplaneprojection.cpp
+++ b/modules/newhorizons/rendering/renderableplaneprojection.cpp
@@ -166,7 +166,7 @@ void RenderablePlaneProjection::update(const UpdateData& data) {
else
_hasImage = true;
- openspace::SpiceManager::ref().getPositionTransformMatrix(_target.frame, GalacticFrame, time, _stateMatrix);
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_target.frame, GalacticFrame, time);
double timePast = abs(img.startTime - _previousTime);
@@ -331,7 +331,7 @@ std::string RenderablePlaneProjection::findClosestTarget(double currentTime) {
double lt;
glm::dvec3 p =
- SpiceManager::ref().targetPosition(_spacecraft, "SSB", GalacticFrame, SpiceManager::AberrationCorrection(), currentTime, lt);
+ SpiceManager::ref().targetPosition(_spacecraft, "SSB", GalacticFrame, {}, currentTime, lt);
psc spacecraftPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
@@ -341,7 +341,7 @@ std::string RenderablePlaneProjection::findClosestTarget(double currentTime) {
if (possibleTarget != nullptr) {
hasBody = possibleTarget->hasBody();
if (hasBody && possibleTarget->getBody(targetBody)) {
- openspace::SpiceManager::ref().targetWithinFieldOfView(_instrument, targetBody, _spacecraft, "ELLIPSOID", "NONE", currentTime, found);
+ found = SpiceManager::ref().isTargetInFieldOfView(targetBody, _spacecraft, _instrument, SpiceManager::FieldOfViewMethod::Ellipsoid, {}, currentTime);
if (found){
targets.push_back(node->name()); // get name from propertyOwner
distance = (node->worldPosition() - spacecraftPos).length();
diff --git a/modules/newhorizons/rendering/renderableplanetprojection.cpp b/modules/newhorizons/rendering/renderableplanetprojection.cpp
index 3bca6c46c6..4ee9f68761 100644
--- a/modules/newhorizons/rendering/renderableplanetprojection.cpp
+++ b/modules/newhorizons/rendering/renderableplanetprojection.cpp
@@ -408,8 +408,8 @@ glm::mat4 RenderablePlanetProjection::computeProjectorMatrix(const glm::vec3 loc
void RenderablePlanetProjection::attitudeParameters(double time){
// precomputations for shader
- openspace::SpiceManager::ref().getPositionTransformMatrix(_frame, _mainFrame, _time, _stateMatrix);
- openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _mainFrame, time, _instrumentMatrix);
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_frame, _mainFrame, _time);
+ _instrumentMatrix = SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _mainFrame, time);
_transform = glm::mat4(1);
//90 deg rotation w.r.t spice req.
@@ -512,7 +512,7 @@ void RenderablePlanetProjection::render(const RenderData& data){
double lt;
glm::dvec3 p =
- openspace::SpiceManager::ref().targetPosition("SUN", _projecteeID, "GALACTIC", SpiceManager::AberrationCorrection(), _time, lt);
+ openspace::SpiceManager::ref().targetPosition("SUN", _projecteeID, "GALACTIC", {}, _time, lt);
psc sun_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
// Main renderpass
diff --git a/modules/newhorizons/rendering/renderableshadowcylinder.cpp b/modules/newhorizons/rendering/renderableshadowcylinder.cpp
index 1e60f381c9..71d67d3ffd 100644
--- a/modules/newhorizons/rendering/renderableshadowcylinder.cpp
+++ b/modules/newhorizons/rendering/renderableshadowcylinder.cpp
@@ -132,7 +132,7 @@ void RenderableShadowCylinder::render(const RenderData& data){
}
void RenderableShadowCylinder::update(const UpdateData& data) {
- openspace::SpiceManager::ref().getPositionTransformMatrix(_bodyFrame, _mainFrame, data.time, _stateMatrix);
+ _stateMatrix = SpiceManager::ref().getPositionTransformMatrix(_bodyFrame, _mainFrame, data.time);
_time = data.time;
if (_shader->isDirty())
_shader->rebuildFromFile();
@@ -172,10 +172,8 @@ void RenderableShadowCylinder::createCylinder() {
glm::dvec3 vecLightSource =
SpiceManager::ref().targetPosition(_body, _lightSource, _mainFrame, _aberration, _time, lt);
- glm::dmat3 _stateMatrix;
- openspace::SpiceManager::ref().getPositionTransformMatrix(_bodyFrame, _mainFrame, _time, _stateMatrix);
+ glm::dmat3 _stateMatrix = glm::inverse(SpiceManager::ref().getPositionTransformMatrix(_bodyFrame, _mainFrame, _time));
- _stateMatrix = glm::inverse(_stateMatrix);
vecLightSource = _stateMatrix * vecLightSource;
vecLightSource *= _shadowLength;
diff --git a/modules/newhorizons/util/hongkangparser.cpp b/modules/newhorizons/util/hongkangparser.cpp
index 04be8da049..757bb6a0e4 100644
--- a/modules/newhorizons/util/hongkangparser.cpp
+++ b/modules/newhorizons/util/hongkangparser.cpp
@@ -286,14 +286,14 @@ bool HongKangParser::augmentWithSpice(Image& image,
double time = image.startTime;
for (int k = 0; k < exposureTime; k++){
time += k;
- success = openspace::SpiceManager::ref().targetWithinFieldOfView(
+ _withinFOV = SpiceManager::ref().isTargetInFieldOfView(
+ potentialTargets[i],
+ spacecraft,
image.activeInstruments[j],
- potentialTargets[i],
- spacecraft,
- "ELLIPSOID",
- "NONE",
- time,
- _withinFOV);
+ SpiceManager::FieldOfViewMethod::Ellipsoid,
+ {},
+ time
+ );
if (_withinFOV){
image.target = potentialTargets[i];
_withinFOV = false;
diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp
index 64ec5b4b04..63f7d9cc2b 100644
--- a/src/rendering/renderengine.cpp
+++ b/src/rendering/renderengine.cpp
@@ -453,7 +453,7 @@ void RenderEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 &vi
double lt;
glm::dvec3 p =
- SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", SpiceManager::AberrationCorrection(), currentTime, lt);
+ SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt);
psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z);
float a, b, c;
SpiceManager::ref().getPlanetEllipsoid("PLUTO", a, b, c);
diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp
index 3e6e96e4f4..36d116a2a2 100644
--- a/src/util/spicemanager.cpp
+++ b/src/util/spicemanager.cpp
@@ -55,6 +55,15 @@ namespace {
);
}
}
+
+ const char* toString(openspace::SpiceManager::FieldOfViewMethod m) {
+ switch (m) {
+ case openspace::SpiceManager::FieldOfViewMethod::Ellipsoid:
+ return "ELLIPSOID";
+ case openspace::SpiceManager::FieldOfViewMethod::Point:
+ return "POINT";
+ }
+ }
}
using fmt::format;
@@ -506,290 +515,194 @@ glm::dmat3 SpiceManager::frameTransformationMatrix(const std::string& from,
return glm::transpose(transform);
}
-bool SpiceManager::getSurfaceIntercept(const std::string& target,
- const std::string& observer,
- const std::string& fovFrame,
- const std::string& referenceFrame,
- AberrationCorrection aberrationCorrection,
- double ephemerisTime,
- glm::dvec3& directionVector,
- glm::dvec3& surfaceIntercept,
- glm::dvec3& surfaceVector,
- bool& isVisible
- ) const
+SpiceManager::SurfaceInterceptResult SpiceManager::getSurfaceIntercept(
+ const std::string& target, const std::string& observer, const std::string& fovFrame,
+ const std::string& referenceFrame, AberrationCorrection aberrationCorrection,
+ double ephemerisTime, const glm::dvec3& directionVector) const
{
+ ghoul_assert(!target.empty(), "Target must not be empty");
+ ghoul_assert(!observer.empty(), "Observer must not be empty");
+ ghoul_assert(target != observer, "Target and observer must be different");
+ ghoul_assert(!fovFrame.empty(), "FOV frame must not be empty");
+ ghoul_assert(!referenceFrame.empty(), "Reference frame must not be empty");
+ ghoul_assert(directionVector != glm::dvec3(0.0), "Direction vector must not be zero");
+
const std::string ComputationMethod = "ELLIPSOID";
- // make pretty latr
- double dvec[3], spoint[3], et;
- glm::dvec3 srfvec;
- int found;
- bool convert;
-
- dvec[0] = directionVector[0];
- dvec[1] = directionVector[1];
- dvec[2] = directionVector[2];
-
- // allow client specify non-inertial frame.
- std::string bodyfixed = "IAU_";
- convert = (referenceFrame.find(bodyfixed) == std::string::npos);
- if (convert) {
- bodyfixed = frameFromBody(target);
- } else {
- bodyfixed = referenceFrame;
- }
+ SurfaceInterceptResult result;
+ SpiceBoolean found;
sincpt_c(ComputationMethod.c_str(),
- target.c_str(),
- ephemerisTime,
- bodyfixed.c_str(),
- aberrationCorrection,
- observer.c_str(),
- fovFrame.c_str(),
- dvec,
- spoint,
- &et,
- glm::value_ptr(srfvec),
- &found);
+ target.c_str(),
+ ephemerisTime,
+ referenceFrame.c_str(),
+ aberrationCorrection,
+ observer.c_str(),
+ fovFrame.c_str(),
+ glm::value_ptr(directionVector),
+ glm::value_ptr(result.surfaceIntercept),
+ &result.interceptEpoch,
+ glm::value_ptr(result.surfaceVector),
+ &found
+ );
+ result.interceptFound = (found == SPICETRUE);
- isVisible = (found == SPICETRUE);
-
- throwOnSpiceError("Error retrieving surface intercept on target '" + target + "'" +
- "viewed from observer '" + observer + "' in " +
- "reference frame '" + bodyfixed + "' at time '" +
- std::to_string(ephemerisTime) + "'");
-
- if (convert)
- srfvec = SpiceManager::ref().frameTransformationMatrix(bodyfixed, referenceFrame, ephemerisTime) * srfvec;
-
- if (found){
- memcpy(glm::value_ptr(directionVector), dvec, sizeof(dvec));
- memcpy(glm::value_ptr(surfaceIntercept), spoint, sizeof(spoint));
- surfaceVector = srfvec;
- }
- return true;
+ throwOnSpiceError(format(
+ "Error retrieving surface intercept on target '{}' viewed from observer '{}' in "
+ "reference frame '{}' at time '{}'",
+ target, observer, referenceFrame, ephemerisTime
+ ));
+
+ return result;
}
-
-bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
- const std::string& target,
- const std::string& observer,
- const std::string& method,
- const std::string& referenceFrame,
- const std::string& aberrationCorrection,
- double& targetEpoch,
- bool& isVisible
- ) const
+bool SpiceManager::isTargetInFieldOfView(const std::string& target,
+ const std::string& observer, const std::string& referenceFrame,
+ const std::string& instrument, FieldOfViewMethod method,
+ AberrationCorrection aberrationCorrection, double& ephemerisTime) const
{
+ ghoul_assert(!target.empty(), "Target must not be empty");
+ ghoul_assert(!observer.empty(), "Observer must not be empty");
+ ghoul_assert(target != observer, "Target and observer must be different");
+ ghoul_assert(!referenceFrame.empty(), "Reference frame must not be empty");
+ ghoul_assert(!instrument.empty(), "Instrument must not be empty");
+
int visible;
fovtrg_c(instrument.c_str(),
- target.c_str(),
- method.c_str(),
- referenceFrame.c_str(),
- aberrationCorrection.c_str(),
- observer.c_str(),
- &targetEpoch,
- &visible);
- isVisible = (visible == SPICETRUE);
+ target.c_str(),
+ toString(method),
+ referenceFrame.c_str(),
+ aberrationCorrection,
+ observer.c_str(),
+ &ephemerisTime,
+ &visible
+ );
- throwOnSpiceError("Checking if target '" + target +
- "' is in view of instrument '" + instrument + "' failed");
+ throwOnSpiceError(format(
+ "Checking if target '{}' is in view of instrument '{}' failed",
+ target, instrument
+ ));
- return true;
+ return visible == SPICETRUE;
}
-bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
- const std::string& target,
- const std::string& observer,
- const std::string& method,
- const std::string& aberrationCorrection,
- double& targetEpoch,
- bool& isVisible
- ) const{
-
- int visible;
-
- std::string frame = frameFromBody(target);
-
- fovtrg_c(instrument.c_str(),
- target.c_str(),
- method.c_str(),
- frame.c_str(),
- aberrationCorrection.c_str(),
- observer.c_str(),
- &targetEpoch,
- &visible);
- isVisible = (visible == SPICETRUE);
-
- throwOnSpiceError("Checking if target '" + target +
- "' is in view of instrument '" + instrument + "' failed");
-
- return true;
-}
-
-
-// Not called at the moment @AA
-bool SpiceManager::getTargetState(const std::string& target,
- const std::string& observer,
- const std::string& referenceFrame,
- const std::string& aberrationCorrection,
- double ephemerisTime,
- glm::dvec3& targetPosition,
- glm::dvec3& targetVelocity,
- double& lightTime) const
+bool SpiceManager::isTargetInFieldOfView(const std::string& target,
+ const std::string& observer, const std::string& instrument,
+ FieldOfViewMethod method, AberrationCorrection aberrationCorrection,
+ double& ephemerisTime) const
{
+ return isTargetInFieldOfView(
+ target,
+ observer,
+ frameFromBody(target),
+ instrument,
+ method,
+ aberrationCorrection,
+ ephemerisTime
+ );
+}
+
+SpiceManager::TargetStateResult SpiceManager::getTargetState(const std::string& target,
+ const std::string& observer, const std::string& referenceFrame,
+ AberrationCorrection aberrationCorrection, double ephemerisTime) const
+{
+ ghoul_assert(!target.empty(), "Target must not be empty");
+ ghoul_assert(!observer.empty(), "Observer must not be empty");
+ ghoul_assert(!referenceFrame.empty(), "Reference frame must not be empty");
+
+ TargetStateResult result;
+ result.lightTime = 0.0;
+
double buffer[6];
+
+ spkezr_c(
+ target.c_str(),
+ ephemerisTime,
+ referenceFrame.c_str(),
+ aberrationCorrection,
+ observer.c_str(),
+ buffer,
+ &result.lightTime
+ );
+
+ throwOnSpiceError(format(
+ "Error retrieving state of target '{}' viewed from observer '{}' in reference "
+ "frame '{}' at time '{}'",
+ target, observer, referenceFrame, ephemerisTime
+ ));
+
+ memmove(glm::value_ptr(result.position), buffer, sizeof(double) * 3);
+ memmove(glm::value_ptr(result.velocity), buffer + 3, sizeof(double) * 3);
+ return result;
+}
+
+SpiceManager::TransformMatrix SpiceManager::getStateTransformMatrix(
+ const std::string& fromFrame, const std::string& toFrame, double ephemerisTime) const
+{
+ ghoul_assert(!fromFrame.empty(), "fromFrame must not be empty");
+ ghoul_assert(!toFrame.empty(), "toFrame must not be empty");
- spkezr_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
- aberrationCorrection.c_str(), observer.c_str(), buffer, &lightTime);
-
- throwOnSpiceError("Error retrieving state of target '" + target + "'" +
- "viewed from observer '" + observer + "' in " +
- "reference frame '" + referenceFrame + "' at time '" +
- std::to_string(ephemerisTime) + "'");
- memmove(glm::value_ptr(targetPosition), buffer, sizeof(double) * 3);
- memmove(glm::value_ptr(targetVelocity), buffer + 3, sizeof(double) * 3);
- return true;
+ TransformMatrix m;
+ sxform_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ ephemerisTime,
+ reinterpret_cast(m.data())
+ );
+ throwOnSpiceError(format(
+ "Error retrieved state transform matrix from frame '{}' to frame '{}' at time "
+ "'{}'",
+ fromFrame, toFrame, ephemerisTime
+ ));
+ return m;
}
-// Not called at the moment @AA
-bool SpiceManager::getTargetState(const std::string& target,
- const std::string& observer,
- const std::string& referenceFrame,
- const std::string& aberrationCorrection,
- double ephemerisTime,
- PowerScaledCoordinate& position,
- PowerScaledCoordinate& velocity,
- double& lightTime) const
+glm::dmat3 SpiceManager::getPositionTransformMatrix(const std::string& fromFrame,
+ const std::string& toFrame, double ephemerisTime) const
{
- double state[6];
- std::fill_n(state, 6, NULL);
-
- spkezr_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
- aberrationCorrection.c_str(), observer.c_str(), state, &lightTime);
-
- throwOnSpiceError("Error retrieving state of target '" + target + "'" +
- "viewed from observer '" + observer + "' in " +
- "reference frame '" + referenceFrame + "' at time '" +
- std::to_string(ephemerisTime) + "'");
-
- position = PowerScaledCoordinate::CreatePowerScaledCoordinate(state[0], state[1], state[2]);
- velocity = PowerScaledCoordinate::CreatePowerScaledCoordinate(state[3], state[4], state[5]);
-
- return true;
-}
-
-// Not called at the moment @AA
-bool SpiceManager::getStateTransformMatrix(const std::string& fromFrame,
- const std::string& toFrame,
- double ephemerisTime,
- TransformMatrix& stateMatrix) const
-{
- sxform_c(fromFrame.c_str(), toFrame.c_str(),
- ephemerisTime, (double(*)[6])stateMatrix.data());
+ ghoul_assert(!fromFrame.empty(), "fromFrame must not be empty");
+ ghoul_assert(!toFrame.empty(), "toFrame must not be empty");
- throwOnSpiceError("Error retrieved state transform matrix from frame '" +
- fromFrame + "' to frame '" + toFrame + "' at time '" +
- std::to_string(ephemerisTime) + "'");
- return true;
-}
-
-bool SpiceManager::getPositionTransformMatrix(const std::string& fromFrame,
- const std::string& toFrame,
- double ephemerisTime,
- glm::dmat3& positionMatrix) const
-{
- bool estimated = false;
- pxform_c(fromFrame.c_str(), toFrame.c_str(),
- ephemerisTime, (double(*)[3])glm::value_ptr(positionMatrix));
+ glm::dmat3 result;
+ pxform_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ ephemerisTime,
+ reinterpret_cast(glm::value_ptr(result))
+ );
SpiceBoolean success = !(failed_c());
reset_c();
- if (!success) {
- estimated = getEstimatedTransformMatrix(ephemerisTime, fromFrame, toFrame, positionMatrix);
- }
+ bool estimated = false;
+ if (!success)
+ result = getEstimatedTransformMatrix(fromFrame, toFrame, ephemerisTime);
- positionMatrix = glm::transpose(positionMatrix);
-
- return estimated || success;
+ return glm::transpose(result);
}
-// Not called at the moment @AA
-bool SpiceManager::getPositionTransformMatrix(const std::string& fromFrame,
- const std::string& toFrame,
- double ephemerisTimeFrom,
- double ephemerisTimeTo,
- glm::dmat3& positionMatrix) const{
-
- pxfrm2_c(fromFrame.c_str(), toFrame.c_str(), ephemerisTimeFrom, ephemerisTimeTo, (double(*)[3])glm::value_ptr(positionMatrix));
-
- throwOnSpiceError("Error retrieving position transform matrix from "
- "frame '" + fromFrame + "' to frame '" + toFrame +
- "' from time '" + std::to_string(ephemerisTimeFrom) + " to time '"
- + std::to_string(ephemerisTimeTo) + "'");
- positionMatrix = glm::transpose(positionMatrix);
-
- return true;
-}
-
-
-bool SpiceManager::getEstimatedTransformMatrix(const double time, const std::string fromFrame,
- const std::string toFrame, glm::dmat3& positionMatrix) const
+glm::dmat3 SpiceManager::getPositionTransformMatrix(const std::string& fromFrame,
+ const std::string& toFrame, double ephemerisTimeFrom, double ephemerisTimeTo) const
{
- int idFrame;
-
- bool frameFound = hasFrameId(fromFrame);
- if (!frameFound) {
- return false;
- }
- idFrame = frameId(fromFrame);
+ ghoul_assert(!fromFrame.empty(), "fromFrame must not be empty");
+ ghoul_assert(!toFrame.empty(), "toFrame must not be empty");
- if (_ckCoverageTimes.find(idFrame) == _ckCoverageTimes.end()){ // no coverage
- return false;
- }
+ glm::dmat3 result;
- double earlier, later, difference, quote;
-
- std::set coveredTimes = _ckCoverageTimes.find(idFrame)->second;
-
- std::set::iterator first = coveredTimes.begin();
- std::set::iterator last = coveredTimes.end();
-
- if (coveredTimes.lower_bound(time) == first) { // coverage later, fetch first transform
- pxform_c(fromFrame.c_str(), toFrame.c_str(),
- *first, (double(*)[3])glm::value_ptr(positionMatrix));
- }
- else if (coveredTimes.upper_bound(time) == last) { // coverage earlier, fetch last transform
- pxform_c(fromFrame.c_str(), toFrame.c_str(),
- *(coveredTimes.rbegin()), (double(*)[3])glm::value_ptr(positionMatrix));
- }
- else { // coverage both earlier and later, interpolate these transformations
- earlier = *std::prev((coveredTimes.lower_bound(time)));
- later = *(coveredTimes.upper_bound(time));
-
- glm::dmat3 earlierTransform, laterTransform;
-
- pxform_c(fromFrame.c_str(), toFrame.c_str(),
- earlier, (double(*)[3])glm::value_ptr(earlierTransform));
- pxform_c(fromFrame.c_str(), toFrame.c_str(),
- later, (double(*)[3])glm::value_ptr(laterTransform));
-
- difference = later - earlier;
- quote = (time - earlier) / difference;
-
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- positionMatrix[i][j] = (earlierTransform[i][j] * (1 - quote) + laterTransform[i][j] * quote);
- }
- }
- }
- throwOnSpiceError("Error estimating transform matrix from frame: "
- + fromFrame + ", to frame: " + toFrame);
-
- return true;
+ pxfrm2_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ ephemerisTimeFrom,
+ ephemerisTimeTo,
+ reinterpret_cast(glm::value_ptr(result))
+ );
+ throwOnSpiceError(format(
+ "Error retrieving position transform matrix from '{}' at time '{}' to frame '{}' "
+ "at time '{}'",
+ fromFrame, ephemerisTimeFrom, toFrame, ephemerisTimeTo
+ ));
+ return glm::transpose(result);
}
-
bool SpiceManager::getFieldOfView(const std::string& instrument, std::string& fovShape,
std::string& frameName, glm::dvec3& boresightVector,
std::vector& bounds) const
@@ -1101,13 +1014,94 @@ glm::dvec3 SpiceManager::getEstimatedPosition(const std::string& target,
));
// linear interpolation
- double timeDifference = timeLater - timeEarlier;
- double t = (ephemerisTime - timeEarlier) / timeDifference;
+ double t = (ephemerisTime - timeEarlier) / (timeLater - timeEarlier);
pos = posEarlier * (1.0 - t) + posLater * t;
lightTime = ltEarlier * (1.0 - t) + ltLater * t;
}
return pos;
}
+
+glm::dmat3 SpiceManager::getEstimatedTransformMatrix(const std::string& fromFrame,
+ const std::string& toFrame,
+ double time) const
+{
+ glm::dmat3 result;
+ int idFrame = frameId(fromFrame);
+
+ if (_ckCoverageTimes.find(idFrame) == _ckCoverageTimes.end()) {
+ // no coverage
+ throw SpiceKernelException(format(
+ "No data available for the transform matrix from '{}' to '{}' at any time",
+ fromFrame, toFrame
+ ));
+ }
+
+ std::set coveredTimes = _ckCoverageTimes.find(idFrame)->second;
+
+ if (coveredTimes.lower_bound(time) == coveredTimes.begin()) {
+ // coverage later, fetch first transform
+ pxform_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ *(coveredTimes.begin()),
+ reinterpret_cast(glm::value_ptr(result))
+ );
+ throwOnSpiceError(format(
+ "Error estimating transform matrix from frame '{}' to from '{}' at time '{}'",
+ fromFrame, toFrame, time
+ ));
+
+ }
+ else if (coveredTimes.upper_bound(time) == coveredTimes.end()) {
+ // coverage earlier, fetch last transform
+ pxform_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ *(coveredTimes.rbegin()),
+ reinterpret_cast(glm::value_ptr(result))
+ );
+ throwOnSpiceError(format(
+ "Error estimating transform matrix from frame '{}' to from '{}' at time '{}'",
+ fromFrame, toFrame, time
+ ));
+ }
+ else {
+ // coverage both earlier and later, interpolate these transformations
+ double earlier = *std::prev((coveredTimes.lower_bound(time)));
+ double later = *(coveredTimes.upper_bound(time));
+
+ glm::dmat3 earlierTransform;
+ pxform_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ earlier,
+ reinterpret_cast(glm::value_ptr(earlierTransform))
+ );
+ throwOnSpiceError(format(
+ "Error estimating transform matrix from frame '{}' to from '{}' at time '{}'",
+ fromFrame, toFrame, time
+ ));
+
+ glm::dmat3 laterTransform;
+ pxform_c(
+ fromFrame.c_str(),
+ toFrame.c_str(),
+ later,
+ reinterpret_cast(glm::value_ptr(laterTransform))
+ );
+ throwOnSpiceError(format(
+ "Error estimating transform matrix from frame '{}' to from '{}' at time '{}'",
+ fromFrame, toFrame, time
+ ));
+
+ double t = (time - earlier) / (later - earlier);
+ result = earlierTransform * (1.0 - t) + laterTransform * t;
+ }
+
+ return result;
+}
+
+
} // namespace openspace