1 /*************************************************************************** 2 * Free Heroes of Might and Magic II: https://github.com/ihhub/fheroes2 * 3 * Copyright (C) 2020 * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 ***************************************************************************/ 20 21 #pragma once 22 23 #include <cmath> 24 #include <cstdint> 25 26 #ifndef M_PI 27 #define M_PI 3.14159265358979323846 28 #endif 29 30 // Below source code was partially taken from https://github.com/ihhub/penguinv open source project 31 namespace fheroes2 32 { 33 // overload this function for floating types 34 template <typename _Type> isEqual(const _Type & value1,const _Type & value2)35 bool isEqual( const _Type & value1, const _Type & value2 ) 36 { 37 return ( value1 == value2 ); 38 } 39 40 template <typename _Type> 41 struct PointBase2D 42 { PointBase2DPointBase2D43 PointBase2D() 44 : x( 0 ) 45 , y( 0 ) 46 {} 47 PointBase2DPointBase2D48 PointBase2D( _Type _x, _Type _y ) 49 : x( _x ) 50 , y( _y ) 51 {} 52 53 bool operator==( const PointBase2D & point ) const 54 { 55 return isEqual( x, point.x ) && isEqual( y, point.y ); 56 } 57 58 bool operator!=( const PointBase2D & point ) const 59 { 60 return !( *this == point ); 61 } 62 63 PointBase2D & operator+=( const PointBase2D & point ) 64 { 65 x += point.x; 66 y += point.y; 67 return *this; 68 } 69 70 PointBase2D & operator-=( const PointBase2D & point ) 71 { 72 x -= point.x; 73 y -= point.y; 74 return *this; 75 } 76 77 PointBase2D operator+( const PointBase2D & point ) const 78 { 79 return PointBase2D( x + point.x, y + point.y ); 80 } 81 82 PointBase2D operator-( const PointBase2D & point ) const 83 { 84 return PointBase2D( x - point.x, y - point.y ); 85 } 86 87 bool operator<( const PointBase2D & point ) const 88 { 89 return x == point.x ? y < point.y : x < point.x; 90 } 91 92 _Type x; 93 _Type y; 94 }; 95 96 template <typename _Type> 97 struct SizeBase2D 98 { SizeBase2DSizeBase2D99 SizeBase2D() 100 : width( 0 ) 101 , height( 0 ) 102 {} 103 SizeBase2DSizeBase2D104 SizeBase2D( _Type _width, _Type _height ) 105 : width( _width ) 106 , height( _height ) 107 {} 108 109 bool operator==( const SizeBase2D & size ) const 110 { 111 return isEqual( width, size.width ) && isEqual( height, size.height ); 112 } 113 114 bool operator!=( const SizeBase2D & size ) const 115 { 116 return !( *this == size ); 117 } 118 119 bool operator<( const SizeBase2D & size ) const 120 { 121 return width < size.width || ( width == size.width && height < size.height ); 122 } 123 124 SizeBase2D & operator+=( const SizeBase2D & size ) 125 { 126 width += size.width; 127 height += size.height; 128 return *this; 129 } 130 131 SizeBase2D & operator-=( const SizeBase2D & size ) 132 { 133 width -= size.width; 134 height -= size.height; 135 return *this; 136 } 137 138 SizeBase2D operator+( const SizeBase2D & size ) const 139 { 140 return SizeBase2D( width + size.width, height + size.height ); 141 } 142 143 SizeBase2D operator-( const SizeBase2D & size ) const 144 { 145 return SizeBase2D( width - size.width, height - size.height ); 146 } 147 148 _Type width; 149 _Type height; 150 }; 151 152 template <typename _TypePoint, typename _TypeSize> 153 struct RectBase2D 154 { RectBase2DRectBase2D155 RectBase2D() 156 : x( 0 ) 157 , y( 0 ) 158 , width( 0 ) 159 , height( 0 ) 160 {} 161 RectBase2DRectBase2D162 RectBase2D( _TypePoint _x, _TypePoint _y, _TypeSize _width, _TypeSize _height ) 163 : x( _x ) 164 , y( _y ) 165 , width( _width ) 166 , height( _height ) 167 {} 168 RectBase2DRectBase2D169 RectBase2D( const PointBase2D<_TypePoint> & point, const SizeBase2D<_TypeSize> & size ) 170 : x( point.x ) 171 , y( point.y ) 172 , width( size.width ) 173 , height( size.height ) 174 {} 175 176 bool operator==( const RectBase2D & rect ) const 177 { 178 return isEqual( x, rect.x ) && isEqual( y, rect.y ) && isEqual( width, rect.width ) && isEqual( height, rect.height ); 179 } 180 181 bool operator!=( const RectBase2D & rect ) const 182 { 183 return !( *this == rect ); 184 } 185 186 RectBase2D & operator+=( const PointBase2D<_TypePoint> & point ) 187 { 188 x += point.x; 189 y += point.y; 190 return *this; 191 } 192 193 RectBase2D & operator-=( const PointBase2D<_TypePoint> & point ) 194 { 195 x -= point.x; 196 y -= point.y; 197 return *this; 198 } 199 200 RectBase2D operator+( const PointBase2D<_TypePoint> & point ) const 201 { 202 return RectBase2D( x + point.x, y + point.y, width, height ); 203 } 204 205 RectBase2D operator-( const PointBase2D<_TypePoint> & point ) const 206 { 207 return RectBase2D( x - point.x, y - point.y, width, height ); 208 } 209 210 // Check whether a point within the rectangle 211 bool operator&( const PointBase2D<_TypePoint> & point ) const 212 { 213 return point.x >= x && point.y >= y && point.x < ( x + width ) && point.y < ( y + height ); 214 } 215 216 // Check whether rectangles are intersecting each other 217 bool operator&( const RectBase2D & rect ) const 218 { 219 return x <= rect.x + rect.width && rect.x <= x + width && y <= rect.y + rect.height && rect.y <= y + height; 220 } 221 222 // Find intersection rectangle 223 RectBase2D operator^( const RectBase2D & rect ) const 224 { 225 RectBase2D output = rect; 226 if ( output.x < x ) { 227 const _TypePoint diff = x - output.x; 228 output.x = x; 229 output.width -= diff; 230 } 231 if ( output.y < y ) { 232 const _TypePoint diff = y - output.y; 233 output.y = y; 234 output.height -= diff; 235 } 236 237 if ( output.x > x + width || output.y > y + height ) 238 return RectBase2D(); 239 240 if ( output.x + output.width > x + width ) { 241 const _TypePoint diff = output.x + output.width - ( x + width ); 242 output.width -= diff; 243 } 244 245 if ( output.y + output.height > y + height ) { 246 const _TypePoint diff = output.y + output.height - ( y + height ); 247 output.height -= diff; 248 } 249 250 return output; 251 } 252 getPositionRectBase2D253 PointBase2D<_TypePoint> getPosition() const 254 { 255 return PointBase2D<_TypePoint>( x, y ); 256 } 257 258 _TypePoint x; 259 _TypePoint y; 260 _TypeSize width; 261 _TypeSize height; 262 }; 263 264 using Point = PointBase2D<int32_t>; 265 using Size = SizeBase2D<int32_t>; 266 using Rect = RectBase2D<int32_t, int32_t>; 267 } 268