Superellipse

From Rosetta Code
Task
Superellipse
You are encouraged to solve this task according to the task description, using any language you may know.

A superellipse is a geometric figure defined as the set of all points (x, y) with



where n, a, and b are positive numbers.


Task

Draw a superellipse with n = 2.5, and a = b = 200

C[edit]

Interactive program to draw a SuperEllipse. Requires the WinBGIm library.

 
/*Abhishek Ghosh, 18th September 2017*/
 
#include<graphics.h>
#include<stdio.h>
#include<math.h>
 
#define pi M_PI
 
int main(){
 
double a,b,n,i,incr = 0.0001;
 
printf("Enter major and minor axes of the SuperEllipse : ");
scanf("%lf%lf",&a,&b);
 
printf("Enter n : ");
scanf("%lf",&n);
 
initwindow(500,500,"Superellipse");
 
for(i=0;i<2*pi;i+=incr){
putpixel(250 + a*pow(fabs(cos(i)),2/n)*(pi/2<i && i<3*pi/2?-1:1),250 + b*pow(fabs(sin(i)),2/n)*(pi<i && i<2*pi?-1:1),15);
}
 
printf("Done. %lf",i);
 
getch();
 
closegraph();
}

EchoLisp[edit]

Link to the super-ellipse image.

 
(lib 'plot)
(define (eaxpt x n) (expt (abs x) n))
(define (Ellie x y) (+ (eaxpt (// x 200) 2.5) (eaxpt (// y 200) 2.5) -1))
 
(plot-xy Ellie -400 -400)
(("x:auto" -400 400) ("y:auto" -400 400))
 

FreeBASIC[edit]

' version 23-10-2016
' compile with: fbc -s console
 
Const scr_x = 800 ' screen 800 x 800
Const scr_y = 600
Const m_x = scr_x \ 2 ' middle of screen
Const m_y = scr_y \ 2
 
 
Sub superellipse(a As Long, b As Long, n As Double)
 
ReDim As Long y(0 To a)
Dim As Long x
 
y(0) = b ' value for x = 0
y(a) = 0 ' value for x = a
 
'(0,0) is in upper left corner
 
PSet (m_x, m_y - y(0)) ' set starting point
 
For x = 1 To a-1
y(x) = Int( Exp( Log(1 - ((x / a) ^ n)) / n ) * b )
Line - ((m_x + x), (m_y - y(x)))
Next
 
For x = a To 0 Step -1
Line - ((m_x + x), (m_y + y(x)))
Next
 
For x = 0 To a
Line - ((m_x - x), (m_y + y(x)))
Next
 
For x = a To 0 Step -1
Line - ((m_x - x), (m_y - y(x)))
Next
 
End Sub
 
' ------=< MAIN >=------
 
ScreenRes scr_x, scr_y, 32
 
Dim As Long a = 200
Dim As Long b = 150
Dim As Double n = 2.5
 
superellipse(a, b, n)
 
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

Haskell[edit]

Use the ghcjs compiler to compile to JavaScript that runs in a browser. The reflex-dom library is used to help with SVG rendering and input.

{-# LANGUAGE OverloadedStrings, RankNTypes #-}
import Reflex
import Reflex.Dom
import Data.Text (Text, pack, unpack)
import Data.Map (Map, fromList, empty)
import Text.Read (readMaybe)
 
width = 600
height = 500
 
type Point = (Float,Float)
type Segment = (Point,Point)
 
data Ellipse = Ellipse {a :: Float, b :: Float, n :: Float}
 
toFloat :: Text -> Maybe Float
toFloat = readMaybe.unpack
 
toEllipse :: Maybe Float -> Maybe Float -> Maybe Float -> Maybe Ellipse
toEllipse (Just a) (Just b) (Just n) =
if a < 1.0 || b <= 1.0 || n <= 0.0 -- not all floats are valid
then Nothing
else Just $ Ellipse a b n
 
toEllipse _ _ _ = Nothing
 
showError :: Maybe a -> String
showError Nothing = "invalid input"
showError _ = ""
 
reflect45 pts = pts ++ fmap (\(x,y) -> ( y, x)) (reverse pts)
rotate90 pts = pts ++ fmap (\(x,y) -> ( y, -x)) pts
rotate180 pts = pts ++ fmap (\(x,y) -> (-x, -y)) pts
scale a b = fmap (\(x,y) -> ( a*x, b*y ))
segments pts = zip pts $ tail pts
 
toLineMap :: Maybe Ellipse -> Map Int ((Float,Float),(Float,Float))
toLineMap (Just (Ellipse a b n)) =
let f p = (1 - p**n)**(1/n)
dp = iterate (*0.9) 1.0
ip = map (\p -> 1.0 -p) dp
points s =
if n > 1.0
then (\p -> zip p (map f p)) ip
else (\p -> zip (map f p) p) dp
 
in fromList $ -- changes list to map (for listWithKey)
zip [0..] $ -- annotates segments with index
segments $ -- changes points to line segments
scale a b $
rotate180 $ -- doubles the point count
rotate90 $ -- doubles the point count
reflect45 $ -- doubles the point count
takeWhile (\(x,y) -> x < y ) $ -- stop at 45 degree line
points 0.9
 
toLineMap Nothing = empty
 
lineAttrs :: Segment -> Map Text Text
lineAttrs ((x1,y1), (x2,y2)) =
fromList [ ( "x1", pack $ show (width/2+x1))
, ( "y1", pack $ show (height/2+y1))
, ( "x2", pack $ show (width/2+x2))
, ( "y2", pack $ show (height/2+y2))
, ( "style", "stroke:brown;stroke-width:2")
]
 
showLine :: MonadWidget t m => Int -> Dynamic t Segment -> m ()
showLine _ dSegment = do
elSvgns "line" (lineAttrs <$> dSegment) $ return ()
return ()
 
main = mainWidget $ do
elAttr "h1" ("style" =: "color:brown") $ text "Superellipse"
ta <- el "div" $ do
text "a: "
textInput def { _textInputConfig_initialValue = "200"}
 
tb <- el "div" $ do
text "b: "
textInput def { _textInputConfig_initialValue = "200"}
 
tn <- el "div" $ do
text "n: "
textInput def { _textInputConfig_initialValue = "2.5"}
let
ab = zipDynWith toEllipse (toFloat <$> value ta) (toFloat <$> value tb)
dEllipse = zipDynWith ($) ab (toFloat <$> value tn)
dLines = fmap toLineMap dEllipse
 
dAttrs = constDyn $ fromList
[ ("width" , pack $ show width)
, ("height", pack $ show height)
]
elAttr "div" ("style" =: "color:red") $ dynText $ fmap (pack.showError) dEllipse
el "div" $ elSvgns "svg" dAttrs $ listWithKey dLines showLine
return ()
 
-- At end to avoid Rosetta Code unmatched quotes problem.
elSvgns :: forall t m a. MonadWidget t m => Text -> Dynamic t (Map Text Text) -> m a -> m (El t, a)
elSvgns = elDynAttrNS' (Just "http://www.w3.org/2000/svg")

Link to live demo: https://dc25.github.io/superEllipseReflex/

J[edit]

J-superellipse.png

We will fill the ellipse so that we do not have to worry about the size and shape of our pixels:

selips=: 4 :0
'n a b'=. y
1 >: ((n^~a%~]) +&|/ n^~b%~]) i:x
)
 
require'viewmat'
viewmat 300 selips 2.5 200 200

Java[edit]

Superellipse java.png
Works with: Java version 8
import java.awt.*;
import java.awt.geom.Path2D;
import static java.lang.Math.pow;
import java.util.Hashtable;
import javax.swing.*;
import javax.swing.event.*;
 
public class SuperEllipse extends JPanel implements ChangeListener {
private double exp = 2.5;
 
public SuperEllipse() {
setPreferredSize(new Dimension(650, 650));
setBackground(Color.white);
setFont(new Font("Serif", Font.PLAIN, 18));
}
 
void drawGrid(Graphics2D g) {
g.setStroke(new BasicStroke(2));
g.setColor(new Color(0xEEEEEE));
 
int w = getWidth();
int h = getHeight();
int spacing = 25;
 
for (int i = 0; i < w / spacing; i++) {
g.drawLine(0, i * spacing, w, i * spacing);
g.drawLine(i * spacing, 0, i * spacing, w);
}
g.drawLine(0, h - 1, w, h - 1);
 
g.setColor(new Color(0xAAAAAA));
g.drawLine(0, w / 2, w, w / 2);
g.drawLine(w / 2, 0, w / 2, w);
}
 
void drawLegend(Graphics2D g) {
g.setColor(Color.black);
g.setFont(getFont());
g.drawString("n = " + String.valueOf(exp), getWidth() - 150, 45);
g.drawString("a = b = 200", getWidth() - 150, 75);
}
 
void drawEllipse(Graphics2D g) {
 
final int a = 200; // a = b
double[] points = new double[a + 1];
 
Path2D p = new Path2D.Double();
p.moveTo(a, 0);
 
// calculate first quadrant
for (int x = a; x >= 0; x--) {
points[x] = pow(pow(a, exp) - pow(x, exp), 1 / exp); // solve for y
p.lineTo(x, -points[x]);
}
 
// mirror to others
for (int x = 0; x <= a; x++)
p.lineTo(x, points[x]);
 
for (int x = a; x >= 0; x--)
p.lineTo(-x, points[x]);
 
for (int x = 0; x <= a; x++)
p.lineTo(-x, -points[x]);
 
g.translate(getWidth() / 2, getHeight() / 2);
g.setStroke(new BasicStroke(2));
 
g.setColor(new Color(0x25B0C4DE, true));
g.fill(p);
 
g.setColor(new Color(0xB0C4DE)); // LightSteelBlue
g.draw(p);
}
 
@Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
 
drawGrid(g);
drawLegend(g);
drawEllipse(g);
}
 
@Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
exp = source.getValue() / 2.0;
repaint();
}
 
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Super Ellipse");
f.setResizable(false);
SuperEllipse panel = new SuperEllipse();
f.add(panel, BorderLayout.CENTER);
 
JSlider exponent = new JSlider(JSlider.HORIZONTAL, 1, 9, 5);
exponent.addChangeListener(panel);
exponent.setMajorTickSpacing(1);
exponent.setPaintLabels(true);
exponent.setBackground(Color.white);
exponent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
 
Hashtable<Integer, JLabel> labelTable = new Hashtable<>();
for (int i = 1; i < 10; i++)
labelTable.put(i, new JLabel(String.valueOf(i * 0.5)));
exponent.setLabelTable(labelTable);
 
f.add(exponent, BorderLayout.SOUTH);
 
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}

JavaScript[edit]

 
var n = 2.5, a = 200, b = 200, ctx;
 
function point( x, y ) {
ctx.fillRect( x, y, 1, 1);
}
 
function start() {
var can = document.createElement('canvas');
can.width = can.height = 600;
ctx = can.getContext( "2d" );
ctx.rect( 0, 0, can.width, can.height );
ctx.fillStyle = "#000000"; ctx.fill();
document.body.appendChild( can );
 
ctx.fillStyle = "#ffffff";
for( var t = 0; t < 1000; t += .1 ) {
x = Math.pow( Math.abs( Math.cos( t ) ), 2 / n ) * a * Math.sign( Math.cos( t ) );
y = Math.pow( Math.abs( Math.sin( t ) ), 2 / n ) * b * Math.sign( Math.sin( t ) );
 
point( x + ( can.width >> 1 ), y + ( can.height >> 1 ) );
}
}
 

Kotlin[edit]

The following is based on the Java entry but dispenses with the grid and slider as these aren't really part of the task.

// version 1.1.2
 
import java.awt.*
import java.awt.geom.Path2D
import javax.swing.*
import java.lang.Math.pow
 
/* assumes a == b */
class SuperEllipse(val n: Double, val a: Int) : JPanel() {
init {
require(n > 0.0 && a > 0)
preferredSize = Dimension(650, 650)
background = Color.black
}
 
private fun drawEllipse(g: Graphics2D) {
val points = DoubleArray(a + 1)
val p = Path2D.Double()
p.moveTo(a.toDouble(), 0.0)
 
// calculate first quadrant
for (x in a downTo 0) {
points[x] = pow(pow(a.toDouble(), n) - pow(x.toDouble(), n), 1.0 / n)
p.lineTo(x.toDouble(), -points[x])
}
 
// mirror to others
for (x in 0..a) p.lineTo(x.toDouble(), points[x])
for (x in a downTo 0) p.lineTo(-x.toDouble(), points[x])
for (x in 0..a) p.lineTo(-x.toDouble(), -points[x])
 
with(g) {
translate(width / 2, height / 2)
color = Color.yellow
fill(p)
}
}
 
override fun paintComponent(gg: Graphics) {
super.paintComponent(gg)
val g = gg as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON)
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
drawEllipse(g)
}
}
 
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
with (f) {
defaultCloseOperation = JFrame.EXIT_ON_CLOSE
title = "Super Ellipse"
isResizable = false
add(SuperEllipse(2.5, 200), BorderLayout.CENTER)
pack()
setLocationRelativeTo(null)
isVisible = true
}
}
}

Maple[edit]

The built-in command ImplicitPlot accepts an equation in 2 variables:

plots:-implicitplot(abs((1/200)*x^2.5)+abs((1/200)*y^2.5) = 1, x = -10 .. 10, y = -10 .. 10);

Mathematica[edit]

The built-in function ContourPlot accepts and equation in 2 variables and creates the desired plot

ContourPlot[
Abs[x/200]^2.5 + Abs[y/200]^2.5 == 1, {x, -200, 200}, {y, -200, 200}]

ooRexx[edit]

This program draws 5 super ellipses:
black 120,120,1.5
blue  160,160,2
red   200,200,2.5
green 240,240,3  
black 280,280,4
/* REXX ***************************************************************
* Create a BMP file showing a few super ellipses
**********************************************************************/

Parse Version v
If pos('Regina',v)>0 Then
superegg='superegga.bmp'
Else
superegg='supereggx.bmp'
'erase' superegg
s='424d4600000000000000360000002800000038000000280000000100180000000000'X||,
'1000000000000000000000000000000000000000'x
z.0=0
black='000000'x
white='ffffff'x
red ='00ff00'x
green='ff0000'x
blue ='0000ff'x
m=80
n=80
hor=m*8 /* 56 */
ver=n*8 /* 40 */
s=overlay(lend(hor),s,19,4)
s=overlay(lend(ver),s,23,4)
z.=copies('f747ff'x,3192%3)
z.=copies('ffffff'x,8*m)
z.0=648
u=320
v=320
Call supegg black,120,120,1.5,u,v
Call supegg blue,160,160,2,u,v
Call supegg red,200,200,2.5,u,v
Call supegg green,240,240,3,u,v
Call supegg black,280,280,4,u,v
 
Do i=1 To z.0
s=s||z.i
End
 
Call lineout superegg,s
Call lineout superegg
Exit
 
supegg:
Parse Arg color,a,b,n,u,v
Do y=0 To b
t=(1-rxCalcpower(y/b,n))
x=a*rxCalcpower(t,1/n)
Call point color,format(u+x,4,0),format(v+y,4,0)
Call point color,format(u-x,4,0),format(v+y,4,0)
Call point color,format(u+x,4,0),format(v-y,4,0)
Call point color,format(u-x,4,0),format(v-y,4,0)
End
Do x=0 To a
t=(1-rxCalcpower(x/b,n))
y=a*rxCalcpower(t,1/n)
Call point color,format(u+x,4,0),format(v+y,4,0)
Call point color,format(u-x,4,0),format(v+y,4,0)
Call point color,format(u+x,4,0),format(v-y,4,0)
Call point color,format(u-x,4,0),format(v-y,4,0)
End
Return
 
lend:
Return reverse(d2c(arg(1),4))
 
point: Procedure Expose z.
Call trace 'O'
Parse Arg color,x0,y0
--Say x0 y0
Do x=x0-2 To x0+2
Do y=y0-2 To y0+2
z.y=overlay(copies(color,3),z.y,3*x)
End
End
Return
 
::requires rxMath library

Perl 6[edit]

Works with: rakudo version 2016-01

Generate an svg image to STDOUT. Redirect into a file to capture it.

constant a = 200;
constant b = 200;
constant n = 2.5;
 
# y in terms of x
sub y ($x) { sprintf "%d", b * (1 - ($x / a).abs ** n ) ** (1/n) }
 
# find point pairs for one quadrant
my @q = flat map -> \x { x, y(x) }, (0, 2 ... 200);
 
# Generate an SVG image
INIT say qq:to/STOP/;
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="{b*2}" width="{a*2}" version="1.1" xmlns="http://www.w3.org/2000/svg">
STOP
END say '</svg>';
 
.put for
pline( @q ),
pline( @q «*» ( 1,-1) ), # flip and mirror
pline( @q «*» (-1,-1) ), # for the other
pline( @q «*» (-1, 1) ); # three quadrants
 
sub pline (@q) {
qq:to/END/;
<polyline points="{@q}"
style="fill:none; stroke:black; stroke-width:3" transform="translate({a}, {b})" />
END
}

See Superellipse image

Python[edit]

 
# Superellipse drawing in Python 2.7.9
# pic can see at http://www.imgup.cz/image/712
 
import matplotlib.pyplot as plt
from math import sin, cos, pi
 
def sgn(x):
return ((x>0)-(x<0))*1
 
a,b,n=200,200,2.5 # param n making shape
na=2/n
step=100 # accuracy
piece=(pi*2)/step
xp=[];yp=[]
 
t=0
for t1 in range(step+1):
# because sin^n(x) is mathematically the same as (sin(x))^n...
x=(abs((cos(t)))**na)*a*sgn(cos(t))
y=(abs((sin(t)))**na)*b*sgn(sin(t))
xp.append(x);yp.append(y)
t+=piece
 
plt.plot(xp,yp) # plotting all point from array xp, yp
plt.title("Superellipse with parameter "+str(n))
plt.show()
 

Racket[edit]

#lang racket
(require plot)
#;(plot-new-window? #t)
 
(define ((superellipse a b n) x y)
(+ (expt (abs (/ x a)) n)
(expt (abs (/ y b)) n)))
 
(plot (isoline (superellipse 200 200 2.5) 1
-220 220 -220 220))

REXX[edit]

Translation of: ooRexx

Here you can see a picture: http://austria-forum.org/af/User/Pachl%20Walter

/* REXX ***************************************************************
* Create a BMP file showing a few super ellipses
**********************************************************************/

Parse Version v
If pos('Regina',v)>0 Then
superegg='superegga.bmp'
Else
superegg='supereggo.bmp'
'erase' superegg
s='424d4600000000000000360000002800000038000000280000000100180000000000'X||,
'1000000000000000000000000000000000000000'x
z.0=0
black='000000'x
white='ffffff'x
red ='00ff00'x
green='ff0000'x
blue ='0000ff'x
m=80
n=80
hor=m*8 /* 56 */
ver=n*8 /* 40 */
s=overlay(lend(hor),s,19,4)
s=overlay(lend(ver),s,23,4)
z.=copies('f747ff'x,3192%3)
z.=copies('ffffff'x,8*m)
z.0=648
u=320
v=320
Call supegg black,080,080,0.5,u,v
Call supegg black,110,110,1 ,u,v
Call supegg black,140,140,1.5,u,v
Call supegg blue ,170,170,2 ,u,v
Call supegg red ,200,200,2.5,u,v
Call supegg green,230,230,3 ,u,v
Call supegg black,260,260,4 ,u,v
Call supegg black,290,290,7 ,u,v
Do i=1 To z.0
s=s||z.i
End
 
Call lineout superegg,s
Call lineout superegg
Exit
 
supegg:
Parse Arg color,a,b,n,u,v
Do y=0 To b
t=(1-power(y/b,n))
x=a*power(t,1/n)
Call point color,format(u+x,4,0),format(v+y,4,0)
Call point color,format(u-x,4,0),format(v+y,4,0)
Call point color,format(u+x,4,0),format(v-y,4,0)
Call point color,format(u-x,4,0),format(v-y,4,0)
End
Do x=0 To a
t=(1-power(x/b,n))
y=a*power(t,1/n)
Call point color,format(u+x,4,0),format(v+y,4,0)
Call point color,format(u-x,4,0),format(v+y,4,0)
Call point color,format(u+x,4,0),format(v-y,4,0)
Call point color,format(u-x,4,0),format(v-y,4,0)
End
Return
 
lend:
Return reverse(d2c(arg(1),4))
 
point: Procedure Expose z.
Call trace 'O'
Parse Arg color,x0,y0
--Say x0 y0
Do x=x0-2 To x0+2
Do y=y0-2 To y0+2
z.y=overlay(copies(color,3),z.y,3*x)
End
End
Return
 
power: Procedure
/***********************************************************************
* Return b**x for any x -- with reasonable or specified precision
* 920903 Walter Pachl
***********************************************************************/

Parse Arg b,x,prec
If prec<9 Then prec=9
Numeric Digits (2*prec)
Numeric Fuzz 3
If b=0 Then Return 0
If b<>'' Then x=x*ln(b,prec+2)
o=1
u=1
r=1
Do i=1 By 1
ra=r
o=o*x
u=u*i
r=r+(o/u)
If r=ra Then Leave
End
Numeric Digits (prec)
Return r+0
 
ln: Procedure
/***********************************************************************
* Return ln(x) -- with specified precision
* Three different series are used for the ranges 0 to 0.5
* 0.5 to 1.5
* 1.5 to infinity
* 920903 Walter Pachl
***********************************************************************/

Parse Arg x,prec,b
If prec='' Then prec=9
Numeric Digits (2*prec)
Numeric Fuzz 3
Select
When x<=0 Then r='*** invalid argument ***'
When x<0.5 Then Do
z=(x-1)/(x+1)
o=z
r=z
k=1
Do i=3 By 2
ra=r
k=k+1
o=o*z*z
r=r+o/i
If r=ra Then Leave
End
r=2*r
End
When x<1.5 Then Do
z=(x-1)
o=z
r=z
k=1
Do i=2 By 1
ra=r
k=k+1
o=-o*z
r=r+o/i
If r=ra Then Leave
End
End
Otherwise /* 1.5<=x */ Do
z=(x+1)/(x-1)
o=1/z
r=o
k=1
Do i=3 By 2
ra=r
k=k+1
o=o/(z*z)
r=r+o/i
If r=ra Then Leave
End
r=2*r
End
End
If b<>'' Then
r=r/ln(b)
Numeric Digits (prec)
Return r+0

Sidef[edit]

Translation of: Perl 6
const (
a = 200,
b = 200,
n = 2.5,
)
 
# y in terms of x
func y(x) { b * (1 - abs(x/a)**n -> root(n)) -> int }
 
func pline(q) {
<<-"EOT";
<polyline points="#{q.join(' ')}"
style="fill:none; stroke:black; stroke-width:3" transform="translate(#{a}, #{b})" />
EOT
}
 
# Generate an SVG image
say <<-"EOT"
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="#{b*2}" width="#{a*2}" version="1.1" xmlns="http://www.w3.org/2000/svg">
EOT
 
# find point pairs for one quadrant
var q = { |x| (x, y(x)) }.map(0..200 `by` 2)
 
[
pline(q),
pline(q »*« [ 1,-1]), # flip and mirror
pline(q »*« [-1,-1]), # for the other
pline(q »*« [-1, 1]), # three quadrants
].each { .print }
 
say '</svg>'

zkl[edit]

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

SuperEllipse.zkl.jpg
fcn superEllipse(plot,n,color=0xff0000){ // we'll assume width <= height
a,p:=(plot.w/2).toFloat(), 1.0/n; // just calculate upper right quadrant
foreach x in ([0.0 .. a]){
y:=(a.pow(n) - x.pow(n)).pow(p); // a==b>0 --> y=(a^n - x^n)^(1/n)
//println( (x/a).abs().pow(n) + (y/b).abs().pow(n) ); // sanity check
plot[x,y]=plot[-x,-y]=plot[-x,y]=plot[x,-y]=color; // all 4 quadrants
}
plot
}
w:=h:=600;
plot:=PPM(w+1,h+1,0x909090); plot.cross(w/2,h/2);
foreach n in ([0.01..1, 0.14]){ superEllipse(plot,n, 0x0000bb) }// 0-1: blue
foreach n in ([1.0.. 2, 0.14]){ superEllipse(plot,n, 0x00ff00) }// 1-2: green
foreach n in ([2.0..10, 1.4]) { superEllipse(plot,n, 0xff0000) }// 2+: red
 
plot.writeJPGFile("superEllipse.jpg");