JFreeChart et XYSplineRenderer
Fermé
bt33
Messages postés
5
Date d'inscription
mardi 22 janvier 2013
Statut
Membre
Dernière intervention
25 janvier 2013
-
Modifié par bt33 le 22/01/2013 à 18:42
bt33 - 29 janv. 2013 à 10:05
bt33 - 29 janv. 2013 à 10:05
8 réponses
Bonjour,
J'ai pu voir tes images (depuis chez moi!). J'ai malheureusement le même résultat alors que ce que je devrais obtenir est ceci :
<a href='http://imageshack.us/a/img94/4125/jfimageoriginale.png'>Image</a>
Quelque chose me dit que ça a l'air impossible.
En tout cas, merci de passer du temps sur mon problème.
J'ai pu voir tes images (depuis chez moi!). J'ai malheureusement le même résultat alors que ce que je devrais obtenir est ceci :
<a href='http://imageshack.us/a/img94/4125/jfimageoriginale.png'>Image</a>
Quelque chose me dit que ça a l'air impossible.
En tout cas, merci de passer du temps sur mon problème.
KX
Messages postés
16754
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 020
22 janv. 2013 à 19:00
22 janv. 2013 à 19:00
Est-ce que tu aurais un bout de code pour tester ?
bt33
Messages postés
5
Date d'inscription
mardi 22 janvier 2013
Statut
Membre
Dernière intervention
25 janvier 2013
24 janv. 2013 à 10:45
24 janv. 2013 à 10:45
Bonjour,
Voici du code simplement recupéré du code de l'appli qui reproduit mon pb (il genere une image jfreechart sur D:) !
Merci
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;
public class MonSpline {
private XYSeriesCollection dataset = new XYSeriesCollection();
private JFreeChart jFreeChart;
private XYPlot plot;
public void creation() throws IOException{
jFreeChart = ChartFactory.createXYLineChart("", "", "", dataset,
PlotOrientation.VERTICAL, false,
false,
false
);
plot = (XYPlot) jFreeChart.getPlot();
plot.setBackgroundPaint(Color.white);
plot.setOutlineVisible(true);
addRepere();
affecteData();
XYLineAndShapeRenderer renderer2 = new XYSplineRenderer();
renderer2.setSeriesShapesVisible(0, false);
BasicStroke newStroke = new BasicStroke((float) (4.0));
renderer2.setSeriesStroke(0, newStroke);
renderer2.setSeriesPaint(0, java.awt.Color.black);
renderer2.setSeriesVisibleInLegend(0,false);
plot.setRenderer(0, renderer2);
// Creation de l'image finale
BufferedImage bufferImage = jFreeChart.createBufferedImage(
1200,
1500, BufferedImage.BITMASK, null);
String fileJFreeChart = "D:/JF_IMAGE.PNG";
ChartUtilities.saveChartAsPNG(new File(fileJFreeChart), jFreeChart, 1200, 1500, null, false, 0);
}
/*
* Creation des axes
*/
public void addRepere() {
//Axe des abscisses
NumberAxis axeAbscisse = new NumberAxis("Axe 1");
axeAbscisse.setAxisLinePaint(Color.BLACK);
axeAbscisse.setLabelPaint(Color.BLACK);
axeAbscisse.setPositiveArrowVisible(true);
axeAbscisse.setNegativeArrowVisible(true);
axeAbscisse.setInverted(false);
axeAbscisse.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
axeAbscisse.setAutoRangeIncludesZero(false);
axeAbscisse.setRange(-1,18.0);
axeAbscisse.setVisible(true);
axeAbscisse.setTickUnit(new NumberTickUnit(Math.abs(1.0)));
axeAbscisse.setTickMarkOutsideLength(11.0f);// longueur du ticker
axeAbscisse.setMinorTickCount(9);
axeAbscisse.setMinorTickMarksVisible(true);
axeAbscisse.setMinorTickMarkOutsideLength(10.0f);
axeAbscisse.setTickMarkStroke(new BasicStroke(2.0f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
axeAbscisse.setTickLabelPaint(Color.BLACK);
axeAbscisse.setTickLabelPaint(Color.BLACK);
plot.setDomainAxis(axeAbscisse);
plot.getDomainAxis().setVisible(true);
// axe vertical gauche
//---------------------------------------
NumberAxis axeOrdonnee1 = new NumberAxis("Axe 2");
axeOrdonnee1.setPositiveArrowVisible(true);
axeOrdonnee1.setNegativeArrowVisible(true);
axeOrdonnee1.setInverted(false);
axeOrdonnee1.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
axeOrdonnee1.setAutoRangeIncludesZero(false);
axeOrdonnee1.setAxisLinePaint(Color.BLACK);
axeOrdonnee1.setLabelPaint(Color.BLACK);
axeOrdonnee1.setRange(0.0, 100.0);
axeOrdonnee1.setAutoRange(false);
axeOrdonnee1.setTickUnit(new NumberTickUnit(10.0));
axeOrdonnee1.setTickMarkOutsideLength(11.0f);
axeOrdonnee1.setTickLabelsVisible(true);
axeOrdonnee1.setTickLabelPaint(Color.black);
axeOrdonnee1.setMinorTickCount(4);
axeOrdonnee1.setMinorTickMarksVisible(true);
axeOrdonnee1.setMinorTickMarkOutsideLength(10.0f);
axeOrdonnee1.setTickMarkStroke(new BasicStroke(2.0f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
axeOrdonnee1.setTickLabelInsets(new RectangleInsets(4, 15, 4, 4));
axeOrdonnee1.setTickLabelPaint(Color.BLACK);
plot.setRangeAxis(0, axeOrdonnee1);
plot.getRangeAxis().setVisible(true);
}
/**
* Crée les series
*/
void affecteData(){
final XYSeriesCollection dataset = new XYSeriesCollection();
Double[] tabAbscisses = new Double []{0.00644026, -0.0744425, 0.147181, 0.82995, 0.878902, -0.102915};
Double[] tabOrdonnes = new Double []{0.0, 10.0, 20.0, 30.0, 40.0, 50.0};
dataset.addSeries(affecteSerie(tabAbscisses, tabOrdonnes, "maCoubre"));
plot.setDataset(0,dataset);
}
/**
* Valorise les XYSeries
* @param tabAbsisses
* @param tabOrdonnes
* @param name
* @return
*/
public XYSeries affecteSerie(Double[] tabAbsisses,Double[] tabOrdonnes, String name ){
XYSeries series = new XYSeries(name, false, true);
for (int indexgrille = 0; indexgrille < tabAbsisses.length; indexgrille++) {
double abscisse = tabAbsisses[indexgrille];
double ordonnee = tabOrdonnes[indexgrille];
series.add(abscisse, ordonnee);
}
return series;
}
}
Voici du code simplement recupéré du code de l'appli qui reproduit mon pb (il genere une image jfreechart sur D:) !
Merci
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;
public class MonSpline {
private XYSeriesCollection dataset = new XYSeriesCollection();
private JFreeChart jFreeChart;
private XYPlot plot;
public void creation() throws IOException{
jFreeChart = ChartFactory.createXYLineChart("", "", "", dataset,
PlotOrientation.VERTICAL, false,
false,
false
);
plot = (XYPlot) jFreeChart.getPlot();
plot.setBackgroundPaint(Color.white);
plot.setOutlineVisible(true);
addRepere();
affecteData();
XYLineAndShapeRenderer renderer2 = new XYSplineRenderer();
renderer2.setSeriesShapesVisible(0, false);
BasicStroke newStroke = new BasicStroke((float) (4.0));
renderer2.setSeriesStroke(0, newStroke);
renderer2.setSeriesPaint(0, java.awt.Color.black);
renderer2.setSeriesVisibleInLegend(0,false);
plot.setRenderer(0, renderer2);
// Creation de l'image finale
BufferedImage bufferImage = jFreeChart.createBufferedImage(
1200,
1500, BufferedImage.BITMASK, null);
String fileJFreeChart = "D:/JF_IMAGE.PNG";
ChartUtilities.saveChartAsPNG(new File(fileJFreeChart), jFreeChart, 1200, 1500, null, false, 0);
}
/*
* Creation des axes
*/
public void addRepere() {
//Axe des abscisses
NumberAxis axeAbscisse = new NumberAxis("Axe 1");
axeAbscisse.setAxisLinePaint(Color.BLACK);
axeAbscisse.setLabelPaint(Color.BLACK);
axeAbscisse.setPositiveArrowVisible(true);
axeAbscisse.setNegativeArrowVisible(true);
axeAbscisse.setInverted(false);
axeAbscisse.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
axeAbscisse.setAutoRangeIncludesZero(false);
axeAbscisse.setRange(-1,18.0);
axeAbscisse.setVisible(true);
axeAbscisse.setTickUnit(new NumberTickUnit(Math.abs(1.0)));
axeAbscisse.setTickMarkOutsideLength(11.0f);// longueur du ticker
axeAbscisse.setMinorTickCount(9);
axeAbscisse.setMinorTickMarksVisible(true);
axeAbscisse.setMinorTickMarkOutsideLength(10.0f);
axeAbscisse.setTickMarkStroke(new BasicStroke(2.0f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
axeAbscisse.setTickLabelPaint(Color.BLACK);
axeAbscisse.setTickLabelPaint(Color.BLACK);
plot.setDomainAxis(axeAbscisse);
plot.getDomainAxis().setVisible(true);
// axe vertical gauche
//---------------------------------------
NumberAxis axeOrdonnee1 = new NumberAxis("Axe 2");
axeOrdonnee1.setPositiveArrowVisible(true);
axeOrdonnee1.setNegativeArrowVisible(true);
axeOrdonnee1.setInverted(false);
axeOrdonnee1.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
axeOrdonnee1.setAutoRangeIncludesZero(false);
axeOrdonnee1.setAxisLinePaint(Color.BLACK);
axeOrdonnee1.setLabelPaint(Color.BLACK);
axeOrdonnee1.setRange(0.0, 100.0);
axeOrdonnee1.setAutoRange(false);
axeOrdonnee1.setTickUnit(new NumberTickUnit(10.0));
axeOrdonnee1.setTickMarkOutsideLength(11.0f);
axeOrdonnee1.setTickLabelsVisible(true);
axeOrdonnee1.setTickLabelPaint(Color.black);
axeOrdonnee1.setMinorTickCount(4);
axeOrdonnee1.setMinorTickMarksVisible(true);
axeOrdonnee1.setMinorTickMarkOutsideLength(10.0f);
axeOrdonnee1.setTickMarkStroke(new BasicStroke(2.0f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
axeOrdonnee1.setTickLabelInsets(new RectangleInsets(4, 15, 4, 4));
axeOrdonnee1.setTickLabelPaint(Color.BLACK);
plot.setRangeAxis(0, axeOrdonnee1);
plot.getRangeAxis().setVisible(true);
}
/**
* Crée les series
*/
void affecteData(){
final XYSeriesCollection dataset = new XYSeriesCollection();
Double[] tabAbscisses = new Double []{0.00644026, -0.0744425, 0.147181, 0.82995, 0.878902, -0.102915};
Double[] tabOrdonnes = new Double []{0.0, 10.0, 20.0, 30.0, 40.0, 50.0};
dataset.addSeries(affecteSerie(tabAbscisses, tabOrdonnes, "maCoubre"));
plot.setDataset(0,dataset);
}
/**
* Valorise les XYSeries
* @param tabAbsisses
* @param tabOrdonnes
* @param name
* @return
*/
public XYSeries affecteSerie(Double[] tabAbsisses,Double[] tabOrdonnes, String name ){
XYSeries series = new XYSeries(name, false, true);
for (int indexgrille = 0; indexgrille < tabAbsisses.length; indexgrille++) {
double abscisse = tabAbsisses[indexgrille];
double ordonnee = tabOrdonnes[indexgrille];
series.add(abscisse, ordonnee);
}
return series;
}
}
KX
Messages postés
16754
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 020
24 janv. 2013 à 16:41
24 janv. 2013 à 16:41
Dans affecteData, les données devraient être dans l'ordre croissant des abscisses, pas des ordonnées, sinon ta courbe rebrousse chemin sur les X.
Voici comment trier tes tableaux automatiquement :
Mais sinon, pour que ta courbe soit lisse il faut lui augmenter sa précision lors de sa construction :
Voici comment trier tes tableaux automatiquement :
public static void trier(Double[] abs, Double[] ord) { int n=abs.length; if (n!=ord.length) throw new IllegalArgumentException("Tailles incompatibles"); Point2D.Double[] tab = new Point2D.Double[n]; for (int i=0; i<n; i++) tab[i] = new Point2D.Double(abs[i], ord[i]); Arrays.sort(tab, new Comparator<Point2D.Double>() { public int compare(Point2D.Double d1, Point2D.Double d2) { return Double.compare(d1.x, d2.x); } }); for (int i=0; i<n; i++) { abs[i] = tab[i].x; ord[i] = tab[i].y; } } trier(tabAbscisses,tabOrdonnes); dataset.addSeries(affecteSerie(tabAbscisses, tabOrdonnes, "maCourbe"));
Mais sinon, pour que ta courbe soit lisse il faut lui augmenter sa précision lors de sa construction :
renderer2 = new XYSplineRenderer(20);
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
bt33
Messages postés
5
Date d'inscription
mardi 22 janvier 2013
Statut
Membre
Dernière intervention
25 janvier 2013
25 janv. 2013 à 10:12
25 janv. 2013 à 10:12
Merci pour cette réponse.
Je vais la tester.
Je vais la tester.
bt33
Messages postés
5
Date d'inscription
mardi 22 janvier 2013
Statut
Membre
Dernière intervention
25 janvier 2013
25 janv. 2013 à 10:52
25 janv. 2013 à 10:52
Il y a un léger mieux.
Mais la courbe que je devrais obtenir est particuliere (presque vertical)
Cette courbe part du point (-0.102915,50) et descend en ondulant jusqu'au point (6.44026E-03,0).
Elle descend de l'ordonnée 50, puis 40, 30, 20, 10 puis 0. (ou monte de 0 à 50)
Mon resultat est une courbe saccadée qui va du point en ordonnée 50 puis, 0, puis 20, 10 et 40 (avec abscisses croissants).
Si je remplace le XYLineAndShapeRenderer() par un XYLineAndShapeRenderer(), sans procéder à aucun tri, la courbe s'affiche correctement mais elle n'est pas lissée.
Mais la courbe que je devrais obtenir est particuliere (presque vertical)
Cette courbe part du point (-0.102915,50) et descend en ondulant jusqu'au point (6.44026E-03,0).
Elle descend de l'ordonnée 50, puis 40, 30, 20, 10 puis 0. (ou monte de 0 à 50)
Mon resultat est une courbe saccadée qui va du point en ordonnée 50 puis, 0, puis 20, 10 et 40 (avec abscisses croissants).
Si je remplace le XYLineAndShapeRenderer() par un XYLineAndShapeRenderer(), sans procéder à aucun tri, la courbe s'affiche correctement mais elle n'est pas lissée.
KX
Messages postés
16754
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 020
25 janv. 2013 à 11:35
25 janv. 2013 à 11:35
"Si je remplace le XYLineAndShapeRenderer() par un XYLineAndShapeRenderer()"
Ce n'est pas clair ça...
La seule chose que j'ai faite, c'est remplacer le constructeur par défaut new XYSplineRenderer(); par le constructeur new XYSplineRenderer(20); qui spécifie une précision pour le lissage.
Donc au départ on avait ça : JF_IMAGE_1.PNG
Avec cette petite modification, on a bien lissage et ça donne ça : JF_IMAGE_2.PNG
"Elle descend de l'ordonnée 50, puis 40, 30, 20, 10 puis 0."
Ce n'est pas du tout ce que tu donnes dans le code :
Donc moi j'ai fait un tri pour avoir les abscisses croissantes, ce qui donne,
Ce qui fait ça : JF_IMAGE_3.PNG
Mais ce n'est pas une descente 50,40,30,20,10,0... alors on pourrait le faire bien sûr, mais il faut le dire dans le code !
Ce qui donne ça : JF_IMAGE_4.PNG
Alors il y a effectivement un petit truc "ennuyeux", c'est cette boucle qui remonte alors qu'elle ne devrait peut-être pas, mais c'est parce que le XYSplineRenderer ne fais pas juste un lissage de la courbe, il essaye de deviner ce que devrait être la courbe, et ici il l'approche à équation d'ordre 3, ce qui donne ce petit sursaut.
Ce n'est pas clair ça...
La seule chose que j'ai faite, c'est remplacer le constructeur par défaut new XYSplineRenderer(); par le constructeur new XYSplineRenderer(20); qui spécifie une précision pour le lissage.
Donc au départ on avait ça : JF_IMAGE_1.PNG
Avec cette petite modification, on a bien lissage et ça donne ça : JF_IMAGE_2.PNG
"Elle descend de l'ordonnée 50, puis 40, 30, 20, 10 puis 0."
Ce n'est pas du tout ce que tu donnes dans le code :
Double[] tabAbscisses = new Double []{0.00644026, -0.0744425, 0.147181, 0.82995, 0.878902, -0.102915}; Double[] tabOrdonnes = new Double []{0.0, 10.0, 20.0, 30.0, 40.0, 50.0};
Donc moi j'ai fait un tri pour avoir les abscisses croissantes, ce qui donne,
X = [-0.102915, -0.0744425, 0.00644026, 0.147181, 0.82995, 0.878902] Y = [50.0, 10.0, 0.0, 20.0, 30.0, 40.0]
Ce qui fait ça : JF_IMAGE_3.PNG
Mais ce n'est pas une descente 50,40,30,20,10,0... alors on pourrait le faire bien sûr, mais il faut le dire dans le code !
Double[] tabAbscisses = {-0.102915, -0.0744425, 0.00644026, 0.147181, 0.82995, 0.878902}; Double[] tabOrdonnes = {50.0, 40.0, 30.0, 20.0, 10.0, 0.0};
Ce qui donne ça : JF_IMAGE_4.PNG
Alors il y a effectivement un petit truc "ennuyeux", c'est cette boucle qui remonte alors qu'elle ne devrait peut-être pas, mais c'est parce que le XYSplineRenderer ne fais pas juste un lissage de la courbe, il essaye de deviner ce que devrait être la courbe, et ici il l'approche à équation d'ordre 3, ce qui donne ce petit sursaut.
bt33
Messages postés
5
Date d'inscription
mardi 22 janvier 2013
Statut
Membre
Dernière intervention
25 janvier 2013
25 janv. 2013 à 13:29
25 janv. 2013 à 13:29
Je ne peux pas visualiser tes images.
J'ai un officescan qui bloque...
J'ai un officescan qui bloque...
KX
Messages postés
16754
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 020
25 janv. 2013 à 17:35
25 janv. 2013 à 17:35
"J'ai un officescan qui bloque...". Encore un truc bien inutile...
J'ai mis les images ailleurs mais si ça bloque encore il doit bien y avoir un moyen de dire à ton soft d'accepter quand même ces sites (tu n'es pas en Corée du Nord quand même !)
JF_IMAGE_1. PNG / JF_IMAGE_2. PNG / JF_IMAGE_3. PNG / JF_IMAGE_4. PNG
J'ai mis les images ailleurs mais si ça bloque encore il doit bien y avoir un moyen de dire à ton soft d'accepter quand même ces sites (tu n'es pas en Corée du Nord quand même !)
JF_IMAGE_1. PNG / JF_IMAGE_2. PNG / JF_IMAGE_3. PNG / JF_IMAGE_4. PNG
27 janv. 2013 à 22:48
Ce qui donne : JF_IMAGE_0.PNG, c'est quasiment ce que tu veux... si on tourne la tête ^^
J'avoue ne pas trop connaître jFreeChart, j'aide comme je peux, mais il y a sûrement moyen de faire pivoter automatiquement l'image, ou d'utiliser un autre rendu pour lisser la courbe malgré tout...
27 janv. 2013 à 23:20
28 janv. 2013 à 10:07
28 janv. 2013 à 10:21
Avec le spline on fait une régression polynomiale sur ces points, et pour que ça marche bien il faut que les abscisses se suivent, sinon ça donne un peu n'importe quoi parce que l'algortihme ne doit pas prévoir ce genre de cas. Donc deux solutions soit on ordonne les abscisses (ce qui était ma première idée) mais ça ne correspond pas vraiment à ce que tu cherches, soit on permute abscisses et ordonnées pour faire la régression sur les ordonnées, là ça donne bien ce que tu veux sauf qu'il faudrait réussir à re-permuter les axes une fois la régression effectuée.
Pour l'instant, le mieux que j'ai trouvé c'est donc faire cette petite modification d'orientation :
public void creation() throws IOException{ jFreeChart = ChartFactory.createXYLineChart("", "", "", dataset, PlotOrientation.HORIZONTAL, false, false, false );
29 janv. 2013 à 10:05
Grace à toi j'ai trouvé une version expérimentale de JFreechart qui me donne presque le rendu que j'attends. Je vais essayé d'améliorer mon résultat et je te montrerai une image finale.
Le code que j'ai trouvé recalcule des points et joue en effet sur l'orientation du graphique.
Merci