Вот код, который я использую для создания диаграммы :
Код: Выделить всё
private JFreeChart createMultiAxisChart(List reportsData, Map attributes, TemperatureStatistics temperatureStats, HumidityStatistics humidityStatistics) {
List reportData = generateDummyData();
XYDataset temperatureDataset = createMultiTemperatureDataset(reportData);
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"Temperature & Humidity",
"Time",
"Temperature (°C)",
temperatureDataset,true,true,false);
XYPlot plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.WHITE);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.GRAY);
plot.setRangeGridlinePaint(Color.GRAY);
Font axisLabelFont = new Font("SansSerif", Font.BOLD, 12);
Font tickLabelFont = new Font("SansSerif", Font.BOLD, 10);
Color axisLabelColor = Color.BLACK;
DateAxis dateAxis = new DateAxis("Time");
dateAxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));
dateAxis.setAutoTickUnitSelection(true);
dateAxis.setAutoRange(true);
dateAxis.setLabelFont(axisLabelFont);
dateAxis.setTickLabelFont(tickLabelFont);
dateAxis.setLabelPaint(axisLabelColor);
dateAxis.setTickLabelPaint(axisLabelColor);
plot.setDomainAxis(dateAxis);
XYBezierRenderer tempRenderer = new XYBezierRenderer(5,0.05);
for (int i = 0; i < temperatureDataset.getSeriesCount(); i++) {
tempRenderer.setSeriesPaint(i, getSeriesColor(i));
tempRenderer.setSeriesShapesVisible(i, false);
}
plot.setRenderer(0, tempRenderer);
NumberAxis tempAxis = (NumberAxis) plot.getRangeAxis();
tempAxis.setLabelFont(axisLabelFont);
tempAxis.setTickLabelFont(tickLabelFont);
tempAxis.setLabelPaint(axisLabelColor);
tempAxis.setTickLabelPaint(axisLabelColor);
double minTemperature = calculateMinTemperature(temperatureStats);
double maxTemperature = calculateMaxTemperature(temperatureStats);
tempAxis.setRange(0, 100);
tempAxis.setAutoRangeIncludesZero(false);
tempAxis.setLowerMargin(0.05);
tempAxis.setUpperMargin(0.05);
XYDataset humidityDataset = createMultiHumidityDataset(reportData);
NumberAxis humidityAxis = new NumberAxis("Humidity (%)");
double minHumidity = calculateMinHumidity(humidityStatistics);
double maxHumidity = calculateMaxHumidity(humidityStatistics);
humidityAxis.setLabelFont(axisLabelFont);
humidityAxis.setTickLabelFont(tickLabelFont);
humidityAxis.setLabelPaint(axisLabelColor);
humidityAxis.setTickLabelPaint(axisLabelColor);
humidityAxis.setRange(0, 100);
humidityAxis.setTickUnit(new NumberTickUnit(10));
humidityAxis.setUpperMargin(0.05);
humidityAxis.setLowerMargin(0.05);
humidityAxis.setAutoRangeIncludesZero(false);
plot.setRangeAxis(1, humidityAxis);
plot.setDataset(1, humidityDataset);
plot.mapDatasetToRangeAxis(1, 1);
XYBezierRenderer humidityRenderer = new XYBezierRenderer(5,0.05);
for (int i = 0; i < humidityDataset.getSeriesCount(); i++) {
humidityRenderer.setSeriesPaint(i, getSeriesColor(i + temperatureDataset.getSeriesCount()));
humidityRenderer.setSeriesShapesVisible(i, false);
}
plot.setRenderer(1, humidityRenderer);
LegendItemCollection legendItems = new LegendItemCollection();
XYItemRenderer renderer0 = plot.getRenderer(0);
XYItemRenderer renderer1 = plot.getRenderer(1);
for (int i = 0; i < temperatureDataset.getSeriesCount(); i++) {
Paint seriesPaint = renderer0.getSeriesPaint(i);
LegendItem legendItem = new LegendItem(
temperatureDataset.getSeriesKey(i).toString(),
"",
"",
"",
new Rectangle(10, 10),
seriesPaint
);
legendItem.setLabelPaint(seriesPaint);
legendItems.add(legendItem);
}
for (int i = 0; i < humidityDataset.getSeriesCount(); i++) {
Paint seriesPaint = renderer1.getSeriesPaint(i);
LegendItem legendItem = new LegendItem(
humidityDataset.getSeriesKey(i).toString(),
"",
"",
"",
new Rectangle(10, 10),
seriesPaint
);
legendItem.setLabelPaint(seriesPaint);
legendItems.add(legendItem);
}
plot.setFixedLegendItems(legendItems);
return chart;
}
Код: Выделить всё
private List generateDummyData() {
List dummyData = new ArrayList();
Random random = new Random();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = Calendar.getInstance();calendar.add(Calendar.DAY_OF_YEAR, -30); // Start 30 days ago // Generate data every 7.5 hours (96 points over 30 days)
int hoursPerReading = 7;
int minutesPerReading = 30;
for (int i = 0; i < 96; i++) {
EntityAuditDto dto = new EntityAuditDto();
// Generate timestamp
calendar.add(Calendar.HOUR, hoursPerReading);
calendar.add(Calendar.MINUTE, minutesPerReading);
dto.setDateTime(dateFormat.format(calendar.getTime()));
// Generate data with realistic variations
double timeProgress = i / 95.0; // Normalized time progress (0 to 1)
double dailyCycle = Math.sin(2 * Math.PI * timeProgress * 4); // 4 complete cycles over the period
double weeklyCycle = Math.sin(2 * Math.PI * timeProgress * (4.0/7)); // 4/7 cycles (4 weeks) over the period
// Generate values for each sensor within specified ranges
double t1Base = 55 + 35 * dailyCycle + 5 * weeklyCycle; // 10 to 100
double t2Base = 45 + 10 * dailyCycle + 3 * weeklyCycle; // 30 to 60
double t3Base = 15 + 10 * dailyCycle + 3 * weeklyCycle; // 0 to 30
double h1Base = 75 + 20 * dailyCycle + 3 * weeklyCycle; // 50 to 100
double h2Base = 35 + 10 * dailyCycle + 3 * weeklyCycle; // 20 to 50
// Add random noise and ensure values are within specified ranges
dto.setT1(String.format("%.2f", clamp(t1Base + random.nextGaussian() * 3, 10, 100)));
dto.setT2(String.format("%.2f", clamp(t2Base + random.nextGaussian() * 2, 30, 60)));
dto.setT3(String.format("%.2f", clamp(t3Base + random.nextGaussian() * 2, 0, 30)));
dto.setH1(String.format("%.2f", clamp(h1Base + random.nextGaussian() * 3, 50, 100)));
dto.setH2(String.format("%.2f", clamp(h2Base + random.nextGaussian() * 2, 20, 50)));
dummyData.add(dto);
}
return dummyData;
}
// Helper method to clamp values between min and max
private double clamp(double value, double min, double max) {
return Math.max(min, Math.min(max, value));
}` .
может ли кто-нибудь помочь?
Я пробовал использовать различные значения точности и натяжения. Но, наконец, XYBezierRenderer(5,0.05) добился лучших результатов. https://www.jfree.org/forum/viewtopic.php?t=116831 здесь было предложено использовать собственный класс XYCardinalSplineRenderer, который я попробовал и работал несколько лучше. результаты с ним были хорошие при напряжении 0,05 и сегментах 16? . Я думаю, что решение было еще в 2014 году и не включено в jfreechart. Может ли кто-нибудь помочь мне с этим?
Подробнее здесь: https://stackoverflow.com/questions/790 ... dinalsplin