math_2d.h
1 /*************************************************************************/
2 /* math_2d.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef MATH_2D_H
30 #define MATH_2D_H
31 
32 #include "math_funcs.h"
33 #include "ustring.h"
37 enum Margin {
38 
39  MARGIN_LEFT,
40  MARGIN_TOP,
41  MARGIN_RIGHT,
42  MARGIN_BOTTOM
43 };
44 
45 enum Orientation {
46 
47  HORIZONTAL,
48  VERTICAL
49 };
50 
51 enum HAlign {
52 
53  HALIGN_LEFT,
54  HALIGN_CENTER,
55  HALIGN_RIGHT
56 };
57 
58 enum VAlign {
59 
60  VALIGN_TOP,
61  VALIGN_CENTER,
62  VALIGN_BOTTOM
63 };
64 
65 struct Vector2 {
66 
67  union {
68  float x;
69  float width;
70  };
71  union {
72  float y;
73  float height;
74  };
75 
76 
77  _FORCE_INLINE_ float& operator[](int p_idx) {
78  return p_idx?y:x;
79  }
80  _FORCE_INLINE_ const float& operator[](int p_idx) const {
81  return p_idx?y:x;
82  }
83 
84  void normalize();
85  Vector2 normalized() const;
86 
87  float length() const;
88  float length_squared() const;
89 
90  float distance_to(const Vector2& p_vector2) const;
91  float distance_squared_to(const Vector2& p_vector2) const;
92  float angle_to(const Vector2& p_vector2) const;
93  float angle_to_point(const Vector2& p_vector2) const;
94 
95  float dot(const Vector2& p_other) const;
96  float cross(const Vector2& p_other) const;
97  Vector2 cross(real_t p_other) const;
98  Vector2 project(const Vector2& p_vec) const;
99 
100  Vector2 plane_project(real_t p_d, const Vector2& p_vec) const;
101 
102  Vector2 clamped(real_t p_len) const;
103 
104  _FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2& p_a, const Vector2& p_b,float p_t);
105  _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2& p_b,float p_t) const;
106  Vector2 cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const;
107  Vector2 cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const;
108 
109  Vector2 slide(const Vector2& p_vec) const;
110  Vector2 reflect(const Vector2& p_vec) const;
111 
112  Vector2 operator+(const Vector2& p_v) const;
113  void operator+=(const Vector2& p_v);
114  Vector2 operator-(const Vector2& p_v) const;
115  void operator-=(const Vector2& p_v);
116  Vector2 operator*(const Vector2 &p_v1) const;
117 
118  Vector2 operator*(const float &rvalue) const;
119  void operator*=(const float &rvalue);
120  void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; }
121 
122  Vector2 operator/(const Vector2 &p_v1) const;
123 
124  Vector2 operator/(const float &rvalue) const;
125 
126  void operator/=(const float &rvalue);
127 
128  Vector2 operator-() const;
129 
130  bool operator==(const Vector2& p_vec2) const;
131  bool operator!=(const Vector2& p_vec2) const;
132 
133  bool operator<(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y<p_vec2.y):(x<p_vec2.x); }
134  bool operator<=(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y<=p_vec2.y):(x<=p_vec2.x); }
135 
136  real_t angle() const;
137 
138  void set_rotation(float p_radians) {
139 
140  x=Math::sin(p_radians);
141  y=Math::cos(p_radians);
142  }
143 
144  _FORCE_INLINE_ Vector2 abs() const {
145 
146  return Vector2( Math::abs(x), Math::abs(y) );
147  }
148 
149  Vector2 rotated(float p_by) const;
150  Vector2 tangent() const {
151 
152  return Vector2(y,-x);
153  }
154 
155  Vector2 floor() const;
156  Vector2 snapped(const Vector2& p_by) const;
157  float get_aspect() const { return width/height; }
158 
159 
160  operator String() const { return String::num(x)+","+String::num(y); }
161 
162  _FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; }
163  _FORCE_INLINE_ Vector2() { x=0; y=0; }
164 };
165 
166 _FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2& p_vec) const {
167 
168  return p_vec - *this * ( dot(p_vec) -p_d);
169 }
170 
171 
172 _FORCE_INLINE_ Vector2 operator*(float p_scalar, const Vector2& p_vec) {
173 
174  return p_vec*p_scalar;
175 }
176 
177 Vector2 Vector2::linear_interpolate(const Vector2& p_b,float p_t) const {
178 
179  Vector2 res=*this;
180 
181  res.x+= (p_t * (p_b.x-x));
182  res.y+= (p_t * (p_b.y-y));
183 
184  return res;
185 
186 }
187 
188 Vector2 Vector2::linear_interpolate(const Vector2& p_a, const Vector2& p_b,float p_t) {
189 
190  Vector2 res=p_a;
191 
192  res.x+= (p_t * (p_b.x-p_a.x));
193  res.y+= (p_t * (p_b.y-p_a.y));
194 
195  return res;
196 }
197 
198 typedef Vector2 Size2;
199 typedef Vector2 Point2;
200 
201 struct Matrix32;
202 
203 
204 struct Rect2 {
205 
206  Point2 pos;
207  Size2 size;
208 
209  const Vector2& get_pos() const { return pos; }
210  void set_pos(const Vector2& p_pos) { pos=p_pos; }
211  const Vector2& get_size() const { return size; }
212  void set_size(const Vector2& p_size) { size=p_size; }
213 
214  float get_area() const { return size.width*size.height; }
215 
216  inline bool intersects(const Rect2& p_rect) const {
217  if ( pos.x >= (p_rect.pos.x + p_rect.size.width) )
218  return false;
219  if ( (pos.x+size.width) <= p_rect.pos.x )
220  return false;
221  if ( pos.y >= (p_rect.pos.y + p_rect.size.height) )
222  return false;
223  if ( (pos.y+size.height) <= p_rect.pos.y )
224  return false;
225 
226  return true;
227  }
228 
229  inline float distance_to(const Vector2& p_point) const {
230 
231  float dist = 1e20;
232 
233  if (p_point.x < pos.x) {
234  dist=MIN(dist,pos.x-p_point.x);
235  }
236  if (p_point.y < pos.y) {
237  dist=MIN(dist,pos.y-p_point.y);
238  }
239  if (p_point.x >= (pos.x+size.x) ) {
240  dist=MIN(p_point.x-(pos.x+size.x),dist);
241  }
242  if (p_point.y >= (pos.y+size.y) ) {
243  dist=MIN(p_point.y-(pos.y+size.y),dist);
244  }
245 
246  if (dist==1e20)
247  return 0;
248  else
249  return dist;
250  }
251 
252  _FORCE_INLINE_ bool intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const;
253 
254  bool intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos=NULL, Point2* r_normal=NULL) const;
255 
256  inline bool encloses(const Rect2& p_rect) const {
257 
258  return (p_rect.pos.x>=pos.x) && (p_rect.pos.y>=pos.y) &&
259  ((p_rect.pos.x+p_rect.size.x)<(pos.x+size.x)) &&
260  ((p_rect.pos.y+p_rect.size.y)<(pos.y+size.y));
261 
262  }
263 
264  inline bool has_no_area() const {
265 
266  return (size.x<=0 || size.y<=0);
267 
268  }
269  inline Rect2 clip(const Rect2& p_rect) const {
270 
271  Rect2 new_rect=p_rect;
272 
273  if (!intersects( new_rect ))
274  return Rect2();
275 
276  new_rect.pos.x = MAX( p_rect.pos.x , pos.x );
277  new_rect.pos.y = MAX( p_rect.pos.y , pos.y );
278 
279  Point2 p_rect_end=p_rect.pos+p_rect.size;
280  Point2 end=pos+size;
281 
282  new_rect.size.x=MIN(p_rect_end.x,end.x) - new_rect.pos.x;
283  new_rect.size.y=MIN(p_rect_end.y,end.y) - new_rect.pos.y;
284 
285  return new_rect;
286  }
287 
288  inline Rect2 merge(const Rect2& p_rect) const {
289 
290  Rect2 new_rect;
291 
292  new_rect.pos.x=MIN( p_rect.pos.x , pos.x );
293  new_rect.pos.y=MIN( p_rect.pos.y , pos.y );
294 
295 
296  new_rect.size.x = MAX( p_rect.pos.x+p_rect.size.x , pos.x+size.x );
297  new_rect.size.y = MAX( p_rect.pos.y+p_rect.size.y , pos.y+size.y );
298 
299  new_rect.size = new_rect.size - new_rect.pos; //make relative again
300 
301  return new_rect;
302  };
303  inline bool has_point(const Point2& p_point) const {
304  if (p_point.x < pos.x)
305  return false;
306  if (p_point.y < pos.y)
307  return false;
308 
309  if (p_point.x >= (pos.x+size.x) )
310  return false;
311  if (p_point.y >= (pos.y+size.y) )
312  return false;
313 
314  return true;
315  }
316 
317  inline bool no_area() const { return (size.width<=0 || size.height<=0 ); }
318 
319  bool operator==(const Rect2& p_rect) const { return pos==p_rect.pos && size==p_rect.size; }
320  bool operator!=(const Rect2& p_rect) const { return pos!=p_rect.pos || size!=p_rect.size; }
321 
322  inline Rect2 grow(real_t p_by) const {
323 
324  Rect2 g=*this;
325  g.pos.x-=p_by;
326  g.pos.y-=p_by;
327  g.size.width+=p_by*2;
328  g.size.height+=p_by*2;
329  return g;
330  }
331 
332  inline Rect2 expand(const Vector2& p_vector) const {
333 
334  Rect2 r = *this;
335  r.expand_to(p_vector);
336  return r;
337  }
338 
339  inline void expand_to(const Vector2& p_vector) { //in place function for speed
340 
341  Vector2 begin=pos;
342  Vector2 end=pos+size;
343 
344  if (p_vector.x<begin.x)
345  begin.x=p_vector.x;
346  if (p_vector.y<begin.y)
347  begin.y=p_vector.y;
348 
349  if (p_vector.x>end.x)
350  end.x=p_vector.x;
351  if (p_vector.y>end.y)
352  end.y=p_vector.y;
353 
354  pos=begin;
355  size=end-begin;
356  }
357 
358 
359  operator String() const { return String(pos)+","+String(size); }
360 
361  Rect2() {}
362  Rect2( float p_x, float p_y, float p_width, float p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); }
363  Rect2( const Point2& p_pos, const Size2& p_size ) { pos=p_pos; size=p_size; }
364 };
365 
366 
367 /* INTEGER STUFF */
368 
369 struct Point2i {
370 
371  union {
372  int x;
373  int width;
374  };
375  union {
376  int y;
377  int height;
378  };
379 
380 
381  _FORCE_INLINE_ int& operator[](int p_idx) {
382  return p_idx?y:x;
383  }
384  _FORCE_INLINE_ const int& operator[](int p_idx) const {
385  return p_idx?y:x;
386  }
387 
388  Point2i operator+(const Point2i& p_v) const;
389  void operator+=(const Point2i& p_v);
390  Point2i operator-(const Point2i& p_v) const;
391  void operator-=(const Point2i& p_v);
392  Point2i operator*(const Point2i &p_v1) const;
393 
394  Point2i operator*(const int &rvalue) const;
395  void operator*=(const int &rvalue);
396 
397  Point2i operator/(const Point2i &p_v1) const;
398 
399  Point2i operator/(const int &rvalue) const;
400 
401  void operator/=(const int &rvalue);
402 
403  Point2i operator-() const;
404  bool operator<(const Point2i& p_vec2) const { return (x==p_vec2.x)?(y<p_vec2.y):(x<p_vec2.x); }
405  bool operator>(const Point2i& p_vec2) const { return (x==p_vec2.x)?(y>p_vec2.y):(x>p_vec2.x); }
406 
407  bool operator==(const Point2i& p_vec2) const;
408  bool operator!=(const Point2i& p_vec2) const;
409 
410  float get_aspect() const { return width/(float)height; }
411 
412  operator String() const { return String::num(x)+","+String::num(y); }
413 
414  operator Vector2() const { return Vector2(x,y); }
415  inline Point2i(const Vector2& p_vec2) { x=(int)p_vec2.x; y=(int)p_vec2.y; }
416  inline Point2i(int p_x,int p_y) { x=p_x; y=p_y; }
417  inline Point2i() { x=0; y=0; }
418 };
419 
420 typedef Point2i Size2i;
421 
422 struct Rect2i {
423 
424  Point2i pos;
425  Size2i size;
426 
427  const Point2i& get_pos() const { return pos; }
428  void set_pos(const Point2i& p_pos) { pos=p_pos; }
429  const Point2i& get_size() const { return size; }
430  void set_size(const Point2i& p_size) { size=p_size; }
431 
432  int get_area() const { return size.width*size.height; }
433 
434  inline bool intersects(const Rect2i& p_rect) const {
435  if ( pos.x > (p_rect.pos.x + p_rect.size.width) )
436  return false;
437  if ( (pos.x+size.width) < p_rect.pos.x )
438  return false;
439  if ( pos.y > (p_rect.pos.y + p_rect.size.height) )
440  return false;
441  if ( (pos.y+size.height) < p_rect.pos.y )
442  return false;
443 
444  return true;
445  }
446 
447  inline bool encloses(const Rect2i& p_rect) const {
448 
449  return (p_rect.pos.x>=pos.x) && (p_rect.pos.y>=pos.y) &&
450  ((p_rect.pos.x+p_rect.size.x)<(pos.x+size.x)) &&
451  ((p_rect.pos.y+p_rect.size.y)<(pos.y+size.y));
452 
453  }
454 
455  inline bool has_no_area() const {
456 
457  return (size.x<=0 || size.y<=0);
458 
459  }
460  inline Rect2i clip(const Rect2i& p_rect) const {
461 
462  Rect2i new_rect=p_rect;
463 
464  if (!intersects( new_rect ))
465  return Rect2i();
466 
467  new_rect.pos.x = MAX( p_rect.pos.x , pos.x );
468  new_rect.pos.y = MAX( p_rect.pos.y , pos.y );
469 
470  Point2 p_rect_end=p_rect.pos+p_rect.size;
471  Point2 end=pos+size;
472 
473  new_rect.size.x=(int)(MIN(p_rect_end.x,end.x) - new_rect.pos.x);
474  new_rect.size.y=(int)(MIN(p_rect_end.y,end.y) - new_rect.pos.y);
475 
476  return new_rect;
477  }
478 
479  inline Rect2i merge(const Rect2i& p_rect) const {
480 
481  Rect2i new_rect;
482 
483  new_rect.pos.x=MIN( p_rect.pos.x , pos.x );
484  new_rect.pos.y=MIN( p_rect.pos.y , pos.y );
485 
486 
487  new_rect.size.x = MAX( p_rect.pos.x+p_rect.size.x , pos.x+size.x );
488  new_rect.size.y = MAX( p_rect.pos.y+p_rect.size.y , pos.y+size.y );
489 
490  new_rect.size = new_rect.size - new_rect.pos; //make relative again
491 
492  return new_rect;
493  };
494  bool has_point(const Point2& p_point) const {
495  if (p_point.x < pos.x)
496  return false;
497  if (p_point.y < pos.y)
498  return false;
499 
500  if (p_point.x >= (pos.x+size.x) )
501  return false;
502  if (p_point.y >= (pos.y+size.y) )
503  return false;
504 
505  return true;
506  }
507 
508  bool no_area() { return (size.width<=0 || size.height<=0 ); }
509 
510  bool operator==(const Rect2i& p_rect) const { return pos==p_rect.pos && size==p_rect.size; }
511  bool operator!=(const Rect2i& p_rect) const { return pos!=p_rect.pos || size!=p_rect.size; }
512 
513  Rect2i grow(int p_by) const {
514 
515  Rect2i g=*this;
516  g.pos.x-=p_by;
517  g.pos.y-=p_by;
518  g.size.width+=p_by*2;
519  g.size.height+=p_by*2;
520  return g;
521  }
522 
523  inline void expand_to(const Point2i& p_vector) {
524 
525  Point2i begin=pos;
526  Point2i end=pos+size;
527 
528  if (p_vector.x<begin.x)
529  begin.x=p_vector.x;
530  if (p_vector.y<begin.y)
531  begin.y=p_vector.y;
532 
533  if (p_vector.x>end.x)
534  end.x=p_vector.x;
535  if (p_vector.y>end.y)
536  end.y=p_vector.y;
537 
538  pos=begin;
539  size=end-begin;
540  }
541 
542 
543  operator String() const { return String(pos)+","+String(size); }
544 
545  operator Rect2() const { return Rect2(pos,size); }
546  Rect2i(const Rect2& p_r2) { pos=p_r2.pos; size=p_r2.size; }
547  Rect2i() {}
548  Rect2i( int p_x, int p_y, int p_width, int p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); }
549  Rect2i( const Point2& p_pos, const Size2& p_size ) { pos=p_pos; size=p_size; }
550 };
551 
552 
553 
554 struct Matrix32 {
555 
556 
557  Vector2 elements[3];
558 
559 
560  _FORCE_INLINE_ float tdotx(const Vector2& v) const { return elements[0][0] * v.x + elements[1][0] * v.y; }
561  _FORCE_INLINE_ float tdoty(const Vector2& v) const { return elements[0][1] * v.x + elements[1][1] * v.y; }
562 
563  const Vector2& operator[](int p_idx) const { return elements[p_idx]; }
564  Vector2& operator[](int p_idx) { return elements[p_idx]; }
565 
566  _FORCE_INLINE_ Vector2 get_axis(int p_axis) const { ERR_FAIL_INDEX_V(p_axis,3,Vector2()); return elements[p_axis]; }
567  _FORCE_INLINE_ void set_axis(int p_axis,const Vector2& p_vec) { ERR_FAIL_INDEX(p_axis,3); elements[p_axis]=p_vec; }
568 
569  void invert();
570  Matrix32 inverse() const;
571 
572  void affine_invert();
573  Matrix32 affine_inverse() const;
574 
575  void set_rotation(real_t p_phi);
576  real_t get_rotation() const;
577  _FORCE_INLINE_ void set_rotation_and_scale(real_t p_phi,const Size2& p_scale);
578  void rotate(real_t p_phi);
579 
580  void scale(const Vector2& p_scale);
581  void scale_basis(const Vector2& p_scale);
582  void translate( real_t p_tx, real_t p_ty);
583  void translate( const Vector2& p_translation );
584 
585  float basis_determinant() const;
586 
587  Vector2 get_scale() const;
588 
589  _FORCE_INLINE_ const Vector2& get_origin() const { return elements[2]; }
590  _FORCE_INLINE_ void set_origin(const Vector2& p_origin) { elements[2]=p_origin; }
591 
592  Matrix32 scaled(const Vector2& p_scale) const;
593  Matrix32 basis_scaled(const Vector2& p_scale) const;
594  Matrix32 translated(const Vector2& p_offset) const;
595  Matrix32 rotated(float p_phi) const;
596 
597  Matrix32 untranslated() const;
598 
599 
600  void orthonormalize();
601  Matrix32 orthonormalized() const;
602 
603  bool operator==(const Matrix32& p_transform) const;
604  bool operator!=(const Matrix32& p_transform) const;
605 
606  void operator*=(const Matrix32& p_transform);
607  Matrix32 operator*(const Matrix32& p_transform) const;
608 
609  Matrix32 interpolate_with(const Matrix32& p_transform, float p_c) const;
610 
611  _FORCE_INLINE_ Vector2 basis_xform(const Vector2& p_vec) const;
612  _FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2& p_vec) const;
613  _FORCE_INLINE_ Vector2 xform(const Vector2& p_vec) const;
614  _FORCE_INLINE_ Vector2 xform_inv(const Vector2& p_vec) const;
615  _FORCE_INLINE_ Rect2 xform(const Rect2& p_vec) const;
616  _FORCE_INLINE_ Rect2 xform_inv(const Rect2& p_vec) const;
617 
618 
619  operator String() const;
620 
621 
622  Matrix32(real_t p_rot, const Vector2& p_pos);
623  Matrix32() { elements[0][0]=1.0; elements[1][1]=1.0; }
624 
625 };
626 
627 bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const {
628 
629  //SAT intersection between local and transformed rect2
630 
631  Vector2 xf_points[4]={
632  p_xform.xform(p_rect.pos),
633  p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y)),
634  p_xform.xform(Vector2(p_rect.pos.x,p_rect.pos.y+p_rect.size.y)),
635  p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y+p_rect.size.y)),
636  };
637 
638  real_t low_limit;
639 
640  //base rect2 first (faster)
641 
642  if (xf_points[0].y>pos.y)
643  goto next1;
644  if (xf_points[1].y>pos.y)
645  goto next1;
646  if (xf_points[2].y>pos.y)
647  goto next1;
648  if (xf_points[3].y>pos.y)
649  goto next1;
650 
651  return false;
652 
653  next1:
654 
655  low_limit=pos.y+size.y;
656 
657  if (xf_points[0].y<low_limit)
658  goto next2;
659  if (xf_points[1].y<low_limit)
660  goto next2;
661  if (xf_points[2].y<low_limit)
662  goto next2;
663  if (xf_points[3].y<low_limit)
664  goto next2;
665 
666  return false;
667 
668  next2:
669 
670  if (xf_points[0].x>pos.x)
671  goto next3;
672  if (xf_points[1].x>pos.x)
673  goto next3;
674  if (xf_points[2].x>pos.x)
675  goto next3;
676  if (xf_points[3].x>pos.x)
677  goto next3;
678 
679  return false;
680 
681  next3:
682 
683  low_limit=pos.x+size.x;
684 
685  if (xf_points[0].x<low_limit)
686  goto next4;
687  if (xf_points[1].x<low_limit)
688  goto next4;
689  if (xf_points[2].x<low_limit)
690  goto next4;
691  if (xf_points[3].x<low_limit)
692  goto next4;
693 
694  return false;
695 
696  next4:
697 
698  Vector2 xf_points2[4]={
699  pos,
700  Vector2(pos.x+size.x,pos.y),
701  Vector2(pos.x,pos.y+size.y),
702  Vector2(pos.x+size.x,pos.y+size.y),
703  };
704 
705  real_t maxa=p_xform.elements[0].dot(xf_points2[0]);
706  real_t mina=maxa;
707 
708  real_t dp = p_xform.elements[0].dot(xf_points2[1]);
709  maxa=MAX(dp,maxa);
710  mina=MIN(dp,mina);
711 
712  dp = p_xform.elements[0].dot(xf_points2[2]);
713  maxa=MAX(dp,maxa);
714  mina=MIN(dp,mina);
715 
716  dp = p_xform.elements[0].dot(xf_points2[3]);
717  maxa=MAX(dp,maxa);
718  mina=MIN(dp,mina);
719 
720  real_t maxb=p_xform.elements[0].dot(xf_points[0]);
721  real_t minb=maxb;
722 
723  dp = p_xform.elements[0].dot(xf_points[1]);
724  maxb=MAX(dp,maxb);
725  minb=MIN(dp,minb);
726 
727  dp = p_xform.elements[0].dot(xf_points[2]);
728  maxb=MAX(dp,maxb);
729  minb=MIN(dp,minb);
730 
731  dp = p_xform.elements[0].dot(xf_points[3]);
732  maxb=MAX(dp,maxb);
733  minb=MIN(dp,minb);
734 
735 
736  if ( mina > maxb )
737  return false;
738  if ( minb > maxa )
739  return false;
740 
741  maxa=p_xform.elements[1].dot(xf_points2[0]);
742  mina=maxa;
743 
744  dp = p_xform.elements[1].dot(xf_points2[1]);
745  maxa=MAX(dp,maxa);
746  mina=MIN(dp,mina);
747 
748  dp = p_xform.elements[1].dot(xf_points2[2]);
749  maxa=MAX(dp,maxa);
750  mina=MIN(dp,mina);
751 
752  dp = p_xform.elements[1].dot(xf_points2[3]);
753  maxa=MAX(dp,maxa);
754  mina=MIN(dp,mina);
755 
756  maxb=p_xform.elements[1].dot(xf_points[0]);
757  minb=maxb;
758 
759  dp = p_xform.elements[1].dot(xf_points[1]);
760  maxb=MAX(dp,maxb);
761  minb=MIN(dp,minb);
762 
763  dp = p_xform.elements[1].dot(xf_points[2]);
764  maxb=MAX(dp,maxb);
765  minb=MIN(dp,minb);
766 
767  dp = p_xform.elements[1].dot(xf_points[3]);
768  maxb=MAX(dp,maxb);
769  minb=MIN(dp,minb);
770 
771 
772  if ( mina > maxb )
773  return false;
774  if ( minb > maxa )
775  return false;
776 
777 
778  return true;
779 
780 }
781 
782 Vector2 Matrix32::basis_xform(const Vector2& v) const {
783 
784  return Vector2(
785  tdotx(v),
786  tdoty(v)
787  );
788 }
789 
790 Vector2 Matrix32::basis_xform_inv(const Vector2& v) const{
791 
792  return Vector2(
793  elements[0].dot(v),
794  elements[1].dot(v)
795  );
796 }
797 
798 Vector2 Matrix32::xform(const Vector2& v) const {
799 
800  return Vector2(
801  tdotx(v),
802  tdoty(v)
803  ) + elements[2];
804 }
805 Vector2 Matrix32::xform_inv(const Vector2& p_vec) const {
806 
807  Vector2 v = p_vec - elements[2];
808 
809  return Vector2(
810  elements[0].dot(v),
811  elements[1].dot(v)
812  );
813 
814 }
815 Rect2 Matrix32::xform(const Rect2& p_rect) const {
816 
817  Vector2 x=elements[0]*p_rect.size.x;
818  Vector2 y=elements[1]*p_rect.size.y;
819  Vector2 pos = xform( p_rect.pos );
820 
821  Rect2 new_rect;
822  new_rect.pos=pos;
823  new_rect.expand_to( pos+x );
824  new_rect.expand_to( pos+y );
825  new_rect.expand_to( pos+x+y );
826  return new_rect;
827 }
828 
829 void Matrix32::set_rotation_and_scale(real_t p_rot,const Size2& p_scale) {
830 
831  elements[0][0]=Math::cos(p_rot)*p_scale.x;
832  elements[1][1]=Math::cos(p_rot)*p_scale.y;
833  elements[0][1]=-Math::sin(p_rot)*p_scale.x;
834  elements[1][0]=Math::sin(p_rot)*p_scale.y;
835 
836 }
837 
838 Rect2 Matrix32::xform_inv(const Rect2& p_rect) const {
839 
840  Vector2 ends[4]={
841  xform_inv( p_rect.pos ),
842  xform_inv( Vector2(p_rect.pos.x,p_rect.pos.y+p_rect.size.y ) ),
843  xform_inv( Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y+p_rect.size.y ) ),
844  xform_inv( Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y ) )
845  };
846 
847  Rect2 new_rect;
848  new_rect.pos=ends[0];
849  new_rect.expand_to(ends[1]);
850  new_rect.expand_to(ends[2]);
851  new_rect.expand_to(ends[3]);
852 
853  return new_rect;
854 }
855 
856 
857 #endif
Definition: math_2d.h:422
Definition: math_2d.h:369
Rect2i clip(const Rect2i &p_rect) const
Definition: math_2d.h:460
Definition: math_2d.h:204
Rect2 merge(const Rect2 &p_rect) const
Definition: math_2d.h:288
Rect2 clip(const Rect2 &p_rect) const
Definition: math_2d.h:269
Rect2i merge(const Rect2i &p_rect) const
Definition: math_2d.h:479
Definition: math_2d.h:65
Definition: math_2d.h:554
Definition: ustring.h:64