PolarPlot: Plots different after v1.0.13

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
DJViking
Posts: 10
Joined: Mon May 27, 2013 9:22 am
antibot: No, of course not.

PolarPlot: Plots different after v1.0.13

Post by DJViking » Mon Jun 15, 2015 10:53 am

We have been using JFreeChart 1.0.13 for years. After upgrade to 1.0.19 it seems PolarPlot has been changed.

The plot is no longer the same. If I start two GUIs, one using v1.0.13 and the other using v1.0.19 the plot with the never version is wrong.

This example program will illustrate the problem: Try running it with 1.0.13 and 1.0.19 to see the difference:

Code: Select all

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.PolarChartPanel;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class PolarPlotTest {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            /* (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                init();
            }
        });
    }

    private static void init() {
        XYSeriesCollection series = new XYSeriesCollection();
        XYSeries trackingSeries = new XYSeries("Text", false, true);
        series.addSeries(trackingSeries);

        JFreeChart chart = ChartFactory.createPolarChart(null, series, true, false, false);
        PolarPlot plot = (PolarPlot) chart.getPlot();
        plot.setOutlineVisible(false);

        MyOwnPolarRenderer renderer = new MyOwnPolarRenderer();
        renderer.setSeriesStroke(0, new BasicStroke(1.0f));
        renderer.setSeriesShape(1, null);
        renderer.setSeriesPaint(1, Color.BLACK);
        renderer.setSeriesShape(2, null);
        renderer.setSeriesPaint(2, Color.BLUE);
        plot.setRenderer(renderer);
        plot.setAngleGridlinePaint(Color.white);
        plot.setAngleGridlinesVisible(true);
        plot.setAngleLabelsVisible(false);
        plot.setRadiusGridlinePaint(Color.white);
        plot.setRadiusGridlinesVisible(true);
        plot.setBackgroundPaint(Color.lightGray);

        NumberAxis rangeAxis = (NumberAxis) plot.getAxis();
        rangeAxis.setRange(0.0, 90.0);
        rangeAxis.setTickUnit(new NumberTickUnit(30.0));
        rangeAxis.setInverted(true);
        rangeAxis.setTickLabelsVisible(false);

        PolarChartPanel chartPanel = new PolarChartPanel(chart);

        trackingSeries.add(new XYDataItem(0.0, 90.0));
        trackingSeries.add(new XYDataItem(360.0, 88.99));
        trackingSeries.add(new XYDataItem(14.05, 89.98));
        trackingSeries.add(new XYDataItem(39.22, 90.0));
        trackingSeries.add(new XYDataItem(130.68, 89.95));
        trackingSeries.add(new XYDataItem(130.67, 89.86));
        trackingSeries.add(new XYDataItem(130.63, 89.71));
        trackingSeries.add(new XYDataItem(130.62, 89.63));
        trackingSeries.add(new XYDataItem(130.55, 89.42));
        trackingSeries.add(new XYDataItem(130.54, 89.35));
        trackingSeries.add(new XYDataItem(130.5, 89.21));
        trackingSeries.add(new XYDataItem(130.46, 89.06));
        trackingSeries.add(new XYDataItem(130.46, 89.06));
        trackingSeries.add(new XYDataItem(130.42, 88.91));
        trackingSeries.add(new XYDataItem(130.4, 88.85));
        trackingSeries.add(new XYDataItem(130.4, 88.85));
        trackingSeries.add(new XYDataItem(130.36, 88.73));
        trackingSeries.add(new XYDataItem(130.36, 88.73));
        trackingSeries.add(new XYDataItem(130.31, 88.55));
        trackingSeries.add(new XYDataItem(130.31, 88.55));
        trackingSeries.add(new XYDataItem(130.3, 88.48));
        trackingSeries.add(new XYDataItem(130.3, 88.48));
        trackingSeries.add(new XYDataItem(130.25, 88.34));
        trackingSeries.add(new XYDataItem(130.25, 88.34));
        trackingSeries.add(new XYDataItem(130.21, 88.19));
        trackingSeries.add(new XYDataItem(130.21, 88.19));
        trackingSeries.add(new XYDataItem(130.17, 88.04));
        trackingSeries.add(new XYDataItem(130.17, 88.04));
        trackingSeries.add(new XYDataItem(130.1, 87.8));
        trackingSeries.add(new XYDataItem(130.1, 87.8));
        trackingSeries.add(new XYDataItem(130.06, 87.65));
        trackingSeries.add(new XYDataItem(130.06, 87.65));
        trackingSeries.add(new XYDataItem(130.03, 87.58));
        trackingSeries.add(new XYDataItem(130.03, 87.58));
        trackingSeries.add(new XYDataItem(129.98, 87.43));
        trackingSeries.add(new XYDataItem(129.98, 87.43));
        trackingSeries.add(new XYDataItem(129.92, 87.28));
        trackingSeries.add(new XYDataItem(129.92, 87.28));
        trackingSeries.add(new XYDataItem(129.89, 87.13));
        trackingSeries.add(new XYDataItem(129.89, 87.13));
        trackingSeries.add(new XYDataItem(129.85, 86.99));
        trackingSeries.add(new XYDataItem(129.85, 86.99));
        trackingSeries.add(new XYDataItem(129.78, 86.78));
        trackingSeries.add(new XYDataItem(129.74, 86.63));
        trackingSeries.add(new XYDataItem(129.74, 86.63));
        trackingSeries.add(new XYDataItem(129.69, 86.47));
        trackingSeries.add(new XYDataItem(129.69, 86.47));
        trackingSeries.add(new XYDataItem(129.66, 86.4));
        trackingSeries.add(new XYDataItem(129.64, 86.32));
        trackingSeries.add(new XYDataItem(129.64, 86.32));
        trackingSeries.add(new XYDataItem(129.57, 86.09));
        trackingSeries.add(new XYDataItem(129.57, 86.09));
        trackingSeries.add(new XYDataItem(129.52, 85.92));
        trackingSeries.add(new XYDataItem(129.52, 85.92));
        trackingSeries.add(new XYDataItem(129.5, 85.85));
        trackingSeries.add(new XYDataItem(129.44, 85.69));
        trackingSeries.add(new XYDataItem(129.44, 85.69));
        trackingSeries.add(new XYDataItem(129.39, 85.54));
        trackingSeries.add(new XYDataItem(129.39, 85.54));
        trackingSeries.add(new XYDataItem(129.36, 85.46));
        trackingSeries.add(new XYDataItem(0.0, 90.0));
        trackingSeries.add(new XYDataItem(360.0, 88.99));
        trackingSeries.add(new XYDataItem(14.05, 89.98));
        trackingSeries.add(new XYDataItem(39.22, 90.0));
        trackingSeries.add(new XYDataItem(130.68, 89.95));
        trackingSeries.add(new XYDataItem(130.67, 89.86));
        trackingSeries.add(new XYDataItem(130.63, 89.71));
        trackingSeries.add(new XYDataItem(130.62, 89.63));
        trackingSeries.add(new XYDataItem(130.55, 89.42));
        trackingSeries.add(new XYDataItem(130.54, 89.35));
        trackingSeries.add(new XYDataItem(130.5, 89.21));
        trackingSeries.add(new XYDataItem(130.46, 89.06));
        trackingSeries.add(new XYDataItem(130.46, 89.06));
        trackingSeries.add(new XYDataItem(130.42, 88.91));
        trackingSeries.add(new XYDataItem(130.4, 88.85));
        trackingSeries.add(new XYDataItem(130.4, 88.85));
        trackingSeries.add(new XYDataItem(130.36, 88.73));
        trackingSeries.add(new XYDataItem(130.36, 88.73));
        trackingSeries.add(new XYDataItem(130.31, 88.55));
        trackingSeries.add(new XYDataItem(130.31, 88.55));
        trackingSeries.add(new XYDataItem(130.3, 88.48));
        trackingSeries.add(new XYDataItem(130.3, 88.48));
        trackingSeries.add(new XYDataItem(130.25, 88.34));
        trackingSeries.add(new XYDataItem(130.25, 88.34));
        trackingSeries.add(new XYDataItem(130.21, 88.19));
        trackingSeries.add(new XYDataItem(130.21, 88.19));
        trackingSeries.add(new XYDataItem(130.17, 88.04));
        trackingSeries.add(new XYDataItem(130.17, 88.04));
        trackingSeries.add(new XYDataItem(130.1, 87.8));
        trackingSeries.add(new XYDataItem(130.1, 87.8));
        trackingSeries.add(new XYDataItem(130.06, 87.65));
        trackingSeries.add(new XYDataItem(130.06, 87.65));
        trackingSeries.add(new XYDataItem(130.03, 87.58));
        trackingSeries.add(new XYDataItem(130.03, 87.58));
        trackingSeries.add(new XYDataItem(129.98, 87.43));
        trackingSeries.add(new XYDataItem(129.98, 87.43));
        trackingSeries.add(new XYDataItem(129.92, 87.28));
        trackingSeries.add(new XYDataItem(129.92, 87.28));
        trackingSeries.add(new XYDataItem(129.89, 87.13));
        trackingSeries.add(new XYDataItem(129.89, 87.13));
        trackingSeries.add(new XYDataItem(129.85, 86.99));
        trackingSeries.add(new XYDataItem(129.85, 86.99));
        trackingSeries.add(new XYDataItem(129.78, 86.78));
        trackingSeries.add(new XYDataItem(129.74, 86.63));
        trackingSeries.add(new XYDataItem(129.74, 86.63));
        trackingSeries.add(new XYDataItem(129.69, 86.47));
        trackingSeries.add(new XYDataItem(129.69, 86.47));
        trackingSeries.add(new XYDataItem(129.66, 86.4));
        trackingSeries.add(new XYDataItem(129.64, 86.32));
        trackingSeries.add(new XYDataItem(129.64, 86.32));
        trackingSeries.add(new XYDataItem(129.57, 86.09));
        trackingSeries.add(new XYDataItem(129.57, 86.09));
        trackingSeries.add(new XYDataItem(129.52, 85.92));
        trackingSeries.add(new XYDataItem(129.52, 85.92));
        trackingSeries.add(new XYDataItem(129.5, 85.85));
        trackingSeries.add(new XYDataItem(129.44, 85.69));
        trackingSeries.add(new XYDataItem(129.44, 85.69));
        trackingSeries.add(new XYDataItem(129.39, 85.54));
        trackingSeries.add(new XYDataItem(129.39, 85.54));
        trackingSeries.add(new XYDataItem(129.36, 85.46));
        trackingSeries.add(new XYDataItem(129.32, 85.31));
        trackingSeries.add(new XYDataItem(129.32, 85.31));
        trackingSeries.add(new XYDataItem(129.25, 85.13));
        trackingSeries.add(new XYDataItem(129.25, 85.13));
        trackingSeries.add(new XYDataItem(129.21, 84.98));
        trackingSeries.add(new XYDataItem(129.21, 84.98));
        trackingSeries.add(new XYDataItem(129.18, 84.89));
        trackingSeries.add(new XYDataItem(129.18, 84.89));
        trackingSeries.add(new XYDataItem(129.12, 84.74));
        trackingSeries.add(new XYDataItem(129.12, 84.74));
        trackingSeries.add(new XYDataItem(129.09, 84.65));
        trackingSeries.add(new XYDataItem(129.09, 84.65));
        trackingSeries.add(new XYDataItem(129.01, 84.41));
        trackingSeries.add(new XYDataItem(129.01, 84.41));
        trackingSeries.add(new XYDataItem(128.98, 84.32));
        trackingSeries.add(new XYDataItem(128.98, 84.32));
        trackingSeries.add(new XYDataItem(128.92, 84.13));
        trackingSeries.add(new XYDataItem(128.92, 84.13));
        trackingSeries.add(new XYDataItem(128.86, 83.97));
        trackingSeries.add(new XYDataItem(128.86, 83.97));
        trackingSeries.add(new XYDataItem(128.8, 83.81));
        trackingSeries.add(new XYDataItem(128.8, 83.81));
        trackingSeries.add(new XYDataItem(128.77, 83.73));
        trackingSeries.add(new XYDataItem(128.77, 83.73));
        trackingSeries.add(new XYDataItem(128.73, 83.58));
        trackingSeries.add(new XYDataItem(128.73, 83.58));
        trackingSeries.add(new XYDataItem(128.65, 83.36));
        trackingSeries.add(new XYDataItem(128.65, 83.36));
        trackingSeries.add(new XYDataItem(128.62, 83.28));
        trackingSeries.add(new XYDataItem(128.62, 83.28));

        JFrame frame = new JFrame("PolarPlot Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(chartPanel, BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static final class MyOwnPolarRenderer extends DefaultPolarItemRenderer {

        private static final long serialVersionUID = 2522316048609133214L;

        public MyOwnPolarRenderer() {
            super();
        }

        /* (non-Javadoc)
         * @see org.jfree.chart.renderer.DefaultPolarItemRenderer#drawSeries(java.awt.Graphics2D, java.awt.geom.Rectangle2D, org.jfree.chart.plot.PlotRenderingInfo, org.jfree.chart.plot.PolarPlot, org.jfree.data.xy.XYDataset, int)
         */
        @Override
        public void drawSeries(Graphics2D g2, Rectangle2D dataArea, PlotRenderingInfo info, PolarPlot plot, XYDataset dataset, int seriesIndex) {
            Path2D.Float path = new Path2D.Float();
            int numPoints = dataset.getItemCount(seriesIndex);
            for (int i = 0; i < numPoints; i++) {
                double theta = dataset.getXValue(seriesIndex, i);
                double radius = dataset.getYValue(seriesIndex, i);
                Point p = plot.translateValueThetaRadiusToJava2D(theta, radius, dataArea);
                if (i == 0) {
                    path.moveTo(p.x, p.y);
                } else {
                    path.lineTo(p.x, p.y);
                }
            }

            g2.setPaint(getSeriesPaint(seriesIndex));
            Stroke stroke = getSeriesStroke(seriesIndex);
            if (stroke != null) {
                g2.setStroke(getSeriesStroke(seriesIndex));
            }

            g2.draw(path);
            Shape shape = getSeriesShape(seriesIndex);
            if (shape != null) {
                Point2D last = path.getCurrentPoint();
                if (last != null && seriesIndex == 0) {
                    g2.translate(last.getX(), last.getY());
                    g2.fill(shape);
                    g2.translate(-last.getX(), -last.getY());
                }
            }
        }
    }

}

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: PolarPlot: Plots different after v1.0.13

Post by John Matthews » Wed Jun 17, 2015 3:04 am

You might look at the interim changes to DefaultPolarItemRenderer, seen here.

DJViking
Posts: 10
Joined: Mon May 27, 2013 9:22 am
antibot: No, of course not.

Re: PolarPlot: Plots different after v1.0.13

Post by DJViking » Wed Jun 17, 2015 8:18 am

I could not find anything other than the deprecated method translateValueThetaRadiusToJava2D. I tried using translateToJava2D instead, but the plot result was still wrong.

Code: Select all

Path2D.Float path = new Path2D.Float();
int numPoints = dataset.getItemCount(seriesIndex);
ValueAxis axis = plot.getAxis();
for (int i = 0; i < numPoints; i++) {
  double theta = dataset.getXValue(seriesIndex, i);
  double radius = dataset.getYValue(seriesIndex, i);
  //Point p = plot.translateValueThetaRadiusToJava2D(theta, radius, dataArea);
  Point p = plot.translateToJava2D(theta, radius, axis, dataArea);
  if (i == 0) {
    path.moveTo(p.x, p.y);
  } else {
    path.lineTo(p.x, p.y);
  }
}
Correct PolarPlot using 1.0.13
Imagehttp://paste.opensuse.org/65572258

Wrong PolarPlot using 1.0.19
Imagehttp://paste.opensuse.org/71690108

matinh
Posts: 483
Joined: Fri Aug 11, 2006 10:08 am
Location: Austria

Re: PolarPlot: Plots different after v1.0.13

Post by matinh » Thu Jun 18, 2015 8:25 am

Hi!

Why are you using your own renderer? What is actually different to JFreeChart's DefaultPolarItemRenderer?

Did you try the DefaultPolarItemRenderer? If yes, is there also a difference between the two JFreeChart versions?

Your chart's do not contain any labeling and you did not set any explicit range. Maybe the the auto-range feature detects some other range now? Please set a fixed range and/or add labels to the axis. So we could more easily compare the generated charts.

One more thing: you use an inverted axis. and the changelog for DefaultPolarItemRenderer lists
Fix rendering bug when axis is inverted
Maybe you should have a closer look at this.

hth,
- martin

DJViking
Posts: 10
Joined: Mon May 27, 2013 9:22 am
antibot: No, of course not.

Re: PolarPlot: Plots different after v1.0.13

Post by DJViking » Thu Jun 18, 2015 1:04 pm

matinh wrote: Why are you using your own renderer? What is actually different to JFreeChart's DefaultPolarItemRenderer?

Did you try the DefaultPolarItemRenderer? If yes, is there also a difference between the two JFreeChart versions?
The reason we used our own renderer is because we didn't want to draw the item shapes, but I see now that there was added a method in 1.0.14 to avoid this.

Removing rangeAxis.setInverted(true); fixed the problem I was having.

Now that there is a way to not draw the item shapes with DefaultPolarItemRenderer there is no longer a point using our own renderer.

matinh
Posts: 483
Joined: Fri Aug 11, 2006 10:08 am
Location: Austria

Re: PolarPlot: Plots different after v1.0.13

Post by matinh » Thu Jun 18, 2015 1:18 pm

Glad to hear it's working now!
Removing rangeAxis.setInverted(true); fixed the problem I was having.
So would say the current behavior with setInverted(true) is buggy? Or is it just not what you'd expect?

If you'd call it a bug please describe the problem and expected behavior in more detail and file a bug report at sourceforge.net.

thx,
- martin

DJViking
Posts: 10
Joined: Mon May 27, 2013 9:22 am
antibot: No, of course not.

Re: PolarPlot: Plots different after v1.0.13

Post by DJViking » Thu Jun 18, 2015 2:06 pm

matinh wrote: So would say the current behavior with setInverted(true) is buggy? Or is it just not what you'd expect?
If you'd call it a bug please describe the problem and expected behavior in more detail and file a bug report at sourceforge.net.
The difference with using and not using inverted can be seen with the two images I posted in a previous post. I am not sure what inverted is supposed to do, but we have no need for inverted plots.

Locked