Cleanup: comments (long lines) in blenlib
[blender.git] / source / blender / blenlib / intern / rct.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bli
22  *
23  * A minimalist lib for functions doing stuff with rectangle structs.
24  */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <math.h>
29
30 #include <limits.h>
31 #include <float.h>
32
33 #include "BLI_rect.h"
34 #include "BLI_utildefines.h"
35
36 #include "DNA_vec_types.h"
37
38 /* avoid including BLI_math */
39 static void unit_m4(float m[4][4]);
40
41 /**
42  * Determine if a rect is empty. An empty
43  * rect is one with a zero (or negative)
44  * width or height.
45  *
46  * \return True if \a rect is empty.
47  */
48 bool BLI_rcti_is_empty(const rcti *rect)
49 {
50   return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin));
51 }
52
53 bool BLI_rctf_is_empty(const rctf *rect)
54 {
55   return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin));
56 }
57
58 bool BLI_rcti_isect_x(const rcti *rect, const int x)
59 {
60   if (x < rect->xmin) {
61     return false;
62   }
63   if (x > rect->xmax) {
64     return false;
65   }
66   return true;
67 }
68
69 bool BLI_rcti_isect_y(const rcti *rect, const int y)
70 {
71   if (y < rect->ymin) {
72     return false;
73   }
74   if (y > rect->ymax) {
75     return false;
76   }
77   return true;
78 }
79
80 bool BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
81 {
82   if (x < rect->xmin) {
83     return false;
84   }
85   if (x > rect->xmax) {
86     return false;
87   }
88   if (y < rect->ymin) {
89     return false;
90   }
91   if (y > rect->ymax) {
92     return false;
93   }
94   return true;
95 }
96
97 bool BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2])
98 {
99   if (xy[0] < rect->xmin) {
100     return false;
101   }
102   if (xy[0] > rect->xmax) {
103     return false;
104   }
105   if (xy[1] < rect->ymin) {
106     return false;
107   }
108   if (xy[1] > rect->ymax) {
109     return false;
110   }
111   return true;
112 }
113
114 bool BLI_rctf_isect_x(const rctf *rect, const float x)
115 {
116   if (x < rect->xmin) {
117     return false;
118   }
119   if (x > rect->xmax) {
120     return false;
121   }
122   return true;
123 }
124
125 bool BLI_rctf_isect_y(const rctf *rect, const float y)
126 {
127   if (y < rect->ymin) {
128     return false;
129   }
130   if (y > rect->ymax) {
131     return false;
132   }
133   return true;
134 }
135
136 bool BLI_rctf_isect_pt(const rctf *rect, const float x, const float y)
137 {
138   if (x < rect->xmin) {
139     return false;
140   }
141   if (x > rect->xmax) {
142     return false;
143   }
144   if (y < rect->ymin) {
145     return false;
146   }
147   if (y > rect->ymax) {
148     return false;
149   }
150   return true;
151 }
152
153 bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2])
154 {
155   if (xy[0] < rect->xmin) {
156     return false;
157   }
158   if (xy[0] > rect->xmax) {
159     return false;
160   }
161   if (xy[1] < rect->ymin) {
162     return false;
163   }
164   if (xy[1] > rect->ymax) {
165     return false;
166   }
167   return true;
168 }
169
170 /**
171  * \returns shortest distance from \a rect to x/y (0 if inside)
172  */
173
174 int BLI_rcti_length_x(const rcti *rect, const int x)
175 {
176   if (x < rect->xmin) {
177     return rect->xmin - x;
178   }
179   if (x > rect->xmax) {
180     return x - rect->xmax;
181   }
182   return 0;
183 }
184
185 int BLI_rcti_length_y(const rcti *rect, const int y)
186 {
187   if (y < rect->ymin) {
188     return rect->ymin - y;
189   }
190   if (y > rect->ymax) {
191     return y - rect->ymax;
192   }
193   return 0;
194 }
195
196 float BLI_rctf_length_x(const rctf *rect, const float x)
197 {
198   if (x < rect->xmin) {
199     return rect->xmin - x;
200   }
201   if (x > rect->xmax) {
202     return x - rect->xmax;
203   }
204   return 0.0f;
205 }
206
207 float BLI_rctf_length_y(const rctf *rect, const float y)
208 {
209   if (y < rect->ymin) {
210     return rect->ymin - y;
211   }
212   if (y > rect->ymax) {
213     return y - rect->ymax;
214   }
215   return 0.0f;
216 }
217
218 /**
219  * is \a rct_b inside \a rct_a
220  */
221 bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b)
222 {
223   return ((rct_a->xmin <= rct_b->xmin) && (rct_a->xmax >= rct_b->xmax) &&
224           (rct_a->ymin <= rct_b->ymin) && (rct_a->ymax >= rct_b->ymax));
225 }
226 bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b)
227 {
228   return ((rct_a->xmin <= rct_b->xmin) && (rct_a->xmax >= rct_b->xmax) &&
229           (rct_a->ymin <= rct_b->ymin) && (rct_a->ymax >= rct_b->ymax));
230 }
231
232 /* based closely on 'isect_seg_seg_v2_int',
233  * but in modified so corner cases are treated as intersections */
234 static int isect_segments_i(const int v1[2], const int v2[2], const int v3[2], const int v4[2])
235 {
236   const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) -
237                               (v2[1] - v1[1]) * (v4[0] - v3[0]));
238   if (div == 0.0) {
239     return 1; /* co-linear */
240   }
241   else {
242     const double lambda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) -
243                                    (v1[0] - v3[0]) * (v4[1] - v3[1])) /
244                           div;
245     const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) -
246                                (v1[0] - v3[0]) * (v2[1] - v1[1])) /
247                       div;
248     return (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0);
249   }
250 }
251 static int isect_segments_fl(const float v1[2],
252                              const float v2[2],
253                              const float v3[2],
254                              const float v4[2])
255 {
256   const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) -
257                               (v2[1] - v1[1]) * (v4[0] - v3[0]));
258   if (div == 0.0) {
259     return 1; /* co-linear */
260   }
261   else {
262     const double lambda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) -
263                                    (v1[0] - v3[0]) * (v4[1] - v3[1])) /
264                           div;
265     const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) -
266                                (v1[0] - v3[0]) * (v2[1] - v1[1])) /
267                       div;
268     return (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0);
269   }
270 }
271
272 bool BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2])
273 {
274   /* first do outside-bounds check for both points of the segment */
275   if (s1[0] < rect->xmin && s2[0] < rect->xmin) {
276     return false;
277   }
278   if (s1[0] > rect->xmax && s2[0] > rect->xmax) {
279     return false;
280   }
281   if (s1[1] < rect->ymin && s2[1] < rect->ymin) {
282     return false;
283   }
284   if (s1[1] > rect->ymax && s2[1] > rect->ymax) {
285     return false;
286   }
287
288   /* if either points intersect then we definetly intersect */
289   if (BLI_rcti_isect_pt_v(rect, s1) || BLI_rcti_isect_pt_v(rect, s2)) {
290     return true;
291   }
292   else {
293     /* both points are outside but may insersect the rect */
294     int tvec1[2];
295     int tvec2[2];
296     /* diagonal: [/] */
297     tvec1[0] = rect->xmin;
298     tvec1[1] = rect->ymin;
299     tvec2[0] = rect->xmin;
300     tvec2[1] = rect->ymax;
301     if (isect_segments_i(s1, s2, tvec1, tvec2)) {
302       return true;
303     }
304
305     /* diagonal: [\] */
306     tvec1[0] = rect->xmin;
307     tvec1[1] = rect->ymax;
308     tvec2[0] = rect->xmax;
309     tvec2[1] = rect->ymin;
310     if (isect_segments_i(s1, s2, tvec1, tvec2)) {
311       return true;
312     }
313
314     /* no intersection */
315     return false;
316   }
317 }
318
319 bool BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2])
320 {
321   /* first do outside-bounds check for both points of the segment */
322   if (s1[0] < rect->xmin && s2[0] < rect->xmin) {
323     return false;
324   }
325   if (s1[0] > rect->xmax && s2[0] > rect->xmax) {
326     return false;
327   }
328   if (s1[1] < rect->ymin && s2[1] < rect->ymin) {
329     return false;
330   }
331   if (s1[1] > rect->ymax && s2[1] > rect->ymax) {
332     return false;
333   }
334
335   /* if either points intersect then we definetly intersect */
336   if (BLI_rctf_isect_pt_v(rect, s1) || BLI_rctf_isect_pt_v(rect, s2)) {
337     return true;
338   }
339   else {
340     /* both points are outside but may insersect the rect */
341     float tvec1[2];
342     float tvec2[2];
343     /* diagonal: [/] */
344     tvec1[0] = rect->xmin;
345     tvec1[1] = rect->ymin;
346     tvec2[0] = rect->xmin;
347     tvec2[1] = rect->ymax;
348     if (isect_segments_fl(s1, s2, tvec1, tvec2)) {
349       return true;
350     }
351
352     /* diagonal: [\] */
353     tvec1[0] = rect->xmin;
354     tvec1[1] = rect->ymax;
355     tvec2[0] = rect->xmax;
356     tvec2[1] = rect->ymin;
357     if (isect_segments_fl(s1, s2, tvec1, tvec2)) {
358       return true;
359     }
360
361     /* no intersection */
362     return false;
363   }
364 }
365
366 bool BLI_rcti_isect_circle(const rcti *rect, const float xy[2], const float radius)
367 {
368   float dx, dy;
369
370   if (xy[0] >= rect->xmin && xy[0] <= rect->xmax) {
371     dx = 0;
372   }
373   else {
374     dx = (xy[0] < rect->xmin) ? (rect->xmin - xy[0]) : (xy[0] - rect->xmax);
375   }
376
377   if (xy[1] >= rect->ymin && xy[1] <= rect->ymax) {
378     dy = 0;
379   }
380   else {
381     dy = (xy[1] < rect->ymin) ? (rect->ymin - xy[1]) : (xy[1] - rect->ymax);
382   }
383
384   return dx * dx + dy * dy <= radius * radius;
385 }
386
387 bool BLI_rctf_isect_circle(const rctf *rect, const float xy[2], const float radius)
388 {
389   float dx, dy;
390
391   if (xy[0] >= rect->xmin && xy[0] <= rect->xmax) {
392     dx = 0;
393   }
394   else {
395     dx = (xy[0] < rect->xmin) ? (rect->xmin - xy[0]) : (xy[0] - rect->xmax);
396   }
397
398   if (xy[1] >= rect->ymin && xy[1] <= rect->ymax) {
399     dy = 0;
400   }
401   else {
402     dy = (xy[1] < rect->ymin) ? (rect->ymin - xy[1]) : (xy[1] - rect->ymax);
403   }
404
405   return dx * dx + dy * dy <= radius * radius;
406 }
407
408 void BLI_rctf_union(rctf *rct1, const rctf *rct2)
409 {
410   if (rct1->xmin > rct2->xmin) {
411     rct1->xmin = rct2->xmin;
412   }
413   if (rct1->xmax < rct2->xmax) {
414     rct1->xmax = rct2->xmax;
415   }
416   if (rct1->ymin > rct2->ymin) {
417     rct1->ymin = rct2->ymin;
418   }
419   if (rct1->ymax < rct2->ymax) {
420     rct1->ymax = rct2->ymax;
421   }
422 }
423
424 void BLI_rcti_union(rcti *rct1, const rcti *rct2)
425 {
426   if (rct1->xmin > rct2->xmin) {
427     rct1->xmin = rct2->xmin;
428   }
429   if (rct1->xmax < rct2->xmax) {
430     rct1->xmax = rct2->xmax;
431   }
432   if (rct1->ymin > rct2->ymin) {
433     rct1->ymin = rct2->ymin;
434   }
435   if (rct1->ymax < rct2->ymax) {
436     rct1->ymax = rct2->ymax;
437   }
438 }
439
440 void BLI_rctf_init(rctf *rect, float xmin, float xmax, float ymin, float ymax)
441 {
442   if (xmin <= xmax) {
443     rect->xmin = xmin;
444     rect->xmax = xmax;
445   }
446   else {
447     rect->xmax = xmin;
448     rect->xmin = xmax;
449   }
450   if (ymin <= ymax) {
451     rect->ymin = ymin;
452     rect->ymax = ymax;
453   }
454   else {
455     rect->ymax = ymin;
456     rect->ymin = ymax;
457   }
458 }
459
460 void BLI_rcti_init(rcti *rect, int xmin, int xmax, int ymin, int ymax)
461 {
462   if (xmin <= xmax) {
463     rect->xmin = xmin;
464     rect->xmax = xmax;
465   }
466   else {
467     rect->xmax = xmin;
468     rect->xmin = xmax;
469   }
470   if (ymin <= ymax) {
471     rect->ymin = ymin;
472     rect->ymax = ymax;
473   }
474   else {
475     rect->ymax = ymin;
476     rect->ymin = ymax;
477   }
478 }
479
480 void BLI_rctf_init_pt_radius(rctf *rect, const float xy[2], float size)
481 {
482   rect->xmin = xy[0] - size;
483   rect->xmax = xy[0] + size;
484   rect->ymin = xy[1] - size;
485   rect->ymax = xy[1] + size;
486 }
487
488 void BLI_rcti_init_pt_radius(rcti *rect, const int xy[2], int size)
489 {
490   rect->xmin = xy[0] - size;
491   rect->xmax = xy[0] + size;
492   rect->ymin = xy[1] - size;
493   rect->ymax = xy[1] + size;
494 }
495
496 void BLI_rcti_init_minmax(rcti *rect)
497 {
498   rect->xmin = rect->ymin = INT_MAX;
499   rect->xmax = rect->ymax = INT_MIN;
500 }
501
502 void BLI_rctf_init_minmax(rctf *rect)
503 {
504   rect->xmin = rect->ymin = FLT_MAX;
505   rect->xmax = rect->ymax = -FLT_MAX;
506 }
507
508 void BLI_rcti_do_minmax_v(rcti *rect, const int xy[2])
509 {
510   if (xy[0] < rect->xmin) {
511     rect->xmin = xy[0];
512   }
513   if (xy[0] > rect->xmax) {
514     rect->xmax = xy[0];
515   }
516   if (xy[1] < rect->ymin) {
517     rect->ymin = xy[1];
518   }
519   if (xy[1] > rect->ymax) {
520     rect->ymax = xy[1];
521   }
522 }
523
524 void BLI_rctf_do_minmax_v(rctf *rect, const float xy[2])
525 {
526   if (xy[0] < rect->xmin) {
527     rect->xmin = xy[0];
528   }
529   if (xy[0] > rect->xmax) {
530     rect->xmax = xy[0];
531   }
532   if (xy[1] < rect->ymin) {
533     rect->ymin = xy[1];
534   }
535   if (xy[1] > rect->ymax) {
536     rect->ymax = xy[1];
537   }
538 }
539
540 /* given 2 rectangles - transform a point from one to another */
541 void BLI_rctf_transform_pt_v(const rctf *dst,
542                              const rctf *src,
543                              float xy_dst[2],
544                              const float xy_src[2])
545 {
546   xy_dst[0] = ((xy_src[0] - src->xmin) / (src->xmax - src->xmin));
547   xy_dst[0] = dst->xmin + ((dst->xmax - dst->xmin) * xy_dst[0]);
548
549   xy_dst[1] = ((xy_src[1] - src->ymin) / (src->ymax - src->ymin));
550   xy_dst[1] = dst->ymin + ((dst->ymax - dst->ymin) * xy_dst[1]);
551 }
552
553 /**
554  * Calculate a 4x4 matrix representing the transformation between two rectangles.
555  *
556  * \note Multiplying a vector by this matrix does *not*
557  * give the same value as #BLI_rctf_transform_pt_v.
558  */
559 void BLI_rctf_transform_calc_m4_pivot_min_ex(
560     const rctf *dst, const rctf *src, float matrix[4][4], uint x, uint y)
561 {
562   BLI_assert(x < 3 && y < 3);
563
564   unit_m4(matrix);
565
566   matrix[x][x] = BLI_rctf_size_x(src) / BLI_rctf_size_x(dst);
567   matrix[y][y] = BLI_rctf_size_y(src) / BLI_rctf_size_y(dst);
568   matrix[3][x] = (src->xmin - dst->xmin) * matrix[x][x];
569   matrix[3][y] = (src->ymin - dst->ymin) * matrix[y][y];
570 }
571
572 void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4])
573 {
574   BLI_rctf_transform_calc_m4_pivot_min_ex(dst, src, matrix, 0, 1);
575 }
576
577 void BLI_rcti_translate(rcti *rect, int x, int y)
578 {
579   rect->xmin += x;
580   rect->ymin += y;
581   rect->xmax += x;
582   rect->ymax += y;
583 }
584 void BLI_rctf_translate(rctf *rect, float x, float y)
585 {
586   rect->xmin += x;
587   rect->ymin += y;
588   rect->xmax += x;
589   rect->ymax += y;
590 }
591
592 void BLI_rcti_recenter(rcti *rect, int x, int y)
593 {
594   const int dx = x - BLI_rcti_cent_x(rect);
595   const int dy = y - BLI_rcti_cent_y(rect);
596   BLI_rcti_translate(rect, dx, dy);
597 }
598 void BLI_rctf_recenter(rctf *rect, float x, float y)
599 {
600   const float dx = x - BLI_rctf_cent_x(rect);
601   const float dy = y - BLI_rctf_cent_y(rect);
602   BLI_rctf_translate(rect, dx, dy);
603 }
604
605 /* change width & height around the central location */
606 void BLI_rcti_resize(rcti *rect, int x, int y)
607 {
608   rect->xmin = BLI_rcti_cent_x(rect) - (x / 2);
609   rect->ymin = BLI_rcti_cent_y(rect) - (y / 2);
610   rect->xmax = rect->xmin + x;
611   rect->ymax = rect->ymin + y;
612 }
613
614 void BLI_rctf_resize(rctf *rect, float x, float y)
615 {
616   rect->xmin = BLI_rctf_cent_x(rect) - (x * 0.5f);
617   rect->ymin = BLI_rctf_cent_y(rect) - (y * 0.5f);
618   rect->xmax = rect->xmin + x;
619   rect->ymax = rect->ymin + y;
620 }
621
622 void BLI_rcti_scale(rcti *rect, const float scale)
623 {
624   const int cent_x = BLI_rcti_cent_x(rect);
625   const int cent_y = BLI_rcti_cent_y(rect);
626   const int size_x_half = BLI_rcti_size_x(rect) * (scale * 0.5f);
627   const int size_y_half = BLI_rcti_size_y(rect) * (scale * 0.5f);
628   rect->xmin = cent_x - size_x_half;
629   rect->ymin = cent_y - size_y_half;
630   rect->xmax = cent_x + size_x_half;
631   rect->ymax = cent_y + size_y_half;
632 }
633
634 void BLI_rctf_scale(rctf *rect, const float scale)
635 {
636   const float cent_x = BLI_rctf_cent_x(rect);
637   const float cent_y = BLI_rctf_cent_y(rect);
638   const float size_x_half = BLI_rctf_size_x(rect) * (scale * 0.5f);
639   const float size_y_half = BLI_rctf_size_y(rect) * (scale * 0.5f);
640   rect->xmin = cent_x - size_x_half;
641   rect->ymin = cent_y - size_y_half;
642   rect->xmax = cent_x + size_x_half;
643   rect->ymax = cent_y + size_y_half;
644 }
645
646 void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const float fac)
647 {
648   const float ifac = 1.0f - fac;
649   rect->xmin = (rect_a->xmin * ifac) + (rect_b->xmin * fac);
650   rect->xmax = (rect_a->xmax * ifac) + (rect_b->xmax * fac);
651   rect->ymin = (rect_a->ymin * ifac) + (rect_b->ymin * fac);
652   rect->ymax = (rect_a->ymax * ifac) + (rect_b->ymax * fac);
653 }
654
655 /* BLI_rcti_interp() not needed yet */
656
657 bool BLI_rctf_clamp_pt_v(const rctf *rect, float xy[2])
658 {
659   bool changed = false;
660   if (xy[0] < rect->xmin) {
661     xy[0] = rect->xmin;
662     changed = true;
663   }
664   if (xy[0] > rect->xmax) {
665     xy[0] = rect->xmax;
666     changed = true;
667   }
668   if (xy[1] < rect->ymin) {
669     xy[1] = rect->ymin;
670     changed = true;
671   }
672   if (xy[1] > rect->ymax) {
673     xy[1] = rect->ymax;
674     changed = true;
675   }
676   return changed;
677 }
678
679 bool BLI_rcti_clamp_pt_v(const rcti *rect, int xy[2])
680 {
681   bool changed = false;
682   if (xy[0] < rect->xmin) {
683     xy[0] = rect->xmin;
684     changed = true;
685   }
686   if (xy[0] > rect->xmax) {
687     xy[0] = rect->xmax;
688     changed = true;
689   }
690   if (xy[1] < rect->ymin) {
691     xy[1] = rect->ymin;
692     changed = true;
693   }
694   if (xy[1] > rect->ymax) {
695     xy[1] = rect->ymax;
696     changed = true;
697   }
698   return changed;
699 }
700
701 /**
702  * Clamp \a rect within \a rect_bounds, setting \a r_xy to the offset.
703  *
704  * Keeps the top left corner within the bounds, which for user interface
705  * elements is typically where the most important information is.
706  *
707  * \return true if a change is made.
708  */
709 bool BLI_rctf_clamp(rctf *rect, const rctf *rect_bounds, float r_xy[2])
710 {
711   bool changed = false;
712
713   r_xy[0] = 0.0f;
714   r_xy[1] = 0.0f;
715
716   if (rect->xmax > rect_bounds->xmax) {
717     float ofs = rect_bounds->xmax - rect->xmax;
718     rect->xmin += ofs;
719     rect->xmax += ofs;
720     r_xy[0] += ofs;
721     changed = true;
722   }
723
724   if (rect->xmin < rect_bounds->xmin) {
725     float ofs = rect_bounds->xmin - rect->xmin;
726     rect->xmin += ofs;
727     rect->xmax += ofs;
728     r_xy[0] += ofs;
729     changed = true;
730   }
731
732   if (rect->ymin < rect_bounds->ymin) {
733     float ofs = rect_bounds->ymin - rect->ymin;
734     rect->ymin += ofs;
735     rect->ymax += ofs;
736     r_xy[1] += ofs;
737     changed = true;
738   }
739
740   if (rect->ymax > rect_bounds->ymax) {
741     float ofs = rect_bounds->ymax - rect->ymax;
742     rect->ymin += ofs;
743     rect->ymax += ofs;
744     r_xy[1] += ofs;
745     changed = true;
746   }
747
748   return changed;
749 }
750
751 bool BLI_rcti_clamp(rcti *rect, const rcti *rect_bounds, int r_xy[2])
752 {
753   bool changed = false;
754
755   r_xy[0] = 0;
756   r_xy[1] = 0;
757
758   if (rect->xmax > rect_bounds->xmax) {
759     int ofs = rect_bounds->xmax - rect->xmax;
760     rect->xmin += ofs;
761     rect->xmax += ofs;
762     r_xy[0] += ofs;
763     changed = true;
764   }
765
766   if (rect->xmin < rect_bounds->xmin) {
767     int ofs = rect_bounds->xmin - rect->xmin;
768     rect->xmin += ofs;
769     rect->xmax += ofs;
770     r_xy[0] += ofs;
771     changed = true;
772   }
773
774   if (rect->ymin < rect_bounds->ymin) {
775     int ofs = rect_bounds->ymin - rect->ymin;
776     rect->ymin += ofs;
777     rect->ymax += ofs;
778     r_xy[1] += ofs;
779     changed = true;
780   }
781
782   if (rect->ymax > rect_bounds->ymax) {
783     int ofs = rect_bounds->ymax - rect->ymax;
784     rect->ymin += ofs;
785     rect->ymax += ofs;
786     r_xy[1] += ofs;
787     changed = true;
788   }
789
790   return changed;
791 }
792
793 bool BLI_rctf_compare(const rctf *rect_a, const rctf *rect_b, const float limit)
794 {
795   if (fabsf(rect_a->xmin - rect_b->xmin) < limit) {
796     if (fabsf(rect_a->xmax - rect_b->xmax) < limit) {
797       if (fabsf(rect_a->ymin - rect_b->ymin) < limit) {
798         if (fabsf(rect_a->ymax - rect_b->ymax) < limit) {
799           return true;
800         }
801       }
802     }
803   }
804
805   return false;
806 }
807
808 bool BLI_rcti_compare(const rcti *rect_a, const rcti *rect_b)
809 {
810   if (rect_a->xmin == rect_b->xmin) {
811     if (rect_a->xmax == rect_b->xmax) {
812       if (rect_a->ymin == rect_b->ymin) {
813         if (rect_a->ymax == rect_b->ymax) {
814           return true;
815         }
816       }
817     }
818   }
819
820   return false;
821 }
822
823 bool BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest)
824 {
825   float xmin, xmax;
826   float ymin, ymax;
827
828   xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin);
829   xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax);
830   ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin);
831   ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax);
832
833   if (xmax >= xmin && ymax >= ymin) {
834     if (dest) {
835       dest->xmin = xmin;
836       dest->xmax = xmax;
837       dest->ymin = ymin;
838       dest->ymax = ymax;
839     }
840     return true;
841   }
842   else {
843     if (dest) {
844       dest->xmin = 0;
845       dest->xmax = 0;
846       dest->ymin = 0;
847       dest->ymax = 0;
848     }
849     return false;
850   }
851 }
852
853 bool BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
854 {
855   int xmin, xmax;
856   int ymin, ymax;
857
858   xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin);
859   xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax);
860   ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin);
861   ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax);
862
863   if (xmax >= xmin && ymax >= ymin) {
864     if (dest) {
865       dest->xmin = xmin;
866       dest->xmax = xmax;
867       dest->ymin = ymin;
868       dest->ymax = ymax;
869     }
870     return true;
871   }
872   else {
873     if (dest) {
874       dest->xmin = 0;
875       dest->xmax = 0;
876       dest->ymin = 0;
877       dest->ymax = 0;
878     }
879     return false;
880   }
881 }
882
883 void BLI_rcti_rctf_copy(rcti *dst, const rctf *src)
884 {
885   dst->xmin = floorf(src->xmin + 0.5f);
886   dst->xmax = dst->xmin + floorf(BLI_rctf_size_x(src) + 0.5f);
887   dst->ymin = floorf(src->ymin + 0.5f);
888   dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f);
889 }
890
891 void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src)
892 {
893   dst->xmin = floorf(src->xmin);
894   dst->xmax = floorf(src->xmax);
895   dst->ymin = floorf(src->ymin);
896   dst->ymax = floorf(src->ymax);
897 }
898
899 void BLI_rcti_rctf_copy_round(rcti *dst, const rctf *src)
900 {
901   dst->xmin = floorf(src->xmin + 0.5f);
902   dst->xmax = floorf(src->xmax + 0.5f);
903   dst->ymin = floorf(src->ymin + 0.5f);
904   dst->ymax = floorf(src->ymax + 0.5f);
905 }
906
907 void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
908 {
909   dst->xmin = src->xmin;
910   dst->xmax = src->xmax;
911   dst->ymin = src->ymin;
912   dst->ymax = src->ymax;
913 }
914
915 void print_rctf(const char *str, const rctf *rect)
916 {
917   printf("%s: xmin %.8f, xmax %.8f, ymin %.8f, ymax %.8f (%.12fx%.12f)\n",
918          str,
919          rect->xmin,
920          rect->xmax,
921          rect->ymin,
922          rect->ymax,
923          BLI_rctf_size_x(rect),
924          BLI_rctf_size_y(rect));
925 }
926
927 void print_rcti(const char *str, const rcti *rect)
928 {
929   printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n",
930          str,
931          rect->xmin,
932          rect->xmax,
933          rect->ymin,
934          rect->ymax,
935          BLI_rcti_size_x(rect),
936          BLI_rcti_size_y(rect));
937 }
938
939 /* -------------------------------------------------------------------- */
940 /* Comprehensive math (float only) */
941
942 /** \name Rect math functions
943  * \{ */
944
945 #define ROTATE_SINCOS(r_vec, mat2, vec) \
946   { \
947     (r_vec)[0] = (mat2)[1] * (vec)[0] + (+(mat2)[0]) * (vec)[1]; \
948     (r_vec)[1] = (mat2)[0] * (vec)[0] + (-(mat2)[1]) * (vec)[1]; \
949   } \
950   ((void)0)
951
952 /**
953  * Expand the rectangle to fit a rotated \a src.
954  */
955 void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle)
956 {
957   const float mat2[2] = {sinf(angle), cosf(angle)};
958   const float cent[2] = {BLI_rctf_cent_x(src), BLI_rctf_cent_y(src)};
959   float corner[2], corner_rot[2], corder_max[2];
960
961   /* x is same for both corners */
962   corner[0] = src->xmax - cent[0];
963   corner[1] = src->ymax - cent[1];
964   ROTATE_SINCOS(corner_rot, mat2, corner);
965   corder_max[0] = fabsf(corner_rot[0]);
966   corder_max[1] = fabsf(corner_rot[1]);
967
968   corner[1] *= -1;
969   ROTATE_SINCOS(corner_rot, mat2, corner);
970   corder_max[0] = MAX2(corder_max[0], fabsf(corner_rot[0]));
971   corder_max[1] = MAX2(corder_max[1], fabsf(corner_rot[1]));
972
973   dst->xmin = cent[0] - corder_max[0];
974   dst->xmax = cent[0] + corder_max[0];
975   dst->ymin = cent[1] - corder_max[1];
976   dst->ymax = cent[1] + corder_max[1];
977 }
978
979 #undef ROTATE_SINCOS
980
981 /** \} */
982
983 static void unit_m4(float m[4][4])
984 {
985   m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
986   m[0][1] = m[0][2] = m[0][3] = 0.0f;
987   m[1][0] = m[1][2] = m[1][3] = 0.0f;
988   m[2][0] = m[2][1] = m[2][3] = 0.0f;
989   m[3][0] = m[3][1] = m[3][2] = 0.0f;
990 }