JFreeChart PolarPlot:数学方向

我想创建一个极坐标图,其中数据以数学方向绘制(因此,系列开始,向东并逆时针继续)。 JFreeChart的PolarPlot的默认行为是从北方开始并顺时针继续该系列。

是否有对PolarPlot类内置的支持? 我知道如何转换数据以达到目标,但这种方法相当麻烦,因为我也需要调整角度标注。

另外, org.jfree.chart.plot.PolarPlot似乎是为导航和大地测量应用程序设计的。

使用变换θ’=π/ 4-θrefreshAngleTicks() 建议覆盖refreshAngleTicks() ,可以产生合理的结果。

附录:使用新的PolarPlot API还可以查看此变体 。

阿基米德螺旋

 import java.awt.Color; import java.awt.Dimension; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.NumberTick; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.PolarPlot; import org.jfree.chart.renderer.DefaultPolarItemRenderer; import org.jfree.chart.renderer.PolarItemRenderer; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.ui.TextAnchor; /** * @see http://en.wikipedia.org/wiki/Polar_coordinate_system * @see https://stackoverflow.com/questions/3458824 */ public class ArchimedesSpiral extends JFrame { private static final String title = "Archimedes' Spiral"; public ArchimedesSpiral(String title) { super(title); JFreeChart chart = createChart(createDataset()); ChartPanel panel = new ChartPanel(chart); panel.setPreferredSize(new Dimension(500, 500)); panel.setMouseZoomable(false); this.add(panel); } private static XYDataset createDataset() { XYSeriesCollection result = new XYSeriesCollection(); XYSeries series = new XYSeries(title); for (int t = 0; t <= 3 * 360; t++) { series.add(90 - t, t); } result.addSeries(series); return result; } private static JFreeChart createChart(XYDataset dataset) { ValueAxis radiusAxis = new NumberAxis(); radiusAxis.setTickLabelsVisible(false); PolarItemRenderer renderer = new DefaultPolarItemRenderer(); PolarPlot plot = new PolarPlot(dataset, radiusAxis, renderer) { @Override protected List refreshAngleTicks() { List ticks = new ArrayList(); int delta = (int) this.getAngleTickUnit().getSize(); for (int t = 0; t < 360; t += delta) { int tp = (360 + 90 - t) % 360; NumberTick tick = new NumberTick( Double.valueOf(t), String.valueOf(tp), TextAnchor.CENTER, TextAnchor.CENTER, 0.0); ticks.add(tick); } return ticks; } }; plot.setBackgroundPaint(new Color(0x00f0f0f0)); plot.setRadiusGridlinePaint(Color.gray); plot.addCornerTextItem("r(θ) = θ; 0 < θ < 6π"); JFreeChart chart = new JFreeChart( title, JFreeChart.DEFAULT_TITLE_FONT, plot, true); chart.setBackgroundPaint(Color.white); return chart; } public static void main(String[] args) { ArchimedesSpiral demo = new ArchimedesSpiral(title); demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); demo.pack(); demo.setLocationRelativeTo(null); demo.setVisible(true); } } 

当前版本的JFreeChart似乎更容易解决这个问题:有三种方法可用:

 setCounterClockwise(true) // changes the direction of the ticks setAxisLocation(PolarAxisLocation.EAST_BELOW) // defines the placement of the axis setAngleOffset(0); 

从这里改编的完整示例:

 import java.awt.Color; import java.awt.Dimension; import javax.swing.JFrame; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.ValueAxis; 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 http://en.wikipedia.org/wiki/Polar_coordinate_system * @see https://stackoverflow.com/questions/3458824 * @see https://stackoverflow.com/questions/6540390 * @see https://stackoverflow.com/questions/6576911 * @see https://stackoverflow.com/a/10227275/230513 */ public class ArchimedesSpiral extends JFrame { private static final String title = "Archimedes' Spiral"; public ArchimedesSpiral(String title) { super(title); JFreeChart chart = createChart(createDataset()); ChartPanel panel = new ChartPanel(chart); panel.setPreferredSize(new Dimension(500, 500)); panel.setMouseZoomable(false); this.add(panel); } private static XYDataset createDataset() { XYSeriesCollection result = new XYSeriesCollection(); XYSeries 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) { ValueAxis radiusAxis = new NumberAxis(); radiusAxis.setTickLabelsVisible(false); DefaultPolarItemRenderer renderer = new DefaultPolarItemRenderer(); renderer.setShapesVisible(false); PolarPlot 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π"); JFreeChart chart = new JFreeChart( title, JFreeChart.DEFAULT_TITLE_FONT, plot, true); chart.setBackgroundPaint(Color.white); return chart; } public static void main(String[] args) { ArchimedesSpiral demo = new ArchimedesSpiral(title); demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); demo.pack(); demo.setLocationRelativeTo(null); demo.setVisible(true); } } 

不幸的是,似乎没有内置的支持。 可以通过覆盖PolarPlot的refreshAngleTicks()方法来调整角度标注:

 PolarPlot plot = new PolarPlot() { @Override protected List refreshAngleTicks() { List ticks = new ArrayList(); // produce some ticks, eg NumberTick instances ticks.add(new NumberTick(0, "90", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(45, "45", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(90, "0", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(135, "315", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(180, "270", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(225, "225", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(270, "180", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); ticks.add(new NumberTick(315, "135", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0)); return ticks; } };