diff --git a/Modules/Core/Metadata/src/otbDimapMetadataHelper.cxx b/Modules/Core/Metadata/src/otbDimapMetadataHelper.cxx
index 90573912f4cf2ec5b107c6bafc085def912aa2ff..4cd68828143eedbe1ac488c50254e66508d6b50c 100644
--- a/Modules/Core/Metadata/src/otbDimapMetadataHelper.cxx
+++ b/Modules/Core/Metadata/src/otbDimapMetadataHelper.cxx
@@ -338,7 +338,6 @@ void DimapMetadataHelper::ParseDimapV2(const MetadataSupplierInterface & mds, co
 void DimapMetadataHelper::ParseSpot5Model(const MetadataSupplierInterface & mds, Spot5Param& spot5Param, const std::string & prefix){
 
   using Point3DType = itk::Point<double, 3>;
-  using Point2DType = itk::Point<double, 2>;
   
   std::vector<double> yaw_vector;
   std::vector<double> pitch_vector;
@@ -390,7 +389,7 @@ void DimapMetadataHelper::ParseSpot5Model(const MetadataSupplierInterface & mds,
   ParseVector(mds, expr_attitude,"ROLL", roll_vector);     
   ParseVector(mds, expr_attitude,"TIME", time_vector);  
 
-  for (int i=0; i < yaw_vector.size(); i++){
+  for (size_t i=0; i < yaw_vector.size(); i++){
     Point3DType point3d;
     point3d[0] = pitch_vector[i];
     point3d[1] = roll_vector[i];
@@ -410,15 +409,15 @@ void DimapMetadataHelper::ParseSpot5Model(const MetadataSupplierInterface & mds,
   // Use look angles from Green band
   // /!\ Warning check condition with SWIR band not clear in OSSIM!
   bool bandFound = false;
-  int i = 1;
   std::string expr;
 
   hasValue = false;
 
   if (m_Data.BandIDs.size()>1){
-    while (i < m_Data.BandIDs.size() && !bandFound ){
+    size_t i = 1;
+    while (i < m_Data.BandIDs.size() && !bandFound) {
       expr = prefix + "Data_Strip.Sensor_Configuration.Instrument_Look_Angles_List.Instrument_Look_Angles_"+std::to_string(i)+".BAND_INDEX";
-      mds.GetMetadataValue(expr, hasValue) == "2" ? bandFound=true:i++;
+      mds.GetMetadataValue(expr, hasValue) == "2" ? bandFound=true : i++;
     }
     expr = "Dimap_Document.Data_Strip.Sensor_Configuration.Instrument_Look_Angles_List.Instrument_Look_Angles_"+std::to_string(i)+".Look_Angles_List.Look_Angles";           
   }
@@ -441,7 +440,7 @@ void DimapMetadataHelper::ParseSpot5Model(const MetadataSupplierInterface & mds,
   ParseVector(mds, expr,"Velocity.Z", vel_z);
   ParseVector(mds, expr,"TIME", time_vector);
 
-  for (int i=0; i < pos_x.size(); i++){
+  for (size_t i = 0; i < pos_x.size(); i++) {
     Point3DType position;
     Point3DType velocity;
     position[0] = pos_x[i];
diff --git a/Modules/Core/Transform/include/otbBilinearProjection.h b/Modules/Core/Transform/include/otbBilinearProjection.h
index b20e040a4c65347e26fd83913462804fbb2aef81..6e15273c842fe04ef5f0b6e5d8b075f962f2d9ac 100644
--- a/Modules/Core/Transform/include/otbBilinearProjection.h
+++ b/Modules/Core/Transform/include/otbBilinearProjection.h
@@ -54,49 +54,52 @@ public:
   /** Run-time type information (and related methods). */
   itkTypeMacro(BilinearProjection, Object);
 
-  void worldToLineSample(const Point3DType& worldPoint,
-                                  Point2DType&       lineSampPt) const;
-   /*!
-    * METHOD: lineSampleToWorld()
-    * Performs the inverse projection from line, sample to ground (world):
-    */
-   void lineSampleToWorld(const Point2DType& lineSampPt,
-                                  Point3DType&       worldPt) const;
+  Point2DType worldToLineSample(const Point3DType& worldPoint) const;
+  /*!
+  * METHOD: lineSampleToWorld()
+  * Performs the inverse projection from line, sample to ground (world):
+  * @return line sample to 3D pos at height 0.0
+  */
+  Point3DType lineSampleToWorld(Point2DType lineSampPt) const;
    
-   /*!
-    * METHOD: lineSampleHeightToWorld
-    * This projects the image point to the given
-    * elevation above ellipsoid, thereby bypassing reference to a DEM. Useful
-    * for projections that are sensitive to elevation (such as sensor models).
-    */
-   void lineSampleHeightToWorld(const Point2DType& lineSampPt,
-                                        const double&   heightAboveEllipsoid,
-                                        Point3DType&       worldPt) const;
+  /*!
+  * METHOD: lineSampleHeightToWorld
+  * This projects the image point to the given
+  * elevation above ellipsoid, thereby bypassing reference to a DEM. Useful
+  * for projections that are sensitive to elevation (such as sensor models).
+  * 
+  * @return image point to world point at given height
+  */
+  Point3DType lineSampleHeightToWorld(Point2DType lineSampPt,
+                                      const double& heightAboveEllipsoid) const;
 
-   void setTiePoints(const std::vector<Point2DType>& lsPt, 
-                                      const std::vector<Point3DType>& geoPt);
+  const std::vector<Point2DType>& getLineSamplePoints() const;
 
-   void getTiePoints(std::vector<Point2DType>& lsPt, std::vector<Point3DType>& geoPt) const;
+  void setLineSamplePoints(const std::vector<Point2DType>& lsPt);
 
-   /** Return true if there is any nan in the points coordinates */
-   bool imgPointsHaveNan();
+  const std::vector<Point3DType>& getWorldPoints() const;
 
-   /** Return true if there is any nan in the points coordinates */
-   bool worldPointsHaveNan();
+  void setWorldPoints(const std::vector<Point3DType>& wPt);
 
-   /** Resolve the bilinear system */
-   void computeLS();
+  /** Return true if there is any nan in the points coordinates */
+  bool imgPointsHaveNan();
+
+  /** Return true if there is any nan in the points coordinates */
+  bool worldPointsHaveNan();
+
+  /** Resolve the bilinear system */
+  void computeLS();
 
 protected:
   BilinearProjection();
   BilinearProjection(const Point2DType& ul,
-                    const Point2DType& ur,
-                    const Point2DType& lr,
-                    const Point2DType& ll,
-                    const Point3DType& ulg,
-                    const Point3DType& urg,
-                    const Point3DType& lrg,
-                    const Point3DType& llg);
+                     const Point2DType& ur,
+                     const Point2DType& lr,
+                     const Point2DType& ll,
+                     const Point3DType& ulg,
+                     const Point3DType& urg,
+                     const Point3DType& lrg,
+                     const Point3DType& llg);
   virtual ~BilinearProjection() = default;
 
 private:
diff --git a/Modules/Core/Transform/include/otbSpot5ForwardTransform.hxx b/Modules/Core/Transform/include/otbSpot5ForwardTransform.hxx
index 19d5ef4953d3e5ab8e725823cd27eb041f3c6327..cfbd7f8007e73319700d2e47e2c6f0e591868f49 100644
--- a/Modules/Core/Transform/include/otbSpot5ForwardTransform.hxx
+++ b/Modules/Core/Transform/include/otbSpot5ForwardTransform.hxx
@@ -39,9 +39,9 @@ Spot5ForwardTransform<TScalarType, NInputDimensions, NOutputDimensions>::Transfo
   sensorPoint[0] = static_cast<double>(point[0]) - 0.5;
   sensorPoint[1] = static_cast<double>(point[1]) - 0.5;
   if (NInputDimensions > 2)
-    this->m_Transformer->LineSampleHeightToWorld(sensorPoint, static_cast<double>(point[2]), worldPoint);
+    worldPoint = this->m_Transformer->LineSampleHeightToWorld(sensorPoint, static_cast<double>(point[2]));
   else
-    this->m_Transformer->LineSampleToWorld(sensorPoint, worldPoint);
+    worldPoint = this->m_Transformer->LineSampleToWorld(sensorPoint);
 
   OutputPointType pOut;
   pOut[0] = static_cast<TScalarType>(worldPoint[0]);
diff --git a/Modules/Core/Transform/include/otbSpot5InverseTransform.hxx b/Modules/Core/Transform/include/otbSpot5InverseTransform.hxx
index eb9e3a1f38bbb00d3b77fb1f2203dc2fef13ddd5..ab291e1be25d49b55adcb640df09adafcf6c902e 100644
--- a/Modules/Core/Transform/include/otbSpot5InverseTransform.hxx
+++ b/Modules/Core/Transform/include/otbSpot5InverseTransform.hxx
@@ -34,7 +34,6 @@ template <class TScalarType, unsigned int NInputDimensions, unsigned int NOutput
 typename Spot5InverseTransform<TScalarType, NInputDimensions, NOutputDimensions>::OutputPointType
 Spot5InverseTransform<TScalarType, NInputDimensions, NOutputDimensions>::TransformPoint(const InputPointType& point) const
 {
-  Spot5SensorModel::Point2DType sensorPoint;
   Spot5SensorModel::Point3DType worldPoint;
   worldPoint[0] = static_cast<double>(point[0]);
   worldPoint[1] = static_cast<double>(point[1]);
@@ -43,7 +42,7 @@ Spot5InverseTransform<TScalarType, NInputDimensions, NOutputDimensions>::Transfo
   else
     worldPoint[2] = otb::DEMHandler::GetInstance().GetHeightAboveEllipsoid(point[0], point[1]);
 
-  this->m_Transformer->WorldToLineSample(worldPoint, sensorPoint);
+  Spot5SensorModel::Point2DType sensorPoint(this->m_Transformer->WorldToLineSample(worldPoint));
 
   OutputPointType pOut;
 
diff --git a/Modules/Core/Transform/include/otbSpot5SensorModel.h b/Modules/Core/Transform/include/otbSpot5SensorModel.h
index 37aa3068c01267412696da48eac0284af4316020..7f239506329e2d6d9d2de90dfdf0330fbbf2aade 100644
--- a/Modules/Core/Transform/include/otbSpot5SensorModel.h
+++ b/Modules/Core/Transform/include/otbSpot5SensorModel.h
@@ -68,54 +68,52 @@ public:
    * @brief Transform world point (lat,lon,hgt) to image point (col,row).
    * 
    * @param[in] inGeoPoint     ground point in WGS84 (lat, lon, hgt) coordinates
-   * @param[out] outLineSample image point (col,row) coordinates
+   * @return ground point converted to image point (col,row) coordinates
    */
-  void WorldToLineSample(const Point3DType& inGeoPoint,
-                         Point2DType& outLineSample) const;
+  Point2DType WorldToLineSample(const Point3DType& inGeoPoint) const;
 
   /**
    * @brief Transform image point (col, row) with a height to world point (lat,lon,hgt).
    * 
    * @param[in] imPt                 image point (col, row)
    * @param[in] heightAboveEllipsoid height 
-   * @param[out] worldPt             world point (lat,lon,hgt)
+   * @return image point and height converted to world point (lat,lon,hgt)
    */
-  void LineSampleHeightToWorld(const Point2DType& imPt,
-                               double heightAboveEllipsoid,
-                               Point3DType& worldPt) const;
+  Point3DType LineSampleHeightToWorld(Point2DType imPt,
+                                      double heightAboveEllipsoid) const;
 
   /**
    * @brief Transform image point (col, row) to world point (lat,lon,hgt).
    * 
    * @param[in] imPt     image point (col, row)
-   * @param[out] worldPt world point (lat,lon,hgt)
+   * @return image point converted to world point (lat,lon,hgt)
    */
-  void LineSampleToWorld(const Point2DType& imPt, Point3DType& worldPt) const;
+  Point3DType LineSampleToWorld(Point2DType imPt) const;
 
   /**
     * @brief Compute a ray from sensor position and image point.
     * 
     * @param[in] imPt  image point (col row)
-    * @param[out] epPt ephemeris point (3D space point with position and velocity)
+    * @return ephemeris point (3D space point with position and velocity)
     */
-  void ImagingRay(const Point2DType& imPt, Ephemeris&   epPt) const;
+  Ephemeris ImagingRay(Point2DType imPt) const;
 
   /**
    * @brief Compute the nearest intersection (world point) between the ray and the ellipsoid.
    * 
    * @param[in] imRay     ephemeris point (3D space point with position and velocity)
    * @param[in] offset    double offset
-   * @param[out] worldPt  world point (lat,lon,hgt)
+   * @return  world point (lat,lon,hgt)
    */
-  void NearestIntersection(const Ephemeris& imRay, const double& offset, Point3DType& worldPt) const;
+  Point3DType NearestIntersection(const Ephemeris& imRay, const double& offset) const;
 
   /**
    * @brief Compute world point intersected by image ray.
    * 
    * @param[in] imRay     ephemeris point (3D space point with position and velocity)
-   * @param[out] worldPt  world point (lat,lon,hgt)
+   * @return world point (lat,lon,hgt)
    */
-  void IntersectRay(const Ephemeris& imRay, Point3DType& worldPt) const;
+  Point3DType IntersectRay(const Ephemeris& imRay) const;
 
   /**
    * @brief Compute the bilinear interpolation from a 3D point vector with a double time vector.
@@ -123,12 +121,11 @@ public:
    * @param[in] time time to interpolate
    * @param[in] V    3D point vector
    * @param[in] T    Index time double vector
-   * @param[out] li  3D point interpolated
+   * @return 3D point interpolated
    */
-  void GetBilinearInterpolation(const double& time,
-                          const std::vector<Point3DType>& V,
-                          const std::vector<double>& T,
-                          Point3DType& li) const;
+  Point3DType GetBilinearInterpolation(const double& time,
+                                       const std::vector<Point3DType>& V,
+                                       const std::vector<double>& T) const;
 
   /**
   * @brief Compute the lagrange interpolation from a 3D point vector with a double time vector.
@@ -136,28 +133,27 @@ public:
   * @param[in] time time to interpolate
   * @param[in] V    3D point vector
   * @param[in] T    Index time double vector
-  * @param[out] li  3D point interpolated
+  * @return 3D point interpolated
   */
-  void GetLagrangeInterpolation(const double& time,
-                          const std::vector<Point3DType>& V,
-                          const std::vector<double>& T,
-                          Point3DType& li) const;                        
+  Point3DType GetLagrangeInterpolation(const double& time,
+                                       const std::vector<Point3DType>& V,
+                                       const std::vector<double>& T) const;
 
   /**
    * @brief Get the 3D position of the sensor at time (interpolation of position samples vector from metadata).
    * 
    * @param[in] time  input time
-   * @param[out] ecef 3D position
+   * @return 3D position
    */
-  void GetPositionEcf(const double& time, Point3DType& ecef) const;
+  Point3DType GetPositionEcf(const double& time) const;
 
   /**
    * @brief Get the 3D velocity of the sensor at time (interpolation of velocity samples vector from metadata).
    * 
    * @param[in]  time input time
-   * @param[out] ecef 3D position
+   * @return 3D position
    */
-  void GetVelocityEcf(const double& time, Point3DType& ecef) const;
+  Point3DType GetVelocityEcf(const double& time) const;
 
   /**
    * @brief Get look angles on X and Y axis of the sensor at line (interpolation of angles samples vector from metadata).
@@ -172,26 +168,26 @@ public:
    * @brief Get the Attitude of the sensor at time (interpolation of attitude samples vector from metadata).
    * 
    * @param[in] time input time
-   * @param[out] at   3D attitude
+   * @return 3D attitude
    */
-  void GetAttitude(const double& time, Point3DType& at) const;
+  Point3DType GetAttitude(const double& time) const;
 
   /**
    * @brief Compute SatToOrb matrix with an input time.
    * 
-   * @param[out] result 3X3 matrix computed
    * @param[in] t       input time
+   * @return 3X3 matrix computed
    */
-  void ComputeSatToOrbRotation(MatrixType& result, double t) const;
+  MatrixType ComputeSatToOrbRotation(double t) const;
+
 
-                        
   /** 
   * @brief Update a ImageMetadata object with the stored Spot5Param and GCPs, possibly modified from the 
   * original metadata by the Spot5SensorModel
   * 
   * @param[in] imd ImageMetadata to be updated
   */
-   void UpdateImageMetadata(ImageMetadata & imd);
+  void UpdateImageMetadata(ImageMetadata & imd);
 
 
 protected:
diff --git a/Modules/Core/Transform/src/otbBilinearProjection.cxx b/Modules/Core/Transform/src/otbBilinearProjection.cxx
index 1a156395db82900f6d6da2aba8efeb901053ec11..1cf8c9d621bc3c13c0ab646a107042616142d2f9 100644
--- a/Modules/Core/Transform/src/otbBilinearProjection.cxx
+++ b/Modules/Core/Transform/src/otbBilinearProjection.cxx
@@ -31,13 +31,13 @@ BilinearProjection::BilinearProjection()
 }
 
 BilinearProjection::BilinearProjection(const Point2DType& ul,
-                           const Point2DType& ur,
-                           const Point2DType& lr,
-                           const Point2DType& ll,
-                           const Point3DType& ulg,
-                           const Point3DType& urg,
-                           const Point3DType& lrg,
-                           const Point3DType& llg)
+                                       const Point2DType& ur,
+                                       const Point2DType& lr,
+                                       const Point2DType& ll,
+                                       const Point3DType& ulg,
+                                       const Point3DType& urg,
+                                       const Point3DType& lrg,
+                                       const Point3DType& llg)
 {
    m_LatFit = LSQREstimatorType::New();
    m_LonFit = LSQREstimatorType::New();
@@ -56,12 +56,13 @@ BilinearProjection::BilinearProjection(const Point2DType& ul,
    m_worldPoints[2] = lrg;
    m_worldPoints[3] = llg;
 
-    computeLS();
+   computeLS();
 }
 
-void BilinearProjection::worldToLineSample(const Point3DType& worldPoint,
-                                  Point2DType&       lineSampPt) const
+itk::Point<double, 2> BilinearProjection::worldToLineSample(const Point3DType& worldPoint) const
 {
+   // convert Point3D to vector double to use
+   // LeastSquareBilinearTransformEstimator::lsFitValue
    itk::Vector<double,2>  worldptMatrix;
    worldptMatrix[0] = worldPoint[0];
    worldptMatrix[1] = worldPoint[1];
@@ -70,22 +71,21 @@ void BilinearProjection::worldToLineSample(const Point3DType& worldPoint,
 
    m_XFit->lsFitValue(worldptMatrix, x);
    m_YFit->lsFitValue(worldptMatrix, y);
+
+   Point2DType lineSampPt;
    lineSampPt[0] = x;
    lineSampPt[1] = y;
-
+   return lineSampPt;
 }
 
-void BilinearProjection::lineSampleToWorld(const Point2DType& lineSampPt,
-                                  Point3DType&       worldPt) const
+BilinearProjection::Point3DType BilinearProjection::lineSampleToWorld(Point2DType lineSampPt) const
 {
- lineSampleHeightToWorld(lineSampPt,
-                           0.0,
-                           worldPt);
+  return lineSampleHeightToWorld(lineSampPt, 0.0);
 }
 
-void BilinearProjection::lineSampleHeightToWorld(const Point2DType& lineSampPt,
-                                        const double&   heightAboveEllipsoid,
-                                        Point3DType&       worldPt) const
+BilinearProjection::Point3DType BilinearProjection::lineSampleHeightToWorld(
+                                                Point2DType lineSampPt,
+                                                const double& heightAboveEllipsoid) const
 {
    itk::Vector<double,2> lineSampMatrix;
    lineSampMatrix[0] = lineSampPt[0];
@@ -93,22 +93,33 @@ void BilinearProjection::lineSampleHeightToWorld(const Point2DType& lineSampPt,
    double lon, lat;
    m_LonFit->lsFitValue(lineSampMatrix, lon);
    m_LatFit->lsFitValue(lineSampMatrix, lat);
+
+   Point3DType worldPt;
    worldPt[0] = lon;
    worldPt[1] = lat;
    worldPt[2] = heightAboveEllipsoid;
+
+   return worldPt;
+}
+
+const std::vector<itk::Point<double, 2>>& BilinearProjection::getLineSamplePoints() const
+{
+   return m_LineSamplePoints;
+}
+
+void BilinearProjection::setLineSamplePoints(const std::vector<Point2DType>& lsPts)
+{
+   m_LineSamplePoints = lsPts;
 }
 
-void BilinearProjection::setTiePoints(const std::vector<Point2DType>& lsPt, 
-                                    const std::vector<Point3DType>& geoPt)
+const std::vector<BilinearProjection::Point3DType>& BilinearProjection::getWorldPoints() const
 {
-    m_LineSamplePoints = lsPt;
-    m_worldPoints = geoPt;
+   return m_worldPoints;
 }
 
-void BilinearProjection::getTiePoints(std::vector<Point2DType>& lsPt, std::vector<Point3DType>& geoPt) const
+void BilinearProjection::setWorldPoints(const std::vector<Point3DType>& wPts)
 {
-    lsPt = m_LineSamplePoints;
-    geoPt = m_worldPoints;
+   m_worldPoints = wPts;
 }
 
 void BilinearProjection::computeLS()
diff --git a/Modules/Core/Transform/src/otbSpot5SensorModel.cxx b/Modules/Core/Transform/src/otbSpot5SensorModel.cxx
index 15e12272729dbc5c788dedfd62cadd5fb08df268..064c91efd148506fb1ddd9ff27d8ace13d81e5ef 100644
--- a/Modules/Core/Transform/src/otbSpot5SensorModel.cxx
+++ b/Modules/Core/Transform/src/otbSpot5SensorModel.cxx
@@ -49,13 +49,11 @@ Spot5SensorModel::Spot5SensorModel(const ImageMetadata & imd)
 void Spot5SensorModel::InitBilinearTransform(){
     
     Point2DType ul, ur, lr, ll;
-    Point3DType ulg, urg, lrg, llg;
 
     ul[0] = 0; ul[1] = 0;
     ur[0] = m_Spot5Param.ImageSize[0] - 1; ur[1] = 0;
     ll[0] = 0; ll[1] =  m_Spot5Param.ImageSize[1] - 1;
-    lr[0] = m_Spot5Param.ImageSize[0] - 1;
-    lr[1] = m_Spot5Param.ImageSize[1] - 1;
+    lr[0] = m_Spot5Param.ImageSize[0] - 1; lr[1] = m_Spot5Param.ImageSize[1] - 1;
 
     m_ImageRect = PolygonType::New();
     m_ImageRect->AddVertex(Point2DToIndex(ul));
@@ -63,10 +61,10 @@ void Spot5SensorModel::InitBilinearTransform(){
     m_ImageRect->AddVertex(Point2DToIndex(lr));
     m_ImageRect->AddVertex(Point2DToIndex(ll));
 
-    LineSampleToWorld(ul, ulg);
-    LineSampleToWorld(ur, urg);
-    LineSampleToWorld(lr, lrg);
-    LineSampleToWorld(ll, llg);
+    const Point3DType ulg(LineSampleToWorld(ul));
+    const Point3DType urg(LineSampleToWorld(ur));
+    const Point3DType lrg(LineSampleToWorld(lr));
+    const Point3DType llg(LineSampleToWorld(ll));
 
     m_GroundRect = PolygonType::New();
     m_GroundRect->AddVertex(Point3DToIndex(ulg));
@@ -77,9 +75,9 @@ void Spot5SensorModel::InitBilinearTransform(){
     std::vector<Point2DType> impts {ul,ur,lr,ll};
     std::vector<Point3DType> wrldpts {ulg,urg,lrg,llg};
     m_BilinearProj = BilinearProjection::New();
-    m_BilinearProj->setTiePoints(impts,wrldpts);
+    m_BilinearProj->setLineSamplePoints(impts);
+    m_BilinearProj->setWorldPoints(wrldpts);
     m_BilinearProj->computeLS();
-
 }
 
 Spot5SensorModel::ContinuousIndexType 
@@ -98,7 +96,7 @@ Spot5SensorModel::Point3DToIndex(const itk::Point<double, 3> point) const{
   return indexPoint;
 }
 
-void Spot5SensorModel::WorldToLineSample(const Point3DType& inGeoPoint, Point2DType& outLineSample) const
+itk::Point<double, 2> Spot5SensorModel::WorldToLineSample(const Point3DType& inGeoPoint) const
 {
   
   static const double PIXEL_THRESHOLD    = .1; // acceptable pixel error
@@ -111,9 +109,10 @@ void Spot5SensorModel::WorldToLineSample(const Point3DType& inGeoPoint, Point2DT
   int iters = 0;
   Point3DType wdp (inGeoPoint);
 
-  if (!(m_GroundRect->IsInside(Point3DToIndex(wdp))||m_GroundRect->IsOnEdge(Point3DToIndex(wdp)))){
-    m_BilinearProj->worldToLineSample(wdp, outLineSample);
-    return;
+  if (!(m_GroundRect->IsInside(Point3DToIndex(wdp)) ||
+        m_GroundRect->IsOnEdge(Point3DToIndex(wdp))))
+  {
+    return m_BilinearProj->worldToLineSample(wdp);
   }
 
 
@@ -121,8 +120,7 @@ void Spot5SensorModel::WorldToLineSample(const Point3DType& inGeoPoint, Point2DT
 
 
   // Initialize with binilear interpolation
-  Point2DType ip;
-  m_BilinearProj->worldToLineSample(wdp, ip);
+  Point2DType ip(m_BilinearProj->worldToLineSample(wdp));
 
   Point2DType ip_du;
   Point2DType ip_dv;
@@ -148,9 +146,9 @@ void Spot5SensorModel::WorldToLineSample(const Point3DType& inGeoPoint, Point2DT
     //***
     // Compute numerical partials at current guessed point:
     //***
-    LineSampleHeightToWorld(ip,    height, gp);
-    LineSampleHeightToWorld(ip_du, height, gp_du);
-    LineSampleHeightToWorld(ip_dv, height, gp_dv);
+    gp = LineSampleHeightToWorld(ip, height);
+    gp_du = LineSampleHeightToWorld(ip_du, height);
+    gp_dv = LineSampleHeightToWorld(ip_dv, height);
 
     dlat_du = gp_du[1] - gp[1]; //e
     dlon_du = gp_du[0] - gp[0]; //g
@@ -187,87 +185,71 @@ void Spot5SensorModel::WorldToLineSample(const Point3DType& inGeoPoint, Point2DT
   } while (iters < MAX_NUM_ITERATIONS); /* && ((std::abs(delta_u) < PIXEL_THRESHOLD)
                                                && (std::abs(delta_v) < PIXEL_THRESHOLD)) */
 
-  outLineSample = ip - m_Spot5Param.SubImageOffset;
+  return ip - m_Spot5Param.SubImageOffset;
 
 }
 
-void Spot5SensorModel::LineSampleHeightToWorld(const Point2DType& imPt,
-                                             double  heightAboveEllipsoid,
-                                             Point3DType& worldPt) const
+itk::Point<double, 3> Spot5SensorModel::LineSampleHeightToWorld(Point2DType imPt,
+                                             double  heightAboveEllipsoid) const
 {
 
   // Outside the image
   if (!insideImage(imPt, 1.0 - FLT_EPSILON))
   {
-    m_BilinearProj->lineSampleToWorld(imPt, worldPt);
-    return;
+    return m_BilinearProj->lineSampleToWorld(imPt);
   }
 
-  Ephemeris ray;
-  ImagingRay(imPt, ray);
-
   // Ecef coordinate point intersection
-  Point3DType intersectPt;
-  NearestIntersection(ray, heightAboveEllipsoid, intersectPt);
-
   // Conversion to lat long coordinates
-  worldPt = EcefToWorld(intersectPt);
-
+  return EcefToWorld(NearestIntersection(ImagingRay(imPt), heightAboveEllipsoid));
 }
 
-void Spot5SensorModel::LineSampleToWorld(const Point2DType& imPt,
-                                             Point3DType& worldPt) const
+itk::Point<double, 3> Spot5SensorModel::LineSampleToWorld(Point2DType imPt) const
 {
 
   if (!insideImage(imPt, 2.0))
   {
-    m_BilinearProj->lineSampleToWorld(imPt, worldPt);
-    return;
+    return m_BilinearProj->lineSampleToWorld(imPt);
   }
 
   // Determine ray and intersect with terrain model
-  Ephemeris ray;
-  ImagingRay(imPt, ray);
-  IntersectRay(ray, worldPt);
-
+  return IntersectRay(ImagingRay(imPt));
 }
 
 
 
 
-void Spot5SensorModel::GetBilinearInterpolation(
-      const double& time,
-      const std::vector<Point3DType>& V,
-      const std::vector<double>& T,
-      Point3DType& li) const
+itk::Point<double, 3> Spot5SensorModel::GetBilinearInterpolation(
+                                            const double& time,
+                                            const std::vector<Point3DType>& V,
+                                            const std::vector<double>& T) const
 {
   // get iterator to first element >= time
   const auto first_sup_value = std::lower_bound(T.begin(), T.end(), time);
 
   if(first_sup_value == T.begin())
   {
-    li = V[0];
+    return V[0];
   }
   else if(first_sup_value == T.end())
   {
-    li = V[1];
+    return V[1];
   }
   else
   {
     const int32_t samp0 = std::distance(T.begin(), first_sup_value);
     double t = (*(first_sup_value-1)-time)/
                (*(first_sup_value-1) - (*first_sup_value));
-    const auto it_v = V.begin() + samp0;
+    const auto& it_v = V.begin() + samp0;
 
-    li = *(it_v-1) + ((*it_v)-*(it_v-1))*t;
+    return *(it_v-1) + ((*it_v)-*(it_v-1))*t;
   }
 }
 
-void Spot5SensorModel::GetLagrangeInterpolation(
-      const double& time,
-      const std::vector<Point3DType>& V,
-      const std::vector<double>& T,
-      Point3DType& li) const
+itk::Point<double, 3> Spot5SensorModel::GetLagrangeInterpolation(
+                                              const double& time,
+                                              const std::vector<Point3DType>& V,
+                                              const std::vector<double>& T) const
 {
   //
   // Verify that t is within allowable range:
@@ -348,37 +330,34 @@ void Spot5SensorModel::GetLagrangeInterpolation(
     S[2] += p[2];
   }
 
-  li = S;
-
+  return S;
 }
 
 
-void Spot5SensorModel::GetPositionEcf(const double& time,
-                                               Point3DType& ecef)  const
+itk::Point<double, 3> Spot5SensorModel::GetPositionEcf(const double& time)  const
 {
   if((m_Spot5Param.EcefPosSamples.size() < 8)||
     (m_Spot5Param.EcefTimeSamples.size() < 8))
   {
-    GetBilinearInterpolation(time, m_Spot5Param.EcefPosSamples, m_Spot5Param.EcefTimeSamples, ecef);
+    return GetBilinearInterpolation(time, m_Spot5Param.EcefPosSamples, m_Spot5Param.EcefTimeSamples);
   }
   else
   {
-    GetLagrangeInterpolation(time, m_Spot5Param.EcefPosSamples, m_Spot5Param.EcefTimeSamples, ecef);
+    return GetLagrangeInterpolation(time, m_Spot5Param.EcefPosSamples, m_Spot5Param.EcefTimeSamples);
   }                                       
 }
 
 
-void Spot5SensorModel::GetVelocityEcf(const double& time,
-                                               Point3DType& ecef)  const
+itk::Point<double, 3> Spot5SensorModel::GetVelocityEcf(const double& time)  const
 {
   if((m_Spot5Param.EcefVelSamples.size() < 8)||
     (m_Spot5Param.EcefTimeSamples.size() < 8))
   {
-    GetBilinearInterpolation(time, m_Spot5Param.EcefVelSamples, m_Spot5Param.EcefTimeSamples, ecef);
+    return GetBilinearInterpolation(time, m_Spot5Param.EcefVelSamples, m_Spot5Param.EcefTimeSamples);
   }
   else
   {
-    GetLagrangeInterpolation(time, m_Spot5Param.EcefVelSamples, m_Spot5Param.EcefTimeSamples, ecef);
+    return GetLagrangeInterpolation(time, m_Spot5Param.EcefVelSamples, m_Spot5Param.EcefTimeSamples);
   }
 }
 
@@ -398,12 +377,12 @@ void Spot5SensorModel::GetPixelLookAngleXY(unsigned int line,
 
 }
 
-void Spot5SensorModel::GetAttitude(const double& time, Point3DType& at)  const
+itk::Point<double, 3> Spot5SensorModel::GetAttitude(const double& time)  const
 {
-  GetBilinearInterpolation(time, m_Spot5Param.AttitudesSamples, m_Spot5Param.AttitudesSamplesTimes, at);
+  return GetBilinearInterpolation(time, m_Spot5Param.AttitudesSamples, m_Spot5Param.AttitudesSamplesTimes);
 }
 
-void Spot5SensorModel::NearestIntersection(const Ephemeris& imRay, const double& offset, Point3DType& worldPt) const
+itk::Point<double, 3> Spot5SensorModel::NearestIntersection(const Ephemeris& imRay, const double& offset) const
 {
   // WGS 84 parameters conversion
   double wgsA = 6378137.000;
@@ -453,11 +432,11 @@ void Spot5SensorModel::NearestIntersection(const Ephemeris& imRay, const double&
       t = t2;
   }
 
-  worldPt  = imRay.position + imRay.velocity * t; 
+  return imRay.position + imRay.velocity * t; 
 
 }
 
-void Spot5SensorModel::IntersectRay(const Ephemeris& imRay, Point3DType& worldPt) const 
+itk::Point<double, 3> Spot5SensorModel::IntersectRay(const Ephemeris& imRay) const 
 {
 
   static const double CONVERGENCE_THRESHOLD = 0.001; // meters
@@ -469,17 +448,17 @@ void Spot5SensorModel::IntersectRay(const Ephemeris& imRay, Point3DType& worldPt
   double          distance;
   int             iteration_count = 0;
 
-  worldPt = EcefToWorld(prev_intersect_pt);
+  Point3DType worldPt(EcefToWorld(prev_intersect_pt));
 
   // Loop to iterate on ray intersection with variable elevation surface:
   do
   {
-    
+
     // Intersect ray with ellipsoid inflated by h_ellips:
     h_ellips = DEMHandler::GetInstance().GetHeightAboveEllipsoid(worldPt[0], worldPt[1]);
     
 
-    NearestIntersection(imRay, h_ellips, new_intersect_pt);
+    new_intersect_pt = NearestIntersection(imRay, h_ellips);
 
     // Assign the ground point to the latest iteration's intersection point:
     worldPt = EcefToWorld(new_intersect_pt);
@@ -502,14 +481,14 @@ void Spot5SensorModel::IntersectRay(const Ephemeris& imRay, Point3DType& worldPt
                                     << "point. Result is probably inaccurate." << std::endl);
   }
   
+  return worldPt;
 }
 
-void Spot5SensorModel::ComputeSatToOrbRotation(MatrixType& result, double t) const
+itk::Matrix<double, 3, 3> Spot5SensorModel::ComputeSatToOrbRotation(double t) const
 {
-
+  itk::Matrix<double, 3, 3> result;
   /* Linearly interpolate attitudes angles: */
-  Point3DType att;
-  GetAttitude(t, att);
+  Point3DType att(GetAttitude(t));
 
   /* Compute trig functions to populate rotation matrices: ANGLES IN RADIANS */
   double cp = cos(att[0]);
@@ -529,12 +508,12 @@ void Spot5SensorModel::ComputeSatToOrbRotation(MatrixType& result, double t) con
   result(2, 0) = (-sp*sy+cp*sr*cy);
   result(2, 1) = (-sp*cy-cp*sr*sy);
   result(2, 2) =  cp*cr;
+
+  return result;
 }
 
-void Spot5SensorModel::ImagingRay(const Point2DType& imPt, Ephemeris& imRay)  const
+Ephemeris Spot5SensorModel::ImagingRay(Point2DType imPt)  const
 {
-  Point3DType sensorPos; 
-  Point3DType sensorVel;
   Point2DType imPtTmp;
 
   imPtTmp[0] = imPt[0] + m_Spot5Param.SubImageOffset[0];
@@ -544,11 +523,8 @@ void Spot5SensorModel::ImagingRay(const Point2DType& imPt, Ephemeris& imRay)  co
   double timeLine = m_Spot5Param.RefLineTime + m_Spot5Param.LineSamplingPeriod*(imPtTmp[1] - m_Spot5Param.RefLineTimeLine);
 
   /* 2. Interpolate ephemeris position and velocity (in ECF): */
-  Point3DType  ecfPos;
-  Point3DType  ecfVel;
-
-  GetPositionEcf(timeLine, ecfPos);
-  GetVelocityEcf(timeLine, ecfVel);
+  Point3DType  ecfPos(GetPositionEcf(timeLine));
+  Point3DType  ecfVel(GetVelocityEcf(timeLine));
 
   /* 3. Establish the look direction in Vehicle LSR space (S_sat). ANGLES IN RADIANS*/
   double psiX, psiY;
@@ -560,10 +536,7 @@ void Spot5SensorModel::ImagingRay(const Point2DType& imPt, Ephemeris& imRay)  co
   u_sat[2] = -1.0;
 
   /* 4. Transform vehicle LSR space look direction vector to orbital LSR space (S_orb): */
-  MatrixType satToOrbit;
-  ComputeSatToOrbRotation(satToOrbit, timeLine);
-
-  Vector3DType uOrb = satToOrbit*u_sat;
+  Vector3DType uOrb = ComputeSatToOrbRotation(timeLine) * u_sat;
   uOrb.Normalize();
 
   // 5. Transform orbital LSR space look direction vector to ECF.
@@ -601,8 +574,8 @@ void Spot5SensorModel::ImagingRay(const Point2DType& imPt, Ephemeris& imRay)  co
   Vector3DType uEcf  = (orbToEcfRotation*uOrb);
 
   /* Establish the imaging ray given direction and origin: */
-  imRay.position = ecfPos;
-  imRay.velocity = uEcf;
+  // Ephemeris.time , Ephemeris.position, Ephemeris.velocity
+  return {0, ecfPos, uEcf};
 }