From 6a49541d941221fcd2c0ae679d89a0b670974133 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Thu, 16 Oct 2014 14:26:54 +0200 Subject: [PATCH] Force geodetic points longitude range. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should fix some problems in the vicinity of ±π longitude. --- .../java/org/orekit/rugged/api/Rugged.java | 205 +++++++++--------- .../intersection/BasicScanAlgorithm.java | 32 ++- .../intersection/IgnoreDEMAlgorithm.java | 20 +- .../intersection/IntersectionAlgorithm.java | 7 +- .../duvenhage/DuvenhageAlgorithm.java | 121 ++++++----- .../org/orekit/rugged/raster/SimpleTile.java | 24 +- .../java/org/orekit/rugged/raster/Tile.java | 5 +- .../rugged/utils/ExtendedEllipsoid.java | 41 +++- .../rugged/utils/NormalizedGeodeticPoint.java | 58 +++++ .../org/orekit/rugged/api/RuggedTest.java | 3 - design/direct-localization-class-diagram.puml | 2 +- src/site/markdown/design/technical-choices.md | 2 +- src/site/xdoc/changes.xml | 6 +- 13 files changed, 310 insertions(+), 216 deletions(-) create mode 100644 core/src/main/java/org/orekit/rugged/utils/NormalizedGeodeticPoint.java diff --git a/core/src/main/java/org/orekit/rugged/api/Rugged.java b/core/src/main/java/org/orekit/rugged/api/Rugged.java index 51b09ee1..059c3acb 100644 --- a/core/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/core/src/main/java/org/orekit/rugged/api/Rugged.java @@ -49,6 +49,7 @@ import org.orekit.rugged.intersection.IntersectionAlgorithm; import org.orekit.rugged.intersection.duvenhage.DuvenhageAlgorithm; import org.orekit.rugged.raster.TileUpdater; import org.orekit.rugged.utils.ExtendedEllipsoid; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; import org.orekit.rugged.utils.SpacecraftToObservedBody; import org.orekit.time.AbsoluteDate; import org.orekit.utils.AngularDerivativesFilter; @@ -725,102 +726,23 @@ public class Rugged { */ public GeodeticPoint[] directLocalization(final String sensorName, final double lineNumber) throws RuggedException { - try { - - // compute the approximate transform between spacecraft and observed body - final LineSensor sensor = getLineSensor(sensorName); - final AbsoluteDate date = sensor.getDate(lineNumber); - final Transform scToInert = scToBody.getScToInertial(date); - final Transform inertToBody = scToBody.getInertialToBody(date); - final Transform approximate = new Transform(date, scToInert, inertToBody); - - final Vector3D spacecraftVelocity = - scToInert.transformPVCoordinates(PVCoordinates.ZERO).getVelocity(); - - // compute localization of each pixel - final Vector3D pInert = scToInert.transformPosition(sensor.getPosition()); - final GeodeticPoint[] gp = new GeodeticPoint[sensor.getNbPixels()]; - for (int i = 0; i < sensor.getNbPixels(); ++i) { - - final Vector3D obsLInert = scToInert.transformVector(sensor.getLos(i)); - final Vector3D lInert; - if (aberrationOfLightCorrection) { - // apply aberration of light correction - // as the spacecraft velocity is small with respect to speed of light, - // we use classical velocity addition and not relativistic velocity addition - // we look for a positive k such that: c * lInert + vsat = k * obsLInert - // with lInert normalized - final double a = obsLInert.getNormSq(); - final double b = -Vector3D.dotProduct(obsLInert, spacecraftVelocity); - final double c = spacecraftVelocity.getNormSq() - Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT; - final double s = FastMath.sqrt(b * b - a * c); - final double k = (b > 0) ? -c / (s + b) : (s - b) / a; - lInert = new Vector3D( k / Constants.SPEED_OF_LIGHT, obsLInert, - -1.0 / Constants.SPEED_OF_LIGHT, spacecraftVelocity); - } else { - // don't apply aberration of light correction - lInert = obsLInert; - } - - if (lightTimeCorrection) { - // compute DEM intersection with light time correction - final Vector3D sP = approximate.transformPosition(sensor.getPosition()); - final Vector3D sL = approximate.transformVector(sensor.getLos(i)); - final Vector3D eP1 = ellipsoid.transform(ellipsoid.pointOnGround(sP, sL)); - final double deltaT1 = eP1.distance(sP) / Constants.SPEED_OF_LIGHT; - final Transform shifted1 = inertToBody.shiftedBy(-deltaT1); - final GeodeticPoint gp1 = algorithm.intersection(ellipsoid, - shifted1.transformPosition(pInert), - shifted1.transformVector(lInert)); - - final Vector3D eP2 = ellipsoid.transform(gp1); - final double deltaT2 = eP2.distance(sP) / Constants.SPEED_OF_LIGHT; - final Transform shifted2 = inertToBody.shiftedBy(-deltaT2); - gp[i] = algorithm.refineIntersection(ellipsoid, - shifted2.transformPosition(pInert), - shifted2.transformVector(lInert), - gp1); - - } else { - // compute DEM intersection without light time correction - final Vector3D pBody = inertToBody.transformPosition(pInert); - final Vector3D lBody = inertToBody.transformVector(lInert); - gp[i] = algorithm.refineIntersection(ellipsoid, pBody, lBody, - algorithm.intersection(ellipsoid, pBody, lBody)); - } - - } - - return gp; - - } catch (OrekitException oe) { - throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); - } - } - - /** Direct localization of a single line-of-sight. - * @param date date of the localization - * @param position pixel position in spacecraft frame - * @param los normalized line-of-sight in spacecraft frame - * @return ground position of all pixels of the specified sensor line - * @exception RuggedException if line cannot be localized, or sensor is unknown - */ - public GeodeticPoint directLocalization(final AbsoluteDate date, final Vector3D position, final Vector3D los) - throws RuggedException { - try { - // compute the approximate transform between spacecraft and observed body - final Transform scToInert = scToBody.getScToInertial(date); - final Transform inertToBody = scToBody.getInertialToBody(date); - final Transform approximate = new Transform(date, scToInert, inertToBody); + // compute the approximate transform between spacecraft and observed body + final LineSensor sensor = getLineSensor(sensorName); + final AbsoluteDate date = sensor.getDate(lineNumber); + final Transform scToInert = scToBody.getScToInertial(date); + final Transform inertToBody = scToBody.getInertialToBody(date); + final Transform approximate = new Transform(date, scToInert, inertToBody); - final Vector3D spacecraftVelocity = - scToInert.transformPVCoordinates(PVCoordinates.ZERO).getVelocity(); + final Vector3D spacecraftVelocity = + scToInert.transformPVCoordinates(PVCoordinates.ZERO).getVelocity(); - // compute localization of specified pixel - final Vector3D pInert = scToInert.transformPosition(position); + // compute localization of each pixel + final Vector3D pInert = scToInert.transformPosition(sensor.getPosition()); + final GeodeticPoint[] gp = new GeodeticPoint[sensor.getNbPixels()]; + for (int i = 0; i < sensor.getNbPixels(); ++i) { - final Vector3D obsLInert = scToInert.transformVector(los); + final Vector3D obsLInert = scToInert.transformVector(sensor.getLos(i)); final Vector3D lInert; if (aberrationOfLightCorrection) { // apply aberration of light correction @@ -842,34 +764,105 @@ public class Rugged { if (lightTimeCorrection) { // compute DEM intersection with light time correction - final Vector3D sP = approximate.transformPosition(position); - final Vector3D sL = approximate.transformVector(los); - final Vector3D eP1 = ellipsoid.transform(ellipsoid.pointOnGround(sP, sL)); + final Vector3D sP = approximate.transformPosition(sensor.getPosition()); + final Vector3D sL = approximate.transformVector(sensor.getLos(i)); + final Vector3D eP1 = ellipsoid.transform(ellipsoid.pointOnGround(sP, sL, 0.0)); final double deltaT1 = eP1.distance(sP) / Constants.SPEED_OF_LIGHT; final Transform shifted1 = inertToBody.shiftedBy(-deltaT1); - final GeodeticPoint gp1 = algorithm.intersection(ellipsoid, - shifted1.transformPosition(pInert), - shifted1.transformVector(lInert)); + final NormalizedGeodeticPoint gp1 = algorithm.intersection(ellipsoid, + shifted1.transformPosition(pInert), + shifted1.transformVector(lInert)); final Vector3D eP2 = ellipsoid.transform(gp1); final double deltaT2 = eP2.distance(sP) / Constants.SPEED_OF_LIGHT; final Transform shifted2 = inertToBody.shiftedBy(-deltaT2); - return algorithm.refineIntersection(ellipsoid, - shifted2.transformPosition(pInert), - shifted2.transformVector(lInert), - gp1); + gp[i] = algorithm.refineIntersection(ellipsoid, + shifted2.transformPosition(pInert), + shifted2.transformVector(lInert), + gp1); } else { // compute DEM intersection without light time correction final Vector3D pBody = inertToBody.transformPosition(pInert); final Vector3D lBody = inertToBody.transformVector(lInert); - return algorithm.refineIntersection(ellipsoid, pBody, lBody, - algorithm.intersection(ellipsoid, pBody, lBody)); + gp[i] = algorithm.refineIntersection(ellipsoid, pBody, lBody, + algorithm.intersection(ellipsoid, pBody, lBody)); } - } catch (OrekitException oe) { - throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); } + + return gp; + + } + + /** Direct localization of a single line-of-sight. + * @param date date of the localization + * @param position pixel position in spacecraft frame + * @param los normalized line-of-sight in spacecraft frame + * @return ground position of all pixels of the specified sensor line + * @exception RuggedException if line cannot be localized, or sensor is unknown + */ + public GeodeticPoint directLocalization(final AbsoluteDate date, final Vector3D position, final Vector3D los) + throws RuggedException { + + // compute the approximate transform between spacecraft and observed body + final Transform scToInert = scToBody.getScToInertial(date); + final Transform inertToBody = scToBody.getInertialToBody(date); + final Transform approximate = new Transform(date, scToInert, inertToBody); + + final Vector3D spacecraftVelocity = + scToInert.transformPVCoordinates(PVCoordinates.ZERO).getVelocity(); + + // compute localization of specified pixel + final Vector3D pInert = scToInert.transformPosition(position); + + final Vector3D obsLInert = scToInert.transformVector(los); + final Vector3D lInert; + if (aberrationOfLightCorrection) { + // apply aberration of light correction + // as the spacecraft velocity is small with respect to speed of light, + // we use classical velocity addition and not relativistic velocity addition + // we look for a positive k such that: c * lInert + vsat = k * obsLInert + // with lInert normalized + final double a = obsLInert.getNormSq(); + final double b = -Vector3D.dotProduct(obsLInert, spacecraftVelocity); + final double c = spacecraftVelocity.getNormSq() - Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT; + final double s = FastMath.sqrt(b * b - a * c); + final double k = (b > 0) ? -c / (s + b) : (s - b) / a; + lInert = new Vector3D( k / Constants.SPEED_OF_LIGHT, obsLInert, + -1.0 / Constants.SPEED_OF_LIGHT, spacecraftVelocity); + } else { + // don't apply aberration of light correction + lInert = obsLInert; + } + + if (lightTimeCorrection) { + // compute DEM intersection with light time correction + final Vector3D sP = approximate.transformPosition(position); + final Vector3D sL = approximate.transformVector(los); + final Vector3D eP1 = ellipsoid.transform(ellipsoid.pointOnGround(sP, sL, 0.0)); + final double deltaT1 = eP1.distance(sP) / Constants.SPEED_OF_LIGHT; + final Transform shifted1 = inertToBody.shiftedBy(-deltaT1); + final NormalizedGeodeticPoint gp1 = algorithm.intersection(ellipsoid, + shifted1.transformPosition(pInert), + shifted1.transformVector(lInert)); + + final Vector3D eP2 = ellipsoid.transform(gp1); + final double deltaT2 = eP2.distance(sP) / Constants.SPEED_OF_LIGHT; + final Transform shifted2 = inertToBody.shiftedBy(-deltaT2); + return algorithm.refineIntersection(ellipsoid, + shifted2.transformPosition(pInert), + shifted2.transformVector(lInert), + gp1); + + } else { + // compute DEM intersection without light time correction + final Vector3D pBody = inertToBody.transformPosition(pInert); + final Vector3D lBody = inertToBody.transformVector(lInert); + return algorithm.refineIntersection(ellipsoid, pBody, lBody, + algorithm.intersection(ellipsoid, pBody, lBody)); + } + } /** Find the date at which sensor sees a ground point. diff --git a/core/src/main/java/org/orekit/rugged/intersection/BasicScanAlgorithm.java b/core/src/main/java/org/orekit/rugged/intersection/BasicScanAlgorithm.java index fca8fa28..1082570d 100644 --- a/core/src/main/java/org/orekit/rugged/intersection/BasicScanAlgorithm.java +++ b/core/src/main/java/org/orekit/rugged/intersection/BasicScanAlgorithm.java @@ -30,6 +30,7 @@ import org.orekit.rugged.raster.Tile; import org.orekit.rugged.raster.TileUpdater; import org.orekit.rugged.raster.TilesCache; import org.orekit.rugged.utils.ExtendedEllipsoid; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** Intersection computation using a basic algorithm based on exhaustive scan. * <p> @@ -62,30 +63,37 @@ public class BasicScanAlgorithm implements IntersectionAlgorithm { /** {@inheritDoc} */ @Override - public GeodeticPoint intersection(final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los) + public NormalizedGeodeticPoint intersection(final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los) throws RuggedException { try { // find the tiles between the entry and exit point in the Digital Elevation Model - GeodeticPoint entryPoint = null; - GeodeticPoint exitPoint = null; + NormalizedGeodeticPoint entryPoint = null; + NormalizedGeodeticPoint exitPoint = null; double minLatitude = Double.NaN; double maxLatitude = Double.NaN; double minLongitude = Double.NaN; double maxLongitude = Double.NaN; final List<SimpleTile> scannedTiles = new ArrayList<SimpleTile>(); + double centralLongitude = Double.NaN; for (boolean changedMinMax = true; changedMinMax; changedMinMax = checkMinMax(scannedTiles)) { scannedTiles.clear(); // compute entry and exit points entryPoint = ellipsoid.transform(ellipsoid.pointAtAltitude(position, los, Double.isInfinite(hMax) ? 0.0 : hMax), - ellipsoid.getBodyFrame(), null); + ellipsoid.getBodyFrame(), null, + Double.isNaN(centralLongitude) ? 0.0 : centralLongitude); final SimpleTile entryTile = cache.getTile(entryPoint.getLatitude(), entryPoint.getLongitude()); + if (Double.isNaN(centralLongitude)) { + centralLongitude = entryTile.getMinimumLongitude(); + entryPoint = new NormalizedGeodeticPoint(entryPoint.getLatitude(), entryPoint.getLongitude(), + entryPoint.getAltitude(), centralLongitude); + } addIfNotPresent(scannedTiles, entryTile); exitPoint = ellipsoid.transform(ellipsoid.pointAtAltitude(position, los, Double.isInfinite(hMin) ? 0.0 : hMin), - ellipsoid.getBodyFrame(), null); + ellipsoid.getBodyFrame(), null, centralLongitude); final SimpleTile exitTile = cache.getTile(exitPoint.getLatitude(), exitPoint.getLongitude()); addIfNotPresent(scannedTiles, exitTile); @@ -111,12 +119,12 @@ public class BasicScanAlgorithm implements IntersectionAlgorithm { } // scan the tiles - GeodeticPoint intersectionGP = null; + NormalizedGeodeticPoint intersectionGP = null; double intersectionDot = Double.POSITIVE_INFINITY; for (final SimpleTile tile : scannedTiles) { for (int i = latitudeIndex(tile, minLatitude); i <= latitudeIndex(tile, maxLatitude); ++i) { for (int j = longitudeIndex(tile, minLongitude); j <= longitudeIndex(tile, maxLongitude); ++j) { - final GeodeticPoint gp = tile.pixelIntersection(entryPoint, ellipsoid.convertLos(entryPoint, los), i, j); + final NormalizedGeodeticPoint gp = tile.pixelIntersection(entryPoint, ellipsoid.convertLos(entryPoint, los), i, j); if (gp != null) { // improve the point, by projecting it back on the 3D line, fixing the small body curvature at pixel level @@ -124,7 +132,7 @@ public class BasicScanAlgorithm implements IntersectionAlgorithm { final double s = Vector3D.dotProduct(delta, los) / los.getNormSq(); final GeodeticPoint projected = ellipsoid.transform(new Vector3D(1, position, s, los), ellipsoid.getBodyFrame(), null); - final GeodeticPoint gpImproved = tile.pixelIntersection(projected, ellipsoid.convertLos(projected, los), i, j); + final NormalizedGeodeticPoint gpImproved = tile.pixelIntersection(projected, ellipsoid.convertLos(projected, los), i, j); if (gpImproved != null) { final Vector3D point = ellipsoid.transform(gpImproved); @@ -150,9 +158,9 @@ public class BasicScanAlgorithm implements IntersectionAlgorithm { /** {@inheritDoc} */ @Override - public GeodeticPoint refineIntersection(final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los, - final GeodeticPoint closeGuess) + public NormalizedGeodeticPoint refineIntersection(final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los, + final NormalizedGeodeticPoint closeGuess) throws RuggedException { try { final Vector3D delta = ellipsoid.transform(closeGuess).subtract(position); diff --git a/core/src/main/java/org/orekit/rugged/intersection/IgnoreDEMAlgorithm.java b/core/src/main/java/org/orekit/rugged/intersection/IgnoreDEMAlgorithm.java index 06a6d3b3..232fb2d9 100644 --- a/core/src/main/java/org/orekit/rugged/intersection/IgnoreDEMAlgorithm.java +++ b/core/src/main/java/org/orekit/rugged/intersection/IgnoreDEMAlgorithm.java @@ -17,10 +17,9 @@ package org.orekit.rugged.intersection; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; -import org.orekit.bodies.GeodeticPoint; -import org.orekit.errors.OrekitException; import org.orekit.rugged.api.RuggedException; import org.orekit.rugged.utils.ExtendedEllipsoid; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** Intersection ignoring Digital Elevation Model. * <p> @@ -37,22 +36,17 @@ public class IgnoreDEMAlgorithm implements IntersectionAlgorithm { /** {@inheritDoc} */ @Override - public GeodeticPoint intersection(final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los) + public NormalizedGeodeticPoint intersection(final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los) throws RuggedException { - try { - return ellipsoid.pointOnGround(position, los); - } catch (OrekitException oe) { - // this should never happen - throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); - } + return ellipsoid.pointOnGround(position, los, 0.0); } /** {@inheritDoc} */ @Override - public GeodeticPoint refineIntersection(final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los, - final GeodeticPoint closeGuess) + public NormalizedGeodeticPoint refineIntersection(final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los, + final NormalizedGeodeticPoint closeGuess) throws RuggedException { return intersection(ellipsoid, position, los); } diff --git a/core/src/main/java/org/orekit/rugged/intersection/IntersectionAlgorithm.java b/core/src/main/java/org/orekit/rugged/intersection/IntersectionAlgorithm.java index be93c8f0..074bcca9 100644 --- a/core/src/main/java/org/orekit/rugged/intersection/IntersectionAlgorithm.java +++ b/core/src/main/java/org/orekit/rugged/intersection/IntersectionAlgorithm.java @@ -20,6 +20,7 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.orekit.bodies.GeodeticPoint; import org.orekit.rugged.api.RuggedException; import org.orekit.rugged.utils.ExtendedEllipsoid; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** Interface for Digital Elevation Model intersection algorithm. * @author Luc Maisonobe @@ -33,7 +34,7 @@ public interface IntersectionAlgorithm { * @return point at which the line first enters ground * @exception RuggedException if intersection cannot be found */ - GeodeticPoint intersection(ExtendedEllipsoid ellipsoid, Vector3D position, Vector3D los) + NormalizedGeodeticPoint intersection(ExtendedEllipsoid ellipsoid, Vector3D position, Vector3D los) throws RuggedException; /** Refine intersection of line with Digital Elevation Model. @@ -51,8 +52,8 @@ public interface IntersectionAlgorithm { * @return point at which the line first enters ground * @exception RuggedException if intersection cannot be found */ - GeodeticPoint refineIntersection(ExtendedEllipsoid ellipsoid, Vector3D position, Vector3D los, - GeodeticPoint closeGuess) + NormalizedGeodeticPoint refineIntersection(ExtendedEllipsoid ellipsoid, Vector3D position, Vector3D los, + NormalizedGeodeticPoint closeGuess) throws RuggedException; /** Get elevation at a given ground point. diff --git a/core/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java b/core/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java index d390dab1..824e55f1 100644 --- a/core/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java +++ b/core/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java @@ -18,7 +18,6 @@ package org.orekit.rugged.intersection.duvenhage; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathUtils; import org.orekit.bodies.GeodeticPoint; import org.orekit.errors.OrekitException; import org.orekit.rugged.api.RuggedException; @@ -28,6 +27,7 @@ import org.orekit.rugged.raster.Tile; import org.orekit.rugged.raster.TileUpdater; import org.orekit.rugged.raster.TilesCache; import org.orekit.rugged.utils.ExtendedEllipsoid; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** Digital Elevation Model intersection using Bernardt Duvenhage's algorithm. * <p> @@ -66,21 +66,18 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { /** {@inheritDoc} */ @Override - public GeodeticPoint intersection(final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los) + public NormalizedGeodeticPoint intersection(final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los) throws RuggedException { try { // compute intersection with ellipsoid - final GeodeticPoint gp0 = ellipsoid.pointOnGround(position, los); - if (gp0 == null) { - throw new RuggedException(RuggedMessages.LINE_OF_SIGHT_DOES_NOT_REACH_GROUND); - } + final NormalizedGeodeticPoint gp0 = ellipsoid.pointOnGround(position, los, 0.0); // locate the entry tile along the line-of-sight MinMaxTreeTile tile = cache.getTile(gp0.getLatitude(), gp0.getLongitude()); - GeodeticPoint current = null; + NormalizedGeodeticPoint current = null; double hMax = tile.getMaxElevation(); while (current == null) { @@ -90,7 +87,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { // the entry point is behind spacecraft! throw new RuggedException(RuggedMessages.DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT); } - current = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null); + current = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null, tile.getMinimumLongitude()); if (tile.getLocation(current.getLatitude(), current.getLongitude()) != Tile.Location.IN_TILE) { // the entry point is in another tile @@ -120,7 +117,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { final int exitLon = FastMath.max(0, FastMath.min(tile.getLongitudeColumns() - 1, tile.getLongitudeIndex(exit.getPoint().getLongitude()))); - final GeodeticPoint intersection = recurseIntersection(0, ellipsoid, position, los, tile, + final NormalizedGeodeticPoint intersection = recurseIntersection(0, ellipsoid, position, los, tile, current, entryLat, entryLon, exit.getPoint(), exitLat, exitLon); @@ -132,7 +129,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { // select next tile after current point final Vector3D forward = new Vector3D(1.0, ellipsoid.transform(exit.getPoint()), STEP, los); - current = ellipsoid.transform(forward, ellipsoid.getBodyFrame(), null); + current = ellipsoid.transform(forward, ellipsoid.getBodyFrame(), null, tile.getMinimumLongitude()); tile = cache.getTile(current.getLatitude(), current.getLongitude()); if (tile.interpolateElevation(current.getLatitude(), current.getLongitude()) >= current.getAltitude()) { @@ -159,9 +156,9 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { /** {@inheritDoc} */ @Override - public GeodeticPoint refineIntersection(final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los, - final GeodeticPoint closeGuess) + public NormalizedGeodeticPoint refineIntersection(final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los, + final NormalizedGeodeticPoint closeGuess) throws RuggedException { try { if (flatBody) { @@ -171,7 +168,8 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { final Tile tile = cache.getTile(closeGuess.getLatitude(), closeGuess.getLongitude()); final Vector3D exitP = ellipsoid.pointAtAltitude(position, los, tile.getMinElevation()); final Vector3D entryP = ellipsoid.pointAtAltitude(position, los, tile.getMaxElevation()); - final GeodeticPoint entry = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null); + final NormalizedGeodeticPoint entry = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null, + tile.getMinimumLongitude()); return tile.pixelIntersection(entry, ellipsoid.convertLos(entryP, exitP), tile.getLatitudeIndex(closeGuess.getLatitude()), tile.getLongitudeIndex(closeGuess.getLongitude())); @@ -215,11 +213,11 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { * @exception RuggedException if intersection cannot be found * @exception OrekitException if points cannot be converted to geodetic coordinates */ - private GeodeticPoint recurseIntersection(final int depth, final ExtendedEllipsoid ellipsoid, - final Vector3D position, final Vector3D los, - final MinMaxTreeTile tile, - final GeodeticPoint entry, final int entryLat, final int entryLon, - final GeodeticPoint exit, final int exitLat, final int exitLon) + private NormalizedGeodeticPoint recurseIntersection(final int depth, final ExtendedEllipsoid ellipsoid, + final Vector3D position, final Vector3D los, + final MinMaxTreeTile tile, + final NormalizedGeodeticPoint entry, final int entryLat, final int entryLon, + final NormalizedGeodeticPoint exit, final int exitLat, final int exitLon) throws RuggedException, OrekitException { if (depth > 30) { @@ -240,7 +238,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { return null; } - GeodeticPoint previousGP = entry; + NormalizedGeodeticPoint previousGP = entry; int previousLat = entryLat; int previousLon = entryLon; @@ -257,12 +255,13 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { if (longitude >= FastMath.min(entry.getLongitude(), exit.getLongitude()) && longitude <= FastMath.max(entry.getLongitude(), exit.getLongitude())) { - GeodeticPoint crossingGP = null; + NormalizedGeodeticPoint crossingGP = null; if (!flatBody) { try { // full computation of crossing point final Vector3D crossingP = ellipsoid.pointAtLongitude(position, los, longitude); - crossingGP = ellipsoid.transform(crossingP, ellipsoid.getBodyFrame(), null); + crossingGP = ellipsoid.transform(crossingP, ellipsoid.getBodyFrame(), null, + tile.getMinimumLongitude()); } catch (RuggedException re) { // in some very rare cases of numerical noise, we miss the crossing point crossingGP = null; @@ -273,9 +272,10 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { final double d = exit.getLongitude() - entry.getLongitude(); final double cN = (exit.getLongitude() - longitude) / d; final double cX = (longitude - entry.getLongitude()) / d; - crossingGP = new GeodeticPoint(cN * entry.getLatitude() + cX * exit.getLatitude(), - longitude, - cN * entry.getAltitude() + cX * exit.getAltitude()); + crossingGP = new NormalizedGeodeticPoint(cN * entry.getLatitude() + cX * exit.getLatitude(), + longitude, + cN * entry.getAltitude() + cX * exit.getAltitude(), + tile.getMinimumLongitude()); } final int crossingLat = tile.getLatitudeIndex(crossingGP.getLatitude()); @@ -285,9 +285,10 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { if (inRange(crossingLonBefore, entryLon, exitLon)) { // look for intersection - final GeodeticPoint intersection = recurseIntersection(depth + 1, ellipsoid, position, los, tile, - previousGP, previousLat, previousLon, - crossingGP, crossingLat, crossingLonBefore); + final NormalizedGeodeticPoint intersection = + recurseIntersection(depth + 1, ellipsoid, position, los, tile, + previousGP, previousLat, previousLon, + crossingGP, crossingLat, crossingLonBefore); if (intersection != null) { return intersection; } @@ -311,14 +312,15 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { if (latitude >= FastMath.min(entry.getLatitude(), exit.getLatitude()) && latitude <= FastMath.max(entry.getLatitude(), exit.getLatitude())) { - GeodeticPoint crossingGP = null; + NormalizedGeodeticPoint crossingGP = null; if (!flatBody) { // full computation of crossing point try { final Vector3D crossingP = ellipsoid.pointAtLatitude(position, los, tile.getLatitudeAtIndex(crossingLat), ellipsoid.transform(entry)); - crossingGP = ellipsoid.transform(crossingP, ellipsoid.getBodyFrame(), null); + crossingGP = ellipsoid.transform(crossingP, ellipsoid.getBodyFrame(), null, + tile.getMinimumLongitude()); } catch (RuggedException re) { // in some very rare cases of numerical noise, we miss the crossing point crossingGP = null; @@ -329,9 +331,10 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { final double d = exit.getLatitude() - entry.getLatitude(); final double cN = (exit.getLatitude() - latitude) / d; final double cX = (latitude - entry.getLatitude()) / d; - crossingGP = new GeodeticPoint(latitude, - cN * entry.getLongitude() + cX * exit.getLongitude(), - cN * entry.getAltitude() + cX * exit.getAltitude()); + crossingGP = new NormalizedGeodeticPoint(latitude, + cN * entry.getLongitude() + cX * exit.getLongitude(), + cN * entry.getAltitude() + cX * exit.getAltitude(), + tile.getMinimumLongitude()); } final int crossingLon = tile.getLongitudeIndex(crossingGP.getLongitude()); @@ -341,7 +344,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { if (inRange(crossingLatBefore, entryLat, exitLat)) { // look for intersection - final GeodeticPoint intersection = recurseIntersection(depth + 1, ellipsoid, position, los, tile, + final NormalizedGeodeticPoint intersection = recurseIntersection(depth + 1, ellipsoid, position, los, tile, previousGP, previousLat, previousLon, crossingGP, crossingLatBefore, crossingLon); if (intersection != null) { @@ -395,51 +398,48 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { // look for an exit at bottom final Vector3D exitP = ellipsoid.pointAtAltitude(position, los, tile.getMinElevation() - STEP); - final GeodeticPoint exitGP = ellipsoid.transform(exitP, ellipsoid.getBodyFrame(), null); + final NormalizedGeodeticPoint exitGP = ellipsoid.transform(exitP, ellipsoid.getBodyFrame(), null, + tile.getMinimumLongitude()); - // fix longitude discontinuity - final double meanTileLongitude = tile.getLongitudeAtIndex(tile.getLongitudeColumns() / 2); - final double fixedLongitude = MathUtils.normalizeAngle(exitGP.getLongitude(), meanTileLongitude); - - switch (tile.getLocation(exitGP.getLatitude(), fixedLongitude)) { + switch (tile.getLocation(exitGP.getLatitude(), exitGP.getLongitude())) { case SOUTH_WEST : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), selectClosest(ellipsoid.pointAtLatitude(position, los, tile.getMinimumLatitude(), exitP), ellipsoid.pointAtLongitude(position, los, tile.getMinimumLongitude()), position), - true); + true); case WEST : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), ellipsoid.pointAtLongitude(position, los, tile.getMinimumLongitude()), true); case NORTH_WEST: - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), selectClosest(ellipsoid.pointAtLatitude(position, los, tile.getMaximumLatitude(), exitP), ellipsoid.pointAtLongitude(position, los, tile.getMinimumLongitude()), position), - true); + true); case NORTH : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), ellipsoid.pointAtLatitude(position, los, tile.getMaximumLatitude(), exitP), true); case NORTH_EAST : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), selectClosest(ellipsoid.pointAtLatitude(position, los, tile.getMaximumLatitude(), exitP), ellipsoid.pointAtLongitude(position, los, tile.getMaximumLongitude()), position), - true); + true); case EAST : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), ellipsoid.pointAtLongitude(position, los, tile.getMaximumLongitude()), true); case SOUTH_EAST : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), selectClosest(ellipsoid.pointAtLatitude(position, los, tile.getMinimumLatitude(), exitP), ellipsoid.pointAtLongitude(position, los, tile.getMaximumLongitude()), position), - true); + true); case SOUTH : - return new LimitPoint(ellipsoid, + return new LimitPoint(ellipsoid, tile.getMinimumLongitude(), ellipsoid.pointAtLatitude(position, los, tile.getMinimumLatitude(), exitP), true); case IN_TILE : @@ -467,21 +467,24 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { private static class LimitPoint { /** Coordinates. */ - private final GeodeticPoint point; + private final NormalizedGeodeticPoint point; /** Limit status. */ private final boolean side; /** Simple constructor. - * @param cartesian point cartesian * @param ellipsoid reference ellipsoid + * @param centralLongitude reference longitude lc such that the point longitude will + * be normalized between lc-π and lc+π + * @param cartesian Cartesian point * @param side if true, the point is on a side limit, otherwise * it is on a top/bottom limit * @exception OrekitException if geodetic coordinates cannot be computed */ - public LimitPoint(final ExtendedEllipsoid ellipsoid, final Vector3D cartesian, final boolean side) + public LimitPoint(final ExtendedEllipsoid ellipsoid, final double centralLongitude, + final Vector3D cartesian, final boolean side) throws OrekitException { - this(ellipsoid.transform(cartesian, ellipsoid.getBodyFrame(), null), side); + this(ellipsoid.transform(cartesian, ellipsoid.getBodyFrame(), null, centralLongitude), side); } /** Simple constructor. @@ -489,7 +492,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { * @param side if true, the point is on a side limit, otherwise * it is on a top/bottom limit */ - public LimitPoint(final GeodeticPoint point, final boolean side) { + public LimitPoint(final NormalizedGeodeticPoint point, final boolean side) { this.point = point; this.side = side; } @@ -497,7 +500,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { /** Get the point coordinates. * @return point coordinates */ - public GeodeticPoint getPoint() { + public NormalizedGeodeticPoint getPoint() { return point; } diff --git a/core/src/main/java/org/orekit/rugged/raster/SimpleTile.java b/core/src/main/java/org/orekit/rugged/raster/SimpleTile.java index ecb2d701..c2488c50 100644 --- a/core/src/main/java/org/orekit/rugged/raster/SimpleTile.java +++ b/core/src/main/java/org/orekit/rugged/raster/SimpleTile.java @@ -22,6 +22,7 @@ import org.apache.commons.math3.util.Precision; import org.orekit.bodies.GeodeticPoint; import org.orekit.rugged.api.RuggedException; import org.orekit.rugged.api.RuggedMessages; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** Simple implementation of a {@link Tile}. @@ -245,8 +246,8 @@ public class SimpleTile implements Tile { /** {@inheritDoc} */ @Override - public GeodeticPoint pixelIntersection(final GeodeticPoint p, final Vector3D los, - final int latitudeIndex, final int longitudeIndex) + public NormalizedGeodeticPoint pixelIntersection(final GeodeticPoint p, final Vector3D los, + final int latitudeIndex, final int longitudeIndex) throws RuggedException { // ensure neighboring pixels to not fall out of tile @@ -312,8 +313,8 @@ public class SimpleTile implements Tile { } - final GeodeticPoint p1 = interpolate(t1, p, dxA, dyA, los); - final GeodeticPoint p2 = interpolate(t2, p, dxA, dyA, los); + final NormalizedGeodeticPoint p1 = interpolate(t1, p, dxA, dyA, los, x00); + final NormalizedGeodeticPoint p2 = interpolate(t2, p, dxA, dyA, los, x00); // select the first point along line-of-sight if (p1 == null) { @@ -332,11 +333,13 @@ public class SimpleTile implements Tile { * @param dxP relative coordinate of the start point with respect to current pixel * @param dyP relative coordinate of the start point with respect to current pixel * @param los direction of the line-of-sight, in geodetic space + * @param centralLongitude reference longitude lc such that the point longitude will + * be normalized between lc-π and lc+π * @return interpolated point along the line */ - private GeodeticPoint interpolate(final double t, final GeodeticPoint p, - final double dxP, final double dyP, - final Vector3D los) { + private NormalizedGeodeticPoint interpolate(final double t, final GeodeticPoint p, + final double dxP, final double dyP, + final Vector3D los, final double centralLongitude) { if (Double.isInfinite(t)) { return null; @@ -345,9 +348,10 @@ public class SimpleTile implements Tile { final double dx = dxP + t * los.getX() / longitudeStep; final double dy = dyP + t * los.getY() / latitudeStep; if (dx >= -TOLERANCE && dx <= 1 + TOLERANCE && dy >= -TOLERANCE && dy <= 1 + TOLERANCE) { - return new GeodeticPoint(p.getLatitude() + t * los.getY(), - p.getLongitude() + t * los.getX(), - p.getAltitude() + t * los.getZ()); + return new NormalizedGeodeticPoint(p.getLatitude() + t * los.getY(), + p.getLongitude() + t * los.getX(), + p.getAltitude() + t * los.getZ(), + centralLongitude); } else { return null; } diff --git a/core/src/main/java/org/orekit/rugged/raster/Tile.java b/core/src/main/java/org/orekit/rugged/raster/Tile.java index eb91e9d2..96e91ba9 100644 --- a/core/src/main/java/org/orekit/rugged/raster/Tile.java +++ b/core/src/main/java/org/orekit/rugged/raster/Tile.java @@ -19,6 +19,7 @@ package org.orekit.rugged.raster; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.orekit.bodies.GeodeticPoint; import org.orekit.rugged.api.RuggedException; +import org.orekit.rugged.utils.NormalizedGeodeticPoint; /** Interface representing a raster tile. * <p> @@ -193,8 +194,8 @@ public interface Tile extends UpdatableTile { * if it lies within the pixel, null otherwise * @exception RuggedException if intersection point cannot be computed */ - GeodeticPoint pixelIntersection(GeodeticPoint p, Vector3D los, - int latitudeIndex, int longitudeIndex) + NormalizedGeodeticPoint pixelIntersection(GeodeticPoint p, Vector3D los, + int latitudeIndex, int longitudeIndex) throws RuggedException; /** Check if a tile covers a ground point. diff --git a/core/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java b/core/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java index 2218efb3..f02eeeb1 100644 --- a/core/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java +++ b/core/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java @@ -25,6 +25,7 @@ import org.orekit.errors.OrekitException; import org.orekit.frames.Frame; import org.orekit.rugged.api.RuggedException; import org.orekit.rugged.api.RuggedMessages; +import org.orekit.time.AbsoluteDate; /** Transform provider from Spacecraft frame to observed body frame. * @author Luc Maisonobe @@ -154,13 +155,26 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid { /** Get point on ground along a pixel line of sight. * @param position pixel position (in body frame) * @param los pixel line-of-sight, not necessarily normalized (in body frame) + * @param centralLongitude reference longitude lc such that the point longitude will + * be normalized between lc-π and lc+π * @return point on ground - * @exception OrekitException if no such point exists (typically line-of-sight missing body) + * @exception RuggedException if no such point exists (typically line-of-sight missing body) */ - public GeodeticPoint pointOnGround(final Vector3D position, final Vector3D los) - throws OrekitException { - return getIntersectionPoint(new Line(position, new Vector3D(1, position, 1e6, los), 1.0e-12), - position, getBodyFrame(), null); + public NormalizedGeodeticPoint pointOnGround(final Vector3D position, final Vector3D los, + final double centralLongitude) + throws RuggedException { + try { + final GeodeticPoint gp = + getIntersectionPoint(new Line(position, new Vector3D(1, position, 1e6, los), 1.0e-12), + position, getBodyFrame(), null); + if (gp == null) { + throw new RuggedException(RuggedMessages.LINE_OF_SIGHT_DOES_NOT_REACH_GROUND); + } + return new NormalizedGeodeticPoint(gp.getLatitude(), gp.getLongitude(), gp.getAltitude(), + centralLongitude); + } catch (OrekitException oe) { + throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + } } /** Get point at some altitude along a pixel line of sight. @@ -270,4 +284,21 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid { } } + /** Transform a cartesian point to a surface-relative point. + * @param point cartesian point + * @param frame frame in which cartesian point is expressed + * @param date date of the computation (used for frames conversions) + * @param centralLongitude reference longitude lc such that the point longitude will + * be normalized between lc-π and lc+π + * @return point at the same location but as a surface-relative point + * @exception OrekitException if point cannot be converted to body frame + */ + public NormalizedGeodeticPoint transform(final Vector3D point, final Frame frame, final AbsoluteDate date, + final double centralLongitude) + throws OrekitException { + final GeodeticPoint gp = transform(point, frame, date); + return new NormalizedGeodeticPoint(gp.getLatitude(), gp.getLongitude(), gp.getAltitude(), + centralLongitude); + } + } diff --git a/core/src/main/java/org/orekit/rugged/utils/NormalizedGeodeticPoint.java b/core/src/main/java/org/orekit/rugged/utils/NormalizedGeodeticPoint.java new file mode 100644 index 00000000..e60879a6 --- /dev/null +++ b/core/src/main/java/org/orekit/rugged/utils/NormalizedGeodeticPoint.java @@ -0,0 +1,58 @@ +/* Copyright 2013-2014 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (CS) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * CS licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.orekit.rugged.utils; + +import org.apache.commons.math3.util.MathUtils; +import org.orekit.bodies.GeodeticPoint; + +/** Geodetic point whose longitude can be selected with respect to the 2π boundary. + * @author Luc Maisonobe + */ +public class NormalizedGeodeticPoint extends GeodeticPoint { + + /** Serializable UID. */ + private static final long serialVersionUID = 20141016l; + + /** Normalized longitude. */ + private final double normalizedLongitude; + + /** + * Build a new instance. The angular coordinates will be normalized + * to ensure that the latitude is between ±π/2 and the longitude + * is between lc-π and lc+π. + * + * @param latitude latitude of the point + * @param longitude longitude of the point + * @param altitude altitude of the point + * @param centralLongitude central longitude lc + */ + public NormalizedGeodeticPoint(final double latitude, final double longitude, + final double altitude, final double centralLongitude) { + super(latitude, longitude, altitude); + this.normalizedLongitude = MathUtils.normalizeAngle(longitude, centralLongitude); + } + + /** Get the longitude. + * @return longitude, an angular value in the range [lc-π, lc+π], + * where l₀ was selected at construction + */ + @Override + public double getLongitude() { + return normalizedLongitude; + } + +} diff --git a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java index 88923a1e..53a30f65 100644 --- a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java +++ b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java @@ -39,7 +39,6 @@ import org.apache.commons.math3.ode.nonstiff.DormandPrince853Integrator; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.apache.commons.math3.util.FastMath; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -277,7 +276,6 @@ public class RuggedTest { // the following test is disabled by default // it is only used to check timings, and also creates a large (66M) temporary file @Test - @Ignore public void testMayonVolcanoTiming() throws RuggedException, OrekitException, URISyntaxException { @@ -925,7 +923,6 @@ public class RuggedTest { // the following test is disabled by default // it is only used to check timings, and also creates a large (38M) temporary file @Test - @Ignore public void testInverseLocalizationTiming() throws RuggedException, OrekitException, URISyntaxException { diff --git a/design/direct-localization-class-diagram.puml b/design/direct-localization-class-diagram.puml index 8d90bc51..e4e73d4f 100644 --- a/design/direct-localization-class-diagram.puml +++ b/design/direct-localization-class-diagram.puml @@ -30,7 +30,7 @@ package raster #DDEBD8 { interface Tile { +interpolateElevation(φ, λ) - +pixelIntersection(geodeticPoint, los, φ index, λ index) + +pixelIntersection(NormalizedGeodeticPoint, los, φ index, λ index) } } diff --git a/src/site/markdown/design/technical-choices.md b/src/site/markdown/design/technical-choices.md index 7c00e542..3ff7b740 100644 --- a/src/site/markdown/design/technical-choices.md +++ b/src/site/markdown/design/technical-choices.md @@ -186,7 +186,7 @@ Arrival on ellipsoid -------------------- Once a pixel line-of-sight is known in Earth frame, computing its intersection with a reference ellipsoid is straightforward using an -instance of OneAxisEllipsoid. The Orekit library computes this intersection as a GeodeticPoint instance on the ellipsoid surface. +instance of OneAxisEllipsoid. The Orekit library computes this intersection as a NormalizedGeodeticPoint instance on the ellipsoid surface. The line-of-sight is a straight line in the Cartesian 3D space, and once converted to geodetic coordinates (latitude, longitude, altitude), it is not a straight line anymore. Assuming line-of-sight remains a straight line in this space and can be defined by diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index 10a25a72..9cafc4e6 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -22,6 +22,10 @@ <body> <release version="1.0" date="TBD" description="TBD"> + <action dev="luc" type="fix" > + Force geodetic points to remain in the same longitude range as the tile of the + Digital Elevation Model they belong to. + </action> <action dev="luc" type="fix" > Added a protection agains some extremely rare numerical problems in Duvenhage algorithm. @@ -225,7 +229,7 @@ </action> <action dev="luc" type="update"> Remove GroundPoint class. - We use directly the Orekit GeodeticPoint now. + We use directly the Orekit NormalizedGeodeticPoint now. </action> <action dev="luc" type="add"> Added ITRF equinox, for applications that rely on it... -- GitLab