Superellipse: Difference between revisions
(→{{header|zkl}}: added image) |
Thundergnat (talk | contribs) (→{{header|Perl 6}}: Added implementation) |
||
Line 248: | Line 248: | ||
::requires rxMath library</lang> |
::requires rxMath library</lang> |
||
=={{header|Perl 6}}== |
|||
Generate an svg image to STDOUT. Redirect into a file to capture it. |
|||
<lang perl6>my \a = 200; |
|||
my \b = 200; |
|||
my \n = 2.5; |
|||
# y in terms of x |
|||
sub y ($x) { sprintf "%d", b * (1 - ($x / a).abs ** n ) ** (1/n) } |
|||
# find point pairs for one quadrant |
|||
my @q = flat map { $_,.&y }, (0, 5 ... 200); |
|||
# Generate an SVG image |
|||
print [~] qq|<svg height="{b*2}" width="{a*2}">\n|, |
|||
pline( flat @q ), |
|||
pline( flat @q «*» ( 1,-1) ), # flip and mirror |
|||
pline( flat @q «*» (-1,-1) ), # for the other |
|||
pline( flat @q «*» (-1, 1) ), # three quadrants |
|||
'</svg>' |
|||
; |
|||
sub pline (@q) { |
|||
qq|<polyline points="{ join ' ', @q }" |
|||
style="fill:none;stroke:black;stroke-width:3" |
|||
transform="translate({a}, {b})" />\n| |
|||
}</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
Revision as of 23:54, 30 October 2015
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
<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>
Perl 6
Generate an svg image to STDOUT. Redirect into a file to capture it. <lang perl6>my \a = 200; my \b = 200; my \n = 2.5;
- y in terms of x
sub y ($x) { sprintf "%d", b * (1 - ($x / a).abs ** n ) ** (1/n) }
- find point pairs for one quadrant
my @q = flat map { $_,.&y }, (0, 5 ... 200);
- Generate an SVG image
print [~] qq|<svg height="{b*2}" width="{a*2}">\n|,
pline( flat @q ), pline( flat @q «*» ( 1,-1) ), # flip and mirror pline( flat @q «*» (-1,-1) ), # for the other pline( flat @q «*» (-1, 1) ), # three quadrants '</svg>'
sub pline (@q) {
qq|<polyline points="{ join ' ', @q }" style="fill:none;stroke:black;stroke-width:3" transform="translate({a}, {b})" />\n|
}</lang>
Racket
<lang 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))</lang>
REXX
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>
- Output:
http://www.zenkinetic.com/Images/RosettaCode/superEllipse.jpg