krysalis-jcharts/src/java/org/krysalis/jcharts/axisChart RegressionChart.java,NONE,1.1

"Nathaniel G. Auvil" <[email protected]> Fri, 13 Aug 2004 01:47:22 +0000
Newsgroups gmane.comp.krysalis.jcharts.cvs
Message-ID <[email protected]>
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 [email protected]
 * 
 * 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 + "]";
		}
	}

}


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285