2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* math_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2018-01-01 14:40:08 +01:00
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
2014-02-10 02:10:30 +01:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# ifndef MATH_2D_H
# define MATH_2D_H
# include "math_funcs.h"
# include "ustring.h"
/**
@ author Juan Linietsky < reduzio @ gmail . com >
*/
enum Margin {
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
MARGIN_LEFT ,
MARGIN_TOP ,
MARGIN_RIGHT ,
2016-03-09 00:00:52 +01:00
MARGIN_BOTTOM
2014-02-10 02:10:30 +01:00
} ;
2017-06-10 20:44:35 +02:00
enum Corner {
CORNER_TOP_LEFT ,
CORNER_TOP_RIGHT ,
CORNER_BOTTOM_RIGHT ,
CORNER_BOTTOM_LEFT
} ;
2014-02-10 02:10:30 +01:00
enum Orientation {
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
HORIZONTAL ,
VERTICAL
} ;
enum HAlign {
HALIGN_LEFT ,
HALIGN_CENTER ,
HALIGN_RIGHT
} ;
enum VAlign {
VALIGN_TOP ,
VALIGN_CENTER ,
VALIGN_BOTTOM
} ;
struct Vector2 {
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
union {
2017-01-06 06:27:48 +01:00
real_t x ;
real_t width ;
2014-02-10 02:10:30 +01:00
} ;
union {
2017-01-06 06:27:48 +01:00
real_t y ;
real_t height ;
2014-02-10 02:10:30 +01:00
} ;
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ real_t & operator [ ] ( int p_idx ) {
return p_idx ? y : x ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ const real_t & operator [ ] ( int p_idx ) const {
return p_idx ? y : x ;
2014-02-10 02:10:30 +01:00
}
void normalize ( ) ;
Vector2 normalized ( ) const ;
2017-03-31 17:25:09 +02:00
bool is_normalized ( ) const ;
2014-02-10 02:10:30 +01:00
2017-01-06 06:27:48 +01:00
real_t length ( ) const ;
real_t length_squared ( ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
real_t distance_to ( const Vector2 & p_vector2 ) const ;
real_t distance_squared_to ( const Vector2 & p_vector2 ) const ;
real_t angle_to ( const Vector2 & p_vector2 ) const ;
real_t angle_to_point ( const Vector2 & p_vector2 ) const ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
real_t dot ( const Vector2 & p_other ) const ;
real_t cross ( const Vector2 & p_other ) const ;
2014-02-10 02:10:30 +01:00
Vector2 cross ( real_t p_other ) const ;
2017-03-05 16:44:50 +01:00
Vector2 project ( const Vector2 & p_vec ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 plane_project ( real_t p_d , const Vector2 & p_vec ) const ;
2014-02-10 02:10:30 +01:00
Vector2 clamped ( real_t p_len ) const ;
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ static Vector2 linear_interpolate ( const Vector2 & p_a , const Vector2 & p_b , real_t p_t ) ;
_FORCE_INLINE_ Vector2 linear_interpolate ( const Vector2 & p_b , real_t p_t ) const ;
Vector2 cubic_interpolate ( const Vector2 & p_b , const Vector2 & p_pre_a , const Vector2 & p_post_b , real_t p_t ) const ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
Vector2 slide ( const Vector2 & p_normal ) const ;
Vector2 bounce ( const Vector2 & p_normal ) const ;
Vector2 reflect ( const Vector2 & p_normal ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 operator + ( const Vector2 & p_v ) const ;
void operator + = ( const Vector2 & p_v ) ;
Vector2 operator - ( const Vector2 & p_v ) const ;
void operator - = ( const Vector2 & p_v ) ;
2014-02-10 02:10:30 +01:00
Vector2 operator * ( const Vector2 & p_v1 ) const ;
2016-03-09 00:00:52 +01:00
2017-01-06 06:27:48 +01:00
Vector2 operator * ( const real_t & rvalue ) const ;
void operator * = ( const real_t & rvalue ) ;
2014-02-10 02:10:30 +01:00
void operator * = ( const Vector2 & rvalue ) { * this = * this * rvalue ; }
Vector2 operator / ( const Vector2 & p_v1 ) const ;
2016-03-09 00:00:52 +01:00
2017-01-06 06:27:48 +01:00
Vector2 operator / ( const real_t & rvalue ) const ;
2016-03-09 00:00:52 +01:00
2017-01-06 06:27:48 +01:00
void operator / = ( const real_t & rvalue ) ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
Vector2 operator - ( ) const ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
bool operator = = ( const Vector2 & p_vec2 ) const ;
bool operator ! = ( const Vector2 & p_vec2 ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool operator < ( const Vector2 & p_vec2 ) const { return ( x = = p_vec2 . x ) ? ( y < p_vec2 . y ) : ( x < p_vec2 . x ) ; }
bool operator < = ( const Vector2 & p_vec2 ) const { return ( x = = p_vec2 . x ) ? ( y < = p_vec2 . y ) : ( x < = p_vec2 . x ) ; }
2014-02-10 02:10:30 +01:00
2015-11-19 14:41:20 +01:00
real_t angle ( ) const ;
2014-02-10 02:10:30 +01:00
2017-01-06 06:27:48 +01:00
void set_rotation ( real_t p_radians ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
x = Math : : cos ( p_radians ) ;
y = Math : : sin ( p_radians ) ;
2014-02-10 02:10:30 +01:00
}
_FORCE_INLINE_ Vector2 abs ( ) const {
2017-03-05 16:44:50 +01:00
return Vector2 ( Math : : abs ( x ) , Math : : abs ( y ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-06 06:27:48 +01:00
Vector2 rotated ( real_t p_by ) const ;
2014-02-10 02:10:30 +01:00
Vector2 tangent ( ) const {
2017-03-05 16:44:50 +01:00
return Vector2 ( y , - x ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
Vector2 floor ( ) const ;
2017-03-05 16:44:50 +01:00
Vector2 snapped ( const Vector2 & p_by ) const ;
real_t aspect ( ) const { return width / height ; }
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
operator String ( ) const { return String : : num ( x ) + " , " + String : : num ( y ) ; }
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ Vector2 ( real_t p_x , real_t p_y ) {
x = p_x ;
y = p_y ;
}
_FORCE_INLINE_ Vector2 ( ) {
x = 0 ;
y = 0 ;
}
2014-02-10 02:10:30 +01:00
} ;
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ Vector2 Vector2 : : plane_project ( real_t p_d , const Vector2 & p_vec ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
return p_vec - * this * ( dot ( p_vec ) - p_d ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ Vector2 operator * ( real_t p_scalar , const Vector2 & p_vec ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
return p_vec * p_scalar ;
2014-02-10 02:10:30 +01:00
}
2017-12-25 15:58:14 +01:00
_FORCE_INLINE_ Vector2 Vector2 : : operator + ( const Vector2 & p_v ) const {
return Vector2 ( x + p_v . x , y + p_v . y ) ;
}
_FORCE_INLINE_ void Vector2 : : operator + = ( const Vector2 & p_v ) {
x + = p_v . x ;
y + = p_v . y ;
}
_FORCE_INLINE_ Vector2 Vector2 : : operator - ( const Vector2 & p_v ) const {
return Vector2 ( x - p_v . x , y - p_v . y ) ;
}
_FORCE_INLINE_ void Vector2 : : operator - = ( const Vector2 & p_v ) {
x - = p_v . x ;
y - = p_v . y ;
}
_FORCE_INLINE_ Vector2 Vector2 : : operator * ( const Vector2 & p_v1 ) const {
return Vector2 ( x * p_v1 . x , y * p_v1 . y ) ;
} ;
_FORCE_INLINE_ Vector2 Vector2 : : operator * ( const real_t & rvalue ) const {
return Vector2 ( x * rvalue , y * rvalue ) ;
} ;
_FORCE_INLINE_ void Vector2 : : operator * = ( const real_t & rvalue ) {
x * = rvalue ;
y * = rvalue ;
} ;
_FORCE_INLINE_ Vector2 Vector2 : : operator / ( const Vector2 & p_v1 ) const {
return Vector2 ( x / p_v1 . x , y / p_v1 . y ) ;
} ;
_FORCE_INLINE_ Vector2 Vector2 : : operator / ( const real_t & rvalue ) const {
return Vector2 ( x / rvalue , y / rvalue ) ;
} ;
_FORCE_INLINE_ void Vector2 : : operator / = ( const real_t & rvalue ) {
x / = rvalue ;
y / = rvalue ;
} ;
_FORCE_INLINE_ Vector2 Vector2 : : operator - ( ) const {
return Vector2 ( - x , - y ) ;
}
_FORCE_INLINE_ bool Vector2 : : operator = = ( const Vector2 & p_vec2 ) const {
return x = = p_vec2 . x & & y = = p_vec2 . y ;
}
_FORCE_INLINE_ bool Vector2 : : operator ! = ( const Vector2 & p_vec2 ) const {
return x ! = p_vec2 . x | | y ! = p_vec2 . y ;
}
2017-03-05 16:44:50 +01:00
Vector2 Vector2 : : linear_interpolate ( const Vector2 & p_b , real_t p_t ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 res = * this ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
res . x + = ( p_t * ( p_b . x - x ) ) ;
res . y + = ( p_t * ( p_b . y - y ) ) ;
2014-02-10 02:10:30 +01:00
return res ;
}
2017-03-05 16:44:50 +01:00
Vector2 Vector2 : : linear_interpolate ( const Vector2 & p_a , const Vector2 & p_b , real_t p_t ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 res = p_a ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
res . x + = ( p_t * ( p_b . x - p_a . x ) ) ;
res . y + = ( p_t * ( p_b . y - p_a . y ) ) ;
2014-02-10 02:10:30 +01:00
return res ;
}
typedef Vector2 Size2 ;
typedef Vector2 Point2 ;
2017-01-11 04:52:51 +01:00
struct Transform2D ;
2015-02-18 23:39:44 +01:00
2014-02-10 02:10:30 +01:00
struct Rect2 {
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
Point2 position ;
2014-02-10 02:10:30 +01:00
Size2 size ;
2017-06-04 00:25:13 +02:00
const Vector2 & get_position ( ) const { return position ; }
void set_position ( const Vector2 & p_pos ) { position = p_pos ; }
2017-03-05 16:44:50 +01:00
const Vector2 & get_size ( ) const { return size ; }
void set_size ( const Vector2 & p_size ) { size = p_size ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
real_t get_area ( ) const { return size . width * size . height ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
inline bool intersects ( const Rect2 & p_rect ) const {
2017-06-04 00:25:13 +02:00
if ( position . x > = ( p_rect . position . x + p_rect . size . width ) )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( ( position . x + size . width ) < = p_rect . position . x )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( position . y > = ( p_rect . position . y + p_rect . size . height ) )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( ( position . y + size . height ) < = p_rect . position . y )
2014-02-10 02:10:30 +01:00
return false ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
return true ;
}
2017-03-05 16:44:50 +01:00
inline real_t distance_to ( const Vector2 & p_point ) const {
2015-06-06 14:44:38 +02:00
2017-12-27 09:56:52 +01:00
real_t dist ;
bool inside = true ;
2015-06-06 14:44:38 +02:00
2017-06-04 00:25:13 +02:00
if ( p_point . x < position . x ) {
2017-12-27 09:56:52 +01:00
real_t d = position . x - p_point . x ;
dist = inside ? d : MIN ( dist , d ) ;
inside = false ;
2015-06-06 14:44:38 +02:00
}
2017-06-04 00:25:13 +02:00
if ( p_point . y < position . y ) {
2017-12-27 09:56:52 +01:00
real_t d = position . y - p_point . y ;
dist = inside ? d : MIN ( dist , d ) ;
inside = false ;
2015-06-06 14:44:38 +02:00
}
2017-06-04 00:25:13 +02:00
if ( p_point . x > = ( position . x + size . x ) ) {
2017-12-27 09:56:52 +01:00
real_t d = p_point . x - ( position . x + size . x ) ;
dist = inside ? d : MIN ( dist , d ) ;
inside = false ;
2015-06-06 14:44:38 +02:00
}
2017-06-04 00:25:13 +02:00
if ( p_point . y > = ( position . y + size . y ) ) {
2017-12-27 09:56:52 +01:00
real_t d = p_point . y - ( position . y + size . y ) ;
dist = inside ? d : MIN ( dist , d ) ;
inside = false ;
2015-06-06 14:44:38 +02:00
}
2017-12-27 09:56:52 +01:00
if ( inside )
2015-06-06 14:44:38 +02:00
return 0 ;
else
return dist ;
}
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ bool intersects_transformed ( const Transform2D & p_xform , const Rect2 & p_rect ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool intersects_segment ( const Point2 & p_from , const Point2 & p_to , Point2 * r_pos = NULL , Point2 * r_normal = NULL ) const ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
inline bool encloses ( const Rect2 & p_rect ) const {
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
return ( p_rect . position . x > = position . x ) & & ( p_rect . position . y > = position . y ) & &
( ( p_rect . position . x + p_rect . size . x ) < ( position . x + size . x ) ) & &
( ( p_rect . position . y + p_rect . size . y ) < ( position . y + size . y ) ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
inline bool has_no_area ( ) const {
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
return ( size . x < = 0 | | size . y < = 0 ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
inline Rect2 clip ( const Rect2 & p_rect ) const { /// return a clipped rect
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
Rect2 new_rect = p_rect ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
if ( ! intersects ( new_rect ) )
2014-02-10 02:10:30 +01:00
return Rect2 ( ) ;
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
new_rect . position . x = MAX ( p_rect . position . x , position . x ) ;
new_rect . position . y = MAX ( p_rect . position . y , position . y ) ;
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
Point2 p_rect_end = p_rect . position + p_rect . size ;
Point2 end = position + size ;
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
new_rect . size . x = MIN ( p_rect_end . x , end . x ) - new_rect . position . x ;
new_rect . size . y = MIN ( p_rect_end . y , end . y ) - new_rect . position . y ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
return new_rect ;
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
inline Rect2 merge ( const Rect2 & p_rect ) const { ///< return a merged rect
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
Rect2 new_rect ;
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
new_rect . position . x = MIN ( p_rect . position . x , position . x ) ;
new_rect . position . y = MIN ( p_rect . position . y , position . y ) ;
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
new_rect . size . x = MAX ( p_rect . position . x + p_rect . size . x , position . x + size . x ) ;
new_rect . size . y = MAX ( p_rect . position . y + p_rect . size . y , position . y + size . y ) ;
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
new_rect . size = new_rect . size - new_rect . position ; //make relative again
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
return new_rect ;
} ;
2017-03-05 16:44:50 +01:00
inline bool has_point ( const Point2 & p_point ) const {
2017-06-04 00:25:13 +02:00
if ( p_point . x < position . x )
2016-03-09 00:00:52 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( p_point . y < position . y )
2016-03-09 00:00:52 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( p_point . x > = ( position . x + size . x ) )
2016-03-09 00:00:52 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( p_point . y > = ( position . y + size . y ) )
2016-03-09 00:00:52 +01:00
return false ;
2014-02-10 02:10:30 +01:00
return true ;
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
inline bool no_area ( ) const { return ( size . width < = 0 | | size . height < = 0 ) ; }
2016-03-09 00:00:52 +01:00
2017-06-04 00:25:13 +02:00
bool operator = = ( const Rect2 & p_rect ) const { return position = = p_rect . position & & size = = p_rect . size ; }
bool operator ! = ( const Rect2 & p_rect ) const { return position ! = p_rect . position | | size ! = p_rect . size ; }
2016-03-09 00:00:52 +01:00
2014-04-17 13:30:40 +02:00
inline Rect2 grow ( real_t p_by ) const {
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
Rect2 g = * this ;
2017-06-04 00:25:13 +02:00
g . position . x - = p_by ;
g . position . y - = p_by ;
2017-03-05 16:44:50 +01:00
g . size . width + = p_by * 2 ;
g . size . height + = p_by * 2 ;
2014-02-10 02:10:30 +01:00
return g ;
}
2017-12-21 23:51:46 +01:00
2017-05-29 13:36:14 +02:00
inline Rect2 grow_margin ( Margin p_margin , real_t p_amount ) const {
Rect2 g = * this ;
2017-12-21 23:51:46 +01:00
g = g . grow_individual ( ( MARGIN_LEFT = = p_margin ) ? p_amount : 0 ,
2017-05-29 13:36:14 +02:00
( MARGIN_TOP = = p_margin ) ? p_amount : 0 ,
( MARGIN_RIGHT = = p_margin ) ? p_amount : 0 ,
( MARGIN_BOTTOM = = p_margin ) ? p_amount : 0 ) ;
return g ;
}
inline Rect2 grow_individual ( real_t p_left , real_t p_top , real_t p_right , real_t p_bottom ) const {
Rect2 g = * this ;
2017-06-08 07:45:07 +02:00
g . position . x - = p_left ;
g . position . y - = p_top ;
2017-05-29 13:36:14 +02:00
g . size . width + = p_left + p_right ;
g . size . height + = p_top + p_bottom ;
return g ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
inline Rect2 expand ( const Vector2 & p_vector ) const {
2014-02-10 02:10:30 +01:00
Rect2 r = * this ;
r . expand_to ( p_vector ) ;
return r ;
}
2017-03-05 16:44:50 +01:00
inline void expand_to ( const Vector2 & p_vector ) { //in place function for speed
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
Vector2 begin = position ;
Vector2 end = position + size ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_vector . x < begin . x )
begin . x = p_vector . x ;
if ( p_vector . y < begin . y )
begin . y = p_vector . y ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_vector . x > end . x )
end . x = p_vector . x ;
if ( p_vector . y > end . y )
end . y = p_vector . y ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
position = begin ;
2017-03-05 16:44:50 +01:00
size = end - begin ;
2014-02-10 02:10:30 +01:00
}
2017-11-27 18:41:29 +01:00
inline Rect2 abs ( ) const {
return Rect2 ( Point2 ( position . x + MIN ( size . x , 0 ) , position . y + MIN ( size . y , 0 ) ) , size . abs ( ) ) ;
}
2017-06-04 00:25:13 +02:00
operator String ( ) const { return String ( position ) + " , " + String ( size ) ; }
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
Rect2 ( ) { }
2017-12-06 21:36:34 +01:00
Rect2 ( real_t p_x , real_t p_y , real_t p_width , real_t p_height ) :
position ( Point2 ( p_x , p_y ) ) ,
size ( Size2 ( p_width , p_height ) ) {
2017-03-05 16:44:50 +01:00
}
2017-12-06 21:36:34 +01:00
Rect2 ( const Point2 & p_pos , const Size2 & p_size ) :
position ( p_pos ) ,
size ( p_size ) {
2017-03-05 16:44:50 +01:00
}
2014-02-10 02:10:30 +01:00
} ;
/* INTEGER STUFF */
struct Point2i {
union {
int x ;
int width ;
} ;
union {
int y ;
int height ;
} ;
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ int & operator [ ] ( int p_idx ) {
return p_idx ? y : x ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ const int & operator [ ] ( int p_idx ) const {
return p_idx ? y : x ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Point2i operator + ( const Point2i & p_v ) const ;
void operator + = ( const Point2i & p_v ) ;
Point2i operator - ( const Point2i & p_v ) const ;
void operator - = ( const Point2i & p_v ) ;
2014-02-10 02:10:30 +01:00
Point2i operator * ( const Point2i & p_v1 ) const ;
Point2i operator * ( const int & rvalue ) const ;
void operator * = ( const int & rvalue ) ;
Point2i operator / ( const Point2i & p_v1 ) const ;
Point2i operator / ( const int & rvalue ) const ;
void operator / = ( const int & rvalue ) ;
Point2i operator - ( ) const ;
2017-03-05 16:44:50 +01:00
bool operator < ( const Point2i & p_vec2 ) const { return ( x = = p_vec2 . x ) ? ( y < p_vec2 . y ) : ( x < p_vec2 . x ) ; }
bool operator > ( const Point2i & p_vec2 ) const { return ( x = = p_vec2 . x ) ? ( y > p_vec2 . y ) : ( x > p_vec2 . x ) ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool operator = = ( const Point2i & p_vec2 ) const ;
bool operator ! = ( const Point2i & p_vec2 ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
real_t get_aspect ( ) const { return width / ( real_t ) height ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
operator String ( ) const { return String : : num ( x ) + " , " + String : : num ( y ) ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
operator Vector2 ( ) const { return Vector2 ( x , y ) ; }
inline Point2i ( const Vector2 & p_vec2 ) {
x = ( int ) p_vec2 . x ;
y = ( int ) p_vec2 . y ;
}
inline Point2i ( int p_x , int p_y ) {
x = p_x ;
y = p_y ;
}
inline Point2i ( ) {
x = 0 ;
y = 0 ;
}
2014-02-10 02:10:30 +01:00
} ;
typedef Point2i Size2i ;
struct Rect2i {
2017-06-04 00:25:13 +02:00
Point2i position ;
2014-02-10 02:10:30 +01:00
Size2i size ;
2017-06-04 00:25:13 +02:00
const Point2i & get_position ( ) const { return position ; }
void set_position ( const Point2i & p_pos ) { position = p_pos ; }
2017-03-05 16:44:50 +01:00
const Point2i & get_size ( ) const { return size ; }
void set_size ( const Point2i & p_size ) { size = p_size ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int get_area ( ) const { return size . width * size . height ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
inline bool intersects ( const Rect2i & p_rect ) const {
2017-06-04 00:25:13 +02:00
if ( position . x > ( p_rect . position . x + p_rect . size . width ) )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( ( position . x + size . width ) < p_rect . position . x )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( position . y > ( p_rect . position . y + p_rect . size . height ) )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( ( position . y + size . height ) < p_rect . position . y )
2014-02-10 02:10:30 +01:00
return false ;
return true ;
}
2017-03-05 16:44:50 +01:00
inline bool encloses ( const Rect2i & p_rect ) const {
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
return ( p_rect . position . x > = position . x ) & & ( p_rect . position . y > = position . y ) & &
( ( p_rect . position . x + p_rect . size . x ) < ( position . x + size . x ) ) & &
( ( p_rect . position . y + p_rect . size . y ) < ( position . y + size . y ) ) ;
2014-02-10 02:10:30 +01:00
}
inline bool has_no_area ( ) const {
2017-03-05 16:44:50 +01:00
return ( size . x < = 0 | | size . y < = 0 ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
inline Rect2i clip ( const Rect2i & p_rect ) const { /// return a clipped rect
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Rect2i new_rect = p_rect ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( ! intersects ( new_rect ) )
2014-02-10 02:10:30 +01:00
return Rect2i ( ) ;
2017-06-04 00:25:13 +02:00
new_rect . position . x = MAX ( p_rect . position . x , position . x ) ;
new_rect . position . y = MAX ( p_rect . position . y , position . y ) ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
Point2 p_rect_end = p_rect . position + p_rect . size ;
Point2 end = position + size ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
new_rect . size . x = ( int ) ( MIN ( p_rect_end . x , end . x ) - new_rect . position . x ) ;
new_rect . size . y = ( int ) ( MIN ( p_rect_end . y , end . y ) - new_rect . position . y ) ;
2014-02-10 02:10:30 +01:00
return new_rect ;
}
2017-03-05 16:44:50 +01:00
inline Rect2i merge ( const Rect2i & p_rect ) const { ///< return a merged rect
2014-02-10 02:10:30 +01:00
Rect2i new_rect ;
2017-06-04 00:25:13 +02:00
new_rect . position . x = MIN ( p_rect . position . x , position . x ) ;
new_rect . position . y = MIN ( p_rect . position . y , position . y ) ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
new_rect . size . x = MAX ( p_rect . position . x + p_rect . size . x , position . x + size . x ) ;
new_rect . size . y = MAX ( p_rect . position . y + p_rect . size . y , position . y + size . y ) ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
new_rect . size = new_rect . size - new_rect . position ; //make relative again
2014-02-10 02:10:30 +01:00
return new_rect ;
} ;
2017-03-05 16:44:50 +01:00
bool has_point ( const Point2 & p_point ) const {
2017-06-04 00:25:13 +02:00
if ( p_point . x < position . x )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( p_point . y < position . y )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( p_point . x > = ( position . x + size . x ) )
2014-02-10 02:10:30 +01:00
return false ;
2017-06-04 00:25:13 +02:00
if ( p_point . y > = ( position . y + size . y ) )
2014-02-10 02:10:30 +01:00
return false ;
return true ;
}
2017-03-05 16:44:50 +01:00
bool no_area ( ) { return ( size . width < = 0 | | size . height < = 0 ) ; }
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
bool operator = = ( const Rect2i & p_rect ) const { return position = = p_rect . position & & size = = p_rect . size ; }
bool operator ! = ( const Rect2i & p_rect ) const { return position ! = p_rect . position | | size ! = p_rect . size ; }
2014-02-10 02:10:30 +01:00
Rect2i grow ( int p_by ) const {
2017-03-05 16:44:50 +01:00
Rect2i g = * this ;
2017-06-04 00:25:13 +02:00
g . position . x - = p_by ;
g . position . y - = p_by ;
2017-03-05 16:44:50 +01:00
g . size . width + = p_by * 2 ;
g . size . height + = p_by * 2 ;
2014-02-10 02:10:30 +01:00
return g ;
}
2017-03-05 16:44:50 +01:00
inline void expand_to ( const Point2i & p_vector ) {
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
Point2i begin = position ;
Point2i end = position + size ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_vector . x < begin . x )
begin . x = p_vector . x ;
if ( p_vector . y < begin . y )
begin . y = p_vector . y ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_vector . x > end . x )
end . x = p_vector . x ;
if ( p_vector . y > end . y )
end . y = p_vector . y ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
position = begin ;
2017-03-05 16:44:50 +01:00
size = end - begin ;
2014-02-10 02:10:30 +01:00
}
2017-06-04 00:25:13 +02:00
operator String ( ) const { return String ( position ) + " , " + String ( size ) ; }
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
operator Rect2 ( ) const { return Rect2 ( position , size ) ; }
2017-12-06 21:36:34 +01:00
Rect2i ( const Rect2 & p_r2 ) :
position ( p_r2 . position ) ,
size ( p_r2 . size ) {
2017-03-05 16:44:50 +01:00
}
2014-02-10 02:10:30 +01:00
Rect2i ( ) { }
2017-12-06 21:36:34 +01:00
Rect2i ( int p_x , int p_y , int p_width , int p_height ) :
position ( Point2 ( p_x , p_y ) ) ,
size ( Size2 ( p_width , p_height ) ) {
2017-03-05 16:44:50 +01:00
}
2017-12-06 21:36:34 +01:00
Rect2i ( const Point2 & p_pos , const Size2 & p_size ) :
position ( p_pos ) ,
size ( p_size ) {
2017-03-05 16:44:50 +01:00
}
2014-02-10 02:10:30 +01:00
} ;
2017-01-11 04:52:51 +01:00
struct Transform2D {
// Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper":
2017-01-06 06:27:48 +01:00
// M = (elements[0][0] elements[1][0])
// (elements[0][1] elements[1][1])
// This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as elements[i].
// Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to elements[1][0] here.
// This requires additional care when working with explicit indices.
2017-03-05 16:44:50 +01:00
// See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading.
2017-01-06 06:27:48 +01:00
// Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down,
// and angle is measure from +X to +Y in a clockwise-fashion.
2014-02-10 02:10:30 +01:00
Vector2 elements [ 3 ] ;
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ real_t tdotx ( const Vector2 & v ) const { return elements [ 0 ] [ 0 ] * v . x + elements [ 1 ] [ 0 ] * v . y ; }
_FORCE_INLINE_ real_t tdoty ( const Vector2 & v ) const { return elements [ 0 ] [ 1 ] * v . x + elements [ 1 ] [ 1 ] * v . y ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
const Vector2 & operator [ ] ( int p_idx ) const { return elements [ p_idx ] ; }
Vector2 & operator [ ] ( int p_idx ) { return elements [ p_idx ] ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ Vector2 get_axis ( int p_axis ) const {
ERR_FAIL_INDEX_V ( p_axis , 3 , Vector2 ( ) ) ;
return elements [ p_axis ] ;
}
_FORCE_INLINE_ void set_axis ( int p_axis , const Vector2 & p_vec ) {
ERR_FAIL_INDEX ( p_axis , 3 ) ;
elements [ p_axis ] = p_vec ;
}
2014-02-10 02:10:30 +01:00
void invert ( ) ;
2017-01-11 04:52:51 +01:00
Transform2D inverse ( ) const ;
2014-02-10 02:10:30 +01:00
void affine_invert ( ) ;
2017-01-11 04:52:51 +01:00
Transform2D affine_inverse ( ) const ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
void set_rotation ( real_t p_rot ) ;
2014-02-10 02:10:30 +01:00
real_t get_rotation ( ) const ;
2017-08-11 21:10:05 +02:00
_FORCE_INLINE_ void set_rotation_and_scale ( real_t p_rot , const Size2 & p_scale ) ;
2014-02-10 02:10:30 +01:00
void rotate ( real_t p_phi ) ;
2017-03-05 16:44:50 +01:00
void scale ( const Size2 & p_scale ) ;
void scale_basis ( const Size2 & p_scale ) ;
void translate ( real_t p_tx , real_t p_ty ) ;
void translate ( const Vector2 & p_translation ) ;
2014-07-06 16:49:27 +02:00
2017-01-06 06:27:48 +01:00
real_t basis_determinant ( ) const ;
2014-07-06 16:49:27 +02:00
2016-09-20 06:36:24 +02:00
Size2 get_scale ( ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ const Vector2 & get_origin ( ) const { return elements [ 2 ] ; }
_FORCE_INLINE_ void set_origin ( const Vector2 & p_origin ) { elements [ 2 ] = p_origin ; }
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Transform2D scaled ( const Size2 & p_scale ) const ;
Transform2D basis_scaled ( const Size2 & p_scale ) const ;
Transform2D translated ( const Vector2 & p_offset ) const ;
2017-01-11 04:52:51 +01:00
Transform2D rotated ( real_t p_phi ) const ;
2014-02-10 02:10:30 +01:00
2017-01-11 04:52:51 +01:00
Transform2D untranslated ( ) const ;
2014-02-10 02:10:30 +01:00
void orthonormalize ( ) ;
2017-01-11 04:52:51 +01:00
Transform2D orthonormalized ( ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool operator = = ( const Transform2D & p_transform ) const ;
bool operator ! = ( const Transform2D & p_transform ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
void operator * = ( const Transform2D & p_transform ) ;
Transform2D operator * ( const Transform2D & p_transform ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Transform2D interpolate_with ( const Transform2D & p_transform , real_t p_c ) const ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_FORCE_INLINE_ Vector2 basis_xform ( const Vector2 & p_vec ) const ;
_FORCE_INLINE_ Vector2 basis_xform_inv ( const Vector2 & p_vec ) const ;
_FORCE_INLINE_ Vector2 xform ( const Vector2 & p_vec ) const ;
_FORCE_INLINE_ Vector2 xform_inv ( const Vector2 & p_vec ) const ;
2017-08-11 21:10:05 +02:00
_FORCE_INLINE_ Rect2 xform ( const Rect2 & p_rect ) const ;
_FORCE_INLINE_ Rect2 xform_inv ( const Rect2 & p_rect ) const ;
2014-02-10 02:10:30 +01:00
operator String ( ) const ;
2017-01-11 04:52:51 +01:00
Transform2D ( real_t xx , real_t xy , real_t yx , real_t yy , real_t ox , real_t oy ) {
2016-08-24 18:54:23 +02:00
elements [ 0 ] [ 0 ] = xx ;
elements [ 0 ] [ 1 ] = xy ;
elements [ 1 ] [ 0 ] = yx ;
elements [ 1 ] [ 1 ] = yy ;
elements [ 2 ] [ 0 ] = ox ;
elements [ 2 ] [ 1 ] = oy ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Transform2D ( real_t p_rot , const Vector2 & p_pos ) ;
Transform2D ( ) {
elements [ 0 ] [ 0 ] = 1.0 ;
elements [ 1 ] [ 1 ] = 1.0 ;
}
2014-02-10 02:10:30 +01:00
} ;
2017-03-05 16:44:50 +01:00
bool Rect2 : : intersects_transformed ( const Transform2D & p_xform , const Rect2 & p_rect ) const {
2015-02-18 23:39:44 +01:00
//SAT intersection between local and transformed rect2
2017-03-05 16:44:50 +01:00
Vector2 xf_points [ 4 ] = {
2017-06-04 00:25:13 +02:00
p_xform . xform ( p_rect . position ) ,
p_xform . xform ( Vector2 ( p_rect . position . x + p_rect . size . x , p_rect . position . y ) ) ,
p_xform . xform ( Vector2 ( p_rect . position . x , p_rect . position . y + p_rect . size . y ) ) ,
p_xform . xform ( Vector2 ( p_rect . position . x + p_rect . size . x , p_rect . position . y + p_rect . size . y ) ) ,
2015-02-18 23:39:44 +01:00
} ;
real_t low_limit ;
//base rect2 first (faster)
2017-06-04 00:25:13 +02:00
if ( xf_points [ 0 ] . y > position . y )
2015-02-18 23:39:44 +01:00
goto next1 ;
2017-06-04 00:25:13 +02:00
if ( xf_points [ 1 ] . y > position . y )
2015-02-18 23:39:44 +01:00
goto next1 ;
2017-06-04 00:25:13 +02:00
if ( xf_points [ 2 ] . y > position . y )
2015-02-18 23:39:44 +01:00
goto next1 ;
2017-06-04 00:25:13 +02:00
if ( xf_points [ 3 ] . y > position . y )
2015-02-18 23:39:44 +01:00
goto next1 ;
return false ;
2017-03-05 16:44:50 +01:00
next1 :
2015-02-18 23:39:44 +01:00
2017-06-04 00:25:13 +02:00
low_limit = position . y + size . y ;
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
if ( xf_points [ 0 ] . y < low_limit )
2015-02-18 23:39:44 +01:00
goto next2 ;
2017-03-05 16:44:50 +01:00
if ( xf_points [ 1 ] . y < low_limit )
2015-02-18 23:39:44 +01:00
goto next2 ;
2017-03-05 16:44:50 +01:00
if ( xf_points [ 2 ] . y < low_limit )
2015-02-18 23:39:44 +01:00
goto next2 ;
2017-03-05 16:44:50 +01:00
if ( xf_points [ 3 ] . y < low_limit )
2015-02-18 23:39:44 +01:00
goto next2 ;
return false ;
2017-03-05 16:44:50 +01:00
next2 :
2015-02-18 23:39:44 +01:00
2017-06-04 00:25:13 +02:00
if ( xf_points [ 0 ] . x > position . x )
2015-02-18 23:39:44 +01:00
goto next3 ;
2017-06-04 00:25:13 +02:00
if ( xf_points [ 1 ] . x > position . x )
2015-02-18 23:39:44 +01:00
goto next3 ;
2017-06-04 00:25:13 +02:00
if ( xf_points [ 2 ] . x > position . x )
2015-02-18 23:39:44 +01:00
goto next3 ;
2017-06-04 00:25:13 +02:00
if ( xf_points [ 3 ] . x > position . x )
2015-02-18 23:39:44 +01:00
goto next3 ;
return false ;
2017-03-05 16:44:50 +01:00
next3 :
2015-02-18 23:39:44 +01:00
2017-06-04 00:25:13 +02:00
low_limit = position . x + size . x ;
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
if ( xf_points [ 0 ] . x < low_limit )
2015-02-18 23:39:44 +01:00
goto next4 ;
2017-03-05 16:44:50 +01:00
if ( xf_points [ 1 ] . x < low_limit )
2015-02-18 23:39:44 +01:00
goto next4 ;
2017-03-05 16:44:50 +01:00
if ( xf_points [ 2 ] . x < low_limit )
2015-02-18 23:39:44 +01:00
goto next4 ;
2017-03-05 16:44:50 +01:00
if ( xf_points [ 3 ] . x < low_limit )
2015-02-18 23:39:44 +01:00
goto next4 ;
return false ;
2017-03-05 16:44:50 +01:00
next4 :
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
Vector2 xf_points2 [ 4 ] = {
2017-06-04 00:25:13 +02:00
position ,
Vector2 ( position . x + size . x , position . y ) ,
Vector2 ( position . x , position . y + size . y ) ,
Vector2 ( position . x + size . x , position . y + size . y ) ,
2015-02-18 23:39:44 +01:00
} ;
2017-03-05 16:44:50 +01:00
real_t maxa = p_xform . elements [ 0 ] . dot ( xf_points2 [ 0 ] ) ;
real_t mina = maxa ;
2015-02-18 23:39:44 +01:00
real_t dp = p_xform . elements [ 0 ] . dot ( xf_points2 [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
maxa = MAX ( dp , maxa ) ;
mina = MIN ( dp , mina ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 0 ] . dot ( xf_points2 [ 2 ] ) ;
2017-03-05 16:44:50 +01:00
maxa = MAX ( dp , maxa ) ;
mina = MIN ( dp , mina ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 0 ] . dot ( xf_points2 [ 3 ] ) ;
2017-03-05 16:44:50 +01:00
maxa = MAX ( dp , maxa ) ;
mina = MIN ( dp , mina ) ;
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
real_t maxb = p_xform . elements [ 0 ] . dot ( xf_points [ 0 ] ) ;
real_t minb = maxb ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 0 ] . dot ( xf_points [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
maxb = MAX ( dp , maxb ) ;
minb = MIN ( dp , minb ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 0 ] . dot ( xf_points [ 2 ] ) ;
2017-03-05 16:44:50 +01:00
maxb = MAX ( dp , maxb ) ;
minb = MIN ( dp , minb ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 0 ] . dot ( xf_points [ 3 ] ) ;
2017-03-05 16:44:50 +01:00
maxb = MAX ( dp , maxb ) ;
minb = MIN ( dp , minb ) ;
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
if ( mina > maxb )
2015-02-18 23:39:44 +01:00
return false ;
2017-03-05 16:44:50 +01:00
if ( minb > maxa )
2015-02-18 23:39:44 +01:00
return false ;
2017-03-05 16:44:50 +01:00
maxa = p_xform . elements [ 1 ] . dot ( xf_points2 [ 0 ] ) ;
mina = maxa ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 1 ] . dot ( xf_points2 [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
maxa = MAX ( dp , maxa ) ;
mina = MIN ( dp , mina ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 1 ] . dot ( xf_points2 [ 2 ] ) ;
2017-03-05 16:44:50 +01:00
maxa = MAX ( dp , maxa ) ;
mina = MIN ( dp , mina ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 1 ] . dot ( xf_points2 [ 3 ] ) ;
2017-03-05 16:44:50 +01:00
maxa = MAX ( dp , maxa ) ;
mina = MIN ( dp , mina ) ;
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
maxb = p_xform . elements [ 1 ] . dot ( xf_points [ 0 ] ) ;
minb = maxb ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 1 ] . dot ( xf_points [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
maxb = MAX ( dp , maxb ) ;
minb = MIN ( dp , minb ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 1 ] . dot ( xf_points [ 2 ] ) ;
2017-03-05 16:44:50 +01:00
maxb = MAX ( dp , maxb ) ;
minb = MIN ( dp , minb ) ;
2015-02-18 23:39:44 +01:00
dp = p_xform . elements [ 1 ] . dot ( xf_points [ 3 ] ) ;
2017-03-05 16:44:50 +01:00
maxb = MAX ( dp , maxb ) ;
minb = MIN ( dp , minb ) ;
2015-02-18 23:39:44 +01:00
2017-03-05 16:44:50 +01:00
if ( mina > maxb )
2015-02-18 23:39:44 +01:00
return false ;
2017-03-05 16:44:50 +01:00
if ( minb > maxa )
2015-02-18 23:39:44 +01:00
return false ;
return true ;
}
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
Vector2 Transform2D : : basis_xform ( const Vector2 & p_vec ) const {
2014-02-10 02:10:30 +01:00
return Vector2 (
2017-08-11 21:10:05 +02:00
tdotx ( p_vec ) ,
tdoty ( p_vec ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-11 21:10:05 +02:00
Vector2 Transform2D : : basis_xform_inv ( const Vector2 & p_vec ) const {
2014-02-10 02:10:30 +01:00
return Vector2 (
2017-08-11 21:10:05 +02:00
elements [ 0 ] . dot ( p_vec ) ,
elements [ 1 ] . dot ( p_vec ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-11 21:10:05 +02:00
Vector2 Transform2D : : xform ( const Vector2 & p_vec ) const {
2014-02-10 02:10:30 +01:00
return Vector2 (
2017-08-11 21:10:05 +02:00
tdotx ( p_vec ) ,
tdoty ( p_vec ) ) +
2017-03-05 16:44:50 +01:00
elements [ 2 ] ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Vector2 Transform2D : : xform_inv ( const Vector2 & p_vec ) const {
2014-02-10 02:10:30 +01:00
Vector2 v = p_vec - elements [ 2 ] ;
return Vector2 (
2017-03-05 16:44:50 +01:00
elements [ 0 ] . dot ( v ) ,
elements [ 1 ] . dot ( v ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Rect2 Transform2D : : xform ( const Rect2 & p_rect ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 x = elements [ 0 ] * p_rect . size . x ;
Vector2 y = elements [ 1 ] * p_rect . size . y ;
2017-06-04 00:25:13 +02:00
Vector2 pos = xform ( p_rect . position ) ;
2014-02-10 02:10:30 +01:00
Rect2 new_rect ;
2017-06-04 00:25:13 +02:00
new_rect . position = pos ;
2017-03-05 16:44:50 +01:00
new_rect . expand_to ( pos + x ) ;
new_rect . expand_to ( pos + y ) ;
new_rect . expand_to ( pos + x + y ) ;
2014-02-10 02:10:30 +01:00
return new_rect ;
}
2017-03-05 16:44:50 +01:00
void Transform2D : : set_rotation_and_scale ( real_t p_rot , const Size2 & p_scale ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
elements [ 0 ] [ 0 ] = Math : : cos ( p_rot ) * p_scale . x ;
elements [ 1 ] [ 1 ] = Math : : cos ( p_rot ) * p_scale . y ;
elements [ 1 ] [ 0 ] = - Math : : sin ( p_rot ) * p_scale . y ;
elements [ 0 ] [ 1 ] = Math : : sin ( p_rot ) * p_scale . x ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Rect2 Transform2D : : xform_inv ( const Rect2 & p_rect ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 ends [ 4 ] = {
2017-06-04 00:25:13 +02:00
xform_inv ( p_rect . position ) ,
xform_inv ( Vector2 ( p_rect . position . x , p_rect . position . y + p_rect . size . y ) ) ,
xform_inv ( Vector2 ( p_rect . position . x + p_rect . size . x , p_rect . position . y + p_rect . size . y ) ) ,
xform_inv ( Vector2 ( p_rect . position . x + p_rect . size . x , p_rect . position . y ) )
2014-02-10 02:10:30 +01:00
} ;
Rect2 new_rect ;
2017-06-04 00:25:13 +02:00
new_rect . position = ends [ 0 ] ;
2014-02-10 02:10:30 +01:00
new_rect . expand_to ( ends [ 1 ] ) ;
new_rect . expand_to ( ends [ 2 ] ) ;
new_rect . expand_to ( ends [ 3 ] ) ;
return new_rect ;
}
# endif