/** * Copyright (C) 2008-2010, Squale Project - http://www.squale.org * * This file is part of Squale. * * Squale is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or any later version. * * Squale is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Squale. If not, see <http://www.gnu.org/licenses/>. */ /* * Cr�� le 17 ao�t 05 */ package org.squale.squaleweb.util.graph; import java.awt.Rectangle; import java.awt.Shape; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.annotations.XYLineAnnotation; import org.jfree.chart.axis.LogarithmicAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.squale.squaleweb.resources.WebMessages; /** * @author M400843 Cette classe est responsable de la fabrication d'un scatter. * @see AbstractGraphMaker */ public class ScatterMaker extends AbstractGraphMaker { /** * Hauteur du diagramme par d�faut */ public static final int DEFAULT_HEIGHT = 400; /** * Hauteur du diagramme par d�faut */ public static final int DEFAULT_WIDTH = 400; /** * Taille d'un point (carr�) du graphique */ private static final int DEFAULT_POINT_SIZE = 3; /** * Position par d�faut de l'axe horizontal */ private static final int DEFAULT_HORIZONTAL_AXIS_POS = 7; /** * Position par d�faut de l'axe vertical */ private static final int DEFAULT_VERTICAL_AXIS_POS = 10; /** * Marge par d�faut avec les axes. */ private static final double DEFAULT_AXIS_MARGIN = 2; /** * Contient <code>true</code> si des donn�es peuvent �tre ajout�es */ private boolean mCouldAddDatas = true; /** * Dataset contenant les valeurs � mettre dans le diagramme */ private XYSeriesCollection mDataSet; /** * Logger. */ private final static Log LOG = LogFactory.getLog( ScatterMaker.class ); /** * Constructeur par d�faut */ public ScatterMaker() { mDataSet = new XYSeriesCollection(); // Etiquete figurant sur l'axe horizontal (peut etre null) Par d�faut : "v(g)" mXLabel = WebMessages.getString( "scatter.default.axis.domain" ); // Etiquete figurant sur l'axe des valeurs (peut etre null) Par d�faut : "ev(g)" mYLabel = WebMessages.getString( "scatter.default.axis.value" ); } /** * Constructeur avec le titre du diagramme * * @param pTitle titre du diagramme (peut etre <code>null</code>) */ public ScatterMaker( String pTitle ) { this(); mTitle = pTitle; } /** * Constructeur avec le titre du diagramme et les titres des axes * * @param pTitle titre du diagramme (peut etre <code>null</code>) * @param pDomainAxisLabel titre de l'axe horizontal (peut etre <code>null</code>) * @param pValueAxisLabel titre de l'axe des valeurs (peut etre <code>null</code>) */ public ScatterMaker( String pTitle, String pDomainAxisLabel, String pValueAxisLabel ) { mDataSet = new XYSeriesCollection(); mTitle = pTitle; mXLabel = pDomainAxisLabel; mYLabel = pValueAxisLabel; } /** * @see org.squale.squalecommon.util.graph.AbstractGraphMaker#getDefaultHeight() {@inheritDoc} */ protected int getDefaultHeight() { return DEFAULT_HEIGHT; } /** * @see org.squale.squalecommon.util.graph.AbstractGraphMaker#getDefaultWidth() {@inheritDoc} */ protected int getDefaultWidth() { return DEFAULT_WIDTH; } /** * Ajoute une series de valeurs (x, y) au ScatterPlot. <br /> * <b>Attention : </b>les doublons doivent �tre �vit�s pour des raisons de performances On doit toujours avoir * l'�galit� suivante : pHorizontalValues.length == pVerticalValues.length * * @param pName le nom de la s�rie (peut etre <code>null</code> si c'est la premi�re s�rie, dans ce cas, seule * cette s�rie sera ajout�ee) * @param pHorizontalValues les valeurs de l'axe horizontal * @param pVerticalValues les valeurs de l'axe vertical * @return <code>true</code> si tout s'est bien pass�, <code>false</code> sinon */ public boolean addSerie( String pName, Number[] pHorizontalValues, Number[] pVerticalValues ) { boolean ret = false; // si les nombres de valeurs horizontales et verticales sont �gaux // et que l'on peut encore ajouter des valeurs if ( ( pHorizontalValues.length == pVerticalValues.length ) && ( mCouldAddDatas ) ) { ret = true; // � partir d'ici on consid�re que tout va bien se passer if ( null == pName ) { // si aucun nom n'a �t� pass� en param�tre, on ne peut mettre qu'une et une seule courbe if ( mDataSet.getSeries().size() > 0 ) { // si des courbes sont d�j� dans le dataset, on arrete tout, // on ne peut pas ajouter une courbe sans nom ret = false; } else { mCouldAddDatas = false; mShowLegend = false; } } if ( true == ret ) { // si tout s'est bien pass�, on ajoute les valeurs addXYSeries( pName, pHorizontalValues, pVerticalValues ); } } return ret; } /** * Cr�e une XYSeries et l'ajoute. * * @param pName le nom de la s�rie (peut etre <code>null</code> si c'est la premi�re s�rie, dans ce cas, seule * cette s�rie sera ajout�ee). * @param pHorizontalValues les valeurs de l'axe horizontal. * @param pVerticalValues les valeurs de l'axe vertical. */ private void addXYSeries( String pName, Number[] pHorizontalValues, Number[] pVerticalValues ) { String name = pName; if ( null == name ) { // si aucun nom n'a �t� sp�cifi� on affecte le nom par d�faut pour la courbe name = WebMessages.getString( "scatter.undefined.name" ); } XYSeries series = new XYSeries( name ); // pour toutes les abscisses/ordonn�es for ( int i = 0; i < pVerticalValues.length; i++ ) { if ( ( null != pHorizontalValues[i] ) && ( null != pVerticalValues[i] ) ) { // si on a bien une valeur en abscisse et une en ordonn�e, on l'ajoute � la courbe series.add( pHorizontalValues[i], pVerticalValues[i] ); } } mDataSet.addSeries( series ); String[] tab = { Integer.toString( pVerticalValues.length ) }; LOG.debug( WebMessages.getString( "scatter.debug.addseries", tab ) ); } /** * Construit (ou reconstruit) le diagramme puis le retourne * * @return le diagramme JFreeChart. */ protected JFreeChart getChart() { LOG.debug( WebMessages.getString( "method.entry" ) ); JFreeChart retChart = super.getChart(); if ( null == retChart ) { // G�n�ration du Scatterplot retChart = ChartFactory.createScatterPlot( mTitle, mXLabel, mYLabel, mDataSet, PlotOrientation.VERTICAL, mShowLegend, false, false ); ValueAxis domainAxis = retChart.getXYPlot().getDomainAxis(); ValueAxis rangeAxis = retChart.getXYPlot().getRangeAxis(); // D�termination des bornes en abscisse et en ordonn�e double maxDomain = Math.max( domainAxis.getUpperBound(), DEFAULT_VERTICAL_AXIS_POS + DEFAULT_AXIS_MARGIN ); double minDomain = Math.min( domainAxis.getLowerBound(), DEFAULT_VERTICAL_AXIS_POS - DEFAULT_AXIS_MARGIN ); double maxRange = Math.max( rangeAxis.getUpperBound(), DEFAULT_HORIZONTAL_AXIS_POS + DEFAULT_AXIS_MARGIN ); double minRange = Math.min( rangeAxis.getLowerBound(), DEFAULT_HORIZONTAL_AXIS_POS - DEFAULT_AXIS_MARGIN ); // Mise � l'�chelle logarithmique des axes LogarithmicAxis newDomainAxis = new LogarithmicAxis( domainAxis.getLabel() ); LogarithmicAxis newRangeAxis = new LogarithmicAxis( rangeAxis.getLabel() ); // Affectation des bornes en abscisse et en ordonn�e newDomainAxis.setLowerBound( minDomain ); newDomainAxis.setUpperBound( maxDomain ); newRangeAxis.setLowerBound( minRange ); newRangeAxis.setUpperBound( maxRange ); retChart.getXYPlot().setDomainAxis( newDomainAxis ); retChart.getXYPlot().setRangeAxis( newRangeAxis ); // Le point a une taille fixe Shape shape = new Rectangle( DEFAULT_POINT_SIZE, DEFAULT_POINT_SIZE ); retChart.getXYPlot().getRenderer().setShape( shape ); // Annotations XYLineAnnotation horizontalAxis = new XYLineAnnotation( minDomain, DEFAULT_HORIZONTAL_AXIS_POS, maxDomain, DEFAULT_HORIZONTAL_AXIS_POS ); XYLineAnnotation verticalAxis = new XYLineAnnotation( DEFAULT_VERTICAL_AXIS_POS, minRange, DEFAULT_VERTICAL_AXIS_POS, maxRange ); retChart.getXYPlot().addAnnotation( horizontalAxis ); retChart.getXYPlot().addAnnotation( verticalAxis ); super.setChart( retChart ); } LOG.debug( WebMessages.getString( "method.exit" ) ); return retChart; } }