Revision 2:846fdd5020c9

View differences:

src/main/java/cz/agents/alite/visualizer2d/VisPane.java
3 3
import javax.swing.*;
4 4
import java.awt.*;
5 5
import java.awt.geom.AffineTransform;
6
import java.awt.geom.NoninvertibleTransformException;
7
import java.awt.geom.Point2D;
6 8
import java.awt.image.BufferStrategy;
7 9
import java.util.concurrent.ScheduledThreadPoolExecutor;
8 10
import java.util.concurrent.TimeUnit;
......
12 14
 */
13 15
public class VisPane {
14 16

  
15
    private double scale = 1;
16
    private double transX = 0, transY = 0;
17
    private double rotationInRad = 0;
17
    private AffineTransform transform;
18 18

  
19 19
    private static final int REFRESH_IN_MS = 40; //25 FPS
20 20
    private static final int VIS_THREAD_PRIORITY = Thread.MIN_PRIORITY;
......
29 29
    private final Canvas canvas = new Canvas();
30 30

  
31 31
    public VisPane() {
32
        transform = new AffineTransform();
33
        VisPaneMouseListener mouseListener = new VisPaneMouseListener(this);
34
        canvas.addMouseListener(mouseListener);
35
        canvas.addMouseMotionListener(mouseListener);
36
        canvas.addMouseWheelListener(mouseListener);
37
        canvas.addKeyListener(new VisPaneKeyListener(this));
32 38
        canvas.setBounds(0, 0, 1024, 768);
33 39
        panel.add(canvas);
34 40
    }
......
67 73
        if (canvas.isDisplayable()) {
68 74
            reinitializeBuffers();
69 75

  
76
            AffineTransform originalTransform = graphics.getTransform();
70 77
            AffineTransform affineTransform = calculateAffineTransform();
71 78
            VisCanvas visCanvas = new VisCanvas(affineTransform, graphics);
72 79

  
73 80
            layerContainer.updateLayers(visCanvas);
81

  
82
            graphics.setTransform(originalTransform);
74 83
            strategy.show();
75 84
        }
76 85
    }
77 86

  
78
    private AffineTransform calculateAffineTransform() {
79
        AffineTransform affineTransform = new AffineTransform();
80
        synchronized (this) {
81
            affineTransform.translate(transX, transY);
82
            affineTransform.scale(scale, scale);
83
            affineTransform.rotate(rotationInRad);
84
        }
85
        return affineTransform;
87
    private synchronized AffineTransform calculateAffineTransform() {
88
        return new AffineTransform(transform);
86 89
    }
87 90

  
91
    public final void translate(int deltaX, int deltaY) {
92
        final Point2D deltaScreen = new Point2D.Double(deltaX, deltaY);
93

  
94
        synchronized (this) {
95
            try {
96
                Point2D deltaWorld = new Point2D.Double();
97
                transform.createInverse().deltaTransform(deltaScreen, deltaWorld);
98
                transform.translate(deltaWorld.getX(), deltaWorld.getY());
99
            } catch (NoninvertibleTransformException e) {
100
                e.printStackTrace();
101
            }
102
        }
103
    }
104

  
105
    public final void scaleBy(double multiplyFactor, int zoomCenterX, int zoomCenterY) {
106
        final Point2D scaleCenterScreen = new Point2D.Double(zoomCenterX, zoomCenterY);
107
        final Point2D presScale = new Point2D.Double();
108
        final Point2D postScale = new Point2D.Double();
109

  
110
        synchronized (this) {
111
            try {
112
                transform.inverseTransform(scaleCenterScreen, presScale);
113
                transform.scale(multiplyFactor, multiplyFactor);
114
                transform.inverseTransform(scaleCenterScreen, postScale);
115
                transform.translate(postScale.getX()-presScale.getX(), postScale.getY()-presScale.getY());
116
            } catch (NoninvertibleTransformException e) {
117
                e.printStackTrace();
118
            }
119
        }
120
    }
121

  
122
    public final void rotate(int deltaAngleDeg) {
123
        final double deltaAngleRad = Math.toRadians(deltaAngleDeg);
124
        Rectangle bounds = panel.getBounds();
125
        final Point2D centerScreen = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY());
126
        synchronized (this) {
127
            Point2D centerWorld = new Point2D.Double();
128
            try {
129
                transform.inverseTransform(centerScreen, centerWorld);
130
                transform.rotate(deltaAngleRad, centerWorld.getX(), centerWorld.getY());
131
            } catch (NoninvertibleTransformException e) {
132
                e.printStackTrace();
133
            }
134
        }
135
    }
88 136
}
src/main/java/cz/agents/alite/visualizer2d/VisPaneKeyListener.java
1
package cz.agents.alite.visualizer2d;
2

  
3
import java.awt.event.KeyAdapter;
4
import java.awt.event.KeyEvent;
5

  
6
/**
7
 * @author Ondrej Hrstka (ondrej.hrstka at agents.fel.cvut.cz)
8
 */
9
public class VisPaneKeyListener extends KeyAdapter {
10

  
11
    public static final int ROTATE_ANGLE_STEP_DEG = 5;
12

  
13
    public static final int ROTATE_LEFT_KEY = KeyEvent.VK_Q;
14
    public static final int ROTATE_RIGHT_KEY = KeyEvent.VK_W;
15

  
16
    private final VisPane visPane;
17

  
18
    public VisPaneKeyListener(VisPane visPane) {
19
        this.visPane = visPane;
20
    }
21

  
22
    @Override
23
    public void keyPressed(KeyEvent e) {
24
        switch (e.getKeyCode()) {
25
            case ROTATE_LEFT_KEY:
26
                visPane.rotate(ROTATE_ANGLE_STEP_DEG);
27
                break;
28
            case ROTATE_RIGHT_KEY:
29
                visPane.rotate(-ROTATE_ANGLE_STEP_DEG);
30
                break;
31
        }
32
    }
33
}
src/main/java/cz/agents/alite/visualizer2d/VisPaneMouseListener.java
1
package cz.agents.alite.visualizer2d;
2

  
3
import java.awt.event.*;
4

  
5
/**
6
 * @author Ondrej Hrstka (ondrej.hrstka at agents.fel.cvut.cz)
7
 */
8
public class VisPaneMouseListener implements MouseListener, MouseMotionListener, MouseWheelListener {
9

  
10
    private static final int PANNING_BUTTON = MouseEvent.BUTTON1; //constant for now
11
    private final VisPane visPane;
12

  
13
    private int lastX, lastY;
14
    private boolean panning = false;
15

  
16

  
17
    public VisPaneMouseListener(VisPane visPane) {
18
        this.visPane = visPane;
19
    }
20

  
21
    @Override
22
    public void mouseDragged(MouseEvent e) {
23
        if (panning) {
24
            int deltaX = e.getX() - lastX;
25
            int deltaY = e.getY() - lastY;
26

  
27
            lastX = e.getX();
28
            lastY = e.getY();
29
            visPane.translate(deltaX, deltaY);
30
        }
31
    }
32

  
33
    @Override
34
    public void mouseMoved(MouseEvent e) {}
35

  
36
    @Override
37
    public void mouseClicked(MouseEvent e) {}
38

  
39
    @Override
40
    public void mousePressed(MouseEvent e) {
41
        if (e.getButton() == PANNING_BUTTON && e.getClickCount() == 1) {
42
            panning = true;
43
            lastX = e.getX();
44
            lastY = e.getY();
45
        }
46
    }
47

  
48
    @Override
49
    public void mouseReleased(MouseEvent e) {
50
        panning = false;
51
    }
52

  
53
    @Override
54
    public void mouseEntered(MouseEvent e) {}
55

  
56
    @Override
57
    public void mouseExited(MouseEvent e) {}
58

  
59
    @Override
60
    public void mouseWheelMoved(MouseWheelEvent e) {
61
        int rotation = e.getWheelRotation() * e.getScrollAmount();
62
        if (rotation > 0) {
63
            visPane.scaleBy(1.1 * rotation, e.getX(), e.getY());
64
        } else if (rotation < 0) {
65
            visPane.scaleBy(1/(1.1 * (-rotation)), e.getX(), e.getY());
66
        }
67
    }
68
}
src/main/java/cz/agents/alite/visualizer2d/demo/Demo.java
31 31
        visPane.registerLayer(new ColorLayer(Color.BLACK));
32 32
        visPane.registerLayer(new VisualizableLayer(() -> Arrays.asList(
33 33
                new Point<>(new Point2d(AngleProvider.TRANS_X, AngleProvider.TRANS_Y), 3, Color.RED, IDENTITY),
34
                new Point<>(angleProvider.getPoint(), 3, Color.WHITE, IDENTITY))));
34
                new Point<>(angleProvider.getPoint(), 3, Color.WHITE, IDENTITY),
35
                new Point<>(new Point2d(AngleProvider.TRANS_X+25, AngleProvider.TRANS_Y), 3, Color.GREEN, IDENTITY))));
35 36
        visPane.start();
36 37
        frame.setVisible(true);
37 38
        //frame.pack();
src/main/java/cz/agents/alite/visualizer2d/implementation/Point.java
13 13
public class Point<T> implements Visualizable {
14 14

  
15 15
    private final T centerPosition;
16
    private final int radiusInPx;
16
    private final int radius;
17 17
    private final Point2dAdapter<T> adapter;
18 18
    private final Color color;
19 19

  
20 20
    public Point(T centerPosition, int radius, Color color, Point2dAdapter<T> adapter) {
21 21
        this.centerPosition = centerPosition;
22
        this.radiusInPx = radius;
22
        this.radius = radius;
23 23
        this.adapter = adapter;
24 24
        this.color = color;
25 25
    }
......
29 29
        Point2d center = adapter.convert(centerPosition);
30 30
        canvas.setColor(color);
31 31

  
32
        Ellipse2D point = new Ellipse2D.Double(center.x - radiusInPx, center.y - radiusInPx,
33
                2 * radiusInPx + 1, 2 * radiusInPx + 1);
32
        Ellipse2D point = new Ellipse2D.Double(center.x - radius, center.y - radius,
33
                2 * radius + 1, 2 * radius + 1);
34 34
        canvas.fill(point);
35 35
    }
36 36
}

Also available in: Unified diff