import java.awt.*;
|
|
class Cone extends Biparam implements java.io.Serializable
|
{
|
static final long serialVersionUID = -2558098774090336324L; // new
|
// -679715043452968126L; // old
|
|
Cone()
|
{
|
inPnt = new cVector();
|
name = "Cone";
|
uDivs = 32;
|
vDivs = 16;
|
minUDivs = 3;
|
minVDivs = 1;
|
endcaps = true;
|
retile();
|
base = LA.newVector(0, 0, 0); // -1);
|
apex = LA.newVector(0, 1, 0); // 1);
|
baseRadius = apexRadius = 0.6369; // == 0.5 * 4/3.14 // 0.5; // 0.125;
|
//fromStandard = new double[4][4];
|
//toStandard = new double[4][4];
|
//LA.matIdentity(fromStandard);
|
//LA.matIdentity(toStandard);
|
//orient();
|
recalculate();
|
}
|
|
void recalculate()
|
{
|
cVector axis = new cVector();
|
LA.vecSub(apex, base, axis);
|
height = LA.vecLen(axis);
|
|
super.recalculate();
|
}
|
|
/*
|
void orient()
|
{
|
cVector axis = new cVector();
|
LA.vecSub(apex, base, axis);
|
height = LA.vecLen(axis);
|
LA.matIdentity(fromStandard);
|
LA.matIdentity(toStandard);
|
if (Math.abs(base.x - apex.x) < 0.001 && Math.abs(base.y - apex.y) < 0.001)
|
{
|
if (apex.z < base.z)
|
{
|
LA.matXRotate(fromStandard, 180);
|
LA.matXRotate(toStandard, 180);
|
}
|
} else
|
{
|
LA.vecNormalize(axis);
|
cVector up = LA.newVector(0, 0, 1);
|
cVector x = new cVector();
|
cVector y = new cVector();
|
LA.vecCross(up, axis, x);
|
LA.vecNormalize(x);
|
LA.vecCross(axis, x, y);
|
LA.vecNormalize(y);
|
for (int i=0; i < 3; i++)
|
{
|
fromStandard[0][i] = x.get(i);
|
fromStandard[1][i] = y.get(i);
|
fromStandard[2][i] = axis.get(i);
|
toStandard[i][0] = x.get(i);
|
toStandard[i][1] = y.get(i);
|
toStandard[i][2] = axis.get(i);
|
}
|
|
}
|
LA.matTranslate(fromStandard, base.x, base.y, base.z);
|
double temp[][] = new double[4][4];
|
LA.matIdentity(temp);
|
LA.matTranslate(temp, -base.x, -base.y, -base.z);
|
LA.matConcat(temp, toStandard, toStandard);
|
recalculate();
|
}
|
*/
|
|
Object3D deepCopy()
|
{
|
Cone cone = new Cone();
|
deepCopySelf(cone);
|
return cone;
|
}
|
|
protected void deepCopyNode(Object3D other)
|
{
|
super.deepCopyNode(other);
|
Cone c = (Cone)other;
|
LA.vecCopy(base, c.base);
|
c.baseRadius = baseRadius;
|
LA.vecCopy(apex, c.apex);
|
c.apexRadius = apexRadius;
|
}
|
|
void generatePOV(StringBuffer buffer)
|
{
|
generateNameComment(buffer);
|
generateIndent(buffer);
|
cVector temp = new cVector();
|
if (baseRadius == apexRadius)
|
{
|
buffer.append("cylinder { ");
|
LA.toPOVRay(base, buffer);
|
buffer.append(", ");
|
LA.toPOVRay(apex, buffer);
|
buffer.append(", ");
|
buffer.append(baseRadius);
|
buffer.append("\n");
|
} else
|
{
|
buffer.append("cone { ");
|
LA.toPOVRay(base, buffer);
|
buffer.append(", ");
|
buffer.append(baseRadius);
|
buffer.append(", ");
|
LA.toPOVRay(apex, buffer);
|
buffer.append(", ");
|
buffer.append(apexRadius);
|
buffer.append("\n");
|
}
|
generateTransform(buffer);
|
generateIndent(buffer);
|
buffer.append("}\n");
|
}
|
|
void getBounds(cVector minima, cVector maxima, boolean xform)
|
{
|
super.getBounds(minima, maxima, xform);
|
// july 2014 /*
|
// for (int i=0; i < 3; i++)
|
// {
|
// double amax = apex.get(i) + apexRadius;
|
// double amin = apex.get(i) - apexRadius;
|
// double bmax = base.get(i) + baseRadius;
|
// double bmin = base.get(i) - baseRadius;
|
// minima.set(i, amin >= bmin ? bmin : amin);
|
// maxima.set(i, amax <= bmax ? bmax : amax);
|
// }
|
//
|
// */
|
// double maxr = baseRadius;
|
// if (maxr < apexRadius)
|
// maxr = apexRadius;
|
//
|
// minima.set(0, -maxr); // -1);
|
// minima.set(1, 0); // -1);
|
// minima.set(2, -maxr); // -1);
|
// maxima.set(0, maxr); // 1);
|
// maxima.set(1, height); // 1);
|
// maxima.set(2, maxr); // 1);
|
//
|
// 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);
|
//LA.xformPos(inPnt, toStandard, inPnt);
|
|
double rad1 = inPnt.x * inPnt.x + inPnt.z * inPnt.z;
|
double t = inPnt.y / height;
|
double rad2 = baseRadius + t * (apexRadius - baseRadius);
|
rad2 *= rad2;
|
double f = rad1 - rad2;
|
|
boolean inside = f <= 0;
|
|
if (inPnt.y < 0 || inPnt.y > 1)
|
{
|
f = 1;
|
//super.height = 1;
|
//return false;
|
inside = false;
|
}
|
|
if (depth != -1 && (super.height <= 0 ^ inside))
|
{
|
Simplex.atom = this;
|
}
|
|
depth = 0;
|
|
super.height = f;
|
|
return inside;
|
}
|
|
double uStretch()
|
{
|
return 4; // 3; // Actually 3.14 (I think)
|
}
|
|
double vFlip(double v)
|
{
|
return 1-v;
|
}
|
|
Vertex biparamFunction(double u, double v)
|
{
|
cVector tPos;
|
cVector tNorm;
|
if(bRep != null && bRep.trimmed)
|
{
|
tPos = cStatic.vertex1;
|
tNorm = cStatic.vertex1.norm;
|
if (u < 0)
|
{
|
tPos.set(0, v >= 0.5 ? height : 0, 0); // /2 : -height/2, 0);
|
tNorm.set(0, v >= 0.5 ? 1 : -1, 0);
|
} else
|
{
|
double angle = LA.toRadians(u * 360);
|
double rad = baseRadius + v * (apexRadius - baseRadius);
|
double z = Math.cos(angle);
|
double x = Math.sin(angle);
|
double y = v * height;
|
tPos.set(rad * x, y /*- 1*/, rad * z);
|
/*
|
z = baseRadius * (double)Math.cos(angle);
|
x = baseRadius * (double)Math.sin(angle);
|
*/
|
y = (baseRadius - apexRadius) / height;
|
|
tNorm.set(x, y, z);
|
}
|
|
LA.vecNormalize(tNorm);
|
return cStatic.vertex1;
|
}
|
else
|
{
|
if (u < 0)
|
{
|
tPos = LA.newVector(0, v >= 0.5 ? height : 0, 0); // /2 : -height/2, 0);
|
tNorm = new cVector(0, v >= 0.5 ? 1 : -1, 0);
|
} else
|
{
|
double angle = LA.toRadians(u * 360);
|
double rad = baseRadius + v * (apexRadius - baseRadius);
|
double z = rad * (double)Math.cos(angle);
|
double x = rad * (double)Math.sin(angle);
|
double y = v * height;
|
tPos = LA.newVector(x, y /*- 1*/, z);
|
z = baseRadius * (double)Math.cos(angle);
|
x = baseRadius * (double)Math.sin(angle);
|
y = (baseRadius - apexRadius) / height;
|
tNorm = LA.newVector(x, y, z);
|
}
|
//LA.xformPos(tPos, fromStandard, tPos);
|
//LA.xformDir(tNorm, fromStandard, tNorm);
|
Vertex temp = new Vertex(tPos);
|
//temp.pos = tPos; // useless new cVector()
|
temp.norm = tNorm;
|
LA.vecNormalize(temp.norm);
|
return temp;
|
}
|
}
|
|
void createEditWindow(GroupEditor callee, boolean newWindow)
|
{
|
if (newWindow)
|
objectUI = new ConeEditor(this, deepCopy(), callee);
|
else
|
objectUI = new ConeEditor(this, callee);
|
editWindow = objectUI.GetEditor();
|
}
|
|
void drawEditHandles(//ClickInfo info,
|
int level)
|
{
|
super.drawEditHandles(//info,
|
level);
|
if (level == 1)
|
{
|
return;
|
} //else
|
{
|
cVector temp = new cVector();
|
LA.xformPos(base, toParent, temp);
|
Rectangle baseSpot = calcHotSpot(temp); //, info);
|
LA.xformPos(apex, toParent, temp);
|
Rectangle apexSpot = calcHotSpot(temp); //, info);
|
clickInfo.g.setColor(Color.green);
|
clickInfo.g.fillRect(baseSpot.x, baseSpot.y, baseSpot.width, baseSpot.height);
|
clickInfo.g.fillRect(apexSpot.x, apexSpot.y, apexSpot.width, apexSpot.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 = new cVector();
|
LA.xformPos(base, toParent, temp);
|
Rectangle baseSpot = calcHotSpot(temp); //, info);
|
LA.xformPos(apex, toParent, temp);
|
Rectangle apexSpot = calcHotSpot(temp); //, info);
|
if (baseSpot.contains(clickInfo.x, clickInfo.y))
|
{
|
hitSomething = 2;
|
startRad = baseRadius;
|
} else
|
if (apexSpot.contains(clickInfo.x, clickInfo.y))
|
{
|
hitSomething = 3;
|
startRad = apexRadius;
|
} 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;
|
double newRad = startRad + deltaR;
|
if (newRad < 0)
|
newRad = 0;
|
if (hitSomething == 2)
|
baseRadius = newRad;
|
else
|
apexRadius = newRad;
|
recalculate();
|
clickInfo.pane.repaint();
|
}
|
|
cVector base;
|
cVector apex;
|
double baseRadius;
|
double apexRadius;
|
double height;
|
//double fromStandard[][];
|
//double toStandard[][];
|
protected cVector inPnt;
|
private static final int hitStandard = 1;
|
private static final int hitBase = 2;
|
private static final int hitApex = 3;
|
private static int hitSomething;
|
private static int startX;
|
private static double startRad;
|
}
|