package graphics.draw2d;
import java.awt.*;
import java.util.Vector;
class Shapes extends Shape {
final static int maxCount = 3;
final static double refIndex = 1.2;
Circle2d closestCircle;
private Vector v = new Vector();
public void add(Paintable d) {
if (d == null) {
System.out.println("d==null!!");
}
v.addElement(d);
}
public void paint(Graphics g) {
for (int i = 0; i < v.size(); i++) {
Paintable d =
(Paintable) v.elementAt(i);
d.paint(g);
}
}
public Line2d getLastLine() {
for (int i = v.size() - 1; i >= 0; i--)
if (v.elementAt(i) instanceof Line2d)
return
(Line2d) v.elementAt(i);
return null;
}
public Circle2d getLastCircle() {
for (int i = v.size() - 1; i >= 0; i--)
if (v.elementAt(i) instanceof Circle2d)
return
(Circle2d) v.elementAt(i);
return null;
}
public Vec2d getClosestPoint(Ray2d ray) {
double maxDist = 1000000;
Vec2d closestSoFar = null;
for (int i = v.size() - 1; i >= 0; i--) {
if (!(v.elementAt(i) instanceof Intersects))
continue;
Intersects inter = (Intersects) v.elementAt(i);
Vec2d vc = inter.intersect(ray);
if (vc == null) continue;
if (ray.t >= maxDist) continue;
closestSoFar = vc;
if (v.elementAt(i) instanceof Circle2d) {
closestCircle = (Circle2d) v.elementAt(i);
} else {
closestCircle = null;
}
maxDist = ray.t;
}
return closestSoFar;
}
public void addLineToLastCircle() {
Ray2d rl;
Ray2d rf;
Line2d l = getLastLine();
if (l == null) return;
Ray2d r = new Ray2d(l);
addLineToLastCircle(r);
}
public void addLineToLastCircle(Ray2d r) {
Vec2d v = getClosestPoint(r);
if (v == null) return;
if (closestCircle != null) {
Ray2d rl = getReflectRay(closestCircle, v, r.d);
Ray2d rf = getRefractRay(closestCircle, r.p, v, r.d);
rl.p.add(rl.d);
rf.p.add(rf.d);
add(new Line2d(rl.p, rl.vecOnLine(50)));
add(new Line2d(rf.p, rf.vecOnLine(50)));
if (r.count < maxCount) {
rl.count = r.count + 1;
addLineToLastCircle(rl);
}
if (r.count < maxCount) {
rf.count = r.count + 1;
addLineToLastCircle(rf);
}
}
add(new Line2d(r.p, v));
}
public Ray2d getReflectRay(Circle2d c, Vec2d p, Vec2d d) {
Vec2d n = new Vec2d(p);
n.sub(c.center);
n.normalize();
n.mult(2 * d.dot(n));
d.sub(n);
Ray2d ref = new Ray2d(p, d);
return ref;
}
public Ray2d getRefractRay(Circle2d c, Vec2d o, Vec2d p, Vec2d d) {
double t;
double idx;
Vec2d n = new Vec2d(p);
n.sub(c.center);
n.normalize();
if (c.inside(o)) {
idx = 1 / refIndex;
n.mult(-1);
} else {
idx = refIndex;
}
t = 1 / d.dot(n);
Vec2d u = new Vec2d(d);
Vec2d v = new Vec2d(n);
u.mult(t);
v.add(u);
t = 1 / ((idx * idx) * u.dot(u) - v.dot(v));
u.mult(t);
u.sub(n);
n.mult(t);
u.add(n);
u.normalize();
Ray2d ref = new Ray2d(p, u);
return ref;
}
}