// ____ ______ __ // / __ \ / ____// / // / /_/ // / / / // / ____// /___ / /___ PixInsight Class Library // /_/ \____//_____/ PCL 2.4.23 // ---------------------------------------------------------------------------- // pcl/GridInterpolation.h - Released 2022-03-12T18:59:29Z // ---------------------------------------------------------------------------- // This file is part of the PixInsight Class Library (PCL). // PCL is a multiplatform C++ framework for development of PixInsight modules. // // Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved. // // Redistribution and use in both source and binary forms, with or without // modification, is permitted provided that the following conditions are met: // // 1. All redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. All redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names // of their contributors, may be used to endorse or promote products derived // from this software without specific prior written permission. For written // permission, please contact info@pixinsight.com. // // 4. All products derived from this software, in any form whatsoever, must // reproduce the following acknowledgment in the end-user documentation // and/or other materials provided with the product: // // "This product is based on software from the PixInsight project, developed // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)." // // Alternatively, if that is where third-party acknowledgments normally // appear, this acknowledgment must be reproduced in the product itself. // // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE, // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // ---------------------------------------------------------------------------- #ifndef __PCL_GridInterpolation_h #define __PCL_GridInterpolation_h /// \file pcl/GridInterpolation.h #include #include #include #include #include #include #include #include #include #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION # include # include #endif namespace pcl { // ---------------------------------------------------------------------------- /*! * \class GridInterpolation * \brief Discretized scalar surface interpolation/approximation in two * dimensions. * * This class performs the same tasks as a surface interpolation device, such * as SurfaceSpline or ShepardInterpolation, but allows for much faster * interpolation with negligible accuracy loss in most applications. * * Interpolation from discrete grids can be orders of magnitude faster than * direct evaluation of surface interpolation/approximation devices, depending * on the number of input data points. */ class PCL_CLASS GridInterpolation : public ParallelProcess { public: /*! * Default constructor. Yields an empty instance that cannot be used without * initialization. */ GridInterpolation() = default; /*! * Copy constructor. */ GridInterpolation( const GridInterpolation& ) = default; /*! * Move constructor. */ GridInterpolation( GridInterpolation&& ) = default; /*! * Copy assignment operator. Returns a reference to this object. */ GridInterpolation& operator =( const GridInterpolation& ) = default; /*! * Move assignment operator. Returns a reference to this object. */ GridInterpolation& operator =( GridInterpolation&& ) = default; /*! * Initializes this %GridInterpolation object for the specified input data * and interpolation parameters. * * \param rect Reference rectangle. Interpolation will be initialized * within the boundaries of this rectangle at discrete * \a delta coordinate intervals. * * \param delta Grid distance for calculation of discrete function values. * Must be > 0. * * \param S Reference to a surface interpolation/approximation object * that will be used to evaluate function values at discrete * coordinate intervals. This object must have been * previously initialized and must be valid. * * \param verbose If true, this function will write information to the * standard PixInsight console to provide some feedback to * the user during the (potentially long) initialization * process. If false, no feedback will be provided. * * The template parameter SI must provide a member function of the form: * * double SI::operator ()( int x, int y ) const * * or an equivalent operator member function whose return value can be * statically casted to double, with two by-value parameters that can be * statically casted from the int type. This function will be called * multiple times to evaluate the approximated surface at discrete grid * coordinate pairs {x,y}. The implementation of this member function must * be thread-safe if parallel processing has been enabled and allowed for * this object. * * If parallel processing is allowed, this function executes the * initialization process using multiple concurrent threads. See * EnableParallelProcessing() for additional information. */ template void Initialize( const Rect& rect, int delta, const SI& S, bool verbose = true ) { PCL_PRECONDITION( rect.IsRect() ) PCL_PRECONDITION( delta > 0 ) m_rect = rect.Ordered(); if ( !m_rect.IsRect() ) throw Error( "GridInterpolation::Initialize(): Empty interpolation space." ); m_delta = Abs( delta ); if ( m_delta == 0 ) throw Error( "GridInterpolation::Initialize(): Zero grid distance." ); int w = rect.Width(); int h = rect.Height(); int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); m_G = DMatrix( rows, cols ); StatusMonitor monitor; #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION StandardStatus status; if ( verbose ) { monitor.SetCallback( &status ); monitor.Initialize( "Building surface interpolation grid", rows ); } #endif Array L = Thread::OptimalThreadLoads( rows, 1/*overheadLimit*/, m_parallel ? m_maxProcessors : 1 ); AbstractImage::ThreadData data( monitor, rows ); ReferenceArray > threads; for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) threads.Add( new GridInitializationThread( data, *this, S, n, n + int( L[i] ) ) ); AbstractImage::RunThreads( threads, data ); threads.Destroy(); m_I.Initialize( m_G.Begin(), cols, rows ); } /*! * Initializes this %GridInterpolation object with a prescribed discrete * interpolation matrix. * * \param rect Reference rectangle. Interpolation will be initialized * within the boundaries of this rectangle at discrete * \a delta coordinate intervals. * * \param delta Grid distance for calculation of discrete function values. * Must be > 0. * * \param G interpolation matrix. * * The specified \a G matrix must have \a n rows and \a m columns, which are * given by: * * n = 1 + Ceil( rect.Height()/delta )\n * m = 1 + Ceil( rect.Width()/delta ) * * If the dimensions of the specified matrix are different from the values * defined above, this function will throw an Error exception. * * Matrix elements must be function values computed at discrete \a delta * intervals within \a rect boundaries. For a given matrix row \a r and * matrix column \a c, the corresponding matrix element must be a function * value computed at coordinates {\a x,\a y} given by: * * x = rect.x0 + c*delta\n * y = rect.y0 + r*delta */ void Initialize( const Rect& rect, int delta, const DMatrix& G ) { PCL_PRECONDITION( rect.IsRect() ) PCL_PRECONDITION( delta > 0 ) m_rect = rect.Ordered(); if ( !m_rect.IsRect() ) throw Error( "GridInterpolation::Initialize(): Empty interpolation space." ); m_delta = Abs( delta ); if ( m_delta == 0 ) throw Error( "GridInterpolation::Initialize(): Zero grid distance." ); int w = rect.Width(); int h = rect.Height(); int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); if ( G.Rows() != rows || G.Cols() != cols ) throw Error( "GridInterpolation::Initialize(): Invalid matrix dimensions." ); m_G = G; m_I.Initialize( m_G.Begin(), cols, rows ); } /*! * Returns true iff this is a valid, initialized object ready for * interpolation. */ bool IsValid() const { return !m_G.IsEmpty(); } /*! * Deallocates internal structures, yielding an empty object that cannot be * used before a new call to Initialize(). */ void Clear() { m_I.Clear(); m_G.Clear(); } /*! * Returns the current interpolation reference rectangle. See Initialize() * for more information. */ const Rect& ReferenceRect() const { return m_rect; } /*! * Returns the current grid distance for calculation of discrete function * values. See Initialize() for more information. */ int Delta() const { return m_delta; } /*! * Returns a reference to the discrete matrix used for interpolation of * function values. * * If this object has not been initialized, this member function returns a * reference to an empty matrix. */ const DMatrix& InterpolationMatrix() const { return m_G; } /*! * Returns an interpolated function value at the specified coordinates. */ template double operator ()( T x, T y ) const { double fx = (double( x ) - m_rect.x0)/m_delta; double fy = (double( y ) - m_rect.y0)/m_delta; return m_I( fx, fy ); } /*! * Returns an interpolated function value at \a p.x and \a p.y coordinates. */ template double operator ()( const GenericPoint& p ) const { return operator ()( p.x, p.y ); } private: /*! * N.B.: Here we need a smooth interpolation function without negative * lobes, in order to prevent small-scale oscillations. Other options are * BilinearInterpolation and CubicBSplineFilter. */ typedef BicubicBSplineInterpolation grid_interpolation; Rect m_rect; int m_delta; DMatrix m_G; grid_interpolation m_I; template class GridInitializationThread : public Thread { public: GridInitializationThread( const AbstractImage::ThreadData& data, GridInterpolation& grid, const SI& surface, int startRow, int endRow ) : m_data( data ) , m_grid( grid ) , m_surface( surface ) , m_startRow( startRow ) , m_endRow( endRow ) { } PCL_HOT_FUNCTION void Run() override { INIT_THREAD_MONITOR() for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) { for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_G.Cols(); ++j, x += m_grid.m_delta ) m_grid.m_G[i][j] = m_surface( x, y ); UPDATE_THREAD_MONITOR( 32 ) } } private: const AbstractImage::ThreadData& m_data; GridInterpolation& m_grid; const SI& m_surface; int m_startRow, m_endRow; }; }; // ---------------------------------------------------------------------------- /*! * \class PointGridInterpolation * \brief Discretized vector surface interpolation/approximation in two * dimensions. * * This class performs the same tasks as a point surface interpolation device, * such as PointSurfaceSpline or PointShepardInterpolation, but allows for much * faster interpolation with negligible accuracy loss in most applications. * * Interpolation from discrete grids can be orders of magnitude faster than * direct evaluation of surface interpolation/approximation devices, depending * on the number of input data points. */ class PCL_CLASS PointGridInterpolation : public ParallelProcess { public: /*! * Default constructor. Yields an empty instance that cannot be used without * initialization. */ PointGridInterpolation() = default; /*! * Copy constructor. */ PointGridInterpolation( const PointGridInterpolation& ) = default; /*! * Move constructor. */ PointGridInterpolation( PointGridInterpolation&& ) = default; /*! * Copy assignment operator. Returns a reference to this object. */ PointGridInterpolation& operator =( const PointGridInterpolation& ) = default; /*! * Move assignment operator. Returns a reference to this object. */ PointGridInterpolation& operator =( PointGridInterpolation&& ) = default; /*! * Initializes a %PointGridInterpolation object with a point surface * interpolation/approximation. * * \param rect Reference rectangle. Interpolation will be initialized * within the boundaries of this rectangle at discrete * \a delta coordinate intervals. * * \param delta Grid distance for calculation of discrete function values. * Must be > 0. * * \param PS Reference to a point surface interpolation/approximation * object that will be used to evaluate function values at * discrete coordinate intervals. This object must have been * previously initialized and must be valid. * * \param verbose If true, this function will write information to the * standard PixInsight console to provide some feedback to * the user during the (potentially long) initialization * process. If false, no feedback will be provided. * * The template parameter PSI must provide a member function of the form: * * DPoint PSI::operator ()( int x, int y ) const * * or an equivalent operator member function whose return value can be * statically casted to DPoint, with two by-value parameters that can be * statically casted from the int type. This function will be called * multiple times to evaluate the approximated surface at discrete grid * coordinate pairs {x,y}. The implementation of this member function must * be thread-safe if parallel processing has been enabled and allowed for * this object. * * If parallel processing is allowed, this function executes the * initialization process using multiple concurrent threads. See * EnableParallelProcessing() for additional information. */ template void Initialize( const Rect& rect, int delta, const PSI& PS, bool verbose = true ) { PCL_PRECONDITION( rect.IsRect() ) PCL_PRECONDITION( delta > 0 ) m_rect = rect.Ordered(); if ( !m_rect.IsRect() ) throw Error( "PointGridInterpolation::Initialize(): Empty interpolation space." ); m_delta = Abs( delta ); if ( m_delta == 0 ) throw Error( "PointGridInterpolation::Initialize(): Zero grid distance." ); int w = rect.Width(); int h = rect.Height(); int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); m_Gx = DMatrix( rows, cols ); m_Gy = DMatrix( rows, cols ); StatusMonitor monitor; #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION StandardStatus status; if ( verbose ) { monitor.SetCallback( &status ); monitor.Initialize( "Building surface interpolation grid", rows ); } #endif Array L = Thread::OptimalThreadLoads( rows, 1/*overheadLimit*/, m_parallel ? m_maxProcessors : 1 ); AbstractImage::ThreadData data( monitor, rows ); ReferenceArray > threads; for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) threads.Add( new GridInitializationThread( data, *this, PS, n, n + int( L[i] ) ) ); AbstractImage::RunThreads( threads, data ); threads.Destroy(); m_Ix.Initialize( m_Gx.Begin(), cols, rows ); m_Iy.Initialize( m_Gy.Begin(), cols, rows ); } /*! * Initializes a %PointGridInterpolation object with separate surface * interpolations/approximations for the X and Y directions. * * \param rect Reference rectangle. Interpolation will be initialized * within the boundaries of this rectangle at discrete * \a delta coordinate intervals. * * \param delta Grid distance for calculation of discrete function values. * Must be > 0. * * \param Sx Reference to a surface interpolation/approximation object * that will be used to evaluate function values at discrete * coordinate intervals on the X axis. This object must have * been previously initialized and must be valid. * * \param Sy Reference to a surface interpolation/approximation object * that will be used to evaluate function values at discrete * coordinate intervals on the Y axis. This object must have * been previously initialized and must be valid. * * \param verbose If true, this function will write information to the * standard PixInsight console to provide some feedback to * the user during the (potentially long) initialization * process. If false, no feedback will be provided. * * The template parameter SI must provide a member function of the form: * * double SI::operator ()( int x, int y ) const * * or an equivalent operator member function whose return value can be * statically casted to double, with two by-value parameters that can be * statically casted from the int type. This function will be called * multiple times for the \a Sx and \a Sy objects to evaluate the * approximated surface at discrete grid coordinate pairs {x,y}, * respectively on the X and Y plane directions. The implementation of this * member function must be thread-safe if parallel processing has been * enabled and allowed for this object. * * If parallel processing is allowed, this function executes the * initialization process using multiple concurrent threads. See * EnableParallelProcessing() for additional information. */ template void Initialize( const Rect& rect, int delta, const SI& Sx, const SI& Sy, bool verbose = true ) { PCL_PRECONDITION( rect.IsRect() ) PCL_PRECONDITION( delta > 0 ) m_rect = rect.Ordered(); if ( !m_rect.IsRect() ) throw Error( "PointGridInterpolation::Initialize(): Empty interpolation space." ); m_delta = Abs( delta ); if ( m_delta == 0 ) throw Error( "PointGridInterpolation::Initialize(): Zero grid distance." ); int w = rect.Width(); int h = rect.Height(); int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); m_Gx = DMatrix( rows, cols ); m_Gy = DMatrix( rows, cols ); StatusMonitor monitor; #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION StandardStatus status; if ( verbose ) { monitor.SetCallback( &status ); monitor.Initialize( "Building surface interpolation grid", rows ); } #endif Array L = Thread::OptimalThreadLoads( rows, 1/*overheadLimit*/, m_parallel ? m_maxProcessors : 1 ); AbstractImage::ThreadData data( monitor, rows ); ReferenceArray > threads; for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) threads.Add( new GridInitializationXYThread( data, *this, Sx, Sy, n, n + int( L[i] ) ) ); AbstractImage::RunThreads( threads, data ); threads.Destroy(); m_Ix.Initialize( m_Gx.Begin(), cols, rows ); m_Iy.Initialize( m_Gy.Begin(), cols, rows ); } /*! * Initializes this %PointGridInterpolation object with prescribed * interpolation matrices. * * \param rect Reference rectangle. Interpolation will be initialized * within the boundaries of this rectangle at discrete * \a delta coordinate intervals. * * \param delta Grid distance for calculation of discrete function values. * Must be > 0. * * \param Gx interpolation matrix in the X direction. * * \param Gy Interpolation matrix in the Y direction. * * Both \a Gx and \a Gy matrices must have \a n rows and \a m columns, which * are given by: * * n = 1 + Ceil( rect.Height()/delta )\n * m = 1 + Ceil( rect.Width()/delta ) * * If one or both matrices have different dimensions, this function will * throw an Error exception. * * Matrix elements must be function values computed at discrete \a delta * intervals within \a rect boundaries. For a given matrix row \a r and * matrix column \a c, the corresponding matrix element must be a function * value computed at coordinates {\a x,\a y} given by: * * x = rect.x0 + c*delta\n * y = rect.y0 + r*delta */ void Initialize( const Rect& rect, int delta, const DMatrix& Gx, const DMatrix& Gy ) { PCL_PRECONDITION( rect.IsRect() ) PCL_PRECONDITION( delta > 0 ) m_rect = rect.Ordered(); if ( !m_rect.IsRect() ) throw Error( "PointGridInterpolation::Initialize(): Empty interpolation space." ); m_delta = Abs( delta ); if ( m_delta == 0 ) throw Error( "PointGridInterpolation::Initialize(): Zero grid distance." ); int w = rect.Width(); int h = rect.Height(); int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); if ( Gx.Rows() != rows || Gx.Cols() != cols || Gy.Rows() != rows || Gy.Cols() != cols ) throw Error( "PointGridInterpolation::Initialize(): Invalid matrix dimensions." ); m_Gx = Gx; m_Gy = Gy; m_Ix.Initialize( m_Gx.Begin(), cols, rows ); m_Iy.Initialize( m_Gy.Begin(), cols, rows ); } /*! * */ template void ApplyLocalModel( const PSI& PS, const String& message = "Applying local interpolation model", bool verbose = true ) { PCL_PRECONDITION( IsValid() ) if ( !IsValid() ) throw Error( "PointGridInterpolation::ApplyLocalModel(): Uninitialized interpolation." ); StatusMonitor monitor; #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION StandardStatus status; if ( verbose ) { monitor.SetCallback( &status ); monitor.Initialize( message, m_Gx.Rows() ); } #endif Array L = Thread::OptimalThreadLoads( m_Gx.Rows(), 1/*overheadLimit*/, m_parallel ? m_maxProcessors : 1 ); AbstractImage::ThreadData data( monitor, m_Gx.Rows() ); ReferenceArray > threads; for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) threads.Add( new LocalModelThread( data, *this, PS, n, n + int( L[i] ) ) ); AbstractImage::RunThreads( threads, data ); threads.Destroy(); } /*! * */ template void ApplyLocalModel( const SI& Sx, const SI& Sy, const String& message = "Applying local interpolation model", bool verbose = true ) { PCL_PRECONDITION( IsValid() ) if ( !IsValid() ) throw Error( "PointGridInterpolation::ApplyLocalModel(): Uninitialized interpolation." ); StatusMonitor monitor; #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION StandardStatus status; if ( verbose ) { monitor.SetCallback( &status ); monitor.Initialize( message, m_Gx.Rows() ); } #endif Array L = Thread::OptimalThreadLoads( m_Gx.Rows(), 1/*overheadLimit*/, m_parallel ? m_maxProcessors : 1 ); AbstractImage::ThreadData data( monitor, m_Gx.Rows() ); ReferenceArray > threads; for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) threads.Add( new LocalModelThread2( data, *this, Sx, Sy, n, n + int( L[i] ) ) ); AbstractImage::RunThreads( threads, data ); threads.Destroy(); } /*! * Returns true iff this is a valid, initialized object ready for * interpolation. */ bool IsValid() const { return !m_Gx.IsEmpty() && !m_Gy.IsEmpty(); } /*! * Deallocates internal structures, yielding an empty object that cannot be * used before a new call to Initialize(). */ void Clear() { m_Ix.Clear(); m_Iy.Clear(); m_Gx.Clear(); m_Gy.Clear(); } /*! * Returns the current interpolation reference rectangle. See Initialize() * for more information. * * The returned rectangle is ordered (see pcl::IsOrderedRect()). */ const Rect& ReferenceRect() const { return m_rect; } /*! * Returns the current grid distance for calculation of discrete function * values. See Initialize() for more information. */ int Delta() const { return m_delta; } /*! * Returns a reference to the discrete matrix used for interpolation of * function values in the X direction. * * If this object has not been initialized, this member function returns a * reference to an empty matrix. */ const DMatrix& XInterpolationMatrix() const { return m_Gx; } /*! * Returns a reference to the discrete matrix used for interpolation of * function values in the Y direction. * * If this object has not been initialized, this member function returns a * reference to an empty matrix. */ const DMatrix& YInterpolationMatrix() const { return m_Gy; } /*! * Returns an interpolated point at the specified coordinates. */ template DPoint operator ()( T x, T y ) const { PCL_PRECONDITION( IsValid() ) double fx = (double( x ) - m_rect.x0)/m_delta; double fy = (double( y ) - m_rect.y0)/m_delta; return DPoint( m_Ix( fx, fy ), m_Iy( fx, fy ) ); } /*! * Returns an interpolated point at the given \a p.x and \a p.y coordinates. */ template DPoint operator ()( const GenericPoint& p ) const { return operator ()( p.x, p.y ); } private: /*! * N.B.: Here we need a smooth interpolation function without negative * lobes, in order to prevent small-scale oscillations. Other options are * BilinearInterpolation and CubicBSplineFilter. */ typedef BicubicBSplineInterpolation grid_interpolation; Rect m_rect; int m_delta; DMatrix m_Gx, m_Gy; grid_interpolation m_Ix, m_Iy; template class GridInitializationThread : public Thread { public: GridInitializationThread( const AbstractImage::ThreadData& data, PointGridInterpolation& grid, const PSI& surface, int startRow, int endRow ) : m_data( data ) , m_grid( grid ) , m_surface( surface ) , m_startRow( startRow ) , m_endRow( endRow ) { } PCL_HOT_FUNCTION void Run() override { INIT_THREAD_MONITOR() for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) { for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) { DPoint p = m_surface( x, y ); m_grid.m_Gx[i][j] = p.x; m_grid.m_Gy[i][j] = p.y; } UPDATE_THREAD_MONITOR( 32 ) } } private: const AbstractImage::ThreadData& m_data; PointGridInterpolation& m_grid; const PSI& m_surface; int m_startRow, m_endRow; }; template class GridInitializationXYThread : public Thread { public: GridInitializationXYThread( const AbstractImage::ThreadData& data, PointGridInterpolation& grid, const SI& surfaceX, const SI& surfaceY, int startRow, int endRow ) : m_data( data ) , m_grid( grid ) , m_surfaceX( surfaceX ) , m_surfaceY( surfaceY ) , m_startRow( startRow ) , m_endRow( endRow ) { } PCL_HOT_FUNCTION void Run() override { INIT_THREAD_MONITOR() for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) { for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) { m_grid.m_Gx[i][j] = m_surfaceX( x, y ); m_grid.m_Gy[i][j] = m_surfaceY( x, y ); } UPDATE_THREAD_MONITOR( 32 ) } } private: const AbstractImage::ThreadData& m_data; PointGridInterpolation& m_grid; const SI& m_surfaceX; const SI& m_surfaceY; int m_startRow, m_endRow; }; template class LocalModelThread : public Thread { public: LocalModelThread( const AbstractImage::ThreadData& data, PointGridInterpolation& grid, const PSI& model, int startRow, int endRow ) : m_data( data ) , m_grid( grid ) , m_model( model ) , m_startRow( startRow ) , m_endRow( endRow ) { } PCL_HOT_FUNCTION void Run() override { INIT_THREAD_MONITOR() for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) { for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) { DPoint d = m_model( x, y ); m_grid.m_Gx[i][j] += d.x; m_grid.m_Gy[i][j] += d.y; } UPDATE_THREAD_MONITOR( 32 ) } } private: const AbstractImage::ThreadData& m_data; PointGridInterpolation& m_grid; const PSI& m_model; int m_startRow, m_endRow; }; template class LocalModelThread2 : public Thread { public: LocalModelThread2( const AbstractImage::ThreadData& data, PointGridInterpolation& grid, const SI& modelX, const SI& modelY, int startRow, int endRow ) : m_data( data ) , m_grid( grid ) , m_modelX( modelX ) , m_modelY( modelY ) , m_startRow( startRow ) , m_endRow( endRow ) { } PCL_HOT_FUNCTION void Run() override { INIT_THREAD_MONITOR() for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) { for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) { m_grid.m_Gx[i][j] += m_modelX( x, y ); m_grid.m_Gy[i][j] += m_modelY( x, y ); } UPDATE_THREAD_MONITOR( 32 ) } } private: const AbstractImage::ThreadData& m_data; PointGridInterpolation& m_grid; const SI& m_modelX, m_modelY; int m_startRow, m_endRow; }; }; // ---------------------------------------------------------------------------- } // pcl #endif // __PCL_GridInterpolation_h // ---------------------------------------------------------------------------- // EOF pcl/GridInterpolation.h - Released 2022-03-12T18:59:29Z