import java.io.*;
import java.lang.*;
/**
* Sphere represents a spherical object
*
* @author Anthony Steed
* @version 1.0
*/
public class Sphere extends Object {
/**
* Holds the point that defines the sphere centre
*/
public Point Centre;
/**
* Holds the radius of the sphere
*/
public double Radius;
/**
* Create a default sphere
*/
public Sphere() {
SurfaceMaterial = new Material();
Centre = new Point();
Radius = 1.0;
}
/**
* Create a sphere with the given material, centre and radius
*
* Note values are referenced not copied in the new object
* @param n the material for the plane
* @param p the centre of the sphere
* @param r the radius of the sphere
*/
public Sphere(Material n, Point p, double r) {
SurfaceMaterial = n;
Centre = p;
Radius = r;
}
/**
* Find the normal of an object at the given point on its surface.
*
* Note that a new Vector
is created on each call.
* @param pt the surface point to find the normal at
* @return a reference to the fixed normal of the plane
*/
public Vector normal(Point p) {
return Vector.subtract(p,Centre).normalised();
}
/**
* Find the intersection of the plane and a given ray.
*
* The return value is positive is the intersection is found and
* this value gives the distance along the ray. Negative values
* imply that the intersection was either not successful or the
* intersection point was before the origin. This value can be used
* with the pointAt method of the Ray class (@see Ray#pointAt)
*
* @param ray the ray to intersect with
* @return a double
value that gives the distance
* along the ray.
*/
public double intersect(Ray ray) {
Vector tmp;
double A,B,C,d,t1,t2,t;
tmp = Vector.subtract(ray.Origin, Centre);
A = ray.Direction.squarednorm();
B = Vector.dot(tmp, ray.Direction);
C = tmp.squarednorm() - (Radius*Radius);
if((d=((B*B)-(A*C))) < 0.0) return -1.0; // -1.0 is "false" value
d = Math.sqrt(d);
t = (-B-d)/A;
return t;
}
/**
* Read the sphere from the given source
* @param is the source to read from
* @exception java.io.IOException
* if the light can not be read
* @exception java.io.NumberFormatException
* if there a number format error is encountered
*/
public void read(SceneReader is)
throws IOException, NumberFormatException {
Centre.read(is);
Radius = is.readDouble();
SurfaceMaterial.read(is);
}
/**
* Write the sphere to the given destination
* @param os the destination to write to
* @exception java.io.IOException
* if the write fails.
*/
public void write(SceneWriter os) throws IOException {
Centre.write(os);
os.writeDouble(Radius);
os.writeChar(' ');
SurfaceMaterial.write(os);
}
/**
* Print a human readable version of the sphere definition to the
* given destination
* @param os the destination to write to
* @exception java.io.IOException
* if the write fails.
*/
public void print(SceneWriter os) throws IOException {
os.writeString("Sphere with centre: ");
Centre.print(os);
os.writeString(" and radius: ");
os.writeDouble(Radius);
os.writeString("\n");
SurfaceMaterial.print(os);
os.writeString("\n");
}
}