import java.awt.*;
|
|
class Torus extends Biparam implements java.io.Serializable
|
{
|
static final long serialVersionUID = 331691015398062098L; // new
|
// -7637054329820073252L; // Old
|
|
Torus()
|
{
|
inPnt = new cVector();
|
name = "Torus";
|
uDivs = 61; // 35; // 64;
|
vDivs = 21; // 19; // 24;
|
minUDivs = 3;
|
minVDivs = 3;
|
retile();
|
major = 1;
|
minor = 0.2;
|
recalculate();
|
}
|
|
Object3D deepCopy()
|
{
|
Torus t = new Torus();
|
deepCopySelf(t);
|
return t;
|
}
|
|
protected void deepCopyNode(Object3D other)
|
{
|
super.deepCopyNode(other);
|
Torus t = (Torus)other;
|
t.major = major;
|
t.minor = minor;
|
}
|
|
void createEditWindow(GroupEditor callee, boolean newWindow)
|
{
|
if (newWindow)
|
objectUI = new TorusEditor(this, deepCopy(), callee);
|
else
|
objectUI = new TorusEditor(this, callee);
|
editWindow = objectUI.GetEditor();
|
}
|
|
void generatePOV(StringBuffer buffer)
|
{
|
generateNameComment(buffer);
|
generateIndent(buffer);
|
buffer.append("torus { ");
|
buffer.append(major);
|
buffer.append(", ");
|
buffer.append(minor);
|
buffer.append("\n");
|
generateTransform(buffer);
|
generateIndent(buffer);
|
buffer.append("}\n");
|
}
|
|
double uStretch()
|
{
|
return 6; // Actually 6.28 (I think)
|
}
|
|
Vertex biparamFunction(double u, double v)
|
{
|
if (u == 1)
|
u = 0;
|
if (v == 1)
|
v = 0;
|
|
double uAng = u * 2 * Math.PI;
|
double vAng = -v * 2 * Math.PI;
|
double cosua = Math.cos(uAng);
|
double sinua = Math.sin(uAng);
|
double cosva = Math.cos(vAng);
|
double sinva = Math.sin(vAng);
|
|
double radius = (major + cosva * minor);
|
double x = cosua * radius;
|
double y = sinva * minor;
|
if (Math.abs(y) < 1E-10)
|
y = 0; // hashtable issue
|
|
double z = sinua * radius;
|
cVector tPos = LA.newVector(x, y, z);
|
|
double xx = cosua * cosva * minor;
|
double zz = sinua * cosva * minor;
|
|
cVector tNorm = LA.newVector(xx, y, zz);
|
Vertex temp = new Vertex(tPos);
|
//temp.pos = tPos; // useless new
|
temp.norm = tNorm;
|
LA.vecNormalize(temp.norm);
|
|
temp.y += minor;
|
|
return temp;
|
}
|
|
void getBounds(cVector minima, cVector maxima, boolean xform)
|
{
|
super.getBounds(minima, maxima, xform);
|
// july 2014 minima.x = minima.z = -(major + minor);
|
// maxima.x = maxima.z = major + minor;
|
// minima.y = -minor;
|
// maxima.y = minor;
|
// if (xform)
|
// transformBounds(minima, maxima);
|
}
|
|
boolean inside(double x, double y, double z, boolean xform)
|
{
|
if (xform)
|
untransform(x, y, z, inPnt);
|
else
|
LA.setVector(inPnt, x, y, z);
|
double rad1 = inPnt.x * inPnt.x + inPnt.z * inPnt.z;
|
rad1 = (double)Math.sqrt(rad1);
|
double d = major / rad1;
|
double xx = d * inPnt.x;
|
double zz = d * inPnt.z;
|
inPnt.x -= xx;
|
inPnt.z -= zz;
|
double rad2 = inPnt.x * inPnt.x + inPnt.y * inPnt.y + inPnt.z * inPnt.z;
|
return rad2 <= minor * minor;
|
}
|
|
void drawEditHandles(//ClickInfo info,
|
int level)
|
{
|
if (level == 0)
|
{
|
return;
|
} else
|
{
|
super.drawEditHandles(//info,
|
level);
|
cVector temp = LA.newVector(0, 0, minor);
|
LA.xformPos(temp, toParent, temp);
|
Rectangle majorSpot = calcHotSpot(temp); //, info);
|
majorSpot.translate(4, 4);
|
temp.x = major;
|
temp.y = temp.z = 0;
|
LA.xformPos(temp, toParent, temp);
|
Rectangle minorSpot = calcHotSpot(temp); //, info);
|
minorSpot.translate(4, 4);
|
clickInfo.g.setColor(Color.green);
|
clickInfo.g.fillRect(majorSpot.x, majorSpot.y, majorSpot.width, majorSpot.height);
|
clickInfo.g.fillRect(minorSpot.x, minorSpot.y, minorSpot.width, minorSpot.height);
|
return;
|
}
|
}
|
|
boolean doEditClick(//ClickInfo info,
|
int level)
|
{
|
if (level == 0)
|
return false;
|
hitSomething = 0;
|
if (super.doEditClick(//info,
|
level))
|
{
|
hitSomething = 1;
|
return true;
|
}
|
cVector temp = LA.newVector(0, 0, minor);
|
LA.xformPos(temp, toParent, temp);
|
Rectangle majorSpot = calcHotSpot(temp); //, info);
|
majorSpot.translate(4, 4);
|
temp.x = major;
|
temp.y = temp.z = 0;
|
LA.xformPos(temp, toParent, temp);
|
Rectangle minorSpot = calcHotSpot(temp); //, info);
|
minorSpot.translate(4, 4);
|
if (majorSpot.contains(clickInfo.x, clickInfo.y))
|
{
|
hitSomething = 2;
|
startRad = major;
|
} else
|
if (minorSpot.contains(clickInfo.x, clickInfo.y))
|
{
|
hitSomething = 3;
|
startRad = minor;
|
} else
|
{
|
return false;
|
}
|
startX = clickInfo.x;
|
return true;
|
}
|
|
void doEditDrag(//ClickInfo info,
|
boolean opposite)
|
{
|
if (hitSomething == 0)
|
return;
|
if (hitSomething == 1)
|
{
|
super.doEditDrag(//info,
|
opposite);
|
return;
|
}
|
double deltaR = clickInfo.x - startX;
|
//cVector delta = LA.newVector(info.x - startX, 0, 0);
|
//LA.xformDir(delta, info.camera.fromScreen, delta);
|
deltaR /= 100 * clickInfo.camera.SCALE / clickInfo.camera.Distance();
|
double newRad = startRad + deltaR;
|
if (newRad < 0)
|
newRad = 0;
|
if (hitSomething == 2)
|
major = newRad;
|
else
|
minor = newRad;
|
recalculate();
|
clickInfo.pane.repaint();
|
}
|
|
double major;
|
double minor;
|
protected cVector inPnt;
|
private static final int hitStandard = 1;
|
private static final int hitMajor = 2;
|
private static final int hitMinor = 3;
|
private static int hitSomething;
|
private static int startX;
|
private static double startRad;
|
}
|