Open In App

Implementing a Superellipse

Improve
Improve
Like Article
Like
Save
Share
Report

What is a superellipse
A superellipse, also known as a Lamé curve after Gabriel Lamé, is a closed curve resembling the ellipse, retaining the geometric features of semi-major axis and semi-minor axis, and symmetry about them, but a different overall shape.
In the Cartesian coordinate system, the set of all points (x, y) on the curve satisfy the equation


where n, a and b are positive numbers, and the vertical bars | | around a number indicate the absolute value of the number.

a = 1 and b = 0.75

There are many number of specific cases of superellipse like given in the image down below:

These can be achieved by varying the value of n in the equation. So now we try to implement this in python and to do that we are require some libraries.

Modules Required:

  • matplotlib: To plot the curve of the equation. Its an 3rd party library in python and if you want to install it click here.
  • math : Its an built in library of python which have almost all the mathematical tools.




# Python program to implement 
# Superellipse
  
# importing the required libraries
import matplotlib.pyplot as plt
from math import sin, cos, pi
   
def sgn(x):
    return ((x>0)-(x<0))*1
  
# parameter for marking the shape  
a, b, n = 200, 200, 2.5
na = 2 / n
# defining the accuracy
step = 100 
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()


Output:

when n = 2.5

Now let’s see what happens when we changes the value of n to 0.5




# Python program to implement 
# Superellipse
# importing the required libraries
import matplotlib.pyplot as plt
from math import sin, cos, pi
   
def sgn(x):
    return ((x>0)-(x<0))*1
  
# parameter for marking the shape  
a, b, n = 200, 200, 0.5
na = 2 / n
# defining the accuracy
step = 100 
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()


Output:

Source Code of the program in Java.




// Java program to implement
// Superellipse
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);
        });
    }
}


Output:

Reference Links:

1. Wikipedia – Superellipse
2. WolframMathWorld – Superellipse



Last Updated : 29 Sep, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads