Jump to content

Superellipse

From Rosetta Code
Revision as of 19:28, 22 July 2024 by Chkas (talk | contribs) ({{header|EasyLang}})
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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

Action!

INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

PROC Superellipse(INT x0 BYTE y0 REAL POINTER n BYTE a)
  INT ARRAY f(100)
  REAL ar,xr,tmp1,tmp2,tmp3,one,invn
  INT x

  IntToReal(1,one)
  RealDiv(one,n,invn) ;1/n
  IntToReal(a,ar)
  Power(ar,n,tmp1) ;a^n

  Plot(x0,y0-a)
  FOR x=0 TO a
  DO
    IntToReal(x,xr)
    Power(xr,n,tmp2) ;x^n
    RealSub(tmp1,tmp2,tmp3) ;a^n-x^n
    Power(tmp3,invn,tmp2) ;(a^n-x^n)^(1/n)
    f(x)=RealToInt(tmp2)
    DrawTo(x0+x,y0-f(x))
  OD

  x=a
  WHILE x>=0
  DO
    DrawTo(x0+x,y0+f(x))
    x==-1
  OD

  FOR x=0 TO a
  DO
    DrawTo(x0-x,y0+f(x))
  OD

  x=a
  WHILE x>=0
  DO
    DrawTo(x0-x,y0-f(x))
    x==-1
  OD
RETURN

PROC Main()
  BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6
  REAL n

  Graphics(8+16)
  Color=1
  COLOR1=$0C
  COLOR2=$02

  ValR("2.5",n)
  Superellipse(160,96,n,80)

  DO UNTIL CH#$FF OD
  CH=$FF
RETURN
Output:

Screenshot from Atari 8-bit computer

Ada

Library: SDLAda

Brute force calculation.

with Ada.Numerics.Elementary_Functions;

with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Events.Events;

procedure Superelipse is

   Width  : constant := 600;
   Height : constant := 600;
   A      : constant := 200.0;
   B      : constant := 200.0;
   N      : constant := 2.5;

   Window   : SDL.Video.Windows.Window;
   Renderer : SDL.Video.Renderers.Renderer;
   Event    : SDL.Events.Events.Events;

   procedure Draw_Superelipse
   is
      use type SDL.C.int;
      use Ada.Numerics.Elementary_Functions;
      Xx, Yy : Float;
      subtype Legal_Range is Float range 0.980 .. 1.020;
   begin
      for Y in 0 .. Height loop
         for X in 0 .. Width loop
            Xx := Float (X - Width  / 2);
            Yy := Float (Y - Height / 2);
            if (abs (Xx / A)) ** N + (abs (Yy / B)) ** N in Legal_Range then
               Renderer.Draw (Point => (X => Width  / 2 + SDL.C.int (Xx),
                                        Y => Height / 2 - SDL.C.int (Yy)));
            end if;

         end loop;
      end loop;
   end Draw_Superelipse;

   procedure Wait is
      use type SDL.Events.Event_Types;
   begin
      loop
         while SDL.Events.Events.Poll (Event) loop
            if Event.Common.Event_Type = SDL.Events.Quit then
               return;
            end if;
         end loop;
         delay 0.100;
      end loop;
   end Wait;

begin
   if not SDL.Initialise (Flags => SDL.Enable_Screen) then
      return;
   end if;

   SDL.Video.Windows.Makers.Create (Win      => Window,
                                    Title    => "Superelipse",
                                    Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
                                    Size     => SDL.Positive_Sizes'(Width, Height),
                                    Flags    => 0);
   SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
   Renderer.Set_Draw_Colour ((0, 0, 0, 255));
   Renderer.Fill (Rectangle => (0, 0, Width, Height));
   Renderer.Set_Draw_Colour ((0, 220, 0, 255));

   Draw_Superelipse;
   Window.Update_Surface;

   Wait;
   Window.Finalize;
   SDL.Finalise;
end Superelipse;

AutoHotkey

Requires Gdip Library

n := 2.5
a := 200
b := 200
SuperEllipse(n, a, b)
return

SuperEllipse(n, a, b){
    global
    pToken    := Gdip_Startup()
    π := 3.141592653589793, oCoord := [], oX := [], oY := []
    nn := 2/n
    loop 361
    {
        t := (A_Index-1) * π/180
        ; https://en.wikipedia.org/wiki/Superellipse
        x := abs(cos(t))**nn * a * sgn(cos(t))
        y := abs(sin(t))**nn * b * sgn(sin(t))
        oCoord[A_Index] := [x, y]
        oX[Floor(x)] := true, oY[Floor(y)] := true
    }
    dx := 0 - oX.MinIndex() + 10
    dy := 0 - oY.MinIndex() + 10
    w := oX.MaxIndex()-oX.MinIndex() + 20
    h := oY.MaxIndex()-oY.MinIndex() + 20

    Gdip1(w, h)
    pPen := Gdip_CreatePen("0xFF00FF00", 2)
    for i, obj in oCoord
    {
        x2 := obj.1+dx, y2 := obj.2+dy
        if i>1
            Gdip_DrawLine(G, pPen, x1, y1, x2, y2)
        x1 := x2, y1 := y2
    }
    UpdateLayeredWindow(hwnd, hdc)
}
;----------------------------------------------------------------
sgn(n){
    return (n>0?1:n<0?-1:0)
}
;----------------------------------------------------------------
Gdip1(w:=0, h:=0){
    global
    w := w ? w : A_ScreenWidth
    h := h ? h : A_ScreenHeight
    x := A_ScreenWidth/2 - w/2
    y := A_ScreenHeight/2 - h/2
    Gui, gdip1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +AlwaysOnTop
    Gui, gdip1: Show, w%w% h%h% x%x% y%y%
    hwnd    := WinExist()
    hbm        := CreateDIBSection(w, h)
    hdc        := CreateCompatibleDC()
    obm        := SelectObject(hdc, hbm)
    G        := Gdip_GraphicsFromHDC(hdc)
    Gdip_SetSmoothingMode(G, 4)
    pBrush    := Gdip_BrushCreateSolid("0xFF000000")
    Gdip_FillRoundedRectangle(G, pBrush, 0, 0, w, h, 5)
    Gdip_DeleteBrush(pBrush)
    UpdateLayeredWindow(hwnd, hdc)
    OnMessage(0x201, "WM_LBUTTONDOWN")
}
;----------------------------------------------------------------
Gdip2(){
    global
    SelectObject(hdc, obm)
    DeleteObject(hbm)
    DeleteDC(hdc)
    Gdip_DeleteGraphics(G)
    Gdip_Shutdown(pToken)
}
;----------------------------------------------------------------
WM_LBUTTONDOWN(){
    PostMessage, 0xA1, 2
}
;----------------------------------------------------------------
Exit:
gdip2()
ExitApp
Return
;----------------------------------------------------------------

C

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

#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();
}

Delphi

Works with: Delphi version 6.0
procedure DrawSuperElipse(Image: TImage);
var Points: array of double;
const N = 2.5;
const Border = 10;
var A: integer;
var X: integer;
var W2,H2: integer;
begin
{Make elipse size and position based on window size}
W2:=Image.Width div 2;
H2:=Image.Height div 2;
A:=Min(W2,H2)-Border;
{Fill array with points}
SetLength(Points,A);
for X:=0 to High(Points) do
 Points[X]:=Power(Power(A, N) - Power(X, N), 1 / N);

Image.Canvas.Pen.Color:=clRed;
Image.Canvas.Pen.Width:=2;

{Starting point}
Image.Canvas.MoveTo(W2+High(Points),trunc(H2-Points[High(Points)]));
{Draw Upper right}
for X:=High(Points) downto 0 do
	begin
	Image.Canvas.LineTo(W2+x, trunc(H2-Points[X]))
	end;
{Draw Upper left}
for X:=0 to High(Points) do
	begin
	Image.Canvas.LineTo(W2-X, trunc(H2-Points[X]))
	end;

{Draw Lower left}
for X:=High(Points) downto 0 do
	begin
	Image.Canvas.LineTo(W2-X, trunc(H2+Points[X]))
	end;
{Draw Lower right}
for X:=0 to High(Points) do
	begin
	Image.Canvas.LineTo(W2+X, trunc(H2+Points[X]))
	end;
{Connect back to beginning}
Image.Canvas.LineTo(W2+High(Points),trunc(H2-Points[High(Points)]));
Image.Repaint;
end;
Output:
Elapsed Time: 13.282 ms.

EasyLang

Run it

n = 2.5
a = 200
b = 200
linewidth 0.2
while t <= 360
   x = pow abs cos t (2 / n) * a * sign cos t
   y = pow abs sin t (2 / n) * b * sign sin t
   line x / 5 + 50 y / 5 + 50
   t += 0.5
.

EchoLisp

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

' 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

Go

Library: Go Graphics
package main

import (
    "github.com/fogleman/gg"
    "math"
)

/* assumes a and b are always equal */
func superEllipse(dc *gg.Context, n float64, a int) {
    hw := float64(dc.Width() / 2)
    hh := float64(dc.Height() / 2)

    // calculate y for each x
    y := make([]float64, a+1)
    for x := 0; x <= a; x++ {
        aa := math.Pow(float64(a), n)
        xx := math.Pow(float64(x), n)
        y[x] = math.Pow(aa-xx, 1.0/n)
    }

    // draw quadrants
    for x := a; x >= 0; x-- {
        dc.LineTo(hw+float64(x), hh-y[x])
    }
    for x := 0; x <= a; x++ {
        dc.LineTo(hw+float64(x), hh+y[x])
    }
    for x := a; x >= 0; x-- {
        dc.LineTo(hw-float64(x), hh+y[x])
    }
    for x := 0; x <= a; x++ {
        dc.LineTo(hw-float64(x), hh-y[x])
    }

    dc.SetRGB(1, 1, 1) // white ellipse
    dc.Fill()
}

func main() {
    dc := gg.NewContext(500, 500)
    dc.SetRGB(0, 0, 0) // black background
    dc.Clear()
    superEllipse(dc, 2.5, 200)
    dc.SavePNG("superellipse.png")
}
Output:
Image similar to J entry.

Haskell

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

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

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

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 ) );
    }
}

jq

Adapted from Sidef

Works with: jq

Also works with gojq, the Go implementation of jq.

This entry uses jq to generate SVG.

Generic functions

# Input: [x, y]
def mult($a; $b): [.[0]*$a, .[1]*$b] ;

# Input: a number
def round($n): . * $n | floor / $n;

# svg header boilerplate
def svg($h; $w):
  "<?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='\($h)' width='\($w)' version='1.1' xmlns='http://www.w3.org/2000/svg'>";
</syntaxhighlight�>
'''Superellipse functions'''
<syntaxhighlight lang=jq>
# y in terms of x
# input: {a,b,n}
def y($x): (.b *  pow( (1 - pow( ($x/.a)|length ; .n) ) ; 1/.n )) | round(10);

# input: {a,b,n}
def pline(q): 
  "<polyline points='\(q|map(join(","))|join(" "))'",
  " style='fill:none; stroke:black; stroke-width:3' transform='translate(\(.a + 10), \(.b + 10))' />";

# input: {a,b,n}
def plot: 
  # points for one quadrant
  [range(0;400) as $i | [$i, y($i)] | select(.[1] | isnan | not) ] as $q
  |
    pline($q),
    pline($q | map( mult(1;-1))),  # flip and mirror
    pline($q | map( mult(-1;-1))), # for the other
    pline($q | map( mult(-1;1)))   # three quadrants
;

# Input: {a,b,n} - the constants for the superellipse
def superellipse:
  svg(.b*2 + 10; .a*2 + 10), plot, "</svg>";

{ a: 200,  b: 200,  n: 2.5 }
| superellipse
Output:

Similar to Perl solution.

Julia

function superellipse(n, a, b, step::Int=100)
    @assert n > 0 && a > 0 && b > 0
    na = 2 / n
    pc = 2π / step
    t  = 0
    xp = Vector{Float64}(undef, step + 1)
    yp = Vector{Float64}(undef, step + 1)
    for i in 0:step
        # because sin^n(x) is mathematically the same as (sin(x))^n...
        xp[i+1] = abs((cos(t))) ^ na * a * sign(cos(t))
        yp[i+1] = abs((sin(t))) ^ na * b * sign(sin(t))
        t += pc
    end
    return xp, yp
end

using UnicodePlots

x, y = superellipse(2.5, 200, 200)
println(lineplot(x, y))
Output:
        ┌────────────────────────────────────────┐
    200 │⠀⠀⠀⠀⠀⠀⠀⢀⣠⠤⠔⠒⠊⠉⠉⠉⠉⠉⠉⠉⡏⠉⠉⠉⠉⠉⠉⠒⠒⠢⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀│
        │⠀⠀⠀⠀⣀⠤⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠓⠤⣀⠀⠀⠀⠀│
        │⠀⠀⢀⠜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⡄⠀⠀│
        │⠀⡠⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢆⠀│
        │⢰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆│
        │⡎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢱│
        │⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸│
        │⡧⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⡧⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⢼│
        │⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸│
        │⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡸│
        │⠸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠇│
        │⠀⠱⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠊⠀│
        │⠀⠀⠘⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡔⠁⠀⠀│
        │⠀⠀⠀⠀⠉⠒⢤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠒⠉⠀⠀⠀⠀│
   -200 │⠀⠀⠀⠀⠀⠀⠀⠈⠉⠒⠢⠤⠤⣀⣀⣀⣀⣀⣀⣀⣇⣀⣀⣀⣀⣀⣀⡠⠤⠔⠒⠋⠁⠀⠀⠀⠀⠀⠀⠀│
        └────────────────────────────────────────┘
        -200                                   200

Kotlin

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
        }
    }
}

Lambdatalk

Drawing four super-ellipses, a circle, a rounded square, a square, an astroid.

{def superellipse
 {def sgn {lambda {:n} {if {< :n 0} then - else +}}}

 {lambda {:a :n :t}
  {let { {:a :a} {:n {/ 2 :n}}
         {:cost {cos {* {PI} :t}}}
         {:sint {sin {* {PI} :t}}}
       } {sgn :cost}{* :a {pow {abs :cost} :n}}
         {sgn :sint}{* :a {pow {abs :sint} :n}}
}}}
-> superellipse

We use SVG and the lib_plot library defining the SVG, AXES, stroke functions to draw four superellipses, a circle, a rounded square (as required), a square and an astroid.

{{SVG 600 600}
 {g {AXES 600 600}
  {polyline
   {@ points="{S.map {superellipse 200 2.5} {S.serie -1 1.01 0.01}}"
      {stroke #f00 4}}}
  {polyline
   {@ points="{S.map {superellipse 200 0.5} {S.serie -1 1.01 0.01}}"
      {stroke #0f0 4}}}
  {polyline
   {@ points="{S.map {superellipse 200 1} {S.serie -1 1.01 0.01}}"
      {stroke #888 2}}}
  {polyline
   {@ points="{S.map {superellipse 200 2} {S.serie -1 1.01 0.01}}"
      {stroke #888 2}}}
}}

The output can be seen in http://lambdaway.free.fr/lambdawalks/?view=super_ellipse

Liberty BASIC

Reworked the Julia version to work and added a loop with a spread on n values.

[start]
    nomainwin
    UpperLeftX=1:UpperLeftY=1
    WindowWidth=800:WindowHeight=600
    open "Super Ellipse" for graphics_nf_nsb as #1
    #1 "trapclose [q];down;fill black;flush;color green;size 1"

    n=1.5
    a=200
    b=200

    for n = 0.1 to 5 step .1
        na=2/n
        t=.01
        for i = 0 to 314
            xp=a*sign(cos(t))*abs((cos(t)))^na+350
            yp=b*sign(sin(t))*abs((sin(t)))^na+275
            t=t+.02
            #1 "set ";xp;" ";yp
        next i
    next n

    'plot only the super ellipse for the task
    n=2.5
    na=2/n
    t=.01
    #1 "color white;size 4"
    for i = 0 to 314
        xp=a*sign(cos(t))*abs((cos(t)))^na+350
        yp=b*sign(sin(t))*abs((sin(t)))^na+275
        t=t+.02
        #1 "set ";xp;" ";yp
    next i
wait

[q]
close #1
end

function sign(x)
    if x<0 then sign=1
    if x>0 then sign=-1
    if x=0 then sign=0
end function

Lua

Scale of a and b were reduced to facilitate an ASCII solution:

local abs,cos,floor,pi,pow,sin = math.abs,math.cos,math.floor,math.pi,math.pow,math.sin
local bitmap = {
  init = function(self, w, h, value)
    self.w, self.h, self.pixels = w, h, {}
    for y=1,h do self.pixels[y]={} end
    self:clear(value)
  end,
  clear = function(self, value)
    for y=1,self.h do
      for x=1,self.w do
        self.pixels[y][x] = value or "  "
      end
    end
  end,
  set = function(self, x, y, value)
    x,y = floor(x+0.5),floor(y+0.5)
    if x>0 and y>0 and x<=self.w and y<=self.h then
      self.pixels[y][x] = value or "#"
    end
  end,
  superellipse = function(self, ox, oy, n, a, b, c)
    local function sgn(n) return n>=0 and 1 or -1 end
    for t = 0, 1, 0.002 do
      local theta = t * 2 * pi
      local x = ox + a * pow(abs(cos(theta)), 2/n) * sgn(cos(theta))
      local y = oy + b * pow(abs(sin(theta)), 2/n) * sgn(sin(theta))
      self:set(x, y, c)
    end
  end,
  render = function(self)
    for y=1,self.h do
      print(table.concat(self.pixels[y]))
    end
  end,
}

bitmap:init(80, 60, "..")
bitmap:superellipse(40, 30, 2.5, 38, 28, "[]")
bitmap:render()
Output:
................................................................................................................................................................
..........................................................[][][][][][][][][][][][][][][][][][][][][]............................................................
............................................[][][][][][][]..........................................[][][][][][][]..............................................
......................................[][][][]..................................................................[][][][]........................................
................................[][][][]..............................................................................[][][][]..................................
............................[][][]..........................................................................................[][][]..............................
........................[][][]..................................................................................................[][][]..........................
......................[][]..........................................................................................................[][]........................
..................[][]..................................................................................................................[][]....................
................[][]......................................................................................................................[][]..................
..............[][]..........................................................................................................................[][]................
............[][]..............................................................................................................................[][]..............
............[]..................................................................................................................................[]..............
..........[]......................................................................................................................................[]............
........[][]......................................................................................................................................[][]..........
........[]..........................................................................................................................................[]..........
......[]..............................................................................................................................................[]........
......[]..............................................................................................................................................[]........
....[][]..............................................................................................................................................[][]......
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
..[][]..................................................................................................................................................[][]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[][]..................................................................................................................................................[][]....
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
....[][]..............................................................................................................................................[][]......
......[]..............................................................................................................................................[]........
......[]..............................................................................................................................................[]........
........[]..........................................................................................................................................[]..........
........[][]......................................................................................................................................[][]..........
..........[]......................................................................................................................................[]............
............[]..................................................................................................................................[]..............
............[][]..............................................................................................................................[][]..............
..............[][]..........................................................................................................................[][]................
................[][]......................................................................................................................[][]..................
..................[][]..................................................................................................................[][]....................
......................[][]..........................................................................................................[][]........................
........................[][][]..................................................................................................[][][]..........................
............................[][][]..........................................................................................[][][]..............................
................................[][][][]..............................................................................[][][][]..................................
......................................[][][][]..................................................................[][][][]........................................
............................................[][][][][][][]..........................................[][][][][][][]..............................................
..........................................................[][][][][][][][][][][][][][][][][][][][][]............................................................
................................................................................................................................................................
................................................................................................................................................................

Maple

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 /Wolfram Language

The built-in function ContourPlot accepts an 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}]

Nim

Library: imageman
import math
import imageman

const
  Size = 600
  X0 = Size div 2
  Y0 = Size div 2
  Background = ColorRGBU [byte 0, 0, 0]
  Foreground = ColorRGBU [byte 255, 255, 255]


proc drawSuperEllipse(img: var Image; n: float; a, b: int) =

  var yList = newSeq[int](a + 1)
  for x in 0..a:
    let an = pow(a.toFloat, n)
    let bn = pow(b.toFloat, n)
    let xn = pow(x.toFloat, n)
    let t = max(bn - xn * bn / an, 0.0)   # Avoid negative values due to rounding errors.
    yList[x] = pow(t, 1/n).toInt

  var pos: seq[Point]
  for x in countdown(a, 0):
    pos.add (X0 + x, Y0 - yList[x])
  for x in 0..a:
    pos.add (X0 - x, Y0 - yList[x])
  for x in countdown(a, 0):
    pos.add (X0 - x, Y0 + yList[x])
  for x in 0..a:
    pos.add (X0 + x, Y0 + yList[x])
  img.drawPolyline(true, Foreground, pos)


var image = initImage[ColorRGBU](Size, Size)
image.fill(Background)
image.drawSuperEllipse(2.5, 200, 200)
image.savePNG("super_ellipse.png", compression = 9)

ooRexx

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

Translation of: Raku
use v5.36;
my($a, $b, $n, @q) = (200, 200, 2.5);

# y in terms of x
sub y_from_x ($x) { int $b * abs(1 - ($x/$a) ** $n ) ** (1/$n) }

# find point pairs for one quadrant
push @q, $_, y_from_x($_) for 0..$a;

open  $fh, '>', 'superellipse.svg';
print $fh
  qq|<svg height="@{[2*$b]}" width="@{[2*$a]}" xmlns="http://www.w3.org/2000/svg">\n|,
  pline( 1, 1, @q ),
  pline( 1,-1, @q ), # flip and mirror
  pline(-1,-1, @q ), # for the other
  pline(-1, 1, @q ), # three quadrants
  '</svg>';

sub pline ($sx, $sy, @q) {
  (@q[2*$_] *= $sx, @q[1+2*$_] *= $sy) for 0 .. $#q/2;
  qq|<polyline points="@q"
  style="fill:none;stroke:black;stroke-width:3"
  transform="translate($a, $b)" />\n|
}

Superellipse (offsite image)

Phix

Library: Phix/pGUI
Library: Phix/online

You can run this online here.

--
-- demo\rosetta\Superellipse.exw
-- =============================
--
with javascript_semantics
atom n = 2.5        -- '+' and '-' increase/decrease in steps of 0.1

include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*ih*/)

    integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE"),
             hw = floor(w/2), hh = floor(h/2),
             a = max(10,hw-100),    -- (initially 200, from 602x   )
             b = max(10,hh-50)      -- (initially 200, from    x502)
    sequence y = b&repeat(0,a)
    for x=1 to a-1 do
        y[x+1] = floor(exp(log(1-power(x/a,n))/n)*b)
    end for

    cdCanvasActivate(cddbuffer)
    cdCanvasClear(cddbuffer)
    cdCanvasBegin(cddbuffer, CD_OPEN_LINES) 
    cdCanvasVertex(cddbuffer, hw, hh-b) -- starting point
    for x=1 to a-1     do cdCanvasVertex(cddbuffer, hw+x, hh-y[x+1]) end for
    for x=a to 0 by -1 do cdCanvasVertex(cddbuffer, hw+x, hh+y[x+1]) end for
    for x=0 to a       do cdCanvasVertex(cddbuffer, hw-x, hh+y[x+1]) end for
    for x=a to 0 by -1 do cdCanvasVertex(cddbuffer, hw-x, hh-y[x+1]) end for
    cdCanvasEnd(cddbuffer)
    cdCanvasFlush(cddbuffer)

    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_BLACK)
    return IUP_DEFAULT
end function

function key_cb(Ihandle /*ih*/, atom c)
    if c=K_ESC then return IUP_CLOSE end if
    if c='+' then
        n = min(130,n+0.1) -- (otherwise [>130] power overflow)
        IupUpdate(canvas)
    elsif c='-' then
        n = max(0.1,n-0.1) -- (otherwise [=0.0] divide by zero)
        IupUpdate(canvas)
    end if
    return IUP_CONTINUE
end function

procedure main()
    IupOpen()
    
    canvas = IupCanvas("RASTERSIZE=602x502")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})
    dlg = IupDialog(canvas,"TITLE=Superellipse")
    IupSetCallback(dlg, "KEY_CB", Icallback("key_cb"))
    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

Processing

Translation of: C
//Aamrun, 29th June 2022

float a = 200, b = 200, n = 2.5;
float i, incr = 0.001;
int xMul,yMul;

size(500,500);

stroke(#ff0000);

for(i=0;i<2*PI;i+=incr){
  if(PI/2<i && i<3*PI/2)
    xMul = -1;
  else
    xMul = 1;
  if(PI<i && i<2*PI)
    yMul = -1;
  else
    yMul = 1;
    
  ellipse(width/2 + xMul * a*pow(abs(cos(i)),2/n),height/2 + yMul * b*pow(abs(sin(i)),2/n),1,1);
}

Python

# 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()

QB64

_Title "Super Ellipse"

Dim As Integer sw, sh
Dim As Single i
sw = 480: sh = 480

Screen _NewImage(sw, sh, 8)
Cls , 15

'Show different possible Super Ellipse shapes
Color 10
For i = 0.2 To 5.0 Step .1
    Call SuperEllipse(sw \ 2, sh \ 2, 200, 200, i, 80)
Next

'Show task specified Super Ellipse
Color 0
Call SuperEllipse(sw \ 2, sh \ 2, 200, 200, 2.5, 200)
Sleep
System

Sub SuperEllipse (cX As Integer, cY As Integer, wide As Integer, high As Integer, pow As Double, segs As Integer)
    Dim As Double power, inc, theta, cosTheta, sinTheta
    Dim As Integer x1, y1
    'Limit 'pow' to acceptable values
    If pow < .1 Then pow = .1
    If pow > 150 Then pow = 150
    power = 2 / pow - 1
    inc = 360.0 / segs * 0.0174532925199432957692369
    PSet (wide + cX, cY)
    For theta = inc To 6.28318530717958647692528 + inc Step inc
        cosTheta = Cos(theta): sinTheta = Sin(theta)
        x1 = wide * cosTheta * Abs(cosTheta) ^ power + cX
        y1 = high * sinTheta * Abs(sinTheta) ^ power + cY
        Line -(x1, y1)
    Next
End Sub


QBasic

SCREEN 12
CLS
a = 200
b = 200
n = 2.5
na = 2 / n
t = .01

LINE -(520, 245), 0, BF
FOR i = 0 TO 314
    xp = a * SGN(COS(t)) * ABS((COS(t))) ^ na + 320
    yp = b * SGN(SIN(t)) * ABS((SIN(t))) ^ na + 240
    t = t + .02
    LINE -(xp, yp), 1, BF
NEXT i


Racket

#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))

Raku

(formerly Perl 6)

my (\a, \b, \n) = 200, 200, 2.5;

# y in terms of x
sub y ($x) { floor b × (1 - ($x/a).abs ** n ) ** (1/n) }

# find point pairs for one quadrant
my @q = flat map -> \x { x, y(x) }, ^(a+1);

my $out = open('superellipse.svg', :w);
$out.print: [~] qq|<svg height="{b×2}" width="{a×2}" xmlns="http://www.w3.org/2000/svg">\n|,
  pline( @q ),
  pline( @q «×» < 1 -1> ), # flip and mirror
  pline( @q «×» <-1 -1> ), # for the other
  pline( @q «×» <-1  1> ), # three quadrants
  '</svg>';

sub pline (@q) {
  qq|<polyline points="{@q}"
  style="fill:none;stroke:black;stroke-width:3"
  transform="translate({a}, {b})" />\n|
}

Superellipse (offsite image)

REXX

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

Scala

Java Swing Interoperability

import java.awt._
import java.awt.geom.Path2D
import java.util

import javax.swing._
import javax.swing.event.{ChangeEvent, ChangeListener}

object SuperEllipse extends App {

    SwingUtilities.invokeLater(() => {
      new JFrame("Super Ellipse") {

        class SuperEllipse extends JPanel with ChangeListener {
          setPreferredSize(new Dimension(650, 650))
          setBackground(Color.white)
          setFont(new Font("Serif", Font.PLAIN, 18))
          private var exp = 2.5

          override def paintComponent(gg: Graphics): Unit = {
            val g = gg.asInstanceOf[Graphics2D]

           def drawGrid(g: Graphics2D): Unit = {
              g.setStroke(new BasicStroke(2))
              g.setColor(new Color(0xEEEEEE))
              val w = getWidth
              val h = getHeight
              val spacing = 25

              for (i <- 0 until (w / spacing)) {
                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)
            }

            def drawLegend(g: Graphics2D): Unit = {
              g.setColor(Color.black)
              g.setFont(getFont)
              g.drawString("n = " + String.valueOf(exp), getWidth - 150, 45)
              g.drawString("a = b = 200", getWidth - 150, 75)
            }

            def drawEllipse(g: Graphics2D): Unit = {
              val a = 200
              // calculate first quadrant
              val points = Array.tabulate(a + 1)(n =>
                math.pow(math.pow(a, exp) - math.pow(n, exp), 1 / exp))
              val p = new Path2D.Double

              p.moveTo(a, 0)
              for (n <- a to 0 by -1) p.lineTo(n, -points(n))
              // mirror to others
              for (x <- points.indices) p.lineTo(x, points(x))
              for (y <- a to 0 by -1) p.lineTo(-y, points(y))
              for (z <- points.indices) p.lineTo(-z, -points(z))
              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)
            }

            super.paintComponent(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 def stateChanged(e: ChangeEvent): Unit = {
            val source = e.getSource.asInstanceOf[JSlider]
            exp = source.getValue / 2.0
            repaint()
          }
        }

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
        setResizable(false)
        val panel = new SuperEllipse
        add(panel, BorderLayout.CENTER)
        val exponent = new JSlider(SwingConstants.HORIZONTAL, 1, 9, 5)
        exponent.addChangeListener(panel)
        exponent.setBackground(Color.white)
        exponent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20))
        exponent.setMajorTickSpacing(1)
        exponent.setPaintLabels(true)
        val labelTable = new util.Hashtable[Integer, JLabel]
        for (i <- 1 until 10) labelTable.put(i, new JLabel(String.valueOf(i * 0.5)))

        exponent.setLabelTable(labelTable)
        add(exponent, BorderLayout.SOUTH)
        pack()
        setLocationRelativeTo(null)
        setVisible(true)
      }

    })

}

Sidef

Translation of: Raku
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>'

Stata

sca a=200
sca b=200
sca n=2.5
twoway function y=b*(1-(abs(x/a))^n)^(1/n), range(-200 200) || function y=-b*(1-(abs(x/a))^n)^(1/n), range(-200 200)

Wren

Library: DOME

Uses Go's drawing code but produces a more complex image.

import "graphics" for Canvas, Color, Point

class Game {
    static init() {
        Canvas.resize(500, 500)
        // draw 200 concentric superellipses with gradually decreasing 'n'.
        for (a in 200..1) {
            superEllipse(a/80, a)
        }
    }

    static update() {}

    static draw(alpha) {}

    static superEllipse(n, a) {
        var hw = Canvas.width / 2
        var hh = Canvas.height / 2

        // calculate y for each x
        var y = List.filled(a + 1, 0)
        for (x in 0..a) {
            var aa = a.pow(n)
            var xx = x.pow(n)
            y[x] = (aa-xx).pow(1/n)
        }

        // draw quadrants
        var prev = Point.new(hw + a, hh - y[a])
        for (x in a-1..0) {
            var curr = Point.new(hw + x, hh - y[x])
            Canvas.line(prev.x, prev.y, curr.x, curr.y, Color.white)
            prev = Point.new(curr.x, curr.y)
        }

        prev = Point.new(hw, hh + y[0])
        for (x in 1..a) {
            var curr = Point.new(hw + x, hh + y[x])
            Canvas.line(prev.x, prev.y, curr.x, curr.y, Color.white)
            prev = Point.new(curr.x, curr.y)
        }

        prev = Point.new(hw - a, hh + y[a])
        for (x in a-1..0) {
            var curr = Point.new(hw - x, hh + y[x])
            Canvas.line(prev.x, prev.y, curr.x, curr.y, Color.white)
            prev = Point.new(curr.x, curr.y)
        }

        prev = Point.new(hw, hh - y[0])
        for (x in 1..a) {
            var curr = Point.new(hw - x, hh - y[x])
            Canvas.line(prev.x, prev.y, curr.x, curr.y, Color.white)
            prev = Point.new(curr.x, curr.y)
        }
    }
}

XPL0

def  X0=640/2, Y0=480/2, Scale=25.0, N=2.5;
real X, Y;  int IX, IY;

proc OctPoint; [
Point(X0+IX, Y0-IY, $F);
Point(X0-IX, Y0-IY, $F);
Point(X0+IX, Y0+IY, $F);
Point(X0-IX, Y0+IY, $F);
Point(X0+IY, Y0-IX, $F);
Point(X0-IY, Y0-IX, $F);
Point(X0+IY, Y0+IX, $F);
Point(X0-IY, Y0+IX, $F);
];

[SetVid($101);  \VESA graphics 640x480x8
IX:= 0;
repeat  X:= float(IX)/Scale;
        Y:= Pow(200.0 - Pow(X,N), 1.0/N);
        IY:= fix(Y*Scale);
        OctPoint;
        IX:= IX+1;
until   IX >= IY;
]
Output:
http://www.xpl0.org/rcell.gif

Yabasic

open window 700, 600
backcolor 0,0,0
clear window 

a=200
b=200
n=2.5
na=2/n
t=.01
color 0,0,255
for i = 0 to 314
    xp=a*sig(cos(t))*abs((cos(t)))^na+350
    yp=b*sig(sin(t))*abs((sin(t)))^na+275
    t=t+.02
    line to xp, yp
next i

zkl

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

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");
Cookies help us deliver our services. By using our services, you agree to our use of cookies.