2

I have a dataset with 3 column, x, y, and value at (x,y). I want to plot map similar to bellow map. How to plot this type of figure in jfreechart or any library available for this kind of plot?

enter image description here

Ranjeet
  • 360
  • 2
  • 4
  • 13

3 Answers3

3

Starting with this example and using this idea, you can use a SpectrumPaintScale to get a palette of colors as shown below.

image

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Paint;
import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.PaintScale;
import org.jfree.chart.renderer.xy.XYBlockRenderer;
import org.jfree.chart.title.PaintScaleLegend;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYZDataset;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.chart.ui.RectangleInsets;

/**
 * @see https://stackoverflow.com/a/37235165/230513
 */
public class XYZChartDemo {

    private static final int N = 100;

    public XYZChartDemo(String title) {
        JFrame f = new JFrame(title);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ChartPanel chartPanel = new ChartPanel(createChart(createDataset())) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }
        };
        chartPanel.setMouseZoomable(true, false);
        f.add(chartPanel);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static JFreeChart createChart(XYDataset dataset) {
        NumberAxis xAxis = new NumberAxis("x Axis");
        NumberAxis yAxis = new NumberAxis("y Axis");
        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null);
        XYBlockRenderer r = new XYBlockRenderer();
        r.setDefaultToolTipGenerator(new StandardXYToolTipGenerator());
        SpectrumPaintScale ps = new SpectrumPaintScale(0, N * N);
        r.setPaintScale(ps);
        plot.setRenderer(r);
        JFreeChart chart = new JFreeChart("Title",
            JFreeChart.DEFAULT_TITLE_FONT, plot, false);
        NumberAxis scaleAxis = new NumberAxis("Scale");
        scaleAxis.setAxisLinePaint(Color.white);
        scaleAxis.setTickMarkPaint(Color.white);
        PaintScaleLegend legend = new PaintScaleLegend(ps, scaleAxis);
        legend.setSubdivisionCount(128);
        legend.setAxisLocation(AxisLocation.TOP_OR_RIGHT);
        legend.setPadding(new RectangleInsets(25, 10, 50, 10));
        legend.setStripWidth(20);
        legend.setPosition(RectangleEdge.RIGHT);
        legend.setBackgroundPaint(Color.WHITE);
        chart.addSubtitle(legend);
        chart.setBackgroundPaint(Color.white);
        return chart;
    }

    private static XYZDataset createDataset() {
        DefaultXYZDataset dataset = new DefaultXYZDataset();
        double[][] data = new double[3][N * N];
        for (int i = 0; i < N * N; i++) {
            var x = i % N;
            var y = i / N;
            data[0][i] = x;
            data[1][i] = y;
            data[2][i] = x * y;
        }
        dataset.addSeries("Series", data);
        return dataset;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            XYZChartDemo demo = new XYZChartDemo("XYZ Demo");
        });
    }

    private static class SpectrumPaintScale implements PaintScale {

        private static final float H1 = 0f;
        private static final float H2 = 1f;
        private final double lowerBound;
        private final double upperBound;

        public SpectrumPaintScale(double lowerBound, double upperBound) {
            this.lowerBound = lowerBound;
            this.upperBound = upperBound;
        }

        @Override
        public double getLowerBound() {
            return lowerBound;
        }

        @Override
        public double getUpperBound() {
            return upperBound;
        }

        @Override
        public Paint getPaint(double value) {
            float scaledValue = (float) (value / (getUpperBound() - getLowerBound()));
            float scaledH = H1 + scaledValue * (H2 - H1);
            return Color.getHSBColor(scaledH, 1f, 1f);
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Instead of griding, can we create dataset something like dataset.add(array)? [data to be plotted](https://docs.google.com/spreadsheets/d/1jG9UZboPcU0kKRGD2OTHA_iViz9h49y_NEyXDj10KJ4/edit?usp=sharing) – Ranjeet May 15 '16 at 14:37
  • A related example using `XYLineAndShapeRenderer` with `XYZDataset` is shown [here](https://stackoverflow.com/a/54180207/230513). – trashgod Jan 26 '19 at 17:28
  • @trashgod What is the significance of H1 and H2 here? I want to create a rainbow pallet where the color values (Z) will be dynamic. I tried this implementation, but it doesn't make sufficient colors. – ACB Jul 04 '23 at 23:32
  • I agree; simple, linear interpolation isn't very flexible; a suitable `Paint` implementation will likely be more adaptable to a particular use case. – trashgod Jul 05 '23 at 17:07
2

An XYBlockRenderer looks like a good match. You can use Color.getHSBColor(), like they show here, to make the PaintScale.

image

Community
  • 1
  • 1
Catalina Island
  • 7,027
  • 2
  • 23
  • 42
1

You can use a BubbleChart to illustrate a dataset with 3 columns.

There are some android libs which contain some charts that look pretty well.

HelloCharts for Android: https://github.com/lecho/hellocharts-android

MPAndroidChart: https://github.com/PhilJay/MPAndroidChart

Hope this solve your problem.

hilzj
  • 68
  • 10