// License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2024 Intel Corporation. All Rights Reserved. #pragma once #include "float2.h" #include // max,min #include // floor namespace rs2 { template < typename T > T normalizeT( const T & in_val, const T & min, const T & max ) { if( min >= max ) return 0; return ( ( in_val - min ) / ( max - min ) ); } template < typename T > T unnormalizeT( const T & in_val, const T & min, const T & max ) { if( min == max ) return min; return ( ( in_val * ( max - min ) ) + min ); } struct rect { float x, y; float w, h; void operator=( const rect & other ) { x = other.x; y = other.y; w = other.w; h = other.h; } operator bool() const { return w * w > 0 && h * h > 0; } bool operator==( const rect & other ) const { return x == other.x && y == other.y && w == other.w && h == other.h; } bool operator!=( const rect & other ) const { return ! ( *this == other ); } rect normalize( const rect & normalize_to ) const { return rect{ normalizeT( x, normalize_to.x, normalize_to.x + normalize_to.w ), normalizeT( y, normalize_to.y, normalize_to.y + normalize_to.h ), normalizeT( w, 0.f, normalize_to.w ), normalizeT( h, 0.f, normalize_to.h ) }; } rect unnormalize( const rect & unnormalize_to ) const { return rect{ unnormalizeT( x, unnormalize_to.x, unnormalize_to.x + unnormalize_to.w ), unnormalizeT( y, unnormalize_to.y, unnormalize_to.y + unnormalize_to.h ), unnormalizeT( w, 0.f, unnormalize_to.w ), unnormalizeT( h, 0.f, unnormalize_to.h ) }; } // Calculate the intersection between two rects // If the intersection is empty, a rect with width and height zero will be returned rect intersection( const rect & other ) const { auto x1 = std::max( x, other.x ); auto y1 = std::max( y, other.y ); auto x2 = std::min( x + w, other.x + other.w ); auto y2 = std::min( y + h, other.y + other.h ); return { x1, y1, std::max( x2 - x1, 0.f ), std::max( y2 - y1, 0.f ) }; } // Calculate the area of the rect float area() const { return w * h; } rect cut_by( const rect & r ) const { auto x1 = x; auto y1 = y; auto x2 = x + w; auto y2 = y + h; x1 = std::max( x1, r.x ); x1 = std::min( x1, r.x + r.w ); y1 = std::max( y1, r.y ); y1 = std::min( y1, r.y + r.h ); x2 = std::max( x2, r.x ); x2 = std::min( x2, r.x + r.w ); y2 = std::max( y2, r.y ); y2 = std::min( y2, r.y + r.h ); return { x1, y1, x2 - x1, y2 - y1 }; } bool contains( const float2 & p ) const { return ( p.x >= x ) && ( p.x < x + w ) && ( p.y >= y ) && ( p.y < y + h ); } rect pan( const float2 & p ) const { return { x - p.x, y - p.y, w, h }; } rect center() const { return { x + w / 2.f, y + h / 2.f, 0, 0 }; } rect adjust_ratio( float2 size ) const { auto H = static_cast< float >( h ), W = static_cast< float >( h ) * size.x / size.y; if( W > w ) { auto scale = w / W; W *= scale; H *= scale; } return { float( floor( x + floor( w - W ) / 2 ) ), float( floor( y + floor( h - H ) / 2 ) ), W, H }; } rect scale( float factor ) const { return { x, y, w * factor, h * factor }; } rect grow( int pixels ) const { return { x - pixels, y - pixels, w + pixels * 2, h + pixels * 2 }; } rect grow( int dx, int dy ) const { return { x - dx, y - dy, w + dx * 2, h + dy * 2 }; } rect shrink_by( float2 pixels ) const { return { x + pixels.x, y + pixels.y, w - pixels.x * 2, h - pixels.y * 2 }; } rect center_at( const float2 & new_center ) const { auto c = center(); auto diff_x = new_center.x - c.x; auto diff_y = new_center.y - c.y; return { x + diff_x, y + diff_y, w, h }; } rect fit( rect r ) const { float new_w = w; float new_h = h; if( w < r.w ) new_w = r.w; if( h < r.h ) new_h = r.h; auto res = rect{ x, y, new_w, new_h }; return res.adjust_ratio( { w, h } ); } rect zoom( float zoom_factor ) const { auto c = center(); return scale( zoom_factor ).center_at( { c.x, c.y } ); } rect enclose_in( rect in_rect ) const { rect out_rect{ x, y, w, h }; if( w > in_rect.w || h > in_rect.h ) { return in_rect; } if( x < in_rect.x ) { out_rect.x = in_rect.x; } if( y < in_rect.y ) { out_rect.y = in_rect.y; } if( x + w > in_rect.x + in_rect.w ) { out_rect.x = in_rect.x + in_rect.w - w; } if( y + h > in_rect.y + in_rect.h ) { out_rect.y = in_rect.y + in_rect.h - h; } return out_rect; } bool intersects( const rect & other ) const { return other.contains( { x, y } ) || other.contains( { x + w, y } ) || other.contains( { x, y + h } ) || other.contains( { x + w, y + h } ) || contains( { other.x, other.y } ); } }; } // namespace rs2