You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
5.3 KiB
200 lines
5.3 KiB
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
|
|
#pragma once
|
|
|
|
#include "float2.h"
|
|
|
|
#include <algorithm> // max,min
|
|
#include <cmath> // 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
|