Im Folgenden sehen Sie die Implementierung der
RaytracerKit-Klasse.
package tinyray.raytracer;
import java.util.Iterator;
import java.util.List;
import tinyray.frontend.ParseTreeKit;
/**
* Die Klasse RaytracerKit ist eine konkrete Fabrik, mit der ein
* Syntaxbaum als Raytracer erzeugt werden kann.
* Die Wurzel des Syntaxbaumes ist der Raytracer.
*/
public class RaytracerKit implements ParseTreeKit<Element, Tinyray> {
// Die Wurzel des Syntaxbaumes.
protected Tinyray tinyray;
// Die Default-Parameter.
private Parameters defaults;
/**
* Initialisiert den RaytracerKit.
*/
public RaytracerKit() {
this.tinyray = new Tinyray();
this.defaults = new Parameters();
}
/**
* Gibt einen Tinyray-Knoten zurück, der zugleich auch den Raytracer
* darstellt.
* @param arguments Die Kindelemente des Tinyray-Knotens.
* @return Der Tinyray-Knoten.
*/
public Tinyray getTinyray(List<Element> arguments) {
// Die Wurzel des AST wird schon im Konstruktor erzeugt.
Iterator<Element> iterator = arguments.listIterator();
while (iterator.hasNext()) {
Element next = iterator.next();
if (next instanceof Camera) {
this.tinyray.setCamera((Camera)next);
} else if (next instanceof Background) {
this.tinyray.setBackground((Background)next);
} else if (next instanceof Ambience) {
this.tinyray.setAmbience((Ambience)next);
} else if (next instanceof Fog) {
this.tinyray.setFog((Fog)next);
} else if (next instanceof Geo) {
this.tinyray.addGeo((Geo)next);
} else if (next instanceof Sun) {
this.tinyray.addSun((Sun)next);
}
// Defaults wird nicht in den Baum aufgenommen.
}
return this.tinyray;
}
/**
* Erzeugt einen Camera-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Camera-Knotens.
* @return Der Camera-Knoten.
*/
public Element getCamera(List<Element> arguments) {
Camera result = new Camera();
result.setLocation((Vector3D)arguments.get(0));
result.setLookAt((Vector3D)arguments.get(1));
if (arguments.size() > 2) {
result.setUp((Vector3D)arguments.get(2));
}
return result;
}
/**
* Erzeugt einen Background-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente (Farbe) des Background-Knotens.
* @return Der Background-Knoten.
*/
public Element getBackground(List<Element> arguments) {
return new Background((Vector3D)arguments.get(0));
}
/**
* Erzeugt einen Ambience-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente (Farbe) des Ambience-Knotens.
* @return Der Ambience-Knoten.
*/
public Element getAmbience(List<Element> arguments) {
return new Ambience((Vector3D)arguments.get(0));
}
/**
* Erzeugt einen Fog-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Fog-Knotens.
* @return Der Fog-Knoten.
*/
public Element getFog(List<Element> arguments) {
Vector3D color = (Vector3D)arguments.get(0);
double density = ((Real)arguments.get(1)).getValue();
return new Fog(color, density);
}
/**
* Setzt die gegebenen Parameter auf Defaults und reicht diese durch.
* @param arguments Die Parameter.
* @return Die Defaults-Parameter.
*/
public Element getDefaults(List<Element> arguments) {
this.defaults = (Parameters)arguments.get(0);
return this.defaults;
}
/**
* Erzeugt einen Bounding-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Bounding-Knotens.
* @return Der Bounding-Knoten.
*/
public Element getBounding(List<Element> arguments) {
Bounding result = new Bounding();
result.setParameters(this.defaults);
Iterator<Element> elements = arguments.iterator();
while (elements.hasNext()) {
Element next = elements.next();
if (next instanceof Geo) {
result.addGeo((Geo)next);
}
}
return result;
}
/**
* Erzeugt einen Triangle-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Triangle-Knotens.
* @return Der Triangle-Knoten.
*/
public Element getTriangle(List<Element> arguments) {
Vector3D a = (Vector3D)arguments.get(0);
Vector3D b = (Vector3D)arguments.get(1);
Vector3D c = (Vector3D)arguments.get(2);
Triangle result = new Triangle(a, b, c);
if (arguments.size() > 3) {
result.setParameters((Parameters)arguments.get(3));
} else {
result.setParameters(this.defaults);
}
return result;
}
/**
* Erzeugt einen Sphere-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Sphere-Knotens.
* @return Der Sphere-Knoten.
*/
public Element getSphere(List<Element> arguments) {
Vector3D center = (Vector3D)arguments.get(0);
double radius = ((Real)arguments.get(1)).getValue();
Sphere result = new Sphere(center, radius);
if (arguments.size() > 2) {
result.setParameters((Parameters)arguments.get(2));
} else {
result.setParameters(this.defaults);
}
return result;
}
/**
* Erzeugt einen Plane-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Plane-Knotens.
* @return Der Plane-Knoten.
*/
public Element getPlane(List<Element> arguments) {
Vector3D x = (Vector3D)arguments.get(0);
Vector3D y = (Vector3D)arguments.get(1);
Vector3D z = (Vector3D)arguments.get(2);
Plane result = new Plane(x, y, z);
if (arguments.size() > 3) {
result.setParameters((Parameters)arguments.get(3));
} else {
result.setParameters(this.defaults);
}
return result;
}
/**
* Erzeugt einen Sun-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Sun-Knotens.
* @return Der Sun-Knoten.
*/
public Element getSun(List<Element> arguments) {
Vector3D direction = (Vector3D)arguments.get(0);
Vector3D color = (Vector3D)arguments.get(1);
return new Sun(direction, color);
}
/**
* Erzeugt einen Parameters-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Parameters-Knotens.
* @return Der Parameters-Knoten.
*/
public Element getParameters(List<Element> arguments) {
Parameters result = this.defaults.copy();
if (arguments.size() > 0) {
result.setColor((Vector3D)arguments.get(0));
}
if (arguments.size() > 1) {
result.setAmbient((Vector3D)arguments.get(1));
}
if (arguments.size() > 2) {
result.setSpecular(((Real)arguments.get(2)).getValue());
}
if (arguments.size() > 3) {
result.setShininess(((Real)arguments.get(3)).getValue());
}
if (arguments.size() > 4) {
result.setMirror(((Real)arguments.get(4)).getValue());
}
return result;
}
/**
* Erzeugt einen Vector-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Vector-Knotens.
* @return Der Vector-Knoten.
*/
public Element getVector(List<Element> arguments) {
double[] v = { 0.0, 0.0, 0.0 };
for (int i = 0; i < Math.min(3, arguments.size()); i++) {
v[i] = ((Real)arguments.get(i)).getValue();
}
return new Vector3D(v[0], v[1], v[2]);
}
/**
* Erzeugt einen Real-Knoten und gibt diesen Knoten zurück.
* @param arguments Die Kindelemente des Real-Knotens.
* @return Der Real-Knoten.
*/
public Element getReal(String real) {
return new Real(Double.parseDouble(real));
}
}