I'd like to create a polar plot where the data is plotted in mathematical orientation (thus, the series starts and the east and continues counter-clockwise). The default behavior of JFreeChart's PolarPlot
is to start north and continue the series clockwise.
Is there any support for this built in the PolarPlot
class? I know how to transform the data to reach the goal, but this approach is rather cumbersome, since I'd need to adapt the angle labeling too.
As an aside, org.jfree.chart.plot.PolarPlot
appears to have been designed for navigational and geodetic applications.
Using the transformation θ' = π/4 – θ and overriding refreshAngleTicks()
, as suggested by @mort, produces reasonable results.
Addendum: See also this variation using the new PolarPlot
API. The revised example below incorporates those changes and updates to Java 21, JFreeChart 1.5.5.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PolarAxisLocation;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* @see https://en.wikipedia.org/wiki/Polar_coordinate_system
* @see https://stackoverflow.com/q/3458824/230513
* @see https://stackoverflow.com/a/6541516/230513
* @see https://stackoverflow.com/a/6585876/230513
* @see https://stackoverflow.com/a/10227275/230513
*/
public class ArchimedesSpiral {
private static final String TITLE = "Archimedes' Spiral";
private static XYDataset createDataset() {
var result = new XYSeriesCollection();
var series = new XYSeries(TITLE);
for (int t = 0; t <= 3 * 360; t++) {
series.add(t, t);
}
result.addSeries(series);
return result;
}
private static JFreeChart createChart(XYDataset dataset) {
var radiusAxis = new NumberAxis();
radiusAxis.setTickLabelsVisible(false);
var renderer = new DefaultPolarItemRenderer();
renderer.setShapesVisible(false);
var plot = new PolarPlot(dataset, radiusAxis, renderer);
plot.setCounterClockwise(true);
plot.setAxisLocation(PolarAxisLocation.EAST_BELOW);
plot.setAngleOffset(0);
plot.setBackgroundPaint(new Color(0x00f0f0f0));
plot.setRadiusGridlinePaint(Color.gray);
plot.addCornerTextItem("r(θ) = θ; 0 < θ < 6π");
var chart = new JFreeChart(
TITLE, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
chart.setBackgroundPaint(Color.white);
return chart;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var frame = new JFrame(TITLE);
var chart = createChart(createDataset());
var panel = new ChartPanel(chart) {
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
panel.setMouseZoomable(false);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}