PCL
Rectangle.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.6.5
6 // ----------------------------------------------------------------------------
7 // pcl/Rectangle.h - Released 2024-01-13T15:47:58Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_Rectangle_h
53 #define __PCL_Rectangle_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/Flags.h>
60 #include <pcl/Math.h>
61 #include <pcl/Point.h>
62 #include <pcl/Relational.h>
63 
64 #ifdef __PCL_QT_INTERFACE
65 # include <QtCore/QRect>
66 # ifndef __PCL_QT_NO_RECT_DRAWING_HELPERS
67 # include <QtGui/QPainter>
68 # include <QtGui/QBrush>
69 # endif
70 #endif
71 
72 namespace pcl
73 {
74 
75 // ----------------------------------------------------------------------------
76 
90 namespace Clip
91 {
92  enum mask_type
93  {
94  Left = 0x01, // Clipped at the left side
95  Top = 0x02, // Clipped at the top side
96  Right = 0x04, // Clipped at the right side
97  Bottom = 0x08 // Clipped at the bottom side
98  };
99 }
100 
105 
106 // ----------------------------------------------------------------------------
107 
123 template <typename T> inline
124 bool IsPoint( T x0, T y0, T x1, T y1 ) noexcept
125 {
126  return x0 == x1 && y0 == y1;
127 }
128 
141 template <typename T> inline
142 bool IsLine( T x0, T y0, T x1, T y1 ) noexcept
143 {
144  return ((x0 == x1) ^ (y0 == y1)) != 0;
145 }
146 
158 template <typename T> inline
159 bool IsHorizontalLine( T x0, T y0, T x1, T y1 ) noexcept
160 {
161  return y0 == y1 && x0 != x1;
162 }
163 
175 template <typename T> inline
176 bool IsVerticalLine( T x0, T y0, T x1, T y1 ) noexcept
177 {
178  return x0 == x1 && y0 != y1;
179 }
180 
192 template <typename T> inline
193 bool IsPointOrLine( T x0, T y0, T x1, T y1 ) noexcept
194 {
195  return x0 == x1 || y0 == y1;
196 }
197 
209 template <typename T> inline
210 bool IsRect( T x0, T y0, T x1, T y1 ) noexcept
211 {
212  return x0 != x1 && y0 != y1;
213 }
214 
225 template <typename T> inline
226 bool IsNormalRect( T x0, T y0, T x1, T y1 ) noexcept
227 {
228  return x0 < x1 && y0 < y1;
229 }
230 
242 template <typename T> inline
243 bool IsOrderedRect( T x0, T y0, T x1, T y1 ) noexcept
244 {
245  return x0 <= x1 && y0 <= y1;
246 }
247 
259 template <typename T> inline
260 void OrderRect( T& x0, T& y0, T& x1, T& y1 ) noexcept
261 {
262  if ( x1 < x0 )
263  pcl::Swap( x0, x1 );
264  if ( y1 < y0 )
265  pcl::Swap( y0, y1 );
266 }
267 
268 // ----------------------------------------------------------------------------
269 
270 /*
271  * ### NB: Template class GenericRectangle cannot have virtual member
272  * functions. This is because internal PCL and core routines rely on
273  * GenericRectangle<int>, GenericRectangle<float> and
274  * GenericRectangle<double> to be directly castable to int*, float* and
275  * double*, respectively. See also the PCL_ASSERT_RECT_SIZE() macro.
276  */
277 
278 #define PCL_ASSERT_RECT_SIZE() \
279  static_assert( sizeof( *this ) == 4*sizeof( T ), "Invalid sizeof( GenericRectangle<> )" )
280 
312 template <typename T>
313 class PCL_CLASS GenericRectangle
314 {
315 public:
316 
320  using component = T;
321 
326 
327  /*
328  * Rectangle coordinates: x0=left, y0=top, x1=right, y1=bottom.
329  * The x1 (right) and y1 (bottom) coordinates are excluded from the
330  * rectangular area, so we always have: width=x1-x0 and height=y1-y0.
331  */
336 
341  constexpr GenericRectangle()
342  {
343  PCL_ASSERT_RECT_SIZE();
344  }
345 
356  template <typename T1>
357  constexpr GenericRectangle( T1 left, T1 top, T1 right, T1 bottom )
358  : x0( component( left ) )
359  , y0( component( top ) )
360  , x1( component( right ) )
361  , y1( component( bottom ) )
362  {
363  PCL_ASSERT_RECT_SIZE();
364  }
365 
391  template <typename T1>
392  GenericRectangle( std::initializer_list<T1> l )
393  {
394  PCL_ASSERT_RECT_SIZE();
395  switch ( l.size() )
396  {
397  default:
398  case 4: y1 = component( l.begin()[3] );
399  case 3: x1 = component( l.begin()[2] );
400  case 2: y0 = component( l.begin()[1] );
401  case 1: x0 = component( l.begin()[0] );
402  case 0: break;
403  }
404  switch ( l.size() )
405  {
406  case 0: x0 = component( 0 );
407  case 1: y0 = component( 0 );
408  case 2: x1 = component( 0 );
409  case 3: y1 = component( 0 );
410  default:
411  case 4: break;
412  }
413  }
414 
424  template <typename T1>
425  GenericRectangle( const pcl::GenericPoint<T1>& leftTop, const pcl::GenericPoint<T1>& rightBottom )
426  : GenericRectangle( component( leftTop.x ), component( leftTop.y ),
427  component( rightBottom.x ), component( rightBottom.y ) )
428  {
429  PCL_ASSERT_RECT_SIZE();
430  }
431 
440  constexpr GenericRectangle( component width, component height )
441  : GenericRectangle( component( 0 ), component( 0 ), width, height )
442  {
443  PCL_ASSERT_RECT_SIZE();
444  }
445 
454  : GenericRectangle( d, d, d, d )
455  {
456  PCL_ASSERT_RECT_SIZE();
457  }
458 
463  template <typename T1>
465  : GenericRectangle( component( r.x0 ), component( r.y0 ),
466  component( r.x1 ), component( r.y1 ) )
467  {
468  PCL_ASSERT_RECT_SIZE();
469  }
470 
471 #ifdef __PCL_QT_INTERFACE
472  GenericRectangle( const QRect& r )
473  : GenericRectangle( component( r.left() ), component( r.top() ),
474  component( r.right()+1 ), component( r.bottom()+1 ) )
475  {
476  PCL_ASSERT_RECT_SIZE();
477  }
478 
479  GenericRectangle( const QPoint& p0, const QPoint& p1 )
480  : GenericRectangle( component( p0.x() ), component( p0.y() ),
481  component( p1.x() ), component( p1.y() ) )
482  {
483  PCL_ASSERT_RECT_SIZE();
484  }
485 #endif
486 
491  component Left() const noexcept
492  {
493  return x0;
494  }
495 
500  component Top() const noexcept
501  {
502  return y0;
503  }
504 
509  component Right() const noexcept
510  {
511  return x1;
512  }
513 
518  component Bottom() const noexcept
519  {
520  return y1;
521  }
522 
527  point LeftTop() const noexcept
528  {
529  return point( pcl::Min( x0, x1 ), pcl::Min( y0, y1 ) );
530  }
531 
535  point TopLeft() const noexcept
536  {
537  return LeftTop();
538  }
539 
544  point RightTop() const noexcept
545  {
546  return point( pcl::Max( x0, x1 ), pcl::Min( y0, y1 ) );
547  }
548 
552  point TopRight() const noexcept
553  {
554  return RightTop();
555  }
556 
561  point LeftBottom() const noexcept
562  {
563  return point( pcl::Min( x0, x1 ), pcl::Max( y0, y1 ) );
564  }
565 
569  point BottomLeft() const noexcept
570  {
571  return LeftBottom();
572  }
573 
578  point RightBottom() const noexcept
579  {
580  return point( pcl::Max( x0, x1 ), pcl::Max( y0, y1 ) );
581  }
582 
586  point BottomRight() const noexcept
587  {
588  return RightBottom();
589  }
590 
594  point Center() const noexcept
595  {
596  return point( (x0 + x1)/2, (y0 + y1)/2 );
597  }
598 
602  point CenterTop() const noexcept
603  {
604  return point( (x0 + x1)/2, pcl::Min( y0, y1 ) );
605  }
606 
610  point CenterBottom() const noexcept
611  {
612  return point( (x0 + x1)/2, pcl::Min( y0, y1 ) );
613  }
614 
618  point CenterLeft() const noexcept
619  {
620  return point( pcl::Min( x0, x1 ), (y0 + y1)/2 );
621  }
622 
626  point CenterRight() const noexcept
627  {
628  return point( pcl::Min( x0, x1 ), (y0 + y1)/2 );
629  }
630 
635  component Width() const noexcept
636  {
637  return pcl::Abs( x1 - x0 );
638  }
639 
644  component Height() const noexcept
645  {
646  return pcl::Abs( y1 - y0 );
647  }
648 
653  component Perimeter() const noexcept
654  {
655  component w = Width(), h = Height();
656  return w+w+h+h;
657  }
658 
665  component ManhattanDistance() const noexcept
666  {
667  return Width() + Height();
668  }
669 
674  component Area() const noexcept
675  {
676  return pcl::Abs( (x1 - x0)*(y1 - y0) );
677  }
678 
683  double CenterX() const noexcept
684  {
685  return 0.5*(x0 + x1);
686  }
687 
692  double CenterY() const noexcept
693  {
694  return 0.5*(y0 + y1);
695  }
696 
703  double Hypot() const noexcept
704  {
705  double w = x1 - x0, h = y1 - y0;
706  return w*w + h*h;
707  }
708 
713  double Diagonal() const noexcept
714  {
715  return pcl::Sqrt( Hypot() );
716  }
717 
721  bool IsPoint() const noexcept
722  {
723  return pcl::IsPoint( x0, y0, x1, y1 );
724  }
725 
729  bool IsLine() const noexcept
730  {
731  return pcl::IsLine( x0, y0, x1, y1 );
732  }
733 
737  bool IsHorizontalLine() const noexcept
738  {
739  return pcl::IsHorizontalLine( x0, y0, x1, y1 );
740  }
741 
745  bool IsVerticalLine() const noexcept
746  {
747  return pcl::IsVerticalLine( x0, y0, x1, y1 );
748  }
749 
753  bool IsPointOrLine() const noexcept
754  {
755  return pcl::IsPointOrLine( x0, y0, x1, y1 );
756  }
757 
762  bool IsRect() const noexcept
763  {
764  return pcl::IsRect( x0, y0, x1, y1 );
765  }
766 
770  bool IsNormal() const noexcept
771  {
772  return pcl::IsNormalRect( x0, y0, x1, y1 );
773  }
774 
778  bool IsOrdered() const noexcept
779  {
780  return pcl::IsOrderedRect( x0, y0, x1, y1 );
781  }
782 
786  void Order() noexcept
787  {
788  pcl::OrderRect( x0, y0, x1, y1 );
789  }
790 
794  GenericRectangle Ordered() const noexcept
795  {
796  GenericRectangle r = *this;
797  r.Order();
798  return r;
799  }
800 
809  template <typename T1>
810  ClipFlags ClipCode( T1 x, T1 y ) const noexcept
811  {
812  ClipFlags clip; // defaults to zero
813 
814  if ( x0 <= x1 )
815  {
816  if ( x < x0 ) clip |= Clip::Left;
817  if ( x > x1 ) clip |= Clip::Right;
818  }
819  else
820  {
821  if ( x < x1 ) clip |= Clip::Left;
822  if ( x > x0 ) clip |= Clip::Right;
823  }
824 
825  if ( y0 <= y1 )
826  {
827  if ( y < y0 ) clip |= Clip::Top;
828  if ( y > y1 ) clip |= Clip::Bottom;
829  }
830  else
831  {
832  if ( y < y1 ) clip |= Clip::Top;
833  if ( y > y0 ) clip |= Clip::Bottom;
834  }
835 
836  return clip;
837  }
838 
846  template <typename T1>
847  ClipFlags ClipCode( const pcl::GenericPoint<T1>& p ) const noexcept
848  {
849  return ClipCode( p.x, p.y );
850  }
851 
856  template <typename T1>
857  bool Includes( T1 x, T1 y ) const noexcept
858  {
859  return ((x0 < x1) ? (x >= x0 && x <= x1) : (x >= x1 && x <= x0)) &&
860  ((y0 < y1) ? (y >= y0 && y <= y1) : (y >= y1 && y <= y0));
861  }
862 
866  template <typename T1>
867  bool Includes( const pcl::GenericPoint<T1>& p ) const noexcept
868  {
869  return Includes( p.x, p.y );
870  }
871 
875  template <typename T1>
876  bool Includes( const GenericRectangle<T1>& r ) const noexcept
877  {
878  return Includes( r.x0, r.y0 ) && Includes( r.x1, r.y1 );
879  }
880 
881 #ifdef __PCL_QT_INTERFACE
882  bool Includes( const QPoint& p ) const noexcept
883  {
884  return Includes( p.x(), p.y() );
885  }
886 
887  bool Includes( const QRect& r ) const noexcept
888  {
889  return Includes( r.left(), r.top() ) && Includes( r.right()+1, r.bottom()+1 );
890  }
891 #endif
892 
901  template <typename T1>
902  bool IncludesFast( T1 x, T1 y ) const noexcept
903  {
904  return x >= x0 && y >= y0 && x <= x1 && y <= y1;
905  }
906 
914  template <typename T1>
915  bool IncludesFast( const pcl::GenericPoint<T1>& p ) const noexcept
916  {
917  return IncludesFast( p.x, p.y );
918  }
919 
930  template <typename T1>
931  bool Intersects( T1 left, T1 top, T1 right, T1 bottom ) const noexcept
932  {
933  OrderRect( left, top, right, bottom );
934  return ((x0 < x1) ? (right >= x0 && left <= x1) : (right >= x1 && left <= x0)) &&
935  ((y0 < y1) ? (bottom >= y0 && top <= y1) : (bottom >= y1 && top <= y0));
936  }
937 
941  template <typename T1>
942  bool Intersects( const pcl::GenericRectangle<T1>& r ) const noexcept
943  {
944  return Intersects( r.x0, r.y0, r.x1, r.y1 );
945  }
946 
947 #ifdef __PCL_QT_INTERFACE
948  bool Intersects( const QRect& r ) const noexcept
949  {
950  return Intersects( r.left(), r.top(), r.right()+1, r.bottom()+1 );
951  }
952 #endif
953 
973  template <typename T1>
974  bool IntersectsFast( T1 left, T1 top, T1 right, T1 bottom ) const noexcept
975  {
976  return right >= x0 && left <= x1 && bottom >= y0 && top <= y1;
977  }
978 
985  template <typename T1>
986  bool IntersectsFast( const pcl::GenericRectangle<T1>& r ) const noexcept
987  {
988  return IntersectsFast( r.x0, r.y0, r.x1, r.y1 );
989  }
990 
995  template <typename T1>
996  void Unite( const GenericRectangle<T1>& r ) noexcept
997  {
998  Unite( r.x0, r.y0, r.x1, r.y1 );
999  }
1000 
1011  template <typename T1>
1012  void Unite( T1 left, T1 top, T1 right, T1 bottom ) noexcept
1013  {
1014  if ( right < left )
1015  Swap( left, right );
1016  if ( bottom < top )
1017  Swap( top, bottom );
1018 
1019  if ( x0 <= x1 )
1020  {
1021  x0 = pcl::Min( x0, component( left ) );
1022  x1 = pcl::Max( x1, component( right ) );
1023  }
1024  else
1025  {
1026  x0 = pcl::Max( x0, component( right ) );
1027  x1 = pcl::Min( x1, component( left ) );
1028  }
1029 
1030  if ( y0 <= y1 )
1031  {
1032  y0 = pcl::Min( y0, component( top ) );
1033  y1 = pcl::Max( y1, component( bottom ) );
1034  }
1035  else
1036  {
1037  y0 = pcl::Max( y0, component( bottom ) );
1038  y1 = pcl::Min( y1, component( top ) );
1039  }
1040  }
1041 
1049  template <typename T1>
1050  void UniteFast( const GenericRectangle<T1>& r ) noexcept
1051  {
1052  UniteFast( r.x0, r.y0, r.x1, r.y1 );
1053  }
1054 
1074  template <typename T1>
1075  void UniteFast( T1 left, T1 top, T1 right, T1 bottom ) noexcept
1076  {
1077  x0 = pcl::Min( x0, component( left ) );
1078  y0 = pcl::Min( y0, component( top ) );
1079  x1 = pcl::Max( x1, component( right ) );
1080  y1 = pcl::Max( y1, component( bottom ) );
1081  }
1082 
1086  template <typename T1>
1087  GenericRectangle Union( const GenericRectangle<T1>& r ) const noexcept
1088  {
1089  GenericRectangle r1 = *this;
1090  r1.Unite( r );
1091  return r1;
1092  }
1093 
1100  template <typename T1>
1102  {
1103  GenericRectangle r1 = *this;
1104  r1.UniteFast( r );
1105  return r1;
1106  }
1107 
1112  template <typename T1>
1113  GenericRectangle& operator |=( const GenericRectangle<T1>& r ) noexcept
1114  {
1115  Unite( r );
1116  return *this;
1117  }
1118 
1119 #ifdef __PCL_QT_INTERFACE
1120  void Unite( const QRect& r )
1121  {
1122  Unite( r.left(), r.top(), r.right()+1, r.bottom()+1 );
1123  }
1124 
1125  GenericRectangle Union( const QRect& r ) const noexcept
1126  {
1127  GenericRectangle r1 = *this;
1128  r1.Unite( r );
1129  return r1;
1130  }
1131 
1132  GenericRectangle& operator |=( const QRect& r ) noexcept
1133  {
1134  Unite( r );
1135  return *this;
1136  }
1137 #endif
1138 
1147  template <typename T1>
1148  bool Intersect( const GenericRectangle<T1>& r ) noexcept
1149  {
1150  return Intersect( r.x0, r.y0, r.x1, r.y1 );
1151  }
1152 
1167  template <typename T1>
1168  bool Intersect( T1 left, T1 top, T1 right, T1 bottom ) noexcept
1169  {
1170  if ( right < left )
1171  Swap( left, right );
1172  if ( bottom < top )
1173  Swap( top, bottom );
1174 
1175  if ( x0 <= x1 )
1176  {
1177  x0 = pcl::Max( x0, component( left ) );
1178  x1 = pcl::Min( x1, component( right ) );
1179  }
1180  else
1181  {
1182  x0 = pcl::Min( x0, component( right ) );
1183  x1 = pcl::Max( x1, component( left ) );
1184  }
1185 
1186  if ( y0 <= y1 )
1187  {
1188  y0 = pcl::Max( y0, component( top ) );
1189  y1 = pcl::Min( y1, component( bottom ) );
1190  }
1191  else
1192  {
1193  y0 = pcl::Min( y0, component( bottom ) );
1194  y1 = pcl::Max( y1, component( top ) );
1195  }
1196 
1197  return IsRect();
1198  }
1199 
1211  template <typename T1>
1212  bool IntersectFast( const GenericRectangle<T1>& r ) noexcept
1213  {
1214  return IntersectFast( r.x0, r.y0, r.x1, r.y1 );
1215  }
1216 
1240  template <typename T1>
1241  bool IntersectFast( T1 left, T1 top, T1 right, T1 bottom ) noexcept
1242  {
1243  x0 = pcl::Max( x0, component( left ) );
1244  y0 = pcl::Max( y0, component( top ) );
1245  x1 = pcl::Min( x1, component( right ) );
1246  y1 = pcl::Min( y1, component( bottom ) );
1247  return IsRect();
1248  }
1249 
1254  template <typename T1>
1256  {
1257  GenericRectangle r1 = *this;
1258  (void)r1.Intersect( r );
1259  return r1;
1260  }
1261 
1269  template <typename T1>
1271  {
1272  GenericRectangle r1 = *this;
1273  (void)r1.IntersectFast( r );
1274  return r1;
1275  }
1276 
1281  template <typename T1>
1282  GenericRectangle& operator &=( const GenericRectangle<T1>& r ) noexcept
1283  {
1284  Intersect( r );
1285  return *this;
1286  }
1287 
1288 #ifdef __PCL_QT_INTERFACE
1289  bool Intersect( const QRect& r ) noexcept
1290  {
1291  return Intersect( r.left(), r.top(), r.right()+1, r.bottom()+1 );
1292  }
1293 
1294  GenericRectangle Intersection( const QRect& r ) const noexcept
1295  {
1296  GenericRectangle r1 = *this;
1297  (void)r1.Intersect( r );
1298  return r1;
1299  }
1300 
1301  GenericRectangle& operator &=( const QRect& r ) noexcept
1302  {
1303  Intersect( r );
1304  return *this;
1305  }
1306 #endif
1307 
1314  template <typename T1>
1315  void Set( T1 left, T1 top, T1 right, T1 bottom ) noexcept
1316  {
1317  x0 = component( left );
1318  y0 = component( top );
1319  x1 = component( right );
1320  y1 = component( bottom );
1321  }
1322 
1330  template <typename T1>
1331  void MoveTo( const pcl::GenericPoint<T1>& p ) noexcept
1332  {
1333  MoveTo( p.x, p.y );
1334  }
1335 
1343  template <typename T1>
1344  void MoveTo( T1 x, T1 y ) noexcept
1345  {
1346  component dx = x1 - x0, dy = y1 - y0;
1347  x0 = component( x );
1348  y0 = component( y );
1349  x1 = x0 + dx;
1350  y1 = y0 + dy;
1351  }
1352 
1353 #ifdef __PCL_QT_INTERFACE
1354  void MoveTo( const QPoint& p ) noexcept
1355  {
1356  MoveTo( p.x(), p.y() );
1357  }
1358 #endif
1359 
1366  template <typename T1>
1368  {
1369  GenericRectangle r( *this );
1370  r.MoveTo( p );
1371  return r;
1372  }
1373 
1380  template <typename T1>
1381  GenericRectangle MovedTo( T1 x, T1 y ) const noexcept
1382  {
1383  GenericRectangle r( *this );
1384  r.MoveTo( x, y );
1385  return r;
1386  }
1387 
1392  template <typename T1>
1393  void MoveBy( const pcl::GenericPoint<T1>& d ) noexcept
1394  {
1395  MoveBy( d.x, d.y );
1396  }
1397 
1403  template <typename T1>
1404  void MoveBy( T1 dx, T1 dy ) noexcept
1405  {
1406  x0 += component( dx );
1407  y0 += component( dy );
1408  x1 += component( dx );
1409  y1 += component( dy );
1410  }
1411 
1421  template <typename T1>
1422  void MoveBy( T1 dxy ) noexcept
1423  {
1424  x0 += component( dxy );
1425  y0 += component( dxy );
1426  x1 += component( dxy );
1427  y1 += component( dxy );
1428  }
1429 
1430 #ifdef __PCL_QT_INTERFACE
1431  void MoveBy( const QPoint& p ) noexcept
1432  {
1433  MoveBy( p.x(), p.y() );
1434  }
1435 #endif
1436 
1443  template <typename T1>
1445  {
1446  GenericRectangle r( *this );
1447  r.MoveBy( d );
1448  return r;
1449  }
1450 
1457  template <typename T1>
1458  GenericRectangle MovedBy( T1 dx, T1 dy ) const noexcept
1459  {
1460  GenericRectangle r( *this );
1461  r.MoveBy( dx, dy );
1462  return r;
1463  }
1464 
1475  template <typename T1>
1476  void ResizeTo( T1 w, T1 h ) noexcept
1477  {
1478  if ( x0 <= x1 )
1479  x1 = x0 + component( w );
1480  else
1481  x0 = x1 + component( w );
1482 
1483  if ( y0 <= y1 )
1484  y1 = y0 + component( h );
1485  else
1486  y0 = y1 + component( h );
1487  }
1488 
1495  template <typename T1>
1496  GenericRectangle ResizedTo( T1 w, T1 h ) const noexcept
1497  {
1498  GenericRectangle r( *this );
1499  r.ResizeTo( w, h );
1500  return r;
1501  }
1502 
1514  template <typename T1>
1515  void ResizeBy( T1 dw, T1 dh ) noexcept
1516  {
1517  if ( x0 <= x1 )
1518  x1 += component( dw );
1519  else
1520  x0 += component( dw );
1521 
1522  if ( y0 <= y1 )
1523  y1 += component( dh );
1524  else
1525  y0 += component( dh );
1526  }
1527 
1534  template <typename T1>
1535  GenericRectangle ResizedBy( T1 dw, T1 dh ) const noexcept
1536  {
1537  GenericRectangle r( *this );
1538  r.ResizeBy( dw, dh );
1539  return r;
1540  }
1541 
1550  template <typename T1>
1551  void SetWidth( T1 w ) noexcept
1552  {
1553  if ( x0 <= x1 )
1554  x1 = x0 + component( w );
1555  else
1556  x0 = x1 + component( w );
1557  }
1558 
1567  template <typename T1>
1568  void SetHeight( T1 h ) noexcept
1569  {
1570  if ( y0 <= y1 )
1571  y1 = y0 + component( h );
1572  else
1573  y0 = y1 + component( h );
1574  }
1575 
1581  template <typename T1>
1582  void InflateBy( T1 dx, T1 dy ) noexcept
1583  {
1584  if ( x1 < x0 )
1585  dx = -dx;
1586  if ( y1 < y0 )
1587  dy = -dy;
1588  x0 -= dx;
1589  y0 -= dy;
1590  x1 += dx;
1591  y1 += dy;
1592  }
1593 
1599  template <typename T1>
1600  void InflateBy( T1 d ) noexcept
1601  {
1602  if ( x0 <= x1 )
1603  x0 -= d, x1 += d;
1604  else
1605  x0 += d, x1 -= d;
1606 
1607  if ( y0 <= y1 )
1608  y0 -= d, y1 += d;
1609  else
1610  y0 += d, y1 -= d;
1611  }
1612 
1617  template <typename T1>
1618  GenericRectangle InflatedBy( T1 dx, T1 dy ) const noexcept
1619  {
1620  GenericRectangle r( *this );
1621  r.InflateBy( dx, dy );
1622  return r;
1623  }
1624 
1629  template <typename T1>
1630  GenericRectangle InflatedBy( T1 d ) const noexcept
1631  {
1632  GenericRectangle r( *this );
1633  r.InflateBy( d );
1634  return r;
1635  }
1636 
1642  template <typename T1>
1643  void DeflateBy( T1 dx, T1 dy ) noexcept
1644  {
1645  if ( x1 < x0 )
1646  dx = -dx;
1647  if ( y1 < y0 )
1648  dy = -dy;
1649  x0 += dx;
1650  y0 += dy;
1651  x1 -= dx;
1652  y1 -= dy;
1653  }
1654 
1660  template <typename T1>
1661  void DeflateBy( T1 d ) noexcept
1662  {
1663  if ( x0 <= x1 )
1664  x0 += d, x1 -= d;
1665  else
1666  x0 -= d, x1 += d;
1667 
1668  if ( y0 <= y1 )
1669  y0 += d, y1 -= d;
1670  else
1671  y0 -= d, y1 += d;
1672  }
1673 
1678  template <typename T1>
1679  GenericRectangle DeflatedBy( T1 dx, T1 dy ) const noexcept
1680  {
1681  GenericRectangle r( *this );
1682  r.DeflateBy( dx, dy );
1683  return r;
1684  }
1685 
1690  template <typename T1>
1691  GenericRectangle DeflatedBy( T1 d ) const noexcept
1692  {
1693  GenericRectangle r( *this );
1694  r.DeflateBy( d );
1695  return r;
1696  }
1697 
1704  template <typename T1>
1705  GenericRectangle WidthSetTo( T1 w ) const noexcept
1706  {
1707  GenericRectangle r( *this );
1708  r.SetWidth( w );
1709  return r;
1710  }
1711 
1718  template <typename T1>
1719  GenericRectangle HeightSetTo( T1 h ) const noexcept
1720  {
1721  GenericRectangle r( *this );
1722  r.SetHeight( h );
1723  return r;
1724  }
1725 
1731  template <typename T1, typename T2>
1732  void Rotate( T1 angle, T2 xc, T2 yc ) noexcept
1733  {
1734  T1 sa, ca; pcl::SinCos( angle, sa, ca );
1735  pcl::Rotate( x0, y0, sa, ca, xc, yc );
1736  pcl::Rotate( x1, y1, sa, ca, xc, yc );
1737  }
1738 
1743  template <typename T1, typename T2>
1744  void Rotate( T1 angle, const GenericPoint<T2>& center ) noexcept
1745  {
1746  Rotate( angle, center.x, center.y );
1747  }
1748 
1754  template <typename T1, typename T2>
1755  void Rotate( T1 sa, T1 ca, T2 xc, T2 yc ) noexcept
1756  {
1757  pcl::Rotate( x0, y0, sa, ca, xc, yc );
1758  pcl::Rotate( x1, y1, sa, ca, xc, yc );
1759  }
1760 
1766  template <typename T1, typename T2>
1767  void Rotate( T1 sa, T1 ca, const GenericPoint<T2>& center ) noexcept
1768  {
1769  Rotate( sa, ca, center.x, center.y );
1770  }
1771 
1777  template <typename T1, typename T2>
1778  GenericRectangle Rotated( T1 angle, T2 xc, T2 yc ) const noexcept
1779  {
1780  GenericRectangle r( *this );
1781  r.Rotate( angle, xc, yc );
1782  return r;
1783  }
1784 
1790  template <typename T1, typename T2>
1791  GenericRectangle Rotated( T1 angle, const GenericPoint<T2>& center ) const noexcept
1792  {
1793  GenericRectangle r( *this );
1794  r.Rotate( angle, center );
1795  return r;
1796  }
1797 
1804  template <typename T1, typename T2>
1805  GenericRectangle Rotated( T1 sa, T1 ca, T2 xc, T2 yc ) const noexcept
1806  {
1807  GenericRectangle r( *this );
1808  r.Rotate( sa, ca, xc, yc );
1809  return r;
1810  }
1811 
1818  template <typename T1, typename T2>
1819  GenericRectangle Rotated( T1 sa, T1 ca, const GenericPoint<T2>& center ) const noexcept
1820  {
1821  GenericRectangle r( *this );
1822  r.Rotate( sa, ca, center );
1823  return r;
1824  }
1825 
1830  void Round() noexcept
1831  {
1832  x0 = component( pcl::Round( double( x0 ) ) );
1833  y0 = component( pcl::Round( double( y0 ) ) );
1834  x1 = component( pcl::Round( double( x1 ) ) );
1835  y1 = component( pcl::Round( double( y1 ) ) );
1836  }
1837 
1842  void Round( int n ) noexcept
1843  {
1844  PCL_PRECONDITION( n >= 0 )
1845  if ( n < 0 )
1846  n = 0;
1847  x0 = component( pcl::Round( double( x0 ), n ) );
1848  y0 = component( pcl::Round( double( y0 ), n ) );
1849  x1 = component( pcl::Round( double( x1 ), n ) );
1850  y1 = component( pcl::Round( double( y1 ), n ) );
1851  }
1852 
1857  GenericRectangle Rounded() const noexcept
1858  {
1859  return GenericRectangle( component( pcl::Round( double( x0 ) ) ), component( pcl::Round( double( y0 ) ) ),
1860  component( pcl::Round( double( x1 ) ) ), component( pcl::Round( double( y1 ) ) ) );
1861  }
1862 
1867  GenericRectangle Rounded( int n ) const noexcept
1868  {
1869  PCL_PRECONDITION( n >= 0 )
1870  return GenericRectangle( component( pcl::Round( double( x0 ), n ) ), component( pcl::Round( double( y0 ), n ) ),
1871  component( pcl::Round( double( x1 ), n ) ), component( pcl::Round( double( y1 ), n ) ) );
1872  }
1873 
1879  {
1880  return GenericRectangle<int>( pcl::RoundInt( double( x0 ) ), pcl::RoundInt( double( y0 ) ),
1881  pcl::RoundInt( double( x1 ) ), pcl::RoundInt( double( y1 ) ) );
1882  }
1883 
1889  void Truncate() noexcept
1890  {
1891  x0 = component( pcl::Trunc( double( x0 ) ) );
1892  y0 = component( pcl::Trunc( double( y0 ) ) );
1893  x1 = component( pcl::Trunc( double( x1 ) ) );
1894  y1 = component( pcl::Trunc( double( y1 ) ) );
1895  }
1896 
1903  GenericRectangle Truncated() const noexcept
1904  {
1905  return GenericRectangle( component( pcl::Trunc( double( x0 ) ) ), component( pcl::Trunc( double( y0 ) ) ),
1906  component( pcl::Trunc( double( x1 ) ) ), component( pcl::Trunc( double( y1 ) ) ) );
1907  }
1908 
1916  {
1917  return GenericRectangle<int>( pcl::TruncInt( double( x0 ) ), pcl::TruncInt( double( y0 ) ),
1918  pcl::TruncInt( double( x1 ) ), pcl::TruncInt( double( y1 ) ) );
1919  }
1920 
1925  template <typename T1>
1926  GenericRectangle& operator =( const GenericRectangle<T1>& r ) noexcept
1927  {
1928  x0 = component( r.x0 );
1929  y0 = component( r.y0 );
1930  x1 = component( r.x1 );
1931  y1 = component( r.y1 );
1932  return *this;
1933  }
1934 
1942  template <typename T1>
1943  GenericRectangle& operator =( const pcl::GenericPoint<T1>& p ) noexcept
1944  {
1945  x0 = x1 = component( p.x );
1946  y0 = y1 = component( p.y );
1947  return *this;
1948  }
1949 
1956  GenericRectangle& operator =( component d ) noexcept
1957  {
1958  x0 = y0 = x1 = y1 = d;
1959  return *this;
1960  }
1961 
1962 #ifdef __PCL_QT_INTERFACE
1963  GenericRectangle& operator =( const QRect& r ) noexcept
1964  {
1965  x0 = component( r.left() );
1966  y0 = component( r.top() );
1967  x1 = component( r.right()+1 );
1968  y1 = component( r.bottom()+1 );
1969  return *this;
1970  }
1971 #endif
1972 
1985  template <typename T1>
1986  GenericRectangle& operator +=( const GenericRectangle<T1>& r ) noexcept
1987  {
1988  x0 += component( r.x0 );
1989  y0 += component( r.y0 );
1990  x1 += component( r.x1 );
1991  y1 += component( r.y1 );
1992  return *this;
1993  }
1994 
2008  template <typename T1>
2009  GenericRectangle& operator +=( const pcl::GenericPoint<T1>& p ) noexcept
2010  {
2011  x0 += component( p.x );
2012  y0 += component( p.y );
2013  x1 += component( p.x );
2014  y1 += component( p.y );
2015  return *this;
2016  }
2017 
2032  GenericRectangle& operator +=( component d ) noexcept
2033  {
2034  x0 += d;
2035  y0 += d;
2036  x1 += d;
2037  y1 += d;
2038  return *this;
2039  }
2040 
2041 #ifdef __PCL_QT_INTERFACE
2042  GenericRectangle& operator +=( const QPoint& p ) noexcept
2043  {
2044  component dx = component( p.x() ), dy = component( p.y() );
2045  x0 += dx;
2046  y0 += dy;
2047  x1 += dx;
2048  y1 += dy;
2049  return *this;
2050  }
2051 #endif
2052 
2065  template <typename T1>
2066  GenericRectangle& operator -=( const GenericRectangle<T1>& r ) noexcept
2067  {
2068  x0 -= component( r.x0 );
2069  y0 -= component( r.y0 );
2070  x1 -= component( r.x1 );
2071  y1 -= component( r.y1 );
2072  return *this;
2073  }
2074 
2088  template <typename T1>
2089  GenericRectangle& operator -=( const pcl::GenericPoint<T1>& p ) noexcept
2090  {
2091  x0 -= component( p.x );
2092  y0 -= component( p.y );
2093  x1 -= component( p.x );
2094  y1 -= component( p.y );
2095  return *this;
2096  }
2097 
2112  GenericRectangle& operator -=( component d ) noexcept
2113  {
2114  x0 -= d;
2115  y0 -= d;
2116  x1 -= d;
2117  y1 -= d;
2118  return *this;
2119  }
2120 
2121 #ifdef __PCL_QT_INTERFACE
2122  GenericRectangle& operator -=( const QPoint& p ) noexcept
2123  {
2124  component dx = component( p.x() ), dy = component( p.y() );
2125  x0 -= dx;
2126  y0 -= dy;
2127  x1 -= dx;
2128  y1 -= dy;
2129  return *this;
2130  }
2131 #endif
2132 
2145  template <typename T1>
2146  GenericRectangle& operator *=( const GenericRectangle<T1>& r ) noexcept
2147  {
2148  x0 *= component( r.x0 );
2149  y0 *= component( r.y0 );
2150  x1 *= component( r.x1 );
2151  y1 *= component( r.y1 );
2152  return *this;
2153  }
2154 
2169  template <typename T1>
2170  GenericRectangle& operator *=( const pcl::GenericPoint<T1>& p ) noexcept
2171  {
2172  x0 *= component( p.x );
2173  y0 *= component( p.y );
2174  x1 *= component( p.x );
2175  y1 *= component( p.y );
2176  return *this;
2177  }
2178 
2193  GenericRectangle& operator *=( component d ) noexcept
2194  {
2195  x0 *= d;
2196  y0 *= d;
2197  x1 *= d;
2198  y1 *= d;
2199  return *this;
2200  }
2201 
2202 #ifdef __PCL_QT_INTERFACE
2203  GenericRectangle& operator *=( const QPoint& p ) noexcept
2204  {
2205  component dx = component( p.x() ), dy = component( p.y() );
2206  x0 *= dx; y0 *= dy; x1 *= dx; y1 *= dy;
2207  return *this;
2208  }
2209 #endif
2210 
2223  template <typename T1>
2224  GenericRectangle& operator /=( const GenericRectangle<T1>& r ) noexcept
2225  {
2226  PCL_PRECONDITION( component( r.x0 ) != component( 0 ) && component( r.y0 ) != component( 0 ) &&
2227  component( r.x1 ) != component( 0 ) && component( r.y1 ) != component( 0 ) )
2228  x0 /= component( r.x0 );
2229  y0 /= component( r.y0 );
2230  x1 /= component( r.x1 );
2231  y1 /= component( r.y1 );
2232  return *this;
2233  }
2234 
2249  template <typename T1>
2250  GenericRectangle& operator /=( const pcl::GenericPoint<T1>& p ) noexcept
2251  {
2252  PCL_PRECONDITION( component( p.x ) != component( 0 ) && component( p.y ) != component( 0 ) )
2253  x0 /= component( p.x );
2254  y0 /= component( p.y );
2255  x1 /= component( p.x );
2256  y1 /= component( p.y );
2257  return *this;
2258  }
2259 
2274  GenericRectangle& operator /=( component d ) noexcept
2275  {
2276  PCL_PRECONDITION( d != component( 0 ) )
2277  x0 /= d; y0 /= d; x1 /= d; y1 /= d;
2278  return *this;
2279  }
2280 
2281 #ifdef __PCL_QT_INTERFACE
2282  GenericRectangle& operator /=( const QPoint& p ) noexcept
2283  {
2284  PCL_PRECONDITION( component( p.x() ) != component( 0 ) && component( p.y() ) != component( 0 ) )
2285  component dx = component( p.x() ), dy = component( p.y() );
2286  x0 /= dx;
2287  y0 /= dy;
2288  x1 /= dx;
2289  y1 /= dy;
2290  return *this;
2291  }
2292 #endif
2293 
2297  GenericRectangle operator +() const noexcept
2298  {
2299  return *this;
2300  }
2301 
2308  GenericRectangle operator -() const noexcept
2309  {
2310  return GenericRectangle( -x0, -y0, -x1, -y1 );
2311  }
2312 
2313 #ifdef __PCL_QT_INTERFACE
2314  operator QRect() const noexcept
2315  {
2316  return QRect( int( x0 ), int( y0 ), int( x1-x0 ), int( y1-y0 ) );
2317  }
2318 #endif
2319 
2320 #ifdef __PCL_QT_INTERFACE
2321 # ifndef __PCL_QT_NO_RECT_DRAWING_HELPERS
2322 
2323  void Draw( QPainter& p, const QBrush* b ) const
2324  {
2325  int rx0, ry0, rx1, ry1;
2326 
2327  if ( x0 <= x1 )
2328  rx0 = x0, rx1 = x1;
2329  else
2330  rx0 = x1, rx1 = x0;
2331 
2332  if ( y0 <= y1 )
2333  ry0 = y0, ry1 = y1;
2334  else
2335  ry0 = y1, ry1 = y0;
2336 
2337  if ( rx1 - rx0 <= 1 )
2338  {
2339  if ( ry1 - ry0 <= 1 )
2340  p.drawPoint( rx0, ry0 );
2341  else
2342  p.drawLine( rx0, ry0, rx0, ry1-1 );
2343  }
2344  else if ( ry1 - ry0 <= 1 )
2345  {
2346  p.drawLine( rx0, ry0, rx1-1, ry0 );
2347  }
2348  else
2349  {
2350 # if ( QT_VERSION >= 0x040000 )
2351  int w = rx1-rx0-1, h = ry1-ry0-1;
2352 # else
2353  int w = rx1-rx0, h = ry1-ry0;
2354 # endif
2355  if ( b != 0 )
2356  p.fillRect( rx0, ry0, w, h, *b );
2357  p.drawRect( rx0, ry0, w, h );
2358  }
2359  }
2360 
2361  void Draw( QPainter& p ) const
2362  {
2363  Draw( p, 0 );
2364  }
2365 
2366  void Draw( QPainter& p, const QColor& c ) const
2367  {
2368  QBrush b( c );
2369  Draw( p, &b );
2370  }
2371 
2372 # endif // !__PCL_QT_NO_RECT_DRAWING_HELPERS
2373 #endif // __PCL_QT_INTERFACE
2374 
2375 }; // GenericRectangle<T>
2376 
2377 #undef PCL_ASSERT_RECT_SIZE
2378 
2379 // ----------------------------------------------------------------------------
2380 
2390 template <typename T1, typename T2> inline
2391 bool operator ==( const GenericRectangle<T1>& r1, const GenericRectangle<T2>& r2 ) noexcept
2392 {
2393  return r1.x0 == r2.x0 && r1.y0 == r2.y0 && r1.x1 == r2.x1 && r1.y1 == r2.y1;
2394 }
2395 
2401 template <typename T> inline
2402 bool operator ==( const GenericRectangle<T>& r1, T d2 ) noexcept
2403 {
2404  return r1.x0 == d2 && r1.y0 == d2 && r1.x1 == d2 && r1.y1 == d2;
2405 }
2406 
2413 template <typename T> inline
2414 bool operator ==( T d1, const GenericRectangle<T>& r2 ) noexcept
2415 {
2416  return d1 == r2.x0 && d1 == r2.y0 && d1 == r2.x1 && d1 == r2.y1;
2417 }
2418 
2425 template <typename T1, typename T2> inline
2426 bool operator <( const GenericRectangle<T1>& r1, const GenericRectangle<T2>& r2 ) noexcept
2427 {
2428  T1 x01 = Min( r1.x0, r1.x1 ); T1 y01 = Min( r1.y0, r1.y1 );
2429  T1 x11 = Max( r1.x0, r1.x1 ); T1 y11 = Max( r1.y0, r1.y1 );
2430  T2 x02 = Min( r2.x0, r2.x1 ); T2 y02 = Min( r2.y0, r2.y1 );
2431  T2 x12 = Max( r2.x0, r2.x1 ); T2 y12 = Max( r2.y0, r2.y1 );
2432  if ( y01 != y02 )
2433  return y01 < y02;
2434  if ( x01 != x02 )
2435  return x01 < x02;
2436  if ( y11 != y12 )
2437  return y11 < y12;
2438  return x11 < x12;
2439 }
2440 
2456 template <typename T1, typename T2> inline
2458 {
2459  return GenericRectangle<T1>( T1( r1.x0 + r2.x0 ), T1( r1.y0 + r2.y0 ),
2460  T1( r1.x1 + r2.x1 ), T1( r1.y1 + r2.y1 ) );
2461 }
2462 
2477 template <typename T1, typename T2> inline
2479 {
2480  return GenericRectangle<T1>( T1( r1.x0 + p2.x ), T1( r1.y0 + p2.y ),
2481  T1( r1.x1 + p2.x ), T1( r1.y1 + p2.y ) );
2482 }
2483 
2493 template <typename T1, typename T2> inline
2495 {
2496  return GenericRectangle<T2>( T2( p1.x + r2.x0 ), T2( p1.y + r2.y0 ),
2497  T2( p1.x + r2.x1 ), T2( p1.y + r2.y1 ) );
2498 }
2499 
2514 template <typename T> inline
2516 {
2517  return GenericRectangle<T>( r1.x0+d2, r1.y0+d2, r1.x1+d2, r1.y1+d2 );
2518 }
2519 
2529 template <typename T> inline
2531 {
2532  return GenericRectangle<T>( d1+r2.x0, d1+r2.y0, d1+r2.x1, d1+r2.y1 );
2533 }
2534 
2550 template <typename T1, typename T2> inline
2552 {
2553  return GenericRectangle<T1>( T1( r1.x0 - r2.x0 ), T1( r1.y0 - r2.y0 ),
2554  T1( r1.x1 - r2.x1 ), T1( r1.y1 - r2.y1 ) );
2555 }
2556 
2571 template <typename T1, typename T2> inline
2573 {
2574  return GenericRectangle<T1>( T1( r1.x0 - p2.x ), T1( r1.y0 - p2.y ),
2575  T1( r1.x1 - p2.x ), T1( r1.y1 - p2.y ) );
2576 }
2577 
2592 template <typename T1, typename T2> inline
2594 {
2595  return GenericRectangle<T2>( T2( p1.x - r2.x0 ), T2( p1.y - r2.y0 ),
2596  T2( p1.x - r2.x1 ), T2( p1.y - r2.y1 ) );
2597 }
2598 
2613 template <typename T> inline
2615 {
2616  return GenericRectangle<T>( r1.x0-d2, r1.y0-d2, r1.x1-d2, r1.y1-d2 );
2617 }
2618 
2633 template <typename T> inline
2635 {
2636  return GenericRectangle<T>( d1-r2.x0, d1-r2.y0, d1-r2.x1, d1-r2.y1 );
2637 }
2638 
2654 template <typename T1, typename T2> inline
2656 {
2657  return GenericRectangle<T1>( T1( r1.x0 * r2.x0 ), T1( r1.y0 * r2.y0 ),
2658  T1( r1.x1 * r2.x1 ), T1( r1.y1 * r2.y1 ) );
2659 }
2660 
2675 template <typename T1, typename T2> inline
2677 {
2678  return GenericRectangle<T1>( T1( r1.x0 * p2.x ), T1( r1.y0 * p2.y ),
2679  T1( r1.x1 * p2.x ), T1( r1.y1 * p2.y ) );
2680 }
2681 
2691 template <typename T1, typename T2> inline
2693 {
2694  return GenericRectangle<T2>( T2( p1.x * r2.x0 ), T2( p1.y * r2.y0 ),
2695  T2( p1.x * r2.x1 ), T2( p1.y * r2.y1 ) );
2696 }
2697 
2712 template <typename T> inline
2714 {
2715  return GenericRectangle<T>( r1.x0*d2, r1.y0*d2, r1.x1*d2, r1.y1*d2 );
2716 }
2717 
2727 template <typename T> inline
2729 {
2730  return GenericRectangle<T>( d1*r2.x0, d1*r2.y0, d1*r2.x1, d1*r2.y1 );
2731 }
2732 
2748 template <typename T1, typename T2> inline
2750 {
2751  PCL_PRECONDITION( r2.x0 != T2( 0 ) && r2.y0 != T2( 0 ) &&
2752  r2.x1 != T2( 0 ) && r2.y1 != T2( 0 ) )
2753  return GenericRectangle<T1>( T1( r1.x0 / r2.x0 ), T1( r1.y0 / r2.y0 ),
2754  T1( r1.x1 / r2.x1 ), T1( r1.y1 / r2.y1 ) );
2755 }
2756 
2771 template <typename T1, typename T2> inline
2773 {
2774  PCL_PRECONDITION( p2.x != T2( 0 ) && p2.y != T2( 0 ) )
2775  return GenericRectangle<T1>( T1( r1.x0 / p2.x ), T1( r1.y0 / p2.y ),
2776  T1( r1.x1 / p2.x ), T1( r1.y1 / p2.y ) );
2777 }
2778 
2793 template <typename T1, typename T2> inline
2795 {
2796  PCL_PRECONDITION( r2.x0 != T2( 0 ) && r2.y0 != T2( 0 ) &&
2797  r2.x1 != T2( 0 ) && r2.y1 != T2( 0 ) )
2798  return GenericRectangle<T2>( T2( p1.x / r2.x0 ), T2( p1.y / r2.y0 ),
2799  T2( p1.x / r2.x1 ), T2( p1.y / r2.y1 ) );
2800 }
2801 
2816 template <typename T> inline
2818 {
2819  PCL_PRECONDITION( d2 != T( 0 ) )
2820  return GenericRectangle<T>( r1.x0/d2, r1.y0/d2, r1.x1/d2, r1.y1/d2 );
2821 }
2822 
2837 template <typename T> inline
2839 {
2840  PCL_PRECONDITION( r2.x0 != T( 0 ) && r2.y0 != T( 0 ) &&
2841  r2.x1 != T( 0 ) && r2.y1 != T( 0 ) )
2842  return GenericRectangle<T>( d1/r2.x0, d1/r2.y0, d1/r2.x1, d1/r2.y1 );
2843 }
2844 
2860 template <typename T, typename T1, typename T2> inline
2861 void Rotate( GenericRectangle<T>& r, T1 a, T2 xc, T2 yc ) noexcept
2862 {
2863  T1 sa, ca; pcl::SinCos( a, sa, ca );
2864  pcl::Rotate( r.x0, r.y0, sa, ca, xc, yc );
2865  pcl::Rotate( r.x1, r.y1, sa, ca, xc, yc );
2866 }
2867 
2883 template <typename T, typename T1, typename T2> inline
2884 void Rotate( GenericRectangle<T>& r, T1 a, const GenericPoint<T2>& c ) noexcept
2885 {
2886  pcl::Rotate( r, a, c.x, c.y );
2887 }
2888 
2904 template <typename T, typename T1, typename T2> inline
2905 void Rotate( GenericRectangle<T>& r, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept
2906 {
2907  pcl::Rotate( r.x0, r.y0, sa, ca, xc, yc );
2908  pcl::Rotate( r.x1, r.y1, sa, ca, xc, yc );
2909 }
2910 
2926 template <typename T, typename T1, typename T2> inline
2927 void Rotate( GenericRectangle<T>& r, T1 sa, T1 ca, const GenericPoint<T2>& c ) noexcept
2928 {
2929  pcl::Rotate( r, sa, ca, c.x, c.y );
2930 }
2931 
2943 template <typename T> inline
2945 {
2946  pcl::Swap( r1.x0, r2.x0 ); pcl::Swap( r1.y0, r2.y0 );
2947  pcl::Swap( r1.x1, r2.x1 ); pcl::Swap( r1.y1, r2.y1 );
2948 }
2949 
2950 // ----------------------------------------------------------------------------
2951 
2952 #ifndef __PCL_NO_RECT_INSTANTIATE
2953 
2965 using I32Rect = GenericRectangle<int32>;
2966 
2975 using Rect = I32Rect;
2976 
2984 using F32Rect = GenericRectangle<float>;
2985 
2994 using FRect = F32Rect;
2995 
3003 using F64Rect = GenericRectangle<double>;
3004 
3013 using DRect = F64Rect;
3014 
3015 #endif
3016 
3017 // ----------------------------------------------------------------------------
3018 
3019 } // pcl
3020 
3021 #endif // __PCL_Rectangle_h
3022 
3023 // ----------------------------------------------------------------------------
3024 // EOF pcl/Rectangle.h - Released 2024-01-13T15:47:58Z
pcl::GenericRectangle::component
T component
Definition: Rectangle.h:320
pcl::GenericRectangle::Rotate
void Rotate(T1 angle, const GenericPoint< T2 > &center) noexcept
Definition: Rectangle.h:1744
pcl::GenericRectangle::IntersectionFast
GenericRectangle IntersectionFast(const GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:1270
pcl::GenericRectangle::Intersect
bool Intersect(const GenericRectangle< T1 > &r) noexcept
Definition: Rectangle.h:1148
pcl::GenericRectangle::TruncatedToInt
GenericRectangle< int > TruncatedToInt() const noexcept
Definition: Rectangle.h:1915
pcl
PCL root namespace.
Definition: AbstractImage.h:76
pcl::GenericRectangle::RoundedToInt
GenericRectangle< int > RoundedToInt() const noexcept
Definition: Rectangle.h:1878
pcl::GenericRectangle::MovedBy
GenericRectangle MovedBy(T1 dx, T1 dy) const noexcept
Definition: Rectangle.h:1458
pcl::GenericRectangle::TopRight
point TopRight() const noexcept
Definition: Rectangle.h:552
pcl::GenericRectangle::Center
point Center() const noexcept
Definition: Rectangle.h:594
pcl::GenericRectangle::MovedTo
GenericRectangle MovedTo(T1 x, T1 y) const noexcept
Definition: Rectangle.h:1381
Point.h
pcl::GenericRectangle::Rounded
GenericRectangle Rounded(int n) const noexcept
Definition: Rectangle.h:1867
pcl::GenericRectangle::Diagonal
double Diagonal() const noexcept
Definition: Rectangle.h:713
pcl::GenericRectangle::Width
component Width() const noexcept
Definition: Rectangle.h:635
pcl::GenericRectangle::MovedTo
GenericRectangle MovedTo(const pcl::GenericPoint< T1 > &p) const noexcept
Definition: Rectangle.h:1367
pcl::GenericRectangle::MoveBy
void MoveBy(const pcl::GenericPoint< T1 > &d) noexcept
Definition: Rectangle.h:1393
pcl::GenericRectangle::UnionFast
GenericRectangle UnionFast(const GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:1101
pcl::GenericRectangle::IsHorizontalLine
bool IsHorizontalLine() const noexcept
Definition: Rectangle.h:737
pcl::GenericRectangle::y1
component y1
Vertical coordinate of the lower right corner.
Definition: Rectangle.h:335
pcl::GenericRectangle::ClipCode
ClipFlags ClipCode(T1 x, T1 y) const noexcept
Definition: Rectangle.h:810
pcl::GenericRectangle::TopLeft
point TopLeft() const noexcept
Definition: Rectangle.h:535
pcl::GenericRectangle::IntersectFast
bool IntersectFast(T1 left, T1 top, T1 right, T1 bottom) noexcept
Definition: Rectangle.h:1241
pcl::GenericRectangle::MoveBy
void MoveBy(T1 dxy) noexcept
Definition: Rectangle.h:1422
pcl::GenericRectangle::Includes
bool Includes(const GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:876
pcl::Max
constexpr const T & Max(const T &a, const T &b) noexcept
Definition: Utility.h:119
pcl::RoundInt
int RoundInt(T x) noexcept
Definition: Math.h:1503
pcl::GenericPoint
A generic point in the two-dimensional space.
Definition: Point.h:99
pcl::GenericRectangle::GenericRectangle
constexpr GenericRectangle(component d)
Definition: Rectangle.h:453
pcl::GenericRectangle::IntersectsFast
bool IntersectsFast(const pcl::GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:986
pcl::operator==
bool operator==(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
Definition: Array.h:2090
Relational.h
pcl::Round
Complex< T > Round(const Complex< T > &c) noexcept
Definition: Complex.h:938
pcl::GenericRectangle::IsVerticalLine
bool IsVerticalLine() const noexcept
Definition: Rectangle.h:745
pcl::GenericRectangle::BottomRight
point BottomRight() const noexcept
Definition: Rectangle.h:586
pcl::GenericRectangle::Hypot
double Hypot() const noexcept
Definition: Rectangle.h:703
pcl::GenericRectangle::Perimeter
component Perimeter() const noexcept
Definition: Rectangle.h:653
pcl::GenericRectangle::Intersection
GenericRectangle Intersection(const GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:1255
pcl::GenericRectangle::UniteFast
void UniteFast(T1 left, T1 top, T1 right, T1 bottom) noexcept
Definition: Rectangle.h:1075
pcl::GenericRectangle::CenterX
double CenterX() const noexcept
Definition: Rectangle.h:683
pcl::GenericRectangle::Intersect
bool Intersect(T1 left, T1 top, T1 right, T1 bottom) noexcept
Definition: Rectangle.h:1168
F64Rect
64-bit floating-point rectangle in the R^2 space.
I32Rect
32-bit integer rectangle on the plane.
pcl::GenericRectangle::CenterLeft
point CenterLeft() const noexcept
Definition: Rectangle.h:618
pcl::GenericRectangle::IsOrdered
bool IsOrdered() const noexcept
Definition: Rectangle.h:778
pcl::IsNormalRect
bool IsNormalRect(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:226
pcl::IsPointOrLine
bool IsPointOrLine(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:193
pcl::GenericRectangle::CenterY
double CenterY() const noexcept
Definition: Rectangle.h:692
pcl::GenericRectangle::Round
void Round(int n) noexcept
Definition: Rectangle.h:1842
pcl::GenericRectangle::InflatedBy
GenericRectangle InflatedBy(T1 d) const noexcept
Definition: Rectangle.h:1630
pcl::GenericRectangle::IncludesFast
bool IncludesFast(const pcl::GenericPoint< T1 > &p) const noexcept
Definition: Rectangle.h:915
pcl::GenericRectangle::Area
component Area() const noexcept
Definition: Rectangle.h:674
pcl::GenericRectangle::ResizeBy
void ResizeBy(T1 dw, T1 dh) noexcept
Definition: Rectangle.h:1515
pcl::GenericRectangle::Rotated
GenericRectangle Rotated(T1 sa, T1 ca, T2 xc, T2 yc) const noexcept
Definition: Rectangle.h:1805
pcl::operator+
Complex< T1 > operator+(const Complex< T1 > &c1, const Complex< T2 > &c2) noexcept
Definition: Complex.h:464
pcl::GenericRectangle::BottomLeft
point BottomLeft() const noexcept
Definition: Rectangle.h:569
Rect
32-bit integer rectangle on the plane.
pcl::GenericRectangle::Right
component Right() const noexcept
Definition: Rectangle.h:509
pcl::GenericRectangle::SetHeight
void SetHeight(T1 h) noexcept
Definition: Rectangle.h:1568
pcl::GenericRectangle::Intersects
bool Intersects(const pcl::GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:942
pcl::GenericRectangle::Rotated
GenericRectangle Rotated(T1 angle, T2 xc, T2 yc) const noexcept
Definition: Rectangle.h:1778
pcl::GenericRectangle::HeightSetTo
GenericRectangle HeightSetTo(T1 h) const noexcept
Definition: Rectangle.h:1719
pcl::GenericRectangle::Set
void Set(T1 left, T1 top, T1 right, T1 bottom) noexcept
Definition: Rectangle.h:1315
Math.h
pcl::GenericRectangle::Truncated
GenericRectangle Truncated() const noexcept
Definition: Rectangle.h:1903
pcl::GenericRectangle::ManhattanDistance
component ManhattanDistance() const noexcept
Definition: Rectangle.h:665
pcl::GenericRectangle::CenterRight
point CenterRight() const noexcept
Definition: Rectangle.h:626
pcl::GenericRectangle::DeflatedBy
GenericRectangle DeflatedBy(T1 d) const noexcept
Definition: Rectangle.h:1691
pcl::Flags
A type-safe collection of enumerated flags.
Definition: Flags.h:84
pcl::GenericRectangle::WidthSetTo
GenericRectangle WidthSetTo(T1 w) const noexcept
Definition: Rectangle.h:1705
pcl::GenericRectangle
A generic rectangle in the two-dimensional space.
Definition: Rectangle.h:313
pcl::GenericRectangle::x1
component x1
Horizontal coordinate of the lower right corner.
Definition: Rectangle.h:334
pcl::GenericRectangle::IsPointOrLine
bool IsPointOrLine() const noexcept
Definition: Rectangle.h:753
pcl::GenericRectangle::GenericRectangle
GenericRectangle(const GenericRectangle< T1 > &r)
Definition: Rectangle.h:464
pcl::SinCos
void SinCos(T x, T &sx, T &cx) noexcept
Definition: Math.h:1030
pcl::IsOrderedRect
bool IsOrderedRect(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:243
pcl::GenericRectangle::CenterTop
point CenterTop() const noexcept
Definition: Rectangle.h:602
pcl::IsHorizontalLine
bool IsHorizontalLine(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:159
pcl::GenericRectangle::Left
component Left() const noexcept
Definition: Rectangle.h:491
pcl::Sqrt
Complex< T > Sqrt(const Complex< T > &c) noexcept
Definition: Complex.h:674
pcl::GenericRectangle::ResizedBy
GenericRectangle ResizedBy(T1 dw, T1 dh) const noexcept
Definition: Rectangle.h:1535
pcl::operator-
Complex< T1 > operator-(const Complex< T1 > &c1, const Complex< T2 > &c2) noexcept
Definition: Complex.h:504
pcl::GenericRectangle::Height
component Height() const noexcept
Definition: Rectangle.h:644
pcl::GenericRectangle::Rotate
void Rotate(T1 angle, T2 xc, T2 yc) noexcept
Definition: Rectangle.h:1732
pcl::GenericRectangle::IsLine
bool IsLine() const noexcept
Definition: Rectangle.h:729
pcl::GenericRectangle::MoveBy
void MoveBy(T1 dx, T1 dy) noexcept
Definition: Rectangle.h:1404
pcl::GenericRectangle::DeflateBy
void DeflateBy(T1 dx, T1 dy) noexcept
Definition: Rectangle.h:1643
pcl::GenericRectangle::IntersectsFast
bool IntersectsFast(T1 left, T1 top, T1 right, T1 bottom) const noexcept
Definition: Rectangle.h:974
pcl::GenericRectangle::RightBottom
point RightBottom() const noexcept
Definition: Rectangle.h:578
pcl::GenericRectangle::GenericRectangle
constexpr GenericRectangle(component width, component height)
Definition: Rectangle.h:440
pcl::GenericRectangle::ClipCode
ClipFlags ClipCode(const pcl::GenericPoint< T1 > &p) const noexcept
Definition: Rectangle.h:847
pcl::GenericRectangle::MovedBy
GenericRectangle MovedBy(const pcl::GenericPoint< T1 > &d) const noexcept
Definition: Rectangle.h:1444
pcl::GenericRectangle::SetWidth
void SetWidth(T1 w) noexcept
Definition: Rectangle.h:1551
pcl::GenericRectangle::IsPoint
bool IsPoint() const noexcept
Definition: Rectangle.h:721
DRect
64-bit floating-point rectangle in the R^2 space.
pcl::GenericRectangle::LeftBottom
point LeftBottom() const noexcept
Definition: Rectangle.h:561
pcl::GenericRectangle::IncludesFast
bool IncludesFast(T1 x, T1 y) const noexcept
Definition: Rectangle.h:902
F32Rect
32-bit floating-point rectangle in the R^2 space.
pcl::IsRect
bool IsRect(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:210
pcl::GenericRectangle::Unite
void Unite(T1 left, T1 top, T1 right, T1 bottom) noexcept
Definition: Rectangle.h:1012
pcl::operator/
Complex< T1 > operator/(const Complex< T1 > &c1, const Complex< T2 > &c2) noexcept
Definition: Complex.h:592
pcl::GenericRectangle::IsNormal
bool IsNormal() const noexcept
Definition: Rectangle.h:770
pcl::GenericRectangle::UniteFast
void UniteFast(const GenericRectangle< T1 > &r) noexcept
Definition: Rectangle.h:1050
pcl::Swap
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
Definition: Point.h:1459
pcl::GenericRectangle::Top
component Top() const noexcept
Definition: Rectangle.h:500
pcl::GenericRectangle::Includes
bool Includes(T1 x, T1 y) const noexcept
Definition: Rectangle.h:857
pcl::Min
constexpr const T & Min(const T &a, const T &b) noexcept
Definition: Utility.h:90
pcl::GenericRectangle::LeftTop
point LeftTop() const noexcept
Definition: Rectangle.h:527
pcl::IsLine
bool IsLine(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:142
pcl::GenericRectangle::GenericRectangle
GenericRectangle(std::initializer_list< T1 > l)
Definition: Rectangle.h:392
pcl::GenericRectangle::ResizeTo
void ResizeTo(T1 w, T1 h) noexcept
Definition: Rectangle.h:1476
pcl::GenericRectangle::ResizedTo
GenericRectangle ResizedTo(T1 w, T1 h) const noexcept
Definition: Rectangle.h:1496
pcl::GenericRectangle::Unite
void Unite(const GenericRectangle< T1 > &r) noexcept
Definition: Rectangle.h:996
pcl::GenericRectangle::Ordered
GenericRectangle Ordered() const noexcept
Definition: Rectangle.h:794
pcl::GenericRectangle::IsRect
bool IsRect() const noexcept
Definition: Rectangle.h:762
pcl::GenericRectangle::InflateBy
void InflateBy(T1 dx, T1 dy) noexcept
Definition: Rectangle.h:1582
pcl::operator*
Complex< T1 > operator*(const Complex< T1 > &c1, const Complex< T2 > &c2) noexcept
Definition: Complex.h:548
pcl::GenericRectangle::Bottom
component Bottom() const noexcept
Definition: Rectangle.h:518
pcl::GenericRectangle::CenterBottom
point CenterBottom() const noexcept
Definition: Rectangle.h:610
pcl::GenericRectangle::Order
void Order() noexcept
Definition: Rectangle.h:786
pcl::GenericRectangle::Truncate
void Truncate() noexcept
Definition: Rectangle.h:1889
pcl::GenericRectangle::GenericRectangle
constexpr GenericRectangle(T1 left, T1 top, T1 right, T1 bottom)
Definition: Rectangle.h:357
pcl::GenericRectangle::x0
component x0
Horizontal coordinate of the upper left corner.
Definition: Rectangle.h:332
pcl::GenericRectangle::InflateBy
void InflateBy(T1 d) noexcept
Definition: Rectangle.h:1600
pcl::GenericRectangle::GenericRectangle
constexpr GenericRectangle()
Definition: Rectangle.h:341
pcl::GenericRectangle::DeflateBy
void DeflateBy(T1 d) noexcept
Definition: Rectangle.h:1661
pcl::GenericRectangle::Round
void Round() noexcept
Definition: Rectangle.h:1830
pcl::GenericRectangle::Rotated
GenericRectangle Rotated(T1 sa, T1 ca, const GenericPoint< T2 > &center) const noexcept
Definition: Rectangle.h:1819
pcl::GenericRectangle::InflatedBy
GenericRectangle InflatedBy(T1 dx, T1 dy) const noexcept
Definition: Rectangle.h:1618
pcl::GenericRectangle::Rotate
void Rotate(T1 sa, T1 ca, T2 xc, T2 yc) noexcept
Definition: Rectangle.h:1755
pcl::GenericRectangle::y0
component y0
Vertical coordinate of the upper left corner.
Definition: Rectangle.h:333
pcl::TruncInt
int TruncInt(T x) noexcept
Definition: Math.h:1132
FRect
32-bit floating-point rectangle in the R^2 space.
pcl::GenericRectangle::Union
GenericRectangle Union(const GenericRectangle< T1 > &r) const noexcept
Definition: Rectangle.h:1087
Flags.h
pcl::GenericRectangle::GenericRectangle
GenericRectangle(const pcl::GenericPoint< T1 > &leftTop, const pcl::GenericPoint< T1 > &rightBottom)
Definition: Rectangle.h:425
pcl::GenericRectangle::MoveTo
void MoveTo(T1 x, T1 y) noexcept
Definition: Rectangle.h:1344
pcl::IsVerticalLine
bool IsVerticalLine(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:176
pcl::GenericRectangle::Rounded
GenericRectangle Rounded() const noexcept
Definition: Rectangle.h:1857
pcl::IsPoint
bool IsPoint(T x0, T y0, T x1, T y1) noexcept
Definition: Rectangle.h:124
pcl::GenericRectangle::IntersectFast
bool IntersectFast(const GenericRectangle< T1 > &r) noexcept
Definition: Rectangle.h:1212
pcl::GenericRectangle::Intersects
bool Intersects(T1 left, T1 top, T1 right, T1 bottom) const noexcept
Definition: Rectangle.h:931
pcl::GenericRectangle::DeflatedBy
GenericRectangle DeflatedBy(T1 dx, T1 dy) const noexcept
Definition: Rectangle.h:1679
pcl::Abs
T Abs(const Complex< T > &c) noexcept
Definition: Complex.h:429
pcl::GenericRectangle::Includes
bool Includes(const pcl::GenericPoint< T1 > &p) const noexcept
Definition: Rectangle.h:867
pcl::GenericRectangle::Rotate
void Rotate(T1 sa, T1 ca, const GenericPoint< T2 > &center) noexcept
Definition: Rectangle.h:1767
Defs.h
pcl::Trunc
T Trunc(T x) noexcept
Definition: Math.h:1095
pcl::OrderRect
void OrderRect(T &x0, T &y0, T &x1, T &y1) noexcept
Definition: Rectangle.h:260
pcl::GenericRectangle::MoveTo
void MoveTo(const pcl::GenericPoint< T1 > &p) noexcept
Definition: Rectangle.h:1331
pcl::GenericRectangle::Rotated
GenericRectangle Rotated(T1 angle, const GenericPoint< T2 > &center) const noexcept
Definition: Rectangle.h:1791
pcl::GenericRectangle::RightTop
point RightTop() const noexcept
Definition: Rectangle.h:544
pcl::operator<
bool operator<(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
Definition: Array.h:2101
pcl::Rotate
void Rotate(T &x, T &y, T1 sa, T1 ca, T2 xc, T2 yc) noexcept
Definition: Math.h:2024