2
/******************************************************************************
3
* MODULE : rectangles.cpp
4
* DESCRIPTION: Rectangles and lists of rectangles with reference counting.
5
* Used in graphical programs.
6
* COPYRIGHT : (C) 1999 Joris van der Hoeven
7
*******************************************************************************
8
* This software falls under the GNU general public license and comes WITHOUT
9
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
10
* If you don't have this file, write to the Free Software Foundation, Inc.,
11
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
12
******************************************************************************/
14
#include "rectangles.hpp"
16
/******************************************************************************
17
* Routines for rectangles
18
******************************************************************************/
20
rectangle_rep::rectangle_rep (SI x1b, SI y1b, SI x2b, SI y2b):
21
x1 (x1b), y1 (y1b), x2 (x2b), y2 (y2b) { }
23
rectangle::rectangle (SI x1b, SI y1b, SI x2b, SI y2b):
24
rep (new rectangle_rep (x1b, y1b, x2b, y2b)) { }
26
rectangle::operator tree () {
28
as_string (rep->x1), as_string (rep->y1),
29
as_string (rep->x2), as_string (rep->y2));
33
operator << (ostream& out, rectangle r) {
35
<< r->x1 << ", " << r->y1 << ", "
36
<< r->x2 << ", " << r->y2 << ")";
42
return rectangle (r->x1, r->y1, r->x2, r->y2);
46
operator == (rectangle r1, rectangle r2) {
48
(r1->x1==r2->x1) && (r1->y1==r2->y1) &&
49
(r1->x2==r2->x2) && (r1->y2==r2->y2);
53
operator != (rectangle r1, rectangle r2) {
55
(r1->x1!=r2->x1) || (r1->y1!=r2->y1) ||
56
(r1->x2!=r2->x2) || (r1->y2!=r2->y2);
60
operator <= (rectangle r1, rectangle r2) {
62
(r1->x1>=r2->x1) && (r1->x2<=r2->x2) &&
63
(r1->y1>=r2->y1) && (r1->y2<=r2->y2);
67
intersect (rectangle r1, rectangle r2) {
69
(r1->x1<r2->x2) && (r1->x2>r2->x1) &&
70
(r1->y1<r2->y2) && (r1->y2>r2->y1);
74
translate (rectangle r, SI x, SI y) {
75
return rectangle (r->x1+x, r->y1+y, r->x2+x, r->y2+y);
80
double w= max (r->x2 - r->x1, 0);
81
double h= max (r->y2 - r->y1, 0);
85
/******************************************************************************
86
* Miscellaneous subroutines
87
******************************************************************************/
89
// FIXME: Why do we need this? Compiler bug?
90
#define min(x,y) ((x)<=(y)?(x):(y))
91
#define max(x,y) ((x)<=(y)?(y):(x))
94
complement (rectangle r1, rectangle r2, rectangles& l) {
95
if (!intersect (r1, r2)) { r1 >> l; return; }
96
if (r1->x1 < r2->x1) rectangle (r1->x1, r1->y1, r2->x1, r1->y2) >> l;
97
if (r1->x2 > r2->x2) rectangle (r2->x2, r1->y1, r1->x2, r1->y2) >> l;
98
if (r1->y1 < r2->y1) rectangle (max (r1->x1, r2->x1), r1->y1,
99
min (r1->x2, r2->x2), r2->y1) >> l;
100
if (r1->y2 > r2->y2) rectangle (max (r1->x1, r2->x1), r2->y2,
101
min (r1->x2, r2->x2), r1->y2) >> l;
105
complement (rectangles l1, rectangle r2, rectangles& l) {
106
for (; !is_nil (l1); l1= l1->next)
107
complement (l1->item, r2, l);
111
intersection (rectangle r1, rectangle r2, rectangles& l) {
112
if (!intersect (r1, r2)) return;
113
rectangle (max (r1->x1, r2->x1), max (r1->y1, r2->y1),
114
min (r1->x2, r2->x2), min (r1->y2, r2->y2)) >> l;
118
operator * (rectangle r, int d) {
119
return rectangle (r->x1*d, r->y1*d, r->x2*d, r->y2*d);
123
operator / (rectangle r, int d) {
124
return rectangle (r->x1/d, r->y1/d, r->x2/d, r->y2/d);
127
/******************************************************************************
128
* Exported routines for rectangles
129
******************************************************************************/
132
operator - (rectangles l1, rectangles l2) {
134
for (; !is_nil (l2); l2= l2->next) {
136
complement (a, l2->item, b);
143
operator & (rectangles l1, rectangles l2) {
144
rectangles l, lc1, lc2;
145
for (lc1= l1; !is_nil (lc1); lc1= lc1->next)
146
for (lc2= l2; !is_nil (lc2); lc2= lc2->next)
147
intersection (lc1->item, lc2->item, l);
152
adjacent (rectangle r1, rectangle r2) {
154
(((r1->x2==r2->x1) || (r1->x1==r2->x2)) &&
155
((r1->y1==r2->y1) && (r1->y2==r2->y2))) ||
156
(((r1->y2==r2->y1) || (r1->y1==r2->y2)) &&
157
((r1->x1==r2->x1) && (r1->x2==r2->x2)));
161
disjoint_union (rectangles l, rectangle r) {
162
if (is_nil (l)) return r;
163
if (adjacent (l->item, r))
164
return disjoint_union (l->next,
165
least_upper_bound (rectangles (l->item, r)));
166
return rectangles (l->item, disjoint_union (l->next, r));
170
operator | (rectangles l1, rectangles l2) {
171
rectangles l (l1-l2);
172
while (!is_nil (l2)) {
173
l = disjoint_union (l, l2->item);
180
translate (rectangles l, SI x, SI y) {
181
if (is_nil (l)) return l;
182
rectangle& r= l->item;
183
return rectangles (rectangle (r->x1+ x, r->y1+ y, r->x2+ x, r->y2+ y),
184
translate (l->next, x, y));
188
thicken (rectangles l, SI width, SI height) {
189
if (is_nil (l)) return l;
190
rectangle& r= l->item;
191
return rectangles (rectangle (r->x1- width, r->y1- height,
192
r->x2+ width, r->y2+ height),
193
thicken (l->next, width, height));
197
outline (rectangles rs, SI pixel) {
198
return simplify (correct (thicken (rs, pixel, 3*pixel) -
199
thicken (rs, 0, 2*pixel)));
203
operator * (rectangles l, int d) {
204
if (is_nil (l)) return l;
205
return rectangles (l->item*d, l->next*d);
209
operator / (rectangles l, int d) {
210
if (is_nil (l)) return l;
211
return rectangles (l->item/d, l->next/d);
215
correct (rectangles l) {
216
if (is_nil (l)) return l;
217
if ((l->item->x1 >= l->item->x2) || (l->item->y1 >= l->item->y2))
218
return correct (l->next);
219
return rectangles (l->item, correct (l->next));
223
simplify (rectangles l) {
224
if (is_nil (l) || is_atom (l)) return l;
225
return simplify (l->next) | rectangles (l->item);
229
least_upper_bound (rectangles l) {
230
if (is_nil (l)) fatal_error ("no rectangles in list", "least_upper_bound");
231
rectangle r1= copy (l->item);
232
while (!is_nil (l->next)) {
234
rectangle r2= l->item;
235
r1->x1= min (r1->x1, r2->x1);
236
r1->y1= min (r1->y1, r2->y1);
237
r1->x2= max (r1->x2, r2->x2);
238
r1->y2= max (r1->y2, r2->y2);
244
area (rectangles r) {
246
while (!is_nil (r)) {
247
sum += area (r->item);