52 #ifndef __PCL_GridInterpolation_h
53 #define __PCL_GridInterpolation_h
58 #include <pcl/Diagnostics.h>
68 #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION
158 template <
class R,
class SI>
159 void Initialize(
const R& rect,
int delta,
const SI& S,
bool verbose =
true )
161 PCL_PRECONDITION( rect.IsRect() )
162 PCL_PRECONDITION( delta > 0 )
164 m_rect = rect.Ordered();
165 double width = m_rect.Width();
166 double height = m_rect.Height();
167 if ( !m_rect.IsRect() || 1 + width == 1 || 1 + height == 1 )
168 throw Error(
"GridInterpolation::Initialize(): Empty interpolation space." );
170 m_delta =
Abs( delta );
171 if ( 1 + m_delta == 1 )
172 throw Error(
"GridInterpolation::Initialize(): Zero or insignificant grid distance." );
174 int rows = 1 + int(
Ceil( height/m_delta ) );
175 int cols = 1 + int(
Ceil( width/m_delta ) );
179 #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION
184 monitor.
Initialize(
"Building surface interpolation grid", rows );
190 m_parallel ? m_maxProcessors : 1 );
193 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
194 threads.
Add(
new GridInitializationThread<SI>( data, *
this, S, n, n +
int( L[i] ) ) );
198 m_I.Initialize( m_G.Begin(), cols, rows );
234 PCL_PRECONDITION( rect.IsRect() )
235 PCL_PRECONDITION( delta > 0 )
237 m_rect =
DRect( rect.Ordered() );
238 double width = m_rect.Width();
239 double height = m_rect.Height();
240 if ( !m_rect.IsRect() || 1 + width == 1 || 1 + height == 1 )
241 throw Error(
"GridInterpolation::Initialize(): Empty interpolation space." );
243 m_delta =
Abs( delta );
244 if ( 1 + m_delta == 1 )
245 throw Error(
"GridInterpolation::Initialize(): Zero or insignificant grid distance." );
247 int rows = 1 + int(
Ceil( height/m_delta ) );
248 int cols = 1 + int(
Ceil( width/m_delta ) );
249 if ( G.Rows() != rows || G.Cols() != cols )
250 throw Error(
"GridInterpolation::Initialize(): Invalid matrix dimensions." );
253 m_I.Initialize( m_G.Begin(), cols, rows );
262 return !m_G.IsEmpty();
308 template <
typename T>
309 double operator ()( T x, T y )
const
311 double fx = (double( x ) - m_rect.x0)/m_delta;
312 double fy = (double( y ) - m_rect.y0)/m_delta;
313 return m_I( fx, fy );
319 template <
typename T>
322 return operator ()( p.
x, p.
y );
337 grid_interpolation m_I;
340 class GridInitializationThread :
public Thread
348 , m_surface( surface )
349 , m_startRow( startRow )
354 PCL_HOT_FUNCTION
void Run()
override
358 double y = m_grid.m_rect.y0 + m_startRow*m_grid.m_delta;
359 for (
int i = m_startRow; i < m_endRow; ++i, y += m_grid.m_delta )
361 double x = m_grid.m_rect.x0;
362 for (
int j = 0; j < m_grid.m_G.Cols(); ++j, x += m_grid.m_delta )
363 m_grid.m_G[i][j] = m_surface( x, y );
371 const AbstractImage::ThreadData& m_data;
372 GridInterpolation& m_grid;
374 int m_startRow, m_endRow;
460 template <
class R,
class PSI>
461 void Initialize(
const R& rect,
double delta,
const PSI& PS,
bool verbose =
true )
463 PCL_PRECONDITION( rect.IsRect() )
464 PCL_PRECONDITION( delta > 0 )
466 m_rect =
DRect( rect.Ordered() );
467 double width = m_rect.
Width();
468 double height = m_rect.
Height();
469 if ( !m_rect.
IsRect() || 1 + width == 1 || 1 + height == 1 )
470 throw Error(
"PointGridInterpolation::Initialize(): Empty interpolation space." );
472 m_delta =
Abs( delta );
473 if ( 1 + m_delta == 1 )
474 throw Error(
"PointGridInterpolation::Initialize(): Zero or insignificant grid distance." );
476 int rows = 1 + int(
Ceil( height/m_delta ) );
477 int cols = 1 + int(
Ceil( width/m_delta ) );
482 #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION
487 monitor.
Initialize(
"Building surface interpolation grid", rows );
493 m_parallel ? m_maxProcessors : 1 );
496 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
497 threads.
Add(
new GridInitializationThread<PSI>( data, *
this, PS, n, n +
int( L[i] ) ) );
501 m_Ix.Initialize( m_Gx.Begin(), cols, rows );
502 m_Iy.Initialize( m_Gy.Begin(), cols, rows );
548 template <
class R,
class SI>
549 void Initialize(
const R& rect,
double delta,
const SI& Sx,
const SI& Sy,
bool verbose =
true )
551 PCL_PRECONDITION( rect.IsRect() )
552 PCL_PRECONDITION( delta > 0 )
554 m_rect =
DRect( rect.Ordered() );
555 double width = m_rect.
Width();
556 double height = m_rect.
Height();
557 if ( !m_rect.
IsRect() || 1 + width == 1 || 1 + height == 1 )
558 throw Error(
"PointGridInterpolation::Initialize(): Empty interpolation space." );
560 m_delta =
Abs( delta );
561 if ( 1 + m_delta == 1 )
562 throw Error(
"PointGridInterpolation::Initialize(): Zero or insignificant grid distance." );
564 int rows = 1 + int(
Ceil( height/m_delta ) );
565 int cols = 1 + int(
Ceil( width/m_delta ) );
570 #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION
575 monitor.
Initialize(
"Building surface interpolation grid", rows );
581 m_parallel ? m_maxProcessors : 1 );
584 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
585 threads.
Add(
new GridInitializationXYThread<SI>( data, *
this, Sx, Sy, n, n +
int( L[i] ) ) );
589 m_Ix.Initialize( m_Gx.Begin(), cols, rows );
590 m_Iy.Initialize( m_Gy.Begin(), cols, rows );
628 PCL_PRECONDITION( rect.IsRect() )
629 PCL_PRECONDITION( delta > 0 )
631 m_rect =
DRect( rect.Ordered() );
632 double width = m_rect.
Width();
633 double height = m_rect.
Height();
634 if ( !m_rect.
IsRect() || 1 + width == 1 || 1 + height == 1 )
635 throw Error(
"PointGridInterpolation::Initialize(): Empty interpolation region." );
637 m_delta =
Abs( delta );
638 if ( 1 + m_delta == 1 )
639 throw Error(
"PointGridInterpolation::Initialize(): Zero or insignificant grid distance." );
641 int rows = 1 + int(
Ceil( height/m_delta ) );
642 int cols = 1 + int(
Ceil( width/m_delta ) );
643 if ( Gx.
Rows() != rows || Gx.
Cols() != cols || Gy.
Rows() != rows || Gy.
Cols() != cols )
644 throw Error(
"PointGridInterpolation::Initialize(): Invalid matrix dimensions." );
648 m_Ix.Initialize( m_Gx.Begin(), cols, rows );
649 m_Iy.Initialize( m_Gy.Begin(), cols, rows );
656 void ApplyLocalModel(
const PSI& PS,
657 const String& message =
"Applying local interpolation model",
658 bool verbose =
true )
660 PCL_PRECONDITION( IsValid() )
665 #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION
676 m_parallel ? m_maxProcessors : 1 );
677 AbstractImage::ThreadData data( monitor, m_Gx.Rows() );
678 ReferenceArray<LocalModelThread<PSI> > threads;
679 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
680 threads.Add(
new LocalModelThread<PSI>( data, *
this, PS, n, n +
int( L[i] ) ) );
689 void ApplyLocalModel(
const SI& Sx,
const SI& Sy,
690 const String& message =
"Applying local interpolation model",
691 bool verbose =
true )
693 PCL_PRECONDITION( IsValid() )
695 throw Error( "PointGridInterpolation::ApplyLocalModel(): Uninitialized interpolation." );
697 StatusMonitor monitor;
698 #ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION
699 StandardStatus status;
702 monitor.SetCallback( &status );
703 monitor.Initialize( message, m_Gx.Rows() );
709 m_parallel ? m_maxProcessors : 1 );
710 AbstractImage::ThreadData data( monitor, m_Gx.Rows() );
711 ReferenceArray<LocalModelThread2<SI> > threads;
712 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
713 threads.Add(
new LocalModelThread2<SI>( data, *
this, Sx, Sy, n, n +
int( L[i] ) ) );
724 return !m_Gx.IsEmpty() && !m_Gy.IsEmpty();
786 template <
typename T>
789 PCL_PRECONDITION( IsValid() )
790 double fx = (double( x ) - m_rect.
x0)/m_delta;
791 double fy = (double( y ) - m_rect.
y0)/m_delta;
792 return DPoint( m_Ix( fx, fy ), m_Iy( fx, fy ) );
798 template <
typename T>
801 return operator ()( p.
x, p.
y );
816 grid_interpolation m_Ix, m_Iy;
819 class GridInitializationThread :
public Thread
827 , m_surface( surface )
828 , m_startRow( startRow )
833 PCL_HOT_FUNCTION
void Run()
override
837 double y = m_grid.m_rect.y0 + m_startRow*m_grid.m_delta;
838 for (
int i = m_startRow; i < m_endRow; ++i, y += m_grid.m_delta )
840 double x = m_grid.m_rect.x0;
841 for (
int j = 0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta )
843 DPoint p = m_surface( x, y );
844 m_grid.m_Gx[i][j] = p.x;
845 m_grid.m_Gy[i][j] = p.y;
854 const AbstractImage::ThreadData& m_data;
855 PointGridInterpolation& m_grid;
856 const PSI& m_surface;
857 int m_startRow, m_endRow;
861 class GridInitializationXYThread :
public Thread
865 GridInitializationXYThread(
const AbstractImage::ThreadData& data,
866 PointGridInterpolation& grid,
867 const SI& surfaceX,
const SI& surfaceY,
int startRow,
int endRow )
870 , m_surfaceX( surfaceX )
871 , m_surfaceY( surfaceY )
872 , m_startRow( startRow )
877 PCL_HOT_FUNCTION
void Run()
override
881 double y = m_grid.m_rect.y0 + m_startRow*m_grid.m_delta;
882 for (
int i = m_startRow; i < m_endRow; ++i, y += m_grid.m_delta )
884 double x = m_grid.m_rect.x0;
885 for (
int j = 0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta )
887 m_grid.m_Gx[i][j] = m_surfaceX( x, y );
888 m_grid.m_Gy[i][j] = m_surfaceY( x, y );
897 const AbstractImage::ThreadData& m_data;
898 PointGridInterpolation& m_grid;
899 const SI& m_surfaceX;
900 const SI& m_surfaceY;
901 int m_startRow, m_endRow;
905 class LocalModelThread :
public Thread
909 LocalModelThread(
const AbstractImage::ThreadData& data,
910 PointGridInterpolation& grid,
const PSI& model,
int startRow,
int endRow )
914 , m_startRow( startRow )
919 PCL_HOT_FUNCTION
void Run()
override
923 double y = m_grid.m_rect.y0 + m_startRow*m_grid.m_delta;
924 for (
int i = m_startRow; i < m_endRow; ++i, y += m_grid.m_delta )
926 double x = m_grid.m_rect.x0;
927 for (
int j = 0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta )
929 DPoint d = m_model( x, y );
930 m_grid.m_Gx[i][j] += d.x;
931 m_grid.m_Gy[i][j] += d.y;
940 const AbstractImage::ThreadData& m_data;
941 PointGridInterpolation& m_grid;
943 int m_startRow, m_endRow;
947 class LocalModelThread2 :
public Thread
951 LocalModelThread2(
const AbstractImage::ThreadData& data,
952 PointGridInterpolation& grid,
const SI& modelX,
const SI& modelY,
int startRow,
int endRow )
957 , m_startRow( startRow )
962 PCL_HOT_FUNCTION
void Run()
override
966 double y = m_grid.m_rect.y0 + m_startRow*m_grid.m_delta;
967 for (
int i = m_startRow; i < m_endRow; ++i, y += m_grid.m_delta )
969 double x = m_grid.m_rect.x0;
970 for (
int j = 0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta )
972 m_grid.m_Gx[i][j] += m_modelX( x, y );
973 m_grid.m_Gy[i][j] += m_modelY( x, y );
982 const AbstractImage::ThreadData& m_data;
983 PointGridInterpolation& m_grid;
984 const SI& m_modelX, m_modelY;
985 int m_startRow, m_endRow;
988 friend class SplineWorldTransformation;
static void RunThreads(ReferenceArray< thread > &threads, ThreadData &data, bool useAffinity=true)
64-bit floating-point point in the R^2 space.
A simple exception with an associated error message.
Generic dynamic matrix of arbitrary dimensions.
int Cols() const noexcept
int Rows() const noexcept
A generic point in the two-dimensional space.
component x
Abscissa (horizontal, or X-axis coordinate).
component y
Ordinate (vertical, or Y-axis coordinate).
A generic rectangle in the two-dimensional space.
bool IsRect() const noexcept
component y0
Vertical coordinate of the upper left corner.
component x0
Horizontal coordinate of the upper left corner.
component Width() const noexcept
component Height() const noexcept
Discretized scalar surface interpolation/approximation in two dimensions.
GridInterpolation(GridInterpolation &&)=default
void Initialize(const R &rect, double delta, const DMatrix &G)
GridInterpolation(const GridInterpolation &)=default
const DMatrix & InterpolationMatrix() const
const DRect & ReferenceRect() const
GridInterpolation()=default
void Initialize(const R &rect, int delta, const SI &S, bool verbose=true)
A process using multiple concurrent execution threads.
Discretized vector surface interpolation/approximation in two dimensions.
void Initialize(const R &rect, double delta, const SI &Sx, const SI &Sy, bool verbose=true)
const DMatrix & XInterpolationMatrix() const
void Initialize(const R &rect, double delta, const PSI &PS, bool verbose=true)
PointGridInterpolation(const PointGridInterpolation &)=default
const DMatrix & YInterpolationMatrix() const
PointGridInterpolation()=default
void Initialize(const R &rect, int delta, const DMatrix &Gx, const DMatrix &Gy)
PointGridInterpolation(PointGridInterpolation &&)=default
const DRect & ReferenceRect() const
Dynamic array of pointers to objects providing direct iteration and element access by reference.
void Destroy(iterator i, size_type n=1)
void Add(const ReferenceArray &x)
A status monitoring callback that sends progress information to the process console.
An asynchronous status monitoring system.
void SetCallback(StatusCallback *callback)
void Initialize(const String &info, size_type count=0)
Client-side interface to a PixInsight thread.
static Array< size_type > OptimalThreadLoads(size_type count, size_type overheadLimit=1u, int maxThreads=PCL_MAX_PROCESSORS)
T Abs(const Complex< T > &c) noexcept
constexpr T Ceil(T x) noexcept
#define INIT_THREAD_MONITOR()
Declares and initializes local variables used for synchronization of thread status monitoring.
#define UPDATE_THREAD_MONITOR(N)
Synchronized status monitoring of a set of image processing threads.
Thread synchronization data for status monitoring of parallel image processing tasks.