krysalis-jcharts/src/java/org/krysalis/jcharts/axisChart StackedBarChart3D.java,NONE,1.1 AxisChart.java,1.7,1.8

Chris McKay <[email protected]> Mon, 14 Jun 2004 04:59:11 +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-serv3118/src/java/org/krysalis/jcharts/axisChart

Modified Files:
	AxisChart.java 
Added Files:
	StackedBarChart3D.java 
Log Message:
3D stacked bar chart functionality added

--- NEW FILE: StackedBarChart3D.java ---
/***********************************************************************************************
 * 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 org.krysalis.jcharts.chartData.ChartDataException;
import org.krysalis.jcharts.chartData.interfaces.IAxisChartDataSet;
import org.krysalis.jcharts.imageMap.RectMapArea;
import org.krysalis.jcharts.properties.DataAxisProperties;
import org.krysalis.jcharts.properties.StackedBarChart3DProperties;

import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;


/*************************************************************************************
 *
 * @author Steve Skillcorn/Chris McKay
 * @version $Id: StackedBarChart3D.java,v 1.1 2004/06/14 04:59:09 kiwicmc Exp $
 ************************************************************************************/
abstract class StackedBarChart3D
{

	/********************************************************************************************
	 * Draws the chart
	 *
	 * @param axisChart
	 *********************************************************************************************/
	static void render( AxisChart axisChart, IAxisChartDataSet iAxisChartDataSet ) throws ChartDataException
	{
		Graphics2D g2d = axisChart.getGraphics2D();
		StackedBarChart3DProperties stackedBarChart3DProperties = (StackedBarChart3DProperties) iAxisChartDataSet.getChartTypeProperties();


		float barWidth;

		//---y axis position on screen to start drawing.
		float startingX;
		float startingY;
		float width;
		float height;


		DataAxisProperties dataAxisProperties;


		if( axisChart.getAxisProperties().isPlotHorizontal() )
		{
			dataAxisProperties = (DataAxisProperties) axisChart.getAxisProperties().getXAxisProperties();
			barWidth = axisChart.getYAxis().getScalePixelWidth() * stackedBarChart3DProperties.getPercentage();
    
			startingX = axisChart.getXAxis().getZeroLineCoordinate();
			startingY = axisChart.getYAxis().getLastTickY() - (barWidth / 2);
			width = 0;
			height = barWidth;
			Rectangle2D.Float rectangle = new Rectangle2D.Float( startingX, startingY, width, height );

			StackedBarChart3D.horizontalPlot( axisChart, iAxisChartDataSet, stackedBarChart3DProperties, dataAxisProperties, g2d, rectangle, startingX );
		}
		else
		{
			dataAxisProperties = (DataAxisProperties) axisChart.getAxisProperties().getYAxisProperties();
			barWidth = axisChart.getXAxis().getScalePixelWidth() * stackedBarChart3DProperties.getPercentage();

			startingX = axisChart.getXAxis().getTickStart() - (barWidth / 2);
			startingY = axisChart.getYAxis().getZeroLineCoordinate();
			width = barWidth;
			height = 0;
			Rectangle2D.Float rectangle = new Rectangle2D.Float( startingX, startingY, width, height );

			StackedBarChart3D.verticalPlot( axisChart, iAxisChartDataSet, stackedBarChart3DProperties, dataAxisProperties, g2d, rectangle, startingY );
		}
	}


	/**************************************************************************************
	 *
	 * @param axisChart
	 * @param iAxisChartDataSet
	 * @param stackedBarChartProperties
	 * @param dataAxisProperties
	 * @param g2d
	 * @param rectangle
	 * @param startingX
	 **************************************************************************************/
	private static void horizontalPlot( AxisChart axisChart,
													IAxisChartDataSet iAxisChartDataSet,
													StackedBarChart3DProperties stackedBarChart3DProperties,
													DataAxisProperties dataAxisProperties,
													Graphics2D g2d,
													Rectangle2D.Float rectangle,
													float startingX ) throws ChartDataException
	{
		int imageMapLabelIndex = axisChart.getYAxis().getNumberOfScaleItems() - 1;

		//LOOP
		//---initial postion of each line.
		for( int i = 0; i < iAxisChartDataSet.getNumberOfDataItems(); i++ )
		{
			//---draw each bar in stack
			for( int j = 0; j < iAxisChartDataSet.getNumberOfDataSets(); j++ )
			{
				//---if segment has a zero value, draw nothing.
				if( iAxisChartDataSet.getValue( j, i ) == 0 )
				{
					continue;
				}
				else if( iAxisChartDataSet.getValue( j, i ) < 0 )
				{
//todo i think we could support this, but it can wait
					throw new ChartDataException( "Negative values in Stacked Bar charts are not supported yet... Coming soon..." );
/*
					rectangle.x = axisChart.getXAxis().computeAxisCoordinate( axisChart.getXAxis().getOrigin(),
																								 iAxisChartDataSet.getValue( 0, i ),
																								 dataAxisProperties.getScaleCalculator().getMinValue() );
					rectangle.width = startingX - rectangle.x;
*/
				}
				else
				{

					rectangle.width = BarChart.computeScaleHeightOfValue( iAxisChartDataSet.getValue( j, i ), axisChart.getXAxis().getOneUnitPixelSize() );


					//rectangle.x = startingX;
					//rectangle.width = BarChart.computeScaleHeightOfValue( iAxisChartDataSet.getValue( j, i ), axisChart.getXAxis().getOneUnitPixelSize() );
				}


				g2d.setPaint( iAxisChartDataSet.getPaint( j ) );
				g2d.fill( rectangle );

				if( stackedBarChart3DProperties.getShowOutlinesFlag() )
				{
					stackedBarChart3DProperties.getBarOutlineStroke().draw( g2d, rectangle );
				}


				//---if we are generating an ImageMap, store the image coordinates
				if( axisChart.getGenerateImageMapFlag() )
				{
					String label = null;
					if( axisChart.getYAxis().getAxisLabelsGroup() != null )
					{
						label = axisChart.getYAxis().getAxisLabelsGroup().getTextTag( imageMapLabelIndex ).getText();
					}
/* TODO this fix to be added later for combo charts and the ability todetermine which image map relates to what DataSet
					RectMapArea area = new RectMapArea(rectangle, iAxisChartDataSet.getValue(j, i), label, iAxisChartDataSet.getLegendLabel(j));
					int[] index = new int[2];
					index[0] = j;
					index[1] = i;
					area.setIndex(index);
					area.setKey("StackedBarChart3D");
					axisChart.getImageMap().addImageMapArea(area);
 */
				}

				rectangle.x += rectangle.width;
			}

			imageMapLabelIndex--;

			rectangle.y += axisChart.getYAxis().getScalePixelWidth();
			rectangle.x = startingX;
		}
	}


	/**************************************************************************************
	 *
	 * @param axisChart
	 * @param iAxisChartDataSet
	 * @param stackedBarChartProperties
	 * @param dataAxisProperties
	 * @param g2d
	 * @param rectangle
	 * @param startingY
	 **************************************************************************************/
	private static void verticalPlot( AxisChart axisChart,
												 IAxisChartDataSet iAxisChartDataSet,
												 StackedBarChart3DProperties stackedBarChart3DProperties,
												 DataAxisProperties dataAxisProperties,
												 Graphics2D g2d,
												 Rectangle2D.Float rectangle,
												 float startingY )
	{
		//IDataSeries iDataSeries= (IDataSeries) axisChart.getIAxisDataSeries();

		//LOOP
		//---initial postion of each line.
		for( int i = 0; i < iAxisChartDataSet.getNumberOfDataItems(); i++ )
		{
			//---draw each bar in stack
			for( int j = 0; j < iAxisChartDataSet.getNumberOfDataSets(); j++ )
			{
				//---if segment has a zero value, draw nothing.
				if( iAxisChartDataSet.getValue( j, i ) == 0 )
				{
					continue;
				}

				rectangle.height = BarChart.computeScaleHeightOfValue( iAxisChartDataSet.getValue( j, i ), axisChart.getYAxis().getOneUnitPixelSize() );
				rectangle.y -= rectangle.height;

        draw3DRect(g2d, rectangle, iAxisChartDataSet.getPaint(j), stackedBarChart3DProperties);
				
				if( stackedBarChart3DProperties.getShowOutlinesFlag()) {
					stackedBarChart3DProperties.getBarOutlineStroke().draw( g2d, rectangle );
				}

				//---if we are generating an ImageMap, store the image coordinates
				if( axisChart.getGenerateImageMapFlag() )
				{
					String label = null;
					if( axisChart.getXAxis().getAxisLabelsGroup() != null )
					{
						label = axisChart.getXAxis().getAxisLabelsGroup().getTextTag( i ).getText();
					}
/* TODO this fix to be added later for combo charts and the ability todetermine which image map relates to what DataSet
a = new RectMapArea(rectangle, iAxisChartDataSet.getValue(j, i), label, iAxisChartDataSet.getLegendLabel(j));
          int[] index = new int[2];
          index[0] = j;
          index[1] = i;
          area.setIndex(index);
          area.setKey("StackedBarChart3D");
					axisChart.getImageMap().addImageMapArea(area);
*/
				}

			}

			rectangle.x += axisChart.getXAxis().getScalePixelWidth();
			rectangle.y = startingY;
		}
	}
  
  private static void  draw3DRect(Graphics2D g2d, Rectangle2D.Float rectangle, Paint paint, StackedBarChart3DProperties props) {
    GeneralPath       poly;
    float             x, y, depth, width, height, offset;
    Color             color;

    //The rounding stops a lighter shade possibily appearing at the join of the
    //bar and the z axis side due to antialiasing at cross pixel points.
    x = Math.round(rectangle.x);
    width = Math.round(rectangle.width);
    y = rectangle.y;
    depth = props.getDepth();
    height = rectangle.height;
    offset = depth;

    //The bar
    g2d.setPaint(paint);
    g2d.fill(new Rectangle2D.Float(x, y, width, height));
    color = (Color) paint;
    g2d.setPaint(getTopColor(color));
    //The top
    poly = new GeneralPath();
    poly.moveTo(x, y);
    poly.lineTo(x + offset, y - offset);
    poly.lineTo(x + offset + width, y - offset);
    poly.lineTo(x + width, y);
    poly.closePath();
    g2d.fill(poly);
    if (props.getShowOutlinesFlag()) {
      props.getBarOutlineStroke().draw(g2d, poly);
    }
    //The side
    g2d.setPaint(getBackColor(color));
    poly = new GeneralPath();
    poly.moveTo(x + width, y);
    poly.lineTo(x + width + offset, y - offset);
    poly.lineTo(x + width + offset, y - offset + height);
    poly.lineTo(x + width, y + height);
    poly.closePath();
    g2d.fill(poly);
    if (props.getShowOutlinesFlag()) {
      props.getBarOutlineStroke().draw(g2d, poly);
    }

    if (props.getShowOutlinesFlag()) {
      props.getBarOutlineStroke().draw(g2d, new Rectangle2D.Float(x, y, width, height));
    }
    
  }

  
  private static Color getTopColor(Color color) {
    double lightness = lightness(color);

    if (lightness >= 0.90) {
      return (darken(color.getRed(), color.getGreen(), color.getBlue(), 0.100));
    }
    if (lightness <= 0.20) {
      return (lighten(color.getRed(), color.getGreen(), color.getBlue(), 0.600));
    }
    return (lighten(color.getRed(), color.getGreen(), color.getBlue(), 0.600));
  }
  
  public static Color getBackColor(Color color) {
    double lightness = lightness(color);

    if (color == null) {
      return null;
    } 
    if (lightness >= 0.90) {
      return (darken(color.getRed(), color.getGreen(), color.getBlue(), 0.250));
    }
    if (lightness <= 0.20) {
      return (lighten(color.getRed(), color.getGreen(), color.getBlue(), 0.200));
    }
    return (darken(color.getRed(), color.getGreen(), color.getBlue(), 0.250));
  }
  
  private static Color darken(int red, int green, int blue, double percent) throws IllegalArgumentException {
    return new Color(Math.max((int) (red * (1 - percent)), 0), Math.max((int) (green * (1 - percent)), 0), Math.max((int) (blue * (1 - percent)), 0));
  }
  
  private static Color lighten(int red, int green, int blue, double percent) throws IllegalArgumentException {
    int adjustedRed, adjustedGreen, adjustedBlue;

    adjustedRed = red + (int) ((255 - red) * percent);
    adjustedGreen = green + (int) ((255 - green) * percent);
    adjustedBlue = blue + (int) ((255 - blue) * percent);
    return new Color(adjustedRed, adjustedGreen, adjustedBlue);
  }
  
  private static double lightness(Color color) {
    double red, green, blue, max, min;

    if (color == null) {
        return 0;
    } 
    red = color.getRed();
    green = color.getGreen();
    blue = color.getBlue();
    max = (Math.max(red, Math.max(green, blue)) / 255) / 2;
    min = (Math.min(red, Math.min(green, blue)) / 255) / 2;
    return (max + min);
  }
  
}

Index: AxisChart.java
===================================================================
RCS file: /cvsroot/jcharts/krysalis-jcharts/src/java/org/krysalis/jcharts/axisChart/AxisChart.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** AxisChart.java	31 May 2004 16:23:46 -0000	1.7
--- AxisChart.java	14 Jun 2004 04:59:09 -0000	1.8
***************
*** 584,587 ****
--- 584,593 ----
  			StackedBarChart.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet );
  		}
+ 		iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR_STACKED_3D );
+ 		if( iAxisPlotDataSet != null )
+ 		{
+ 			StackedBarChart3D.render( this, ( IAxisChartDataSet ) iAxisPlotDataSet );
+ 		}
+ 
  		iAxisPlotDataSet = this.iAxisDataSeries.getIAxisPlotDataSet( ChartType.BAR_CLUSTERED );
  		if( iAxisPlotDataSet != null )



-------------------------------------------------------
This SF.Net email is sponsored by the new InstallShield X.
From Windows to Linux, servers to mobile, InstallShield X is the
one installation-authoring solution that does it all. Learn more and
evaluate today! http://www.installshield.com/Dev2Dev/0504