Superellipse

From Rosetta Code
Revision as of 17:35, 19 October 2015 by rosettacode>Craigd (→‎{{header|zkl}}: changed background color)
Superellipse is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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

where n, a and b are positive numbers.


The task: draw a superellipse with n = 2.5, and a = b = 200

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>

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>

rosettacode does not currently support image uploads, so you'll just have to imagine what it looks like (or run the code yourself).

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>

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>

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>

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>

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>