source: trunk/src/org/expeditee/core/bounds/AxisAlignedBoxBounds.java@ 1258

Last change on this file since 1258 was 1258, checked in by davidb, 5 years ago

Changed how DisplayController width, height and size are retrieved. Now does this top-level, rather than going through the AxisAlignmentBox. In doing so, can now control for when the window size has you yet been correctly mapped to the screen, and fall back to pre-defined MINIMUM defaults

File size: 9.1 KB
Line 
1package org.expeditee.core.bounds;
2
3import org.expeditee.Util;
4import org.expeditee.core.Dimension;
5import org.expeditee.core.Line;
6import org.expeditee.core.Point;
7import org.expeditee.gui.DisplayController;
8
9/**
10 * A bounds that represents a rectangular area where the left and right sides are parallel
11 * to the y-axis and the top and bottom sides are parallel to the x-axis.
12 *
13 * @author cts16
14 */
15public class AxisAlignedBoxBounds extends Bounds {
16
17 /** The top-left corner of the bounds. */
18 private Point _topLeft;
19 /** The width and height of the rectangular bounds. */
20 private Dimension _size;
21
22 /** Creates an AxisAlignedBoxBounds at the given location with the given size. */
23 public AxisAlignedBoxBounds(Point topLeft, Dimension size)
24 {
25 setTopLeft(topLeft);
26 setSize(size);
27 }
28
29 /** Creates an AxisAlignedBoxBounds at the given location with the given size. */
30 public AxisAlignedBoxBounds(int x, int y, int width, int height)
31 {
32 this(new Point(x, y), new Dimension(width, height));
33 }
34
35 /** Creates an AxisAlignedBoxBounds with the same location and size as <code>other</code>. */
36 public AxisAlignedBoxBounds(AxisAlignedBoxBounds other)
37 {
38 if (other != null) {
39 setTopLeft(other._topLeft);
40 setSize(other._size);
41 } else {
42 setTopLeft(null);
43 setSize(null);
44 }
45 }
46
47 /** Creates an AxisAlignedBoxBounds that completely encloses the given bounds. */
48 public static AxisAlignedBoxBounds getEnclosing(Bounds b)
49 {
50 if (b == null) return null;
51
52 int maxX = b.getMaxX();
53 int minX = b.getMinX();
54 int maxY = b.getMaxY();
55 int minY = b.getMinY();
56
57 Point topLeft = new Point(minX, minY);
58 Dimension size = new Dimension(maxX - minX + 1, maxY - minY + 1);
59
60 return new AxisAlignedBoxBounds(topLeft, size);
61 }
62
63 /** Gets the top-left corner position of this AxisAlignedBoxBounds. */
64 public Point getTopLeft()
65 {
66 return _topLeft;
67 }
68
69 /** Gets the top-left corner position of this AxisAlignedBoxBounds. */
70 public Point getBottomRight()
71 {
72 return _topLeft.clone().add(_size.width - 1, _size.height - 1);
73 }
74
75 /** Sets the top-left corner of this AxisAlignedBoxBounds to the given point. */
76 public void setTopLeft(Point topLeft)
77 {
78 if (topLeft == null) topLeft = new Point(0, 0);
79 this._topLeft = topLeft;
80 }
81
82 /** Gets the size of this Bounds. */
83 public Dimension getSize()
84 {
85 return _size;
86 }
87
88 /** Sets the size of this Bounds (null sets to 1x1). */
89 public void setSize(Dimension size)
90 {
91 if (size == null) size = new Dimension(1, 1);
92 this._size = size;
93 }
94
95 /** Gets the width of this AxisAlignedBoxBounds. */
96 public int getWidth()
97 {
98 return _size.width;
99 }
100
101 /** Gets the height of this AxisAlignedBoxBounds. */
102 public int getHeight()
103 {
104 return _size.height;
105 }
106
107 /** Gets the x-coordinate of the centre of this AxisAlignedBoxBounds. */
108 public int getCentreX()
109 {
110 return _topLeft.getX() + _size.width / 2;
111 }
112
113 /** Gets the y-coordinate of the centre of this AxisAlignedBoxBounds. */
114 public int getCentreY()
115 {
116 return _topLeft.getY() + _size.height / 2;
117 }
118
119 /** Gets the coordinates of the centre of this AxisAlignedBoxBounds. */
120 public Point getCentre()
121 {
122 return new Point(getCentreX(), getCentreY());
123 }
124
125 /**
126 * Updates this Bounds so it covers both its original area and
127 * the area of the given bounds (plus some possible extra area).
128 *
129 * E.g. /////////**********
130 * / / *
131 * / other / \\\\\\
132 * ///////// \ \
133 * * \this\
134 * * result \ \
135 * *************\\\\\\
136 */
137 public AxisAlignedBoxBounds combineWith(AxisAlignedBoxBounds other)
138 {
139 // Can't combine with nothing
140 if (other == null) return this;
141
142 int top = Math.min(this.getMinY(), other.getMinY());
143 int bottom = Math.max(this.getMaxY(), other.getMaxY());
144 int left = Math.min(this.getMinX(), other.getMinX());
145 int right = Math.max(this.getMaxX(), other.getMaxX());
146
147 _topLeft.set(left, top);
148 _size.width = right - left + 1;
149 _size.height = bottom - top + 1;
150
151 return this;
152 }
153
154 /**
155 * Expands the bounds to encompass the given point.
156 *
157 * @param p
158 * The point to cover.
159 */
160 public AxisAlignedBoxBounds combineWith(Point p)
161 {
162 if (p == null) return this;
163
164 return combineWith(new AxisAlignedBoxBounds(p, new Dimension(1, 1)));
165 }
166
167 @Override
168 public boolean contains(int x, int y)
169 {
170 return (x >= _topLeft.getX() &&
171 x < (_topLeft.getX() + _size.width) &&
172 y >= _topLeft.getY() &&
173 y < (_topLeft.getY() + _size.height));
174 }
175
176 @Override
177 public int getMaxX()
178 {
179 return _topLeft.getX() + _size.width - 1;
180 }
181
182 @Override
183 public int getMinX()
184 {
185 return _topLeft.getX();
186 }
187
188 @Override
189 public int getMaxY()
190 {
191 return _topLeft.getY() + _size.height - 1;
192 }
193
194 @Override
195 public int getMinY()
196 {
197 return _topLeft.getY();
198 }
199
200 @Override
201 public AxisAlignedBoxBounds translate(int x, int y)
202 {
203 _topLeft.add(x, y);
204
205 return this;
206 }
207
208 @Override
209 public boolean equals(Bounds other)
210 {
211 if (other instanceof AxisAlignedBoxBounds) {
212 return this.getTopLeft().equals(((AxisAlignedBoxBounds) other).getTopLeft()) && this.getSize().equals(((AxisAlignedBoxBounds) other).getSize());
213 }
214
215 return false;
216 }
217
218 @Override
219 public boolean intersects(AxisAlignedBoxBounds other)
220 {
221 if (other == null) return false;
222
223 boolean completelyAbove = other.getMaxY() < this.getMinY();
224 boolean completelyBelow = other.getMinY() > this.getMaxY();
225 boolean completelyLeft = other.getMaxX() < this.getMinX();
226 boolean completelyRight = other.getMinX() > this.getMaxX();
227
228 return !(completelyAbove || completelyBelow || completelyLeft || completelyRight);
229 }
230
231 @Override
232 public boolean intersects(CombinationBounds other)
233 {
234 // Defer to the CombinationBounds routine
235 return other.intersects(this);
236 }
237
238 @Override
239 public boolean intersects(EllipticalBounds other)
240 {
241 // Defer to the EllipticalBounds routine
242 return other.intersects(this);
243 }
244
245 @Override
246 public boolean intersects(PolygonBounds other)
247 {
248 // Defer to the PolygonBounds routine
249 return other.intersects(this);
250 }
251
252 /** Gets an array of four points representing the corners of the box. */
253 public Point[] getCorners()
254 {
255 Point[] corners = new Point[4];
256
257 corners[0] = new Point(getMinX(), getMinY());
258 corners[1] = new Point(getMaxX(), getMinY());
259 corners[2] = new Point(getMaxX(), getMaxY());
260 corners[3] = new Point(getMinX(), getMaxY());
261
262 return corners;
263 }
264
265 /** Gets an array of four lines representing the border of this Bounds. */
266 public Line[] getBorderLines()
267 {
268 Line[] lines = new Line[4];
269 Point[] corners = getCorners();
270
271 lines[0] = new Line(corners[0], corners[1]);
272 lines[1] = new Line(corners[1], corners[2]);
273 lines[2] = new Line(corners[2], corners[3]);
274 lines[3] = new Line(corners[3], corners[0]);
275
276 return lines;
277 }
278
279 @Override
280 public double getArea()
281 {
282 return _size.width * _size.height;
283 }
284
285 @Override
286 public boolean perimeterContains(Point p, double error)
287 {
288 Line[] borderLines = getBorderLines();
289
290 for (Line borderLine : borderLines) {
291 if (borderLine.contains(p, error)) return true;
292 }
293
294 return false;
295 }
296
297 @Override
298 public boolean completelyContains(AxisAlignedBoxBounds other)
299 {
300 if (other == null) return false;
301
302 return contains(other.getTopLeft()) && contains(other.getBottomRight());
303 }
304
305 @Override
306 public boolean completelyContains(CombinationBounds other)
307 {
308 if (other == null) return false;
309
310 return completelyContains(getEnclosing(other));
311 }
312
313 @Override
314 public boolean completelyContains(EllipticalBounds other)
315 {
316 if (other == null) return false;
317
318 return completelyContains(getEnclosing(other));
319 }
320
321 @Override
322 public boolean completelyContains(PolygonBounds other)
323 {
324 if (other == null) return false;
325
326 return completelyContains(getEnclosing(other));
327 }
328
329 /** Gets a polygon that represents the same area as this box. */
330 public PolygonBounds getPolygon()
331 {
332 return PolygonBounds.fromBox(this);
333 }
334
335 /** Gets the area of intersection between this box and the other. */
336 public AxisAlignedBoxBounds intersectionWith(AxisAlignedBoxBounds other)
337 {
338 if (intersects(other)) {
339 int minX = getMinX() > other.getMinX() ? getMinX() : other.getMinX();
340 int minY = getMinY() > other.getMinY() ? getMinY() : other.getMinY();
341 int maxX = getMaxX() < other.getMaxX() ? getMaxX() : other.getMaxX();
342 int maxY = getMaxY() < other.getMaxY() ? getMaxY() : other.getMaxY();
343
344 return new AxisAlignedBoxBounds(minX, minY, maxX - minX + 1, maxY - minY + 1);
345 } else {
346 return null;
347 }
348 }
349
350 /** Gets the bounds that is linearly-interpolated between the two given bounds. */
351 public static AxisAlignedBoxBounds lerp(AxisAlignedBoxBounds a, AxisAlignedBoxBounds b, float t)
352 {
353 if (a == null || b == null) return null;
354
355 int minX = (int) Util.lerp(a.getMinX(), b.getMinX(), t);
356 int minY = (int) Util.lerp(a.getMinY(), b.getMinY(), t);
357 int width = (int) Util.lerp(a.getWidth(), b.getWidth(), t);
358 int height = (int) Util.lerp(a.getHeight(), b.getHeight(), t);
359
360 return new AxisAlignedBoxBounds(minX, minY, width, height);
361 }
362
363 @Override
364 public AxisAlignedBoxBounds clone()
365 {
366 return new AxisAlignedBoxBounds(this);
367 }
368
369 @Override
370 public String toString() {
371 return "AxisAlignedBoxBounds with (top left, bottom right): " + getTopLeft() + "," + getBottomRight();
372 }
373
374}
Note: See TracBrowser for help on using the repository browser.