Search code examples
javaplotjfreechartaxes

How to set same scale for domain and range axes JFreeChart



I would like to create pole/zero plot similar to pole/zero plot. It is for displaying IIR and FIR filters properties like stability, type...

My question is: How can I set same scale (not range) for both axes?
I use ScatterPlot for chart.

JFreeChart chart = ChartFactory.createScatterPlot("Pole/zero plot", // chart
                                                                        // title
            "real", // x axis label
            "imaginary", // y axis label
            result, // data
            PlotOrientation.VERTICAL, true, // include legend
            true, // tooltips
            false // urls
            );

XYPlot plot = (XYPlot) chart.getPlot();
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.black);
plot.setDomainGridlinePaint(Color.black);

XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();

renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelsVisible(true, true);


plot.setDomainCrosshairVisible(true);
plot.setDomainCrosshairLockedOnData(true);
plot.setRangeCrosshairVisible(true);
plot.setRangeCrosshairLockedOnData(true);

float dash1[] = { 10.0f };
XYShapeAnnotation unitCircle = new XYShapeAnnotation(
    new Ellipse2D.Double(-1, -1, 2, 2), new BasicStroke(1.0f,
    BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f,
    dash1, 0.0f), Color.black);
    plot.addAnnotation(unitCircle);
    plot.setBackgroundPaint(Color.white);

chart.setAntiAlias(true);


chartPanel = new JPanel(new BorderLayout());
ChartPanel cp = new ChartPanel(chart);
cp.setMouseWheelEnabled(true);
cp.setToolTipText("test");
cp.setDisplayToolTips(true);
chartPanel.add(cp);

Solution

  • Sans legend, setting the preferred size of the ChartPanel works pretty well:

    private static final int SIZE = 456;
    chartPanel.setPreferredSize(new Dimension(SIZE, SIZE));
    

    See also Should I avoid the use of set(Preferred|Maximum|Minimum)Size() methods in Java Swing? and this answer regarding chart size.

    enter image description here

    import java.awt.BasicStroke;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.geom.Ellipse2D;
    import java.util.*;
    import javax.swing.AbstractAction;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import org.jfree.chart.*;
    import org.jfree.chart.annotations.XYShapeAnnotation;
    import org.jfree.chart.axis.NumberAxis;
    import org.jfree.chart.axis.NumberTickUnit;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.XYItemRenderer;
    import org.jfree.data.xy.XYDataset;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.xy.XYSeriesCollection;
    
    /**
     * @see http://stackoverflow.com/questions/8048652
     * @see http://stackoverflow.com/questions/7231824
     * @see http://stackoverflow.com/questions/7205742
     * @see http://stackoverflow.com/questions/7208657
     * @see http://stackoverflow.com/questions/7071057
     */
    public class ScatterAdd extends JFrame {
    
        private static final int N = 8;
        private static final int SIZE = 456;
        private static final String title = "Scatter Add Demo";
        private static final Random rand = new Random();
        private XYSeries added = new XYSeries("Added");
    
        public ScatterAdd(String s) {
            super(s);
            final ChartPanel chartPanel = createDemoPanel();
            chartPanel.setPreferredSize(new Dimension(SIZE, SIZE));
            this.add(chartPanel, BorderLayout.CENTER);
            JPanel control = new JPanel();
            control.add(new JButton(new AbstractAction("Add") {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    for (int i = 0; i < N; i++) {
                        added.add(rand.nextGaussian(), rand.nextGaussian());
                    }
                }
            }));
            this.add(control, BorderLayout.SOUTH);
        }
    
        private ChartPanel createDemoPanel() {
            JFreeChart jfreechart = ChartFactory.createScatterPlot(
                title, "X", "Y", createSampleData(),
                PlotOrientation.VERTICAL, false, true, false);
            XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
            xyPlot.setDomainCrosshairVisible(true);
            xyPlot.setRangeCrosshairVisible(true);
            XYItemRenderer renderer = xyPlot.getRenderer();
            renderer.setSeriesPaint(0, Color.blue);
            adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true);
            adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false);
            XYShapeAnnotation unitCircle = new XYShapeAnnotation(
                new Ellipse2D.Double(-1, -1, 2, 2), new BasicStroke(1.0f,
                BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f), Color.black);
            xyPlot.addAnnotation(unitCircle);
            xyPlot.setBackgroundPaint(Color.white);
    
            return new ChartPanel(jfreechart);
        }
    
        private void adjustAxis(NumberAxis axis, boolean vertical) {
            axis.setRange(-1.0, 1.0);
            axis.setTickUnit(new NumberTickUnit(0.5));
            axis.setVerticalTickLabels(vertical);
        }
    
        private XYDataset createSampleData() {
            XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
            XYSeries series = new XYSeries("Random");
            for (int i = 0; i < N * N; i++) {
                series.add(rand.nextGaussian(), rand.nextGaussian());
            }
            xySeriesCollection.addSeries(series);
            xySeriesCollection.addSeries(added);
            return xySeriesCollection;
        }
    
        public static void main(String args[]) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    ScatterAdd demo = new ScatterAdd(title);
                    demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    demo.pack();
                    demo.setLocationRelativeTo(null);
                    demo.setVisible(true);
                }
            });
        }
    }