Search code examples
java2dgraphics2djava-2d

How to draw a butterfly curve multiple times with different scale and translation using a single/simple for loop?


This question is related to my older question.

What I am trying to do is to draw that same butterfly curve up to 30 times. Each time with a random scale/translation/color.

I tried this code:

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    for (int j=0;j<30;j++) {

        double tr = Math.random() * 300;
        g2.translate(tr,tr);
        double sc = Math.random() * 50 + 10;
        g2.scale(sc,sc);
        g2.setStroke(new BasicStroke(0.01f ));
        g2.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255),(int) (Math.random()*255)));
        double x1,y1;
        double x0 = 0;
        int nPoints = 1500;
        double y0 = Math.E-2;

        for(int i=0;i<nPoints;i++) {
            double t= 12*i*Math.PI/nPoints;
            x1=(Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));
            y1 = (Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));
            g2.draw(new Line2D.Double(x0,y0,x1,y1));
            x0=x1;
            y0=y1;
        }
    }
}

The problem with this code is, at the end, it will only show/draw one curve. It won't show more than one. Since painting in Swing is destructive, I suspected that the problem I am facing have something to do with these lines being inside the for loop:

double tr = Math.random() * 300;
g2.translate(tr,tr);
double sc = Math.random() * 50 + 10;
g2.scale(sc,sc);

For a quick test, I tried this code:

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D)g;
    double tr = Math.random() * 300;
    g2.translate(tr,tr);
    double sc = Math.random() * 50 + 10;
    g2.scale(sc,sc);

    for (int j=0;j<30;j++) {
        g2.setStroke(new BasicStroke(0.01f ));
        g2.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255),(int) (Math.random()*255)));
        double x1,y1;
        double x0 = 0;
        int nPoints = 1500;
        double y0 = Math.E-2;
        g2.drawLine(5,j,100,j);
    }
}

This drew 30 lines, and when I added the scale and translate methods inside the loop, it only drew 1 line. So I guess that I am right.

Can a simple for loop do the job or should I be going with a bit of more complex algorithm to draw that butterfly curve multiple times while changing scale and translation?


Solution

  • I found a solution using AffineTransform to scale and translate.

    Basically, the solution was to get rid of g2.scale and g2.translate, and use g2.setTransform(tx);. tx being an AffineTransform which scales and translates.

    Here's the code that did it for me:

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
    
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
        for (int j=0;j<30;j++) {
            double sc = Math.random() * 30 + 10;
            AffineTransform tx = new AffineTransform();
            tx.scale(sc, sc);
            tx.translate(Math.random() * 50, Math.random() * 50);
            g2.setTransform(tx);
            g2.setStroke(new BasicStroke(0.01f ));
            g2.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255),(int) (Math.random()*255)));
            double x1,y1;
            double x0 = 0;
            int nPoints = 1500;
            double y0 = Math.E-2;
    
            for(int i=0;i<nPoints;i++) {
                double t= 12*i*Math.PI/nPoints;
                x1=(Math.sin(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));
                y1 = (Math.cos(t)*(Math.pow(Math.E,Math.cos(t))-2*Math.cos(4*t)-Math.pow(Math.sin(t/12),5)));
                g2.draw(new Line2D.Double(x0,y0,x1,y1));
                x0=x1;
                y0=y1;
            }
        }
    }
    

    Butterfly Images