Superellipse

From Rosetta Code
Revision as of 17:59, 30 July 2022 by SqrtNegInf (talk | contribs) (→‎{{header|Raku}}: redundant 'flat's)
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!

<lang 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</lang>

Output:

Screenshot from Atari 8-bit computer

Ada

Library: SDLAda

Brute force calculation.

<lang Ada>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;</lang>

AutoHotkey

Requires Gdip Library <lang AutoHotkey>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

----------------------------------------------------------------</lang>

C

Interactive program to draw a SuperEllipse. Requires the WinBGIm library. <lang C>

  1. include<graphics.h>
  2. include<stdio.h>
  3. include<math.h>
  1. 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(); }</lang>

EchoLisp

Link to the super-ellipse image. <lang scheme> (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))

</lang>

FreeBASIC

<lang 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</lang>

Go

Library: Go Graphics

<lang go>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")

}</lang>

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. <lang haskell>{-# 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")</lang>

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:

<lang J>selips=: 4 :0

 'n a b'=. y
 1 >: ((n^~a%~]) +&|/ n^~b%~]) i:x

)

  require'viewmat'
  viewmat 300 selips 2.5 200 200</lang>

Java

Works with: Java version 8

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

}</lang>

JavaScript

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

} </lang>

Julia

<lang 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))</lang>

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. <lang scala>// 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
       }
   }

}</lang>

Liberty BASIC

Reworked the Julia version to work and added a loop with a spread on n values. <lang lb> [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 </lang>

Lua

Scale of a and b were reduced to facilitate an ASCII solution: <lang lua>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()</lang>

Output:
................................................................................................................................................................
..........................................................[][][][][][][][][][][][][][][][][][][][][]............................................................
............................................[][][][][][][]..........................................[][][][][][][]..............................................
......................................[][][][]..................................................................[][][][]........................................
................................[][][][]..............................................................................[][][][]..................................
............................[][][]..........................................................................................[][][]..............................
........................[][][]..................................................................................................[][][]..........................
......................[][]..........................................................................................................[][]........................
..................[][]..................................................................................................................[][]....................
................[][]......................................................................................................................[][]..................
..............[][]..........................................................................................................................[][]................
............[][]..............................................................................................................................[][]..............
............[]..................................................................................................................................[]..............
..........[]......................................................................................................................................[]............
........[][]......................................................................................................................................[][]..........
........[]..........................................................................................................................................[]..........
......[]..............................................................................................................................................[]........
......[]..............................................................................................................................................[]........
....[][]..............................................................................................................................................[][]......
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
..[][]..................................................................................................................................................[][]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[]......................................................................................................................................................[]....
..[][]..................................................................................................................................................[][]....
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
....[]..................................................................................................................................................[]......
....[][]..............................................................................................................................................[][]......
......[]..............................................................................................................................................[]........
......[]..............................................................................................................................................[]........
........[]..........................................................................................................................................[]..........
........[][]......................................................................................................................................[][]..........
..........[]......................................................................................................................................[]............
............[]..................................................................................................................................[]..............
............[][]..............................................................................................................................[][]..............
..............[][]..........................................................................................................................[][]................
................[][]......................................................................................................................[][]..................
..................[][]..................................................................................................................[][]....................
......................[][]..........................................................................................................[][]........................
........................[][][]..................................................................................................[][][]..........................
............................[][][]..........................................................................................[][][]..............................
................................[][][][]..............................................................................[][][][]..................................
......................................[][][][]..................................................................[][][][]........................................
............................................[][][][][][][]..........................................[][][][][][][]..............................................
..........................................................[][][][][][][][][][][][][][][][][][][][][]............................................................
................................................................................................................................................................
................................................................................................................................................................

Maple

The built-in command ImplicitPlot accepts an equation in 2 variables: <lang maple>plots:-implicitplot(abs((1/200)*x^2.5)+abs((1/200)*y^2.5) = 1, x = -10 .. 10, y = -10 .. 10);</lang>

Mathematica/Wolfram Language

The built-in function ContourPlot accepts and equation in 2 variables and creates the desired plot <lang Mathematica>ContourPlot[Abs[x/200]^2.5 + Abs[y/200]^2.5 == 1, {x, -200, 200}, {y, -200, 200}]</lang>

Nim

Library: imageman

<lang Nim>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)</lang>

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

<lang oorexx>/* 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</lang>

Perl

Translation of: Raku

<lang perl>my $a = 200; my $b = 200; my $n = 2.5;

  1. y in terms of x

sub y_from_x {

   my($x) = @_;
   int $b * abs(1 - ($x / $a) ** $n ) ** (1/$n)

}

  1. find point pairs for one quadrant

push @q, $_, y_from_x($_) for 0..200;

  1. Generate an SVG image

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 {

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

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

<lang java> //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);

}

</lang>

Python

<lang python>

  1. Superellipse drawing in Python 2.7.9
  2. 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() </lang>

QB64

<lang 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</lang>


QBasic

<lang 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</lang>


Racket

<lang Racket>#lang racket (require plot)

  1. (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))</lang>

Raku

(formerly Perl 6) <lang perl6>my (\a, \b, \n) = 200, 200, 2.5;

  1. y in terms of x

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

  1. 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|

}</lang> Superellipse (offsite image)

REXX

Translation of: ooRexx

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

<lang rexx>/* 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</lang>

Scala

Java Swing Interoperability

<lang Scala>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)
     }
   })

}</lang>

Sidef

Translation of: Raku

<lang ruby>const (

   a = 200,
   b = 200,
   n = 2.5,

)

  1. 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

}

  1. 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
  1. 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>'</lang>

Stata

<lang 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)</lang>

Wren

Library: DOME

Uses Go's drawing code but produces a more complex image. <lang ecmascript>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)
       }
   }

}</lang>

XPL0

<lang 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; ]</lang>

Output:
http://www.xpl0.org/rcell.gif

Yabasic

<lang 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</lang>

zkl

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

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

}</lang> <lang zkl>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");</lang>