1 package org.djutils.quadtree;
2
3 import java.io.Serializable;
4
5 import org.djutils.exceptions.Throw;
6
7 /**
8 * Rectangle defines an area bounded by a lower and left edges (inclusive) and a upper and right edges (not inclusive). The
9 * boundary values are stored in the object; unlike the Rectangle2D class where the width and height are stored and to the left
10 * and bottom. Doing it this way absolutely ensures that we can make a grid of rectangles that have no ULP width gaps.
11 * Additionally, this Rectangle object is immutable. Finally, there is no annoying name collision with the java.lang.Double
12 * class.<br>
13 * <br>
14 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
15 * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
16 * distributed under a three-clause BSD-style license, which can be found at
17 * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. <br>
18 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19 * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
20 */
21 public class Rectangle implements Serializable
22 {
23 /** ... */
24 private static final long serialVersionUID = 20200904L;
25
26 /** Left boundary (inclusive). */
27 private final double left;
28
29 /** Bottom boundary (inclusive). */
30 private final double bottom;
31
32 /** Right boundary (not inclusive). */
33 private final double right;
34
35 /** Top boundary (not inclusive). */
36 private final double top;
37
38 /**
39 * Construct a new Rectangle; all arguments are checked for having sensible values.
40 * @param left double; the left boundary (inclusive)
41 * @param bottom double; the bottom boundary (inclusive)
42 * @param right double; the right boundary (not inclusive)
43 * @param top double; the top boundary (not inclusive)
44 * @param check boolean; if true; the values are checked for making sense
45 */
46 public Rectangle(final double left, final double bottom, final double right, final double top, final boolean check)
47 {
48 this(left, bottom, right, top);
49 if (check)
50 {
51 Throw.when(Double.isNaN(left), IllegalArgumentException.class, "The value of left may not be NaN");
52 Throw.when(Double.isNaN(bottom), IllegalArgumentException.class, "The value of bottom may not be NaN");
53 Throw.when(Double.isNaN(right), IllegalArgumentException.class, "The value of right may not be NaN");
54 Throw.when(Double.isNaN(top), IllegalArgumentException.class, "The value of top may not be NaN");
55 Throw.when(left > right, IllegalArgumentException.class, "The value of left may not exceed the value of right");
56 Throw.when(bottom > top, IllegalArgumentException.class, "The value of bottom may not exceed the value of top");
57 }
58 }
59
60 /**
61 * Construct a new Rectangle without checking the arguments for making sense.
62 * @param left double; the left boundary (inclusive)
63 * @param bottom double; the bottom boundary (inclusive)
64 * @param right double; the right boundary (not inclusive)
65 * @param top double; the top boundary (not inclusive)
66 */
67 public Rectangle(final double left, final double bottom, final double right, final double top)
68 {
69 this.left = left;
70 this.bottom = bottom;
71 this.right = right;
72 this.top = top;
73 }
74
75 /**
76 * Retrieve the left boundary value.
77 * @return double; the left boundary value
78 */
79 public double getLeft()
80 {
81 return this.left;
82 }
83
84 /**
85 * Retrieve the bottom boundary value.
86 * @return double; the bottom boundary value
87 */
88 public double getBottom()
89 {
90 return this.bottom;
91 }
92
93 /**
94 * Retrieve the right boundary value.
95 * @return double; the right boundary value
96 */
97 public double getRight()
98 {
99 return this.right;
100 }
101
102 /**
103 * Retrieve the top boundary value.
104 * @return double; the top boundary value
105 */
106 public double getTop()
107 {
108 return this.top;
109 }
110
111 /**
112 * Return the width of this Rectangle.
113 * @return double; the width of this Rectangle
114 */
115 public double getWidth()
116 {
117 return this.right - this.left;
118 }
119
120 /**
121 * Return the height of this Rectangle.
122 * @return double; the height of this Rectangle
123 */
124 public double getHeight()
125 {
126 return this.top - this.bottom;
127 }
128
129 /**
130 * Determine if this Rectangle intersects another Rectangle.
131 * @param other Rectangle; the other rectangle
132 * @return boolean; true if the rectangles intersect, false if the rectangles do not intersect
133 */
134 public boolean intersects(final Rectangle other)
135 {
136 return this.left < other.right && this.bottom < other.top && other.left < this.right && other.bottom < this.top;
137 }
138
139 /**
140 * Determine if this Rectangle contains a point.
141 * @param x double; x-coordinate of the point
142 * @param y double; y-coordinate of the point
143 * @return boolean; true if this Rectangle contains the point; false if this Rectangle does not contain the point
144 */
145 public boolean contains(final double x, final double y)
146 {
147 return (this.left <= x && x < this.right && this.bottom <= y && y < this.top);
148 }
149
150 /**
151 * Determine if this Rectangle contains all points of another Rectangle.
152 * @param other Rectangle; the other rectangle
153 * @return boolean; true if this Rectangle contains all points of the other Rectangle; false if this Rectangle does not
154 * contain all points of the other Rectangle
155 */
156 public boolean contains(final Rectangle other)
157 {
158 return other.left >= this.left && other.right <= this.right && other.bottom >= this.bottom && other.top <= this.top;
159 }
160
161 /** {@inheritDoc} */
162 @Override
163 public String toString()
164 {
165 return "Rectangle [LB=" + this.left + "," + this.bottom + ", RT=" + this.right + "," + this.top + "]";
166 }
167
168 }