From: Nathaniel G. A. <nat...@us...> - 2004-08-13 01:47:36
|
Update of /cvsroot/jcharts/krysalis-jcharts/src/java/org/krysalis/jcharts/axisChart In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20451/src/java/org/krysalis/jcharts/axisChart Added Files: RegressionChart.java Log Message: --- NEW FILE: RegressionChart.java --- /***************************************************************************************** * File Info: $Id: RegressionChart.java,v 1.1 2004/08/13 01:47:19 nathaniel_auvil Exp $ * Copyright (C) 2002 Author: Nathaniel G. Auvil Contributor(s): * * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved. * * Redistribution and use of this software and associated documentation ("Software"), with * or without modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain copyright statements and notices. * Redistributions must also contain a copy of this document. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote * products derived from this Software without prior written permission of Nathaniel G. * Auvil. For written permission, please contact nat...@us... * * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" * appear in their names without prior written permission of Nathaniel G. Auvil. jCharts * is a registered trademark of Nathaniel G. Auvil. * * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL jCharts OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ****************************************************************************************/ package org.krysalis.jcharts.axisChart; import java.awt.*; import java.awt.geom.*; import java.util.Vector; import java.util.Enumeration; import org.krysalis.jcharts.axisChart.axis.YAxis; import org.krysalis.jcharts.chartData.interfaces.IAxisChartDataSet; import org.krysalis.jcharts.chartData.interfaces.IDataSeries; import org.krysalis.jcharts.imageMap.CircleMapArea; import org.krysalis.jcharts.properties.LineChartProperties; import org.krysalis.jcharts.properties.PropertyException; public class RegressionChart { // STUFF FOR REGRESSION int numberLocs = 0; int sumxx = 0; int sumyy = 0; int sumxy = 0; int sumx = 0; int sumy = 0; double Sxx, Sxy, Syy; double a, b; //regression coefficients Vector v = new Vector(); //vector of points Vector residuals = new Vector(); //vector of residuals public RegressionChart() { }; private double figureY( YAxis yAxis, double num ) { return yAxis.computeAxisCoordinate( yAxis.getOrigin(), num, yAxis.getScaleCalculator().getMinValue() ); } /*************************************************************************************** * Draws the chart * * @param axisChart * @param iAxisChartDataSet * @throws PropertyException **************************************************************************************/ public void render( AxisChart axisChart, IAxisChartDataSet iAxisChartDataSet ) throws PropertyException { Graphics2D g2d = axisChart.getGraphics2D(); LineChartProperties lineChartProperties = (LineChartProperties) iAxisChartDataSet.getChartTypeProperties(); lineChartProperties.validate( iAxisChartDataSet ); //DataAxisProperties dataAxisProperties= (DataAxisProperties) // axisChart.getAxisProperties().getYAxisProperties(); IDataSeries iDataSeries = (IDataSeries) axisChart.getIAxisDataSeries(); //---cache the computed values float[][] yAxisCoordinates = new float[iAxisChartDataSet.getNumberOfDataSets()][iAxisChartDataSet.getNumberOfDataItems()]; //---need this for image map calculation float xMapCoordinate = axisChart.getXAxis().getTickStart(); //LOOP for( int j = 0; j < iAxisChartDataSet.getNumberOfDataItems(); j++ ) { //LOOP for( int i = 0; i < yAxisCoordinates.length; i++ ) { if( iAxisChartDataSet.getValue( i, j ) != Double.NaN ) { yAxisCoordinates[i][j] = axisChart.getYAxis().computeAxisCoordinate( axisChart.getYAxis().getOrigin(), iAxisChartDataSet.getValue( i, j ), axisChart .getYAxis() .getScaleCalculator() .getMinValue() ); addLoc( new Loc( j, iAxisChartDataSet.getValue( i, j ) ) ); //---if we are generating an ImageMap, store the image coordinates if( axisChart.getGenerateImageMapFlag() ) { String label; if( axisChart.getXAxis().getAxisLabelsGroup() != null ) { label = axisChart.getXAxis().getAxisLabelsGroup().getTextTag( j ).getText(); } else { label = null; } axisChart.getImageMap().addImageMapArea( new CircleMapArea( xMapCoordinate, yAxisCoordinates[i][j], iAxisChartDataSet.getValue( i, j ), label, iAxisChartDataSet.getLegendLabel( i ) ) ); } } else { yAxisCoordinates[i][j] = Float.NaN; } } xMapCoordinate += axisChart.getXAxis().getScalePixelWidth(); } AffineTransform originalTransform = null; double[] cornerXOffset = null; double[] cornerYOffset = null; //---check if there are any points to display if( lineChartProperties.getShapes() != null ) { //---when centering the shapes on the points, need x and y offset to do this cornerXOffset = new double[iAxisChartDataSet.getNumberOfDataSets()]; cornerYOffset = new double[iAxisChartDataSet.getNumberOfDataSets()]; //---get the original transform so can reset it. originalTransform = g2d.getTransform(); Rectangle2D rectangle; //LOOP //---pre-compute the dimensions of each Shape so do not do it in loop. for( int i = 0; i < iAxisChartDataSet.getNumberOfDataSets(); i++ ) { if( lineChartProperties.getShapes()[i] != null ) { rectangle = lineChartProperties.getShapes()[i].getBounds2D(); cornerXOffset[i] = rectangle.getWidth() / 2; cornerYOffset[i] = rectangle.getHeight() / 2; Vector v = regress(); // y = yoffset + slope(x) double yoffset, slope; // round to 5 places yoffset = (Math.round( 1.0E5 * a )) * 1.0E-5; slope = (Math.round( 1.0E5 * b )) * 1.0E-5; g2d.setPaint( iAxisChartDataSet.getPaint( i ) ); //g2d.fill( lineChartProperties.getShapes()[ i ] ); g2d.setStroke( lineChartProperties.getLineStrokes()[i] ); //Line2D.Double line = new Line2D.Double(start.x, start.y, end.x, end.y); Line2D.Double line = new Line2D.Double( axisChart.getXAxis().getTickStart(), figureY( axisChart.getYAxis(), (yoffset + slope * 0) ), axisChart.getXAxis().getTickStart() + axisChart.getXAxis().getScalePixelWidth() * (v.size()-1), figureY( axisChart.getYAxis(), (yoffset + slope * v.size()) ) ); //g2d.fill( line ); g2d.draw( line ); g2d.setTransform( originalTransform ); } } } //String form = "formula y = "+String.valueOf(yoffset)+" + // "+String.valueOf(slope)+"x"; //g2d.drawString(form , 151, 156); //---init for first segment /* * Line2D.Float line=new Line2D.Float( axisChart.getXAxis().getTickStart(), * yAxisCoordinates[ 0 ][ 0 ], axisChart.getXAxis().getTickStart(), yAxisCoordinates[ * 0 ][ 0 ] ); */ //---make sure not plotting a chart with only one data point. /* * if( yAxisCoordinates[ 0 ].length > 1 ) { line.y2= yAxisCoordinates[ 0 ][ 1 ]; } */ //LOOP //---draw each line to the image /* * for( int i=0; i < yAxisCoordinates.length; i++ ) { * line.x1=axisChart.getXAxis().getTickStart(); line.y1=yAxisCoordinates[ i ][ 0 ]; * line.x2=line.x1; * * //LOOP for( int j=1; j < yAxisCoordinates[ 0 ].length; j++ ) { //---if current * point on line should be drawn if( !Float.isNaN( yAxisCoordinates[ i ][ j ] ) ) { * //---if the previous point was not drawn, no line if( Float.isNaN( * yAxisCoordinates[ i ][ j - 1 ] ) ) { * line.x2+=axisChart.getXAxis().getScalePixelWidth(); line.x1=line.x2; * line.y1=yAxisCoordinates[ i ][ j ]; line.y2=yAxisCoordinates[ i ][ j ]; * * continue; } * * * line.x2+=axisChart.getXAxis().getScalePixelWidth(); line.y2=yAxisCoordinates[ i ][ * j ]; * * g2d.setPaint( iAxisChartDataSet.getPaint( i ) ); g2d.setStroke( * lineChartProperties.getLineStrokes()[ i ] ); g2d.draw( line ); * * //---plot the Point if( lineChartProperties.getShapes()[ i ] != null ) { * //---translate the Shape into position. g2d.translate( line.x1 - cornerXOffset[ i ], * line.y1 - cornerYOffset[ i ] ); * * g2d.setPaint( iAxisChartDataSet.getPaint( i ) ); g2d.fill( * lineChartProperties.getShapes()[ i ] ); * * //---translate back to the original position g2d.setTransform( originalTransform ); } * * line.x1=line.x2; line.y1=line.y2; } else { if( ( !Float.isNaN( yAxisCoordinates[ i ][ * j - 1 ] ) ) && ( lineChartProperties.getShapes()[ i ] != null ) ) { //---translate * the Shape into position. g2d.translate( line.x1 - cornerXOffset[ i ], line.y1 - * cornerYOffset[ i ] ); * * g2d.setPaint( iAxisChartDataSet.getPaint( i ) ); g2d.fill( * lineChartProperties.getShapes()[ i ] ); * * //---translate back to the original position g2d.setTransform( originalTransform ); } * * line.x2+=axisChart.getXAxis().getScalePixelWidth(); line.x1=line.x2; } } * * * //---put the last shape on the line if( ( !Float.isNaN( yAxisCoordinates[ i ][ * yAxisCoordinates[ i ].length - 1 ] ) ) && ( lineChartProperties.getShapes()[ i ] != * null ) ) { //---translate the Shape into position. g2d.translate( line.x2 - * cornerXOffset[ i ], line.y2 - cornerYOffset[ i ] ); * * g2d.setPaint( iAxisChartDataSet.getPaint( i ) ); g2d.fill( * lineChartProperties.getShapes()[ i ] ); * * //---translate back to the original position g2d.setTransform( originalTransform ); } } */ } private Vector regress() { Vector resid = new Vector(); Loc p, q; double currentResidual; double n = (double) numberLocs; Sxx = sumxx - sumx * sumx / n; Syy = sumyy - sumy * sumy / n; Sxy = sumxy - sumx * sumy / n; b = Sxy / Sxx; a = (sumy - b * sumx) / n; for( Enumeration e = v.elements(); e.hasMoreElements(); ) { p = (Loc) e.nextElement(); currentResidual = p.y - (a + b * p.x); q = new Loc( p.x, (int) currentResidual ); resid.addElement( q ); } return resid; } private void calculate( int numLocs ) { if( numberLocs > 1 ) { residuals = regress(); } } private void addLoc( Loc p ) { v.addElement( p ); numberLocs++; sumx += p.x; sumy += p.y; sumxx += p.x * p.x; sumyy += p.y * p.y; sumxy += p.x * p.y; } private static class Loc { public double x; public double y; public Loc( double x, double y ) { this.x = x; this.y = y; } public String toString() { return "[" + this.x + ", " + this.y + "]"; } } } |