View Javadoc
1   package org.opentrafficsim.base.geometry;
2   
3   import java.util.Iterator;
4   import java.util.NoSuchElementException;
5   
6   import org.djutils.draw.line.Polygon2d;
7   import org.djutils.draw.point.Point2d;
8   import org.djutils.exceptions.Throw;
9   
10  /**
11   * Bounds defined by a circle.
12   * <p>
13   * Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
15   * </p>
16   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
17   */
18  public class BoundingCircle implements OtsBounds2d
19  {
20  
21      /** Number of line segments in polygon representation. */
22      private final static int POLYGON_STEPS = 128;
23  
24      /** Radius. */
25      private final double radius;
26  
27      /** Polygon representation. */
28      private Polygon2d polygon;
29  
30      /**
31       * Constructor.
32       * @param radius double; radius.
33       */
34      public BoundingCircle(final double radius)
35      {
36          Throw.whenNull(radius, "Radius must not be null.");
37          Throw.when(radius <= 0.0, IllegalArgumentException.class, "Radius must be above 0.0.");
38          this.radius = radius;
39      }
40  
41      /** {@inheritDoc} */
42      @Override
43      public double getMinX()
44      {
45          return -this.radius;
46      }
47  
48      /** {@inheritDoc} */
49      @Override
50      public double getMaxX()
51      {
52          return this.radius;
53      }
54  
55      /** {@inheritDoc} */
56      @Override
57      public double getMinY()
58      {
59          return -this.radius;
60      }
61  
62      /** {@inheritDoc} */
63      @Override
64      public double getMaxY()
65      {
66          return this.radius;
67      }
68  
69      /** {@inheritDoc} */
70      @Override
71      public boolean contains(final Point2d point) throws NullPointerException
72      {
73          return CENTER.distance(point) < this.radius;
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public boolean covers(final Point2d point) throws NullPointerException
79      {
80          return CENTER.distance(point) <= this.radius;
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public double signedDistance(final Point2d point)
86      {
87          return CENTER.distance(point) - this.radius;
88      }
89  
90      /** {@inheritDoc} */
91      @Override
92      public Polygon2d asPolygon()
93      {
94          if (this.polygon == null)
95          {
96              if (this.radius == 0.0)
97              {
98                  this.polygon = new Polygon2d(false, new Point2d(0.0, 0.0));
99              }
100             else
101             {
102                 this.polygon = new Polygon2d(new Iterator<Point2d>()
103                 {
104                     /** Step. */
105                     private int step = 0;
106 
107                     /** {@inheritDoc} */
108                     @Override
109                     public boolean hasNext()
110                     {
111                         return this.step <= POLYGON_STEPS;
112                     }
113 
114                     /** {@inheritDoc} */
115                     @Override
116                     public Point2d next()
117                     {
118                         Throw.when(!hasNext(), NoSuchElementException.class, "Iterator has no more elements.");
119                         // at full circle (this.step == POLYGON_STEPS), make sure end point is exactly the same as the start
120                         // point
121                         double ang = this.step == POLYGON_STEPS ? 0.0 : (2.0 * Math.PI * this.step) / POLYGON_STEPS;
122                         this.step++;
123                         return new Point2d(Math.sin(ang) * BoundingCircle.this.radius,
124                                 Math.sin(ang) * BoundingCircle.this.radius);
125                     }
126                 });
127             }
128         }
129         return this.polygon;
130     }
131 
132 }