001    package physics3d;
002    
003    /**
004     * Sphere represents a sphere in 3 space
005     * 
006     * @specfield centerPoint : Vect3 // point of center of sphere
007     * @specfield radius : double // radius of sphere
008     * @specfield texture : String // texture of this object
009     */
010    public strictfp class Sphere implements PhysicsShape {
011      private final Vect3 centerPoint;
012    
013      private final double radius;
014    
015      private final String texture;
016    
017      // Rep. Invariant:
018      // centerPoint != null &&
019      // radius >= 0.0
020    
021      // Abstraction Function:
022      // The sphere with a center at 'centerPoint' and a radius 'radius'
023    
024      // Constructors -----------------------------------
025      /**
026       * @requires <code>r</code> >= 0, <code>center</code> != null,
027       *           <code>texture</code> != null
028       * 
029       * @effects Creates a new circle with the specified size and location.
030       * 
031       * @param center
032       *          the center point of the circle
033       * @param r
034       *          the radius of the circle
035       */
036      public Sphere(Vect3 center, double r, String texture) {
037        if ((r < 0) || (center == null)) {
038          throw new IllegalArgumentException();
039        }
040        centerPoint = center;
041        radius = r;
042        this.texture = texture;
043      }
044    
045      /**
046       * @requires <code>r</code> >= 0, <code>center</code> != null
047       * 
048       * @effects Creates a new circle with the specified size and location.
049       * 
050       * @param center
051       *          the center point of the circle
052       * @param r
053       *          the radius of the circle
054       */
055      public Sphere(Vect3 center, double r) {
056        if ((r < 0) || (center == null)) {
057          throw new IllegalArgumentException();
058        }
059        centerPoint = center;
060        radius = r;
061        this.texture = null;
062      }
063    
064      /**
065       * @requires <code>r</code> >= 0
066       * 
067       * @effects Creates a new circle with the specified size and location.
068       * 
069       * @param cx
070       *          the x coordinate of the center point of the circle
071       * @param cy
072       *          the y coordinate of the center point of the circle
073       * @param cz
074       *          the z coordinate of the center point of the circle
075       * @param r
076       *          the radius of the circle
077       */
078      public Sphere(double cx, double cy, double cz, double r, String texture) {
079        this(new Vect3(cx, cy, cz), r, texture);
080      }
081    
082      @SuppressWarnings("unused")
083      private void checkRep() {
084        if (centerPoint == null || radius < 0.0) {
085          throw new RuntimeException();
086        }
087      }
088    
089      // Observers --------------------------------------
090    
091      /**
092       * @return the center point of this circle.
093       */
094      public Vect3 getCenter() {
095        // checkRep();
096        return centerPoint;
097      }
098    
099      /**
100       * @return the radius of this circle.
101       */
102      public double getRadius() {
103        // checkRep();
104        return radius;
105      }
106    
107      /**
108       * @return texture of this object
109       */
110      public String getTexture() {
111        // checkRep();
112        return this.texture;
113      }
114    
115      /**
116       * @requires p != null
117       * @return true if
118       *         <code>Vect3.isAbout(this.minDistanceToObjectFromP(p),0)</code>,
119       *         false otherwise
120       */
121      public boolean containsPoint(Vect3 p) {
122        // checkRep();
123        return Vect3.isAbout(this.minDistanceToObjectFromP(p), 0);
124      }
125    
126      /**
127       * @requires <code>p</code> is not null
128       * @return the minimum distance between <code>p</code> and <code>this</code>
129       */
130      public double minDistanceToObjectFromP(Vect3 p) {
131        // checkRep();
132        return Math.abs(p.minus(centerPoint).rho() - radius);
133      }
134    
135      /**
136       * @requires center != null, axis != null, axis.rho() > 0, tAngle != null.
137       * @return A Sphere rotated about the line created by center and axis
138       *         counterclockwise by an amount tAngle with same texture.
139       */
140      public Sphere rotateAboutCwithAxisAandAngleT(Vect3 center, Vect3 axis,
141          Angle tAngle) {
142        return new Sphere(this.getCenter().minus(center).rotateAroundVect(axis,
143            tAngle).plus(center), this.getRadius(), this.texture);
144      }
145    
146      /**
147       * @requires t != null
148       * @return A Sphere translated by t with same texture
149       */
150      public Sphere translateByT(Vect3 t) {
151        return new Sphere(this.getCenter().plus(t), this.getRadius(), this.texture);
152      }
153    
154      // Object methods --------------------------------------
155      //
156      // public boolean equals(Sphere c) {
157      // if (c == null) return false;
158      // return (radius == c.radius) && centerPoint.equals(c.centerPoint);
159      // }
160      //
161      // public boolean equals(Object o) {
162      // if (o instanceof Sphere)
163      // return equals((Sphere) o);
164      // else
165      // return false;
166      // }
167      //
168      public String toString() {
169        return "[Sphere center=" + centerPoint + " radius=" + radius + "]";
170      }
171      //
172      // public int hashCode() {
173      // return centerPoint.hashCode() + 17 * (new Double(radius)).hashCode();
174      // }
175    
176    public ShapeClassification getShapeClassification() {
177            return ShapeClassification.SPHERE;
178    }
179    }