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   * Shape 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 CircleShape implements OtsShape
19  {
20  
21      /** Radius. */
22      private final double radius;
23  
24      /** Number of line segments in polygon representation. */
25      private final int polygonSegments;
26  
27      /** Polygon representation. */
28      private Polygon2d polygon;
29  
30      /**
31       * Constructor.
32       * @param radius radius.
33       */
34      public CircleShape(final double radius)
35      {
36          this(radius, DEFAULT_POLYGON_SEGMENTS);
37      }
38  
39      /**
40       * Constructor.
41       * @param radius radius.
42       * @param polygonSegments number of segments in polygon representation.
43       */
44      public CircleShape(final double radius, final int polygonSegments)
45      {
46          Throw.whenNull(radius, "Radius must not be null.");
47          Throw.when(radius <= 0.0, IllegalArgumentException.class, "Radius must be above 0.0.");
48          this.radius = radius;
49          this.polygonSegments = polygonSegments;
50      }
51  
52      @Override
53      public double getMinX()
54      {
55          return -this.radius;
56      }
57  
58      @Override
59      public double getMaxX()
60      {
61          return this.radius;
62      }
63  
64      @Override
65      public double getMinY()
66      {
67          return -this.radius;
68      }
69  
70      @Override
71      public double getMaxY()
72      {
73          return this.radius;
74      }
75  
76      @Override
77      public boolean contains(final Point2d point) throws NullPointerException
78      {
79          return CENTER.distance(point) < this.radius;
80      }
81  
82      @Override
83      public boolean contains(final double x, final double y)
84      {
85          return contains(new Point2d(x, y));
86      }
87  
88      @Override
89      public double signedDistance(final Point2d point)
90      {
91          return CENTER.distance(point) - this.radius;
92      }
93  
94      @Override
95      public Polygon2d asPolygon()
96      {
97          if (this.polygon == null)
98          {
99              if (this.radius == 0.0)
100             {
101                 this.polygon = new Polygon2d(false, new Point2d(0.0, 0.0));
102             }
103             else
104             {
105                 this.polygon = new Polygon2d(new Iterator<Point2d>()
106                 {
107                     /** Step. */
108                     private int step = 0;
109 
110                     @Override
111                     public boolean hasNext()
112                     {
113                         return this.step <= CircleShape.this.polygonSegments;
114                     }
115 
116                     @Override
117                     public Point2d next()
118                     {
119                         Throw.when(!hasNext(), NoSuchElementException.class, "Iterator has no more elements.");
120                         // at full circle (this.step == polygonSegments), make sure end point is exactly the same as the start
121                         // point
122                         double ang = this.step == CircleShape.this.polygonSegments ? 0.0
123                                 : (2.0 * Math.PI * this.step) / CircleShape.this.polygonSegments;
124                         this.step++;
125                         return new Point2d(Math.cos(ang) * CircleShape.this.radius, Math.sin(ang) * CircleShape.this.radius);
126                     }
127                 });
128             }
129         }
130         return this.polygon;
131     }
132 
133     @Override
134     public String toString()
135     {
136         return "CircleShape [radius=" + this.radius + "]";
137     }
138 
139 }