当使用 XYSplineRenderer 进行渲染时,JFreeChart setAutoRange

2024-01-03

图表需要绘制出平滑的形状,因此使用 XYSplineRenderer。 此外,NumberAxis 需要根据数据段自动调整范围。

但在某些情况下,计算样条曲线时,某些样条曲线值超出自动量程段,并且未完整绘制曲线。

似乎在计算样条线之前评估自动范围。

为了缓解这个问题,我通过按范围限制的百分比增加该范围来调整垂直轴的范围。但这会导致图表的曲线拟合不准确,因为根据数据输入,百分比可能高达 25%。

double percentOverRange = 0.05;//2%
double initalRange = series.getMaxY() - series.getMinY();
double increase = initalRange*percentOverRange;
verticalAxis.setRange(new Range(series.getMinY()-increase, series.getMaxY()+increase));

此代码创建了上面的图片,并演示了曲线如何不完全绘制在前两个数据点之间。请注意,域轴是 DateAxis(每日数据),没有周末值

public class MyPlotChart {
    private static Color MetalColor = new Color(255, 152, 0);
    static double[] yData = new double[] { 0.67, 0.67, 0.69, 0.70, 0.70, 0.71, 0.71 };
    static String[] labels = new String[] { "2021-11-09", "2021-11-10", "2021-11-11", "2021-11-12", "2021-11-15", "2021-11-16", "2021-11-17" };
    public static void plot(String metal, int samples) throws IOException, ParseException {
        SimpleDateFormat dateformatyyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateformatdd_MM_yyyy = new SimpleDateFormat("dd-MM-yyyy");
        XYSeries series = new XYSeries(metal);
        for (int i = 0; i < yData.length; i++) {
            Date date = dateformatyyyy_MM_dd.parse(labels[i]);
            series.add(date.getTime(), yData[i]);
        }
        //Configure Vertical Axis
        NumberAxis verticalAxis = new NumberAxis(null);
        NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
        numberFormat.setRoundingMode(RoundingMode.HALF_DOWN);
        numberFormat.setMinimumFractionDigits(2);
        numberFormat.setMaximumFractionDigits(2);
        double vericalTickUnit = (series.getMaxY() - series.getMinY()) / 7;
        NumberTickUnit nt = new NumberTickUnit(vericalTickUnit, numberFormat);
        verticalAxis.setTickUnit(nt);
        double percentOverRange = 0.05;// 2%
        double initalRange = series.getMaxY() - series.getMinY();
        double increase = initalRange * percentOverRange;
        verticalAxis.setRange(new Range(series.getMinY()-increase, series.getMaxY()+increase));
        verticalAxis.setAutoRange(true);
        verticalAxis.setAutoRangeIncludesZero(false);
        verticalAxis.setTickMarksVisible(true);
        verticalAxis.setTickMarkInsideLength(3f);
        //Configure Domain Axis
        DateAxis domainAxis = new DateAxis(null);
        domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 1, dateformatdd_MM_yyyy));
        //Configure Renderer
        XYSplineRenderer r = new XYSplineRenderer(10);
        r.setSeriesPaint(0, MetalColor);
        r.setDefaultShapesVisible(true);
        r.setSeriesStroke(0, new BasicStroke(3.0f));
        XYDataset dataset = new XYSeriesCollection(series);
        XYPlot xyplot = new XYPlot(dataset, domainAxis, verticalAxis, r);
        xyplot.getDomainAxis().setVerticalTickLabels(true);
        xyplot.setDomainGridlinesVisible(false);
        xyplot.setBackgroundImage(null);
        xyplot.setBackgroundPaint(Color.WHITE);
        Font font = xyplot.getDomainAxis().getTickLabelFont();
        Font fontnew = new Font(font.getName(), Font.BOLD, 14);
        xyplot.getDomainAxis().setTickLabelFont(fontnew);
        xyplot.getRangeAxis().setTickLabelFont(fontnew);
        JFreeChart chart = new JFreeChart(xyplot);
        chart.removeLegend();// Remove legend
        chart.setBackgroundPaint(Color.WHITE);
        String fileName = "myChart" + metal + samples + "TEST.png";
        ChartUtils.saveChartAsPNG(new File(fileName), chart, 600, 600);
        }
    public static void main(String[] args) throws IOException, ParseException {
        MyPlotChart.plot("metal", 7);
        }
    }

EDIT

下面的图来自上面的代码,只是更改了 XYSplineRenderer 的精度。

正如 javadoc 中定义的:

XYSplineRenderer:将数据点与自然连接的渲染器 在每个数据点绘制三次样条和/或绘制形状。

公共 XYSplineRenderer(int 精度)

创建一个具有指定精度且不填充的新渲染器 样条曲线“下方”(“0”和“0”之间)的区域。

参数: 精度 - 数据项之间的点数。

这意味着自然三次样条仅根据数据点计算。

另一方面,精度用于定义每对数据点之间的插值点的数量。

精度 = N - 1,其中 N = 每个数据点段之间的插值点数

我只能看到两个选项:

  1. XYSplineRenderer 应该有一个返回自然三次样条集的方法,因此可以计算每个段的最大值,从而可以相应地设置 AutoRange
  2. JFreeChart 应该实现一个基于 NURBS(非均匀有理基样条)的渲染器,而不是自然的三次样条,它通过一组控制点(see https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)

EDIT 2

当没有可用数据(周末)并且 DateAxis 在周五和周一之间插入两天时,问题会加剧:值之间的差距更大,因此样条线也更长。


如中所述JFreeChart 在实际值之外添加趋势线 https://stackoverflow.com/a/23454262/230513,对于不严格单调的函数来说,这种异常是不可避免的。如果没有更详细的样条控制,您可以通过在有问题的轴上启用自动范围(默认)并根据经验调整轴边距来获得更好的结果。

rangeAxis.setAutoRange(true); // true by default
rangeAxis.setLowerMargin(0.08); // 8% lower margin

在下面的变体中,请注意以下几点:

  • setLowerMargin() https://www.jfree.org/jfreechart/javadoc/org/jfree/chart/axis/ValueAxis.html#setLowerMargin(double)将范围轴的下边距减小轴范围的 8%。

  • setNumberFormatOverride() and setDateFormatOverride用于设置刻度标签的格式。

  • XYSplineRenderer是用任意构造的precision of 15.

  • deriveFont()用于更改轴刻度标签字体属性。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see https://stackoverflow.com/q/70021577/230513
 */
public class SplineTest {

    public static void main(String[] args) throws ParseException, IOException {
        SimpleDateFormat formatyyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatdd_MM_yyyy = new SimpleDateFormat("dd-MM-yyyy");
        double[] yData = new double[]{0.67, 0.67, 0.69, 0.70, 0.70, 0.71, 0.71};
        String[] labels = new String[]{"2021-11-09", "2021-11-10", "2021-11-11",
            "2021-11-12", "2021-11-15", "2021-11-16", "2021-11-17"};
        XYSeries series = new XYSeries("Series");
        for (int i = 0; i < yData.length; i++) {
            Date date = formatyyyy_MM_dd.parse(labels[i]);
            series.add(date.getTime(), yData[i]);
        }
        NumberAxis rangeAxis = new NumberAxis(null);
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setRoundingMode(RoundingMode.HALF_DOWN);
        numberFormat.setMinimumFractionDigits(2);
        numberFormat.setMaximumFractionDigits(2);
        rangeAxis.setNumberFormatOverride(numberFormat);
        rangeAxis.setTickMarksVisible(true);
        rangeAxis.setAutoRange(true); // true by default
        rangeAxis.setLowerMargin(0.08); // 8% lower margin
        rangeAxis.setAutoRangeIncludesZero(false);
        DateAxis domainAxis = new DateAxis(null);
        domainAxis.setDateFormatOverride(formatdd_MM_yyyy);
        domainAxis.setVerticalTickLabels(true);
        Font font = domainAxis.getTickLabelFont().deriveFont(Font.BOLD, 10);
        domainAxis.setTickLabelFont(font);
        rangeAxis.setTickLabelFont(font);
        XYSplineRenderer r = new XYSplineRenderer(15);
        r.setSeriesPaint(0, new Color(255, 152, 0));
        r.setDefaultShapesVisible(true);
        r.setSeriesStroke(0, new BasicStroke(3.0f));
        XYDataset dataset = new XYSeriesCollection(series);
        XYPlot xyplot = new XYPlot(dataset, domainAxis, rangeAxis, r);
        xyplot.setDomainGridlinesVisible(false);
        xyplot.setBackgroundImage(null);
        xyplot.setBackgroundPaint(Color.WHITE);
        JFreeChart chart = new JFreeChart(null, null, xyplot, false);
        chart.setBackgroundPaint(Color.WHITE);
        ChartUtils.saveChartAsPNG(new File("temp.png"), chart, 400, 300);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当使用 XYSplineRenderer 进行渲染时,JFreeChart setAutoRange 的相关文章

  • 使用包含图表 5.5.0 的 JRViewer 报告和 jasper 报告打印

    当我使用 JasperReports 创建报告而不使用图表形式 Java 应用程序时 我从 jbutton 调用它 我在 JRViewer 上收到报告 这意味着当我没有在此报告中放入任何图表时 我的应用程序会生成报告 但一旦我修改此报告并添
  • BoxAndWhiskerChart JFreeChart 的绘图方向

    我有一个问题JFreeChart 可以改吗PlotOrientation of a BoxAndWhiskerChart水平 我有一个直方图 我想添加一个BoxAndWhiskerChart以下 我需要它水平 这样我就可以使用相同的轴刻度
  • 如何删除 XYLineAndShapeRenderer 中的点?

    我正在使用 JFreeChart 在 Java 中制作一个应用程序 它显示 XY 折线图 问题是它显示了线上数据集的每个点 而我不想显示这些点 关于如何删除这些点或使它们不可见有什么想法吗 这是一个示例屏幕截图 这是代码 JFrame fr
  • 将按钮插入 JFreeChart 图形中

    我使用代码来显示图表 我想在此图中插入一个按钮 显示详细信息 我将使用该按钮来显示有关该图的一些详细信息 它可以实现吗 谢谢 if jCheckBox3 isSelected try con getConnection jdbc mysql
  • 使用 jFreeChart 在多个图形中绘制多个图形

    我正在尝试使用 jFreechart 生成两个数字 每个数字有 12 个图表 在 jFreeChart 中称为系列 然而 有些图表被简单地跳过了 我知道我在这里遇到同步问题 并尝试使用用户 trashgod 提供给我的方法here http
  • JFreeChart 没有出现在 JPanel 上 - 可能与我的代码逻辑有关

    这个问题涉及到我在这里发布了一个类似的问题 https stackoverflow com questions 16783592 built class to create a jfreechart how do i add it to a
  • JFreechart 中漂亮的饼图

    是否有可能在 JFreechart 中为饼图获得复杂 漂亮的颜色 我的意思是我怎样才能获得如图所示的颜色link http upload wikimedia org wikipedia commons b bf Ml wiki photo
  • jFreeChart:如何隐藏图例中的项目?

    我需要隐藏图例中的第二个 第三个 第四个项目 jFreeChart 有没有办法实现这一点 谢谢 我已经尝试过上述建议 但它似乎对我不起作用 如果您只想从图例中删除系列 您可以使用setSeriesVisibleInLegend 方法 我的情
  • 设置 JFree Chart 图例边框颜色

    问题已在标题中阐述 细节 我在类主题中有代码 用于为图例框架的边框设置特定的非默认颜色 LegendTitle legend jFreeChart getLegend legend setWidth 100 之后我需要设置图例边框的颜色 但
  • 有没有办法改变 JasperReports 图表中的形状大小?

    我正在构建一个基于时间序列的图表 该图表显示时间 gt 双值 该图表至少包含 230 个点 如果我使用 显示线条 选项 图表不会显示任何线条 如果我取消选择 显示形状 耻辱就会消失 但数据所在的位置没有点 如何将图表中的形状更改为圆点 我会
  • 错误 - java.sql.Timestamp 无法转换为 JFreeChart 中的 java.sql.Date

    当我使用 JFreeChart 从数据库检索数据以添加到图表时 出现错误 java sql Timestamp cannot be cast to java sql Date 我有四列 前三列是使用案例正确检索的 但在浏览最后一列时 它会转
  • JFreeChart 链接轴

    我创建了一个带有两个独立 JFree 图表的框架 以 2x1 网格布局保存 顶部图表显示 Canlestick 图表 底部图表显示时间序列图 我想要做的是链接两个图表显示的 X 轴 以便当我放大一个图表时 另一个图表会缩放到相应的时间段 这
  • 从 JTable 中的行生成标准差图

    我正在尝试创建一个JTable我可以单击一行 它将显示标准偏差曲线 这是我的JTable看起来就像现在 例如 字符串的标准差screen saver action gt login login gt disclaimer ok看起来像这样
  • 监听 JFreeChart 中的缩放重置事件

    如何监听 JFreeChart 的缩放重置事件 我用这个做到了 ChartPanel DCP new ChartPanel DailyChart Override public void restoreAutoBounds super re
  • JFreeChart - Java 堆空间问题

    我是第一次使用 JFreeChart 并且使用 TimeSeriesCollection 创建 TimeSeriesChart 我的数据库查询结果集就是全部 大约1000条记录 我在用org jfree date time Minute M
  • 如何像在 Matlab 中一样在 Java 中绘制绘图(相同语法)

    在 Matlab 中绘图非常简单明了 例如 figure Position 100 80 1000 600 plot x y1 or MarkerSize 0 2 MarkerFaceColor r LineWidth 2 xlabel M
  • 如何将 JFreechart 添加到面板?

    我尝试寻找答案来使其正常工作 但没有成功 我快要失去理智了 所以这是我的问题 我最近下载了 JFreeChart 来创建图表并在我的 GUI 中实现它们 这是我想要插入图形的 GUI 和面板 以白色标记 报告1 http www freei
  • JFreeChart奇怪的渲染(无头RedHat)

    我目前正在将一个应用程序从 Windows 环境迁移到 Redhat 环境 该应用程序使用 JfreeChart 1 0 6 它是部署在运行 Open JDK6 的 Redhat 无头环境中的 tomcat 7 中的 Web 应用程序 我得
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • JFreeChart - 创建移动图表时出现问题

    我在我的 java 应用程序中使用 JFreeChart Problem 我想绘制一个XY面积图 whose 域轴 x 轴 当我们开始绘制数据时应该自动水平滚动 我在中看到了同样的事情时间序列图表但我不想要任何时间系列图表 我只想要滚动的

随机推荐