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