Superellipse and SuperellipsoidA Geometric Primitive for Computer Aided DesignWritten by Paul BourkeJanuary 1990 See also Supertoroid, Radiance examples. This is a description of a proposed primitive for computer aided design. In 2 dimensions it includes the circle and ellipse, in 3 dimensions it has the sphere and ellipsoid as special cases. By varying its parameters it can form a continuum of other shapes. 2 dimensions - superellipse In 2 dimensions the superellipse centered at the origin is defined in parametric form as ![]() The curve intersects the x axis at rx and -rx, it intersects the y axis at ry and -ry, ie: the superellipse is enclosed in a rectangle of width 2rx and height 2ry. This is the form most easily employed to draw a superellipse, the angle ø is varied from 0 to 2pi in suitably small steps, a line is drawn to each subsequent value of ø. ![]()
Forming the curve using the parametric form above and uniformly varying the
angle automatically samples the curve with curvature dependent sampling. That
is, there are more samples where the curve is changing rapidly, a desirable
characteristic.
then The above can be used to form the superellipse (although it must be done in quadrants). Solving for y gives Varying n controls the form of the superellipse, some special cases are outlined below ![]() Pictorially ![]() Note that the superellipse always passes through the same points at ø = 0, pi/2, pi, 3pi/2 and so it is possible to have different values of n in each quadrant. 3 dimensions - superellipsoid The superellipse is name given to a family of shapes formed from the spherical product of two superquadratric curves. These shapes can be used to model a wide range of shapes including spheres, cylinders, and parallelepipeds as well as shapes inbetween. In 3 dimensions the superellipse centered at the origin is defined as follows
![]() As for the two dimensional case rx, ry, and rz are the scale factors for each axis (axis intercept). The total shape lies at the centre of a box of dimension 2rx, 2ry, 2rz. The power n1 acts as the "squareness" parameter in the z axis and n2 the squareness in the x-y plane. Some special cases of parameter n1 and n2 ![]() The superellipse can also be written as
where the same relationships as for the 2D case (superellipse) can be made,
namely Closed expressions can be derived for the normal at any point on the superellipsoid making many rendering calculations with lighting models easier. The normal is given by ![]() Interestingly, if n1 and n2 are less than 2 then the equation of the normal of the superellipsoid is another superellipsoid (its dual) with n1 -> 2 - n1, and n2 -> 2 - n2. For example, the normals of a superellipsoid with n1=0.5 and n2=0.2 is another superellipsoid (suitably scaled) with n1=1.5 and n2=1.8. ![]() Bibliography Barr, A.H., Superquadrics and Angle Preserving Transformations. IEEE Computer Graphics and Applications, January 1981. Faux, I.D., and Pratt, M.J., Computational Geometry for Design and Manufacture. Ellis Horwood Ltd., Wiley & Sons, 1979. Wallace, A., Differential Topology, Benjamin/Cummings Co., Reading , Mass, USA, 1968.
OpenGL SuperellipsoidA versatile primitiveWritten by Paul BourkeNovember 2001
The superellipsoid is a versatile primitive that is controlled by two parameters. As special cases it can represent a sphere, square box, and closed cylindrical can. The equations are given below, the powers n1 and n2 are the two parameters.
It should be noted that there are some numerical issues with both very small or very large values of these parameters. Typically, for safety, they should be in the range of 0.1 to about 5.
The code below creates a unit superellipsoid at the origin, it correctly assigns normals and texture coordinates.
/*
Create a superellipse
"method" is 0 for quads, 1 for triangles
(quads look nicer in wireframe mode)/
This is a "unit" ellipsoid (-1 to 1) at the origin,
glTranslate() and glScale() as required.
*/
void CreateSuperEllipse(double power1,double power2,int n,int method)
{
int i,j;
double theta1,theta2,theta3;
XYZ p,p1,p2,en;
double delta;
/* Shall we just draw a point? */
if (n < 4) {
glBegin(GL_POINTS);
glVertex3f(0.0,0.0,0.0);
glEnd();
return;
}
/* Shall we just draw a plus */
if (power1 > 10 && power2 > 10) {
glBegin(GL_LINES);
glVertex3f(-1.0, 0.0, 0.0);
glVertex3f( 1.0, 0.0, 0.0);
glVertex3f( 0.0,-1.0, 0.0);
glVertex3f( 0.0, 1.0, 0.0);
glVertex3f( 0.0, 0.0,-1.0);
glVertex3f( 0.0, 0.0, 1.0);
glEnd();
return;
}
delta = 0.01 * TWOPI / n;
for (j=0;j<n/2;j++) {
theta1 = j * TWOPI / (double)n - PID2;
theta2 = (j + 1) * TWOPI / (double)n - PID2;
if (method == 0)
glBegin(GL_QUAD_STRIP);
else
glBegin(GL_TRIANGLE_STRIP);
for (i=0;i<=n;i++) {
if (i == 0 || i == n)
theta3 = 0;
else
theta3 = i * TWOPI / n;
EvalSuperEllipse(theta2,theta3,power1,power2,&p);
EvalSuperEllipse(theta2+delta,theta3,power1,power2,&p1);
EvalSuperEllipse(theta2,theta3+delta,power1,power2,&p2);
en = CalcNormal(p1,p,p2);
glNormal3f(en.x,en.y,en.z);
glTexCoord2f(i/(double)n,2*(j+1)/(double)n);
glVertex3f(p.x,p.y,p.z);
EvalSuperEllipse(theta1,theta3,power1,power2,&p);
EvalSuperEllipse(theta1+delta,theta3,power1,power2,&p1);
EvalSuperEllipse(theta1,theta3+delta,power1,power2,&p2);
en = CalcNormal(p1,p,p2);
glNormal3f(en.x,en.y,en.z);
glTexCoord2f(i/(double)n,2*j/(double)n);
glVertex3f(p.x,p.y,p.z);
}
glEnd();
}
}
void EvalSuperEllipse(double t1,double t2,double p1,double p2,XYZ *p)
{
double tmp;
double ct1,ct2,st1,st2;
ct1 = cos(t1);
ct2 = cos(t2);
st1 = sin(t1);
st2 = sin(t2);
tmp = SIGN(ct1) * pow(fabs(ct1),p1);
p->x = tmp * SIGN(ct2) * pow(fabs(ct2),p2);
p->y = SIGN(st1) * pow(fabs(st1),p1);
p->z = tmp * SIGN(st2) * pow(fabs(st2),p2);
}
Source code that demonstrates the use of the above: superellipse.c, you may need libraries and this texture: mercury.ppm. The two parameters are controlled by using the arrow keys, the up/down arrows control one power term, the left/right arrows control the other power term.
POVRAY SuperellipsoidsWritten by Paul Bourke
The following grid illustrates the range of superellipsoids as variable "e" and "n" are each varied between 0.2 and 3. The POVRAY source that generated the image below is given here: super.pov. ![]()
Supercircle
![]()
|