Articles Projects Tips Downloads Contacts About
 

FlatteningPathIterator and moving object along Shape path.

To move object along path defined by a custom Shape we can use FlatteningPathIterator based approach. From javadoc "The FlatteningPathIterator class returns a flattened view of another PathIterator object. Other Shape classes can use this class to provide flattening behavior for their paths without having to perform the interpolation calculations themselves."

We can create a custom Shape combining any Shapes in Area class and let object move along the path defined by the Shapes. The demo screenshot is following: Point moves along the combined double ellipses.

The source code of the example with moving point along custom Shape.

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.*;
import java.util.ArrayList;
 
public class PathIteratorTest {
    public static void main(String[] args) {
        JFrame frame = new JFrame("FlatteningPathIterator test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Shape s=new Ellipse2D.Float(10,10,200,100);
        Area a=new Area(new Ellipse2D.Float(150,20,100,200));
        a.add(new Area(s));
        PaintPanel app = new PaintPanel(a);
        JScrollPane scroll = new JScrollPane(app);
        frame.getContentPane().add(scroll);
 
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    static class PaintPanel extends JPanel {
        FlatteningPathIterator iter;
        Shape shape;
        ArrayList<Point> points;
        int index=0;
        public PaintPanel(Shape s) {
            this.shape=s;
            iter=new FlatteningPathIterator(s.getPathIterator(new AffineTransform()), 1);
            points=new ArrayList<Point>();
            float[] coords=new float[6];
            while (!iter.isDone()) {
                iter.currentSegment(coords);
                int x=(int)coords[0];
                int y=(int)coords[1];
                points.add(new Point(x,y));
                iter.next();
            }

            Timer timer=new Timer(50, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    index++;
                    if (index>=points.size()) {
                        index=0;
                    }
                    repaint();
                }
            });
            timer.start();
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.white);
            ((Graphics2D)g).draw(shape);
            g.setColor(Color.blue);
            Point p=points.get(index);
            g.fillOval(p.x, p.y, 5,5);
        }
    }
}