import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import static java.awt.geom.PathIterator.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Test {
static class Drawing extends JComponent {
private Shape rect;
private List<Point2D> points;
private int current;
public Drawing(Shape rect, List<Point2D> points) {
this.rect = rect;
this.points = points;
}
public void next() {
current = (current + 1) % points.size();
repaint();
}
public void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
g2.draw(rect);
g.setColor(Color.RED);
Point2D point = points.get(current);
g2.fill(new Arc2D.Double(point.getX() - 5, point.getY() - 5,
10d, 10d, 0d, 360d, Arc2D.CHORD));
}
}
private Timer timer;
public void show(Shape rect, List<Point2D> points) {
Drawing drawing = new Drawing(rect, points);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (timer != null) {
timer.stop();
}
}
});
frame.add(drawing);
frame.setSize(600, 400);
frame.setVisible(true);
timer = new Timer(250, e->drawing.next());
timer.start();
}
private static List<Point2D> points(PathIterator it) {
List<Point2D> points = new ArrayList<>();
float[] last = new float[]{0f, 0f};
while (!it.isDone()) {
float[] coords = new float[6];
int type = it.currentSegment(coords);
int lastPoint = 0;
switch (type) {
case SEG_MOVETO:
points.add(new Point2D.Float(coords[0], coords[1]));
break;
case SEG_LINETO:
points.addAll(pointsOnLine(last[0], last[1], coords[0], coords[1]));
break;
case SEG_CUBICTO:
points.addAll(pointsOnCubicCurve(last[0], last[1],
coords[0], coords[1], coords[2], coords[3],
coords[4], coords[5]));
lastPoint = 2;
break;
}
last[0] = coords[2*lastPoint];
last[1] = coords[2*lastPoint+1];
it.next();
}
return points;
}
private static List<Point2D> pointsOnLine(float... points) {
List<Point2D> result = new ArrayList<>();
result.add(new Point2D.Float(points[0], points[1]));
for (float t = 0f; t < 1f; t += .2f) {
float r = 1 - t;
result.add(new Point2D.Float(
r*points[0] + t*points[2],
r*points[1] + t*points[3]));
}
return result;
}
private static List<Point2D> pointsOnCubicCurve(float... coords) {
List<Point2D> result = new ArrayList<>();
for (float t = 0f; t < 1f; t += .2f) {
result.add(pointOnCubicCurve(t, coords));
}
result.add(pointOnCubicCurve(1f, coords));
return result;
}
private static Point2D pointOnCubicCurve(float percent, float... coords) {
return new Point2D.Float(
coordinateOnCubicCurve(percent, coords[0], coords[2], coords[4], coords[6]),
coordinateOnCubicCurve(percent, coords[1], coords[3], coords[5], coords[7]));
}
private static float coordinateOnCubicCurve(float t, float... b) {
float r = 1 - t;
return r*(r*(r*b[0] + t*b[1]) + t*(r*b[1] + t*b[2])) +
t*(r*(r*b[1] + t*b[2]) + t*(r*b[2] + t*b[3]));
}
public static void main(String[] args) {
RoundRectangle2D rect = new RoundRectangle2D.Double(
10, 10, 300, 200, 50, 50);
PathIterator it = rect.getPathIterator(new AffineTransform());
SwingUtilities.invokeLater(() -> new Test().show(rect, points(it)));
}
}