mehere Affine Transformationen auf JPanel anwenden

siedler

Mitglied
Hallo erstmal.

Folgendes Problem:
Ich habe ein beliebiges Anfangsbild(z.B. ein Viereck). Auf dieses Bild soll dan eine affine Transformation
angewendet werden und aufs JPanel gemalt werden. dadurch entsteht ein neues Bild(das alte Bild bleibt noch erhalten).

Nun soll auf dieses Bild erneut eine affine Transformation angewesendet werden etc.
Mein Problem ist nun, dass ich es nicht hinbekomme, dass die neue affine Transformation auf das gesamte neue Bild angewendet wird, sondern nur auf das Ursprungsobject.

Habe schon diverese Sachen gegoogled und hier um Forum mich umgesehen, aber bin nicht wirklich weitergekommen. Dabei hab ich schon versucht, das JPanel als Image oder Shape zu bekommen.
Würde mich über Hilfe freuen.
Gruß, Siedler.

Hier noch der bisherige Quellcode:

Ausgelöst werden soll das ganze durch diesen ActionListener:
Java:
class ActionListenerAff2 implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            AffineTransform add = new AffineTransform(0.5, 1, 1.2, 0.4, 80, 20);
            paintarea.setAffineTransform(add);
            paintarea.repaint();
        }
    }


Java:
public class PaintArea extends JPanel {

    private AffineTransform trans;
    private Rectangle rect;

    public PaintArea() {
        this.trans = new AffineTransform(1, 0, 0, 1, 0, 0);
        this.rect = new Rectangle(1, 1, 10, 10);
        this.setSize(300, 300);
    }

    public void setAffineTransform(AffineTransform trans) {
        this.trans = trans;
    }

    public void setRectangle(Rectangle rect) {
        this.rect = rect;
    }
    

    public Rectangle getRectangle() {
        return this.rect;
    }

    public AffineTransform getAffineTransform() {
        return this.trans;
    }
    

    @Override
    public void paint(Graphics g) {
     
        Graphics2D g2d = (Graphics2D) g;
 
        g2d.transform(trans);
        g2d.setColor(Color.red);
        g2d.draw(rect);

    }
}
 

Marco13

Top Contributor
Nochmal: Du willst z.B. nacheinander 3 AT's anwenden, die jeweils um 5 Grad drehen, und dann sollen 4 Bilder zu sehen sein: Das Original, ein um 5 Grad gedrehtes, eins mit 10 und eins mit 15...?
 

siedler

Mitglied
Nicht ganz.
Man hat zb ein Viereck, dieses wird gedreht, das gedrehte Viereck wird dann auf das Panel gemalt.
Die nächste Drehung soll dann auf die beiden Vierecke angewendet werden und immer so weiter.
Das ganze nennt sich Iterativ Function System. Das hätte ich wohl gleich im Eingangspost schreiben sollen.
 

Marco13

Top Contributor
Ah OK, sowas (ganz grob) Lindenmayeriges... da gibt's sicher tausende mögliche Ansätze, und man kann das ganze sehr ausgefeilt machen... Ich vermute aber, dass das schwierig oder sehr aufwändig wäre, wenn man es auf Basis der gezeichneten Daten berechnen wollte. Vielleicht geht es auch gar nicht. Relativ einfach, als erster, pragmatischer Ansatz wäre es, sich die Shapes zu speichern, und in jedem Schritt alle Shapes zu transformieren und für den nächsten Durchgang in einer Liste zu speichern...

*rumspiel*
Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


class IFPanel extends JPanel
{
    private List<Shape> shapes = new ArrayList<Shape>();

    public IFPanel(Shape shape)
    {
        shapes.add(shape);
    }

    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setColor(Color.BLACK);
        for (Shape s : shapes)
        {
            g.draw(s);
        }
        g.setColor(Color.BLUE);
        g.drawString("Drawing "+shapes.size()+" shapes", 10,20);
    }

    public void apply(AffineTransform at)
    {
        List<Shape> newShapes = new ArrayList<Shape>();
        for (Shape s : shapes)
        {
            Shape newShape = at.createTransformedShape(s);
            newShapes.add(newShape);
        }
        shapes.addAll(newShapes);
        repaint();
    }

}

public class IFTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                Shape shape = new Rectangle(300,200,50,50);
                final IFPanel panel = new IFPanel(shape);
                f.getContentPane().setLayout(new BorderLayout());
                f.getContentPane().add(panel, BorderLayout.CENTER);

                JButton b = new JButton("And another one");
                b.addActionListener(new ActionListener()
                {
                    int counter = 0;
                    @Override
                    public void actionPerformed(ActionEvent e)
                    {
                        AffineTransform at =
                            AffineTransform.getRotateInstance(
                                Math.toRadians(15*counter), 325, 225);
                        at.translate(25*counter, 5);
                        panel.apply(at);
                        counter++;
                    }
                });
                f.getContentPane().add(b, BorderLayout.SOUTH);
                f.setSize(600,600);
                f.setVisible(true);
            }
        });
    }
}

Weiß ja nicht wie nahe das dem kommt, was du meinst...
 

Marco13

Top Contributor
Ja, sicher, die Anzahl der Shapes wächst exponentiell, also ist das "eigentlich" komplett unsinnig. Es war ja nicht klar, was erreicht werden soll, und wie so oft: Das ist die einfachste Lösung, aber sicher nicht die beste ;)

Die Alternative wäre natürlich, sich nur die "Regeln" zu speichern, also nur die AffineTransforms, und dann während des Zeichnens ein einzelnes Shape immer wieder richtig zu transformieren. Auch wieder nur schnell hingehackt, mit dem PowerSetIterable aus http://www.java-forum.org/codeschnipsel-u-projekte/81973-combinatorics.html#post646341 :

Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.math.BigInteger;
import java.util.*;


class IFPanel extends JPanel
{
    private Shape shape;
    private List<AffineTransform> ats = new ArrayList<AffineTransform>();

    public IFPanel(Shape shape)
    {
        this.shape = shape;
        //ats.add(new AffineTransform());
    }

    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setColor(Color.BLACK);


        AffineTransform aa[] = ats.toArray(new AffineTransform[ats.size()]);
        PowerSetIterable<AffineTransform> psi =
            new PowerSetIterable<AffineTransform>(aa);
        int count = 0;
        for (AffineTransform as[] : psi)
        {
            AffineTransform a = new AffineTransform();
            for (int i=0; i<as.length; i++)
            {
                a.concatenate(as[i]);
            }
            Shape newShape = a.createTransformedShape(shape);
            g.draw(newShape);
            count++;
        }
        g.setColor(Color.BLUE);
        g.drawString("Drawing "+count+" shapes", 10,20);

    }

    public void apply(AffineTransform at)
    {
        ats.add(at);
        repaint();
    }

}

public class IFTest2
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                Shape shape = new Rectangle(300,200,50,50);
                final IFPanel panel = new IFPanel(shape);
                f.getContentPane().setLayout(new BorderLayout());
                f.getContentPane().add(panel, BorderLayout.CENTER);

                JButton b = new JButton("And another one");
                b.addActionListener(new ActionListener()
                {
                    int counter = 0;
                    @Override
                    public void actionPerformed(ActionEvent e)
                    {
                        AffineTransform at =
                            AffineTransform.getRotateInstance(
                                Math.toRadians(15*counter), 325, 225);
                        at.translate(25*counter, 5);
                        panel.apply(at);
                        counter++;
                    }
                });
                f.getContentPane().add(b, BorderLayout.SOUTH);
                f.setSize(600,600);
                f.setVisible(true);
            }
        });
    }
}












class Combinatorics
{
    public static BigInteger factorial(int n)
    {
        BigInteger f = BigInteger.ONE;
        for (int i = 2; i <= n; i++)
        {
            f = f.multiply(BigInteger.valueOf(i));
        }
        return f;
    }
    public static int countBits(int n)
    {
        int m = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);
        return ((m + (m >> 3)) & 030707070707) % 63;
    }

}
class PowerSetIterable<T> implements Iterable<T[]>
{
    private T input[];
    private int numElements;

    public PowerSetIterable(T... input)
    {
        this.input = input.clone();
        numElements = 1 << input.length;
    }

    public Iterator<T[]> iterator()
    {
        return new Iterator<T[]>()
        {
            int current = 0;

            public boolean hasNext()
            {
                return current < numElements;
            }

            public T[] next()
            {
                int size = Combinatorics.countBits(current);

                @SuppressWarnings("unchecked")
                T element[] = (T[]) java.lang.reflect.Array.newInstance(
                    input.getClass().getComponentType(), size);

                // Insert into the current power set element
                // all elements of the input set that are at
                // indices where the current counter value
                // has a '1' in its binary representation
                int n = 0;
                for (int i = 0; i < input.length; i++)
                {
                    long b = 1 << i;
                    if ((current & b) != 0)
                    {
                        element[n++] = input[i];
                    }
                }
                current++;
                return element;
            }

            public void remove()
            {
                throw new UnsupportedOperationException(
                    "May not remove elements from a power set");
            }
        };

    }
}
 

Ähnliche Java Themen


Oben