Gráfico de dispersão com múltiplas “linhas de dispersão”
-
19-09-2019 - |
Pergunta
Ok, eu conheço o JFreeChart e outros, mas estou codificando meu próprio gráfico de dispersão simples.Já tenho um gráfico de caixa (sem rótulos do eixo y, mas isso não deve ser um grande problema quando explico em meu relatório).
Eu tenho uma classe básica de gráfico de dispersão, mas tentei alterá-la para poder adicionar diferentes valores de dispersão.
Funciona, mas aceita apenas a primeira matriz de dispersão e não desenha o resto.Embora desenhe a primeira matriz de dispersão na cor da última matriz de dispersão...então está semi-funcionando.
Aqui está minha classe ScatterPanel completa:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JPanel;
public class ScatterPanel extends JPanel {
private TwoArray[] values;
private String title;
private String[] color_list;
// Constructor for ScatterPanel
public ScatterPanel(TwoArray[] v, String t, String[] c) {
values = v;
title = t;
color_list = c;
}
/* This will paint the scatter chart
* using the values from the above variables:
* "values", "title" and "color_list"
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// Initialize the titleFont
Font titleFont = new Font("Verdana", Font.BOLD, 16);
FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
// Get the width of the JPanel
Dimension d = getSize();
int clientWidth = d.width;
//int clientHeight = d.height;
// Setup the title position and size
int titleWidth = titleFontMetrics.stringWidth(title);
int title_y = titleFontMetrics.getAscent();
int title_x = (clientWidth - titleWidth) / 2;
// Set the font for the title
g.setFont(titleFont);
// Draw the title
g.drawString(title, title_x, title_y);
// Initialise min and max display scale
double min = -0.5;
double max = 5;
// Iterate through each different algorithm we are comparing
for(int point = 0; point < values.length; point++) {
// Iterate through each algorithm's size array and timing array
for (int i = 0; i < values[point].array_time.length; i++) {
// Find the overall max and min for x and y
double x = (double) values[point].array_size[i];
double y = (double) values[point].array_time[i];
// Adjust max and min to include x and y.
if (x < min)
min = x - 0.5;
if (x > max)
max = x + 0.5;
if (y < min)
min = y - 0.5;
if (y > max)
max = y + 0.5;
}
}
g2.translate(getWidth()/2,getHeight()/2);
g2.scale(getWidth()/(max-min), -getHeight()/(max-min));
g2.translate(-(max+min)/2, -(max+min)/2);
// Horizontal size of a pixel in new coords.
double pixelWidth = (max-min)/getWidth();
// Vertical size of a pixel in new coord.
double pixelHeight = (max-min)/getHeight();
g2.setStroke(new BasicStroke(0));
// Draw the x and y axis
g2.setColor(Color.BLUE);
g2.draw( new Line2D.Double(min,0,max,0));
g2.draw( new Line2D.Double(0,min,0,max));
for(int point = 0; point < values.length; point++) {
if(point % 3 == 0)
g2.setColor(Color.decode(color_list[0]));
else if(point % 3 == 1)
g2.setColor(Color.decode(color_list[4]));
else if(point % 3 == 2)
g2.setColor(Color.decode(color_list[8]));
for (int i = 0; i < values[point].array_time.length; i++) {
long x = values[point].array_size[i];
long y = values[point].array_time[i];
// Plot the x-y co-ords
g2.draw(new Line2D.Double(x-3*pixelWidth,y,x+3*pixelWidth,y));
g2.draw(new Line2D.Double(x,y-3*pixelHeight,x,y+3*pixelHeight));
}
}
}
}
TwoArray é usado apenas para armazenar dois arrays longos.
Dentro da minha classe de interface principal, desenho um gráfico de dispersão como este:
for(int i = 0; i < scat_size.length; i++)
scat_size[i] = i;
for(int i = 0; i < scat_times.length; i++)
scat_times[i] = i;
// This should be 1,1 2,2 3,3 etc. in Red
scatter_values[0] = new TwoArray(scat_size, scat_times);
// Trying to test a large co-ord so this should be green
scat_size[2] = 70;
scat_times[2] = 20;
scatter_values[1] = new TwoArray(scat_size, scat_times);
// Trying to test another different co-ord so this should be blue
scat_size[2] = 3;
scat_times[2] = 7;
scatter_values[2] = new TwoArray(scat_size, scat_times);
myScatter = new ScatterPanel(scatter_values, scat_title, color_list);
Um JPanel está definido como myScatter.Ele funciona e desenha o scatter muito bem, mas não o desenha com pontos de cores diferentes, e desenha o "dispersor vermelho" na cor azul.
Saúde Gente.
P.S.Eu sei que ainda não tenho nenhum código que desenhe uma linha curva através do scatter, vou trabalhar nisso depois de terminar esta parte =)
Solução
scatter_values[] conterá um ponteiro para os arrays scat_size e scat_times.Você está alterando os valores nessas matrizes, portanto a alteração será aplicada a todos os itens da matriz scatter_values.Assim, ele desenhará o terceiro gráfico três vezes um sobre o outro.
Você precisa adicionar uma dimensão aos arrays:
for(int j = 0; j < 3; j++) {
for(int i = 0; i < scat_size.length; i++)
scat_size[j][i] = i;
for(int i = 0; i < scat_times.length; i++)
scat_times[j][i] = i;
}
// This should be 1,1 2,2 3,3 etc. in Red
scatter_values[0] = new TwoArray(scat_size[0], scat_times[0]);
// Trying to test a large co-ord so this should be green
scat_size[1][2] = 70;
scat_times[1][2] = 20;
scatter_values[1] = new TwoArray(scat_size[1], scat_times[1]);
// Trying to test another different co-ord so this should be blue
scat_size[2][2] = 3;
scat_times[2][2] = 7;
scatter_values[2] = new TwoArray(scat_size[2], scat_times[2]);
myScatter = new ScatterPanel(scatter_values, scat_title, color_list);