class Superellipsoid extends Biparam /*Sphere*/ implements java.io.Serializable
|
{
|
static final long serialVersionUID = -251688182693574378L;
|
|
Superellipsoid()
|
{
|
super(); // false);
|
|
inPnt = new cVector();
|
du = new cVector();
|
dv = new cVector();
|
|
name = "Superellipsoid";
|
east = 2;
|
north = 2;
|
//uDivs = vDivs = 32;
|
uDivs = 36;
|
vDivs = 34;
|
minUDivs = 3;
|
minVDivs = 2;
|
|
retile();
|
recalculate();
|
}
|
|
Object3D deepCopy()
|
{
|
Superellipsoid s = new Superellipsoid();
|
deepCopySelf(s);
|
return s;
|
}
|
|
protected void deepCopyNode(Object3D other)
|
{
|
super.deepCopyNode(other);
|
Superellipsoid s = (Superellipsoid)other;
|
s.east = east;
|
s.north = north;
|
}
|
|
void createEditWindow(GroupEditor callee, boolean newWindow)
|
{
|
//editWindow = new SuperEditor(this, deepCopy(), callee);
|
if (newWindow)
|
objectUI = new SuperEditor(this, deepCopy(), callee);
|
else
|
objectUI = new SuperEditor(this, callee);
|
editWindow = objectUI.GetEditor();
|
}
|
|
double signPower(double base, double pow)
|
{
|
//if (base == 0)
|
// base = 0.0000001;
|
|
if (base == 0 && pow == 0 || base == 1)
|
return 1;
|
|
if (base == 0)
|
return 0;
|
|
if (base == -1)
|
return -1;
|
|
if (base >= 0)
|
return (double)Mathpow(base, pow);
|
else
|
return -(double)Mathpow(-base, pow);
|
}
|
|
static int tablelength = 257;
|
|
static double power1 = -1;
|
static double[] powtable1 = new double[tablelength];
|
static double power2 = -1;
|
static double[] powtable2 = new double[tablelength];
|
|
double Mathpow(double base, double pow)
|
{
|
int basei = (int) (base * (tablelength - 1));
|
|
double[] table = null;
|
|
if (pow == power1)
|
{
|
table = powtable1;
|
}
|
else if (pow == power2)
|
{
|
table = powtable2;
|
}
|
else
|
{
|
if (power2 == -1)
|
{
|
power2 = pow;
|
table = powtable2 = new double[tablelength];
|
}
|
else
|
{
|
power1 = pow;
|
table = powtable1 = new double[tablelength];
|
power2 = -1;
|
}
|
}
|
|
if (basei != 0 && table[basei] == 0)
|
{
|
table[basei] = Math.pow(basei/(tablelength - 1.0), pow);
|
//if (table[basei] == 0)
|
// System.out.println("POW == 0 : " + basei);
|
}
|
|
if (table[basei+1] == 0)
|
{
|
table[basei+1] = Math.pow((basei+1.0)/(tablelength - 1.0), pow);
|
//if (table[basei+1] == 0)
|
// System.out.println("POW == 0");
|
}
|
|
double offset = base * (tablelength - 1) - basei;
|
//System.out.println("offset = " + offset);
|
|
return table[basei] * (1 - offset) + table[basei+1] * offset;
|
}
|
|
double DsignPower(double base, double pow)
|
{
|
if (base == 0)
|
base = 0.0000000001;
|
|
if (base == 1 || base == -1)
|
return pow;
|
|
if (base > 0)
|
return pow * (double)(Mathpow(base, pow) / base); // - 1);
|
else // if (base < 0)
|
return pow * (double)(Mathpow(-base, pow) / -base); // - 1);
|
//else
|
//{
|
// if (pow == 1)
|
// return 1;
|
// else
|
// return 0;
|
//}
|
}
|
|
cVector du; // = new cVector();
|
cVector dv; // = new cVector();
|
|
double uStretch()
|
{
|
return 2;
|
}
|
|
double vFlip(double v)
|
{
|
return 1-v;
|
}
|
|
Vertex biparamFunction(double u, double v)
|
{
|
//System.out.println("U = " + u + "; V = " + v);
|
double uAng = LA.toRadians(u * 360);
|
double vAng = LA.toRadians(v * 180 - 90);
|
double mcu = Math.cos(uAng);
|
double msu = Math.sin(uAng);
|
double mcv = Math.cos(vAng);
|
double msv = Math.sin(vAng);
|
if (u == 1)
|
{
|
mcu = 1;
|
msu = 0;
|
}
|
if (v == 1)
|
{
|
mcv = 0;
|
msv = 1;
|
}
|
if (v == 0)
|
{
|
mcv = 0;
|
msv = -1;
|
}
|
double cu = signPower(mcu, north);
|
double su = signPower(msu, north);
|
double cv = signPower(mcv, east);
|
double sv = signPower(msv, east);
|
double z = radius * cv * cu;
|
double x = radius * cv * su;
|
double y = radius * sv + radius;
|
|
double dcu = DsignPower(mcu, north) * -msu;
|
double dsu = DsignPower(msu, north) * mcu;
|
double dcv = DsignPower(mcv, east) * -msv;
|
double dsv = DsignPower(msv, east) * mcv;
|
|
du.z = cv * dcu;
|
du.x = cv * dsu;
|
du.y = 0;
|
dv.z = dcv * cu;
|
dv.x = dcv * su;
|
dv.y = dsv;
|
|
//if (du.length() == 0)
|
// System.out.println("DU is null");
|
//if (dv.length() == 0)
|
// System.out.println("DV is null");
|
LA.vecNormalize(du);
|
LA.vecNormalize(dv);
|
|
Vertex temp = new Vertex();
|
|
temp.norm = LA.newVector(x, y, z);
|
LA.vecCross(du,dv, temp.norm);
|
if (temp.norm.length() == 0)
|
temp.norm.y = 2*v - 1;
|
else
|
LA.vecNormalize(temp.norm);
|
|
temp./*pos.*/x = x; // = LA.newVector(x, y, z);
|
temp./*pos.*/y = y;
|
temp./*pos.*/z = z;
|
|
//if (temp.norm.dot(temp/*.pos*/) < 0)
|
//temp.norm.mul(-1);
|
|
//LA.vecAdd(temp/*.pos*/, center, temp/*.pos*/);
|
|
return temp;
|
}
|
|
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.vecSub(inPnt, center, inPnt);
|
LA.vecScale(inPnt, 1 / radius); // Math.abs(radius));
|
for (int i=0; i < 3; i++)
|
if (inPnt.get(i) < 0)
|
inPnt.set(i, -inPnt.get(i));
|
|
boolean inside = true;
|
|
for (int i=0; i < 3; i++)
|
if (inPnt.get(i) >= 1)
|
{
|
//Simplex.atom = this;
|
//height = 1;
|
//depth = 0;
|
//return false;
|
inside = false;
|
break;
|
}
|
|
double f = 1;
|
|
if (inside)
|
{
|
double e2 = 2 / north;
|
double e1 = 2 / east;
|
f = (double)(Mathpow(inPnt.x, e2) + Mathpow(inPnt.z, e2));
|
f = (double)Math.pow(f, e1/e2); // east/north); // e2 / e1);
|
f += (double)Mathpow(inPnt.y, e1);
|
f -= 1;
|
}
|
//double f = (double)(signPower(inPnt.x, e2) + signPower(inPnt.z, e2));
|
//f = (double)signPower(f, e2 / e1);
|
//f += (double)signPower(inPnt.y, e1);
|
//System.out.println("INSIDE(" + x + ", " + y + ", " + z + ") = " + f);
|
|
inside = f <= 0;
|
|
if (depth != -1 && (height <= 0 ^ inside))
|
{
|
Simplex.atom = this;
|
}
|
height = f;
|
depth = 0;
|
|
return radius<0?!inside:inside;
|
}
|
|
void getBounds(cVector minima, cVector maxima, boolean xform)
|
{
|
super.getBounds(minima, maxima, xform);
|
// july 2014 //for (int i=0; i < 3; i++)
|
// {
|
// double r = Math.abs(radius);
|
// minima.x = -r;
|
// minima.y = -r;
|
// minima.z = -r;
|
// //maxima[i] = center[i] + radius;
|
// maxima.x = r;
|
// maxima.y = r;
|
// maxima.z = r;
|
// }
|
//
|
// if (xform)
|
// transformBounds(minima, maxima);
|
}
|
|
void generatePOV(StringBuffer buffer)
|
{
|
generateNameComment(buffer);
|
generateIndent(buffer);
|
buffer.append("superellipsoid { < ");
|
buffer.append(north);
|
buffer.append(",");
|
buffer.append(east);
|
buffer.append(">\n");
|
generateIndent(buffer);
|
buffer.append(" scale ");
|
buffer.append(radius);
|
buffer.append("\n");
|
//generateIndent(buffer);
|
//buffer.append(" translate ");
|
//LA.toPOVRay(center, buffer);
|
//buffer.append("\n");
|
generateTransform(buffer);
|
generateIndent(buffer);
|
buffer.append("}\n");
|
}
|
|
double east;
|
double north;
|
double radius = 0.5;
|
private cVector inPnt;
|
}
|