1
2 package org.catacomb.datalish;
3
4 import org.catacomb.be.Position;
5
6
7
8
9 public final class Box {
10
11
12 double xmin;
13 double xmax;
14 double ymin;
15 double ymax;
16
17 double subdivDx;
18 double subdivDy;
19
20
21 private boolean noXdata;
22 private boolean noYdata;
23
24 public Box(Position p) {
25 this(p.getX(), p.getY());
26 }
27
28
29 public Box(double x, double y) {
30 xmin = x;
31 xmax = x;
32 ymin = y;
33 ymax = y;
34 noXdata = false;
35 noYdata = false;
36 }
37
38 public Box() {
39 noXdata = true;
40 noYdata = true;
41 }
42
43
44 public Box(double x0, double y0, double x1, double y1) {
45 xmin = x0;
46 ymin = y0;
47 xmax = x1;
48 ymax = y1;
49 noXdata = false;
50 noYdata = false;
51 }
52
53 public Box makeCopy() {
54 return new Box(xmin, ymin, xmax, ymax);
55 }
56
57
58 public String toString() {
59 return " Box x0=" + xmin + " y0=" + ymin + " x1=" + xmax + " y1=" + xmax;
60 }
61
62
63 public void setXMin(double d) {
64 xmin = d;
65 }
66 public void setXMax(double d) {
67 xmax = d;
68 }
69
70 public void setYMin(double d) {
71 ymin = d;
72 }
73
74 public void setYMax(double d) {
75 ymax = d;
76 }
77
78 public double getXmin() {
79 return xmin;
80 }
81
82 public double getXmax() {
83 return xmax;
84 }
85
86
87 public double getYmin() {
88 return ymin;
89 }
90
91 public double getYmax() {
92 return ymax;
93 }
94
95
96 public void subdivide(int n) {
97 subdivDx = (xmax - xmin) / n;
98 subdivDy = (ymax - ymin) / n;
99 }
100
101
102 public int getXSubdivision(double x) {
103 int ret = (int)((x - xmin) / subdivDx);
104 return ret;
105 }
106
107
108 public int getYSubdivision(double y) {
109 int ret = (int)((y - ymin) / subdivDy);
110 return ret;
111 }
112
113
114
115 public int getXSubdivision(double x, int n) {
116 double dx = (xmax - xmin) / n;
117 int ret = (int)((x - xmin) / dx);
118 return ret;
119 }
120
121
122 public int getYSubdivision(double y, int n) {
123 double dy = (ymax - ymin) / n;
124 int ret = (int)((y - ymin) / dy);
125 return ret;
126 }
127
128
129 public void extendTo(Position p) {
130 extendTo(p.getX(), p.getY());
131 }
132
133
134 public void extendTo(Box b) {
135 extendTo(b.xmin, b.ymin);
136 extendTo(b.xmax, b.ymax);
137 }
138
139
140 public void extendTo(double[] xp, double[] yp) {
141 for (int i = 0; i < xp.length; i++) {
142 extendTo(xp[i], yp[i]);
143 }
144 }
145
146
147 public boolean hasData() {
148 return (!(noXdata || noYdata));
149 }
150
151
152 public void extendXTo(double x) {
153 if (noXdata) {
154 xmin = x;
155 xmax = x;
156 noXdata = false;
157 }
158
159 if (x < xmin) {
160 xmin = x;
161 }
162 if (x > xmax) {
163 xmax = x;
164 }
165 }
166
167
168 public void extendTo(double x, double y) {
169 extendXTo(x);
170 extendYTo(y);
171 }
172
173 public void extendYTo(double y) {
174 if (noYdata) {
175 ymin = y;
176 ymax = y;
177 noYdata = false;
178 }
179
180 if (y < ymin) {
181 ymin = y;
182 }
183
184 if (y > ymax) {
185 ymax = y;
186 }
187
188 }
189
190
191 public void pad() {
192 enlarge(0.1);
193 }
194
195 public void enlarge(double f) {
196
197 double dx = f * (xmax - xmin);
198 double dy = f * (ymax - ymin);
199
200 xmin -= dx;
201 xmax += dx;
202
203 ymin -= dy;
204 ymax += dy;
205 }
206
207
208 public void push(double x, double y) {
209 extendTo(x, y);
210 }
211
212 public void push(double[] x, double[] y) {
213 pushX(x, x.length);
214 pushY(y, y.length);
215 }
216
217 public void pushX(double[] v) {
218 pushX(v, v.length);
219 }
220
221 public void pushX(double[] v, int np) {
222 if (np > 0 && noXdata) {
223 xmin = v[0];
224 xmax = v[0];
225 noXdata = false;
226 }
227
228 for (int i = 0; i < np; i++) {
229 double d = v[i];
230 if (xmin > d) {
231 xmin = d;
232 }
233 if (xmax < d) {
234 xmax = d;
235 }
236 }
237 }
238
239 public void pushY(double d) {
240 if (noYdata) {
241 ymin = d;
242 ymax = d;
243 } else {
244 if (ymin > d) {
245 ymin = d;
246 }
247 if (ymax < d) {
248 ymax = d;
249 }
250 }
251 }
252
253 public void pushY(double[] d) {
254 pushY(d, d.length);
255 }
256
257 public void pushY(double[] v, int np) {
258 if (np > 0 && noYdata) {
259 ymin = v[0];
260 ymax = v[0];
261 noYdata = false;
262 }
263
264 for (int i = 0; i < np; i++) {
265 double d = v[i];
266 if (ymin > d) {
267 ymin = d;
268 }
269 if (ymax < d) {
270 ymax = d;
271 }
272 }
273 }
274
275
276 public void push(Position position) {
277 extendTo(position.getX(), position.getY());
278 }
279
280
281 public boolean differentFrom(Box b, double d) {
282 boolean ret = false;
283
284 if (hasData() && b.hasData()) {
285 if (rangesDiffer(xmin, xmax, b.xmin, b.xmax, d) ||
286 rangesDiffer(ymin, ymax, b.ymin, b.ymax, d)) {
287 ret = true;
288 }
289 }
290 return ret;
291 }
292
293
294 private boolean rangesDiffer(double a, double b, double c, double d, double delta) {
295 boolean ret = false;
296 double u = 0.5 * (b - a + d - c);
297 double f1 = (c - a) / u;
298 double f2 = (d - b) / u;
299 ret = (Math.abs(f1) > delta || Math.abs(f2) > delta);
300
301 if (ret) {
302
303 }
304 return ret;
305 }
306
307
308 public Position getCenter() {
309 double cx = 0.5 * (xmin + xmax);
310 double cy = 0.5 * (ymin + ymax);
311 return new Position(cx, cy);
312 }
313
314
315 public double getRadius() {
316 double dx = xmax - xmin;
317 double dy = ymax - ymin;
318 double scl = 0.5 * Math.max(dx, dy);
319 return scl;
320 }
321
322
323 public void tidyLimits() {
324 if (xmin > 0. && (xmax - xmin) / xmin > 5.) {
325 xmin = 0.;
326 } else if (xmin < 0. && (xmax - xmin) / -xmin > 20.) {
327 xmin = 0.;
328 }
329
330 if (ymin > 0. && (ymax - ymin) / ymin > 5.) {
331 ymin = 0.;
332 } else if (ymin < 0. && (ymax - ymin) / -ymin > 20.) {
333 ymin = 0.;
334 }
335 }
336
337
338
339 }