/*******************************************************************************
* Copyright (c) 2008-2009 SWTChart project. All rights reserved.
*
* This code is distributed under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.swtchart.internal.compress;
import java.util.ArrayList;
/**
* A base class for compressor providing default implementations.
*/
public abstract class Compress implements ICompress
{
/** the previous X grid index */
protected int previousXGridIndex;
/** the previous Y grid index */
protected int previousYGridIndex;
/** the configuration for compressor */
protected CompressConfig config;
/** the previous configuration for compressor */
protected CompressConfig prevConfig;
/** the flag indicating whether the data is compressed */
protected boolean compressed;
/** the source X series to be compressed */
protected double[] xSeries = null;
/** the source Y series to be compressed */
protected double[] ySeries = null;
/** the compressed X series */
protected transient double[] compressedXSeries = null;
/** the compressed Y series */
protected transient double[] compressedYSeries = null;
/** the compressed series indexes */
protected transient int[] compressedIndexes = null;
/** the lower value of x range */
protected double xLower;
/** the upper value of x range */
protected double xUpper;
/** the lower value of y range */
protected double yLower;
/** the upper value of y range */
protected double yUpper;
/** the state indicating if x axis is log scale */
private boolean isXLogScale;
/** the state indicating if y axis is log scale */
private boolean isYLogScale;
/** the plot area width in pixels */
private long widthInPixel;
/** the plot area height in pixels */
private long heightInPixel;
/*
* @see ICompress#setXSeries(double[])
*/
public void setXSeries ( double[] xSeries )
{
double[] copiedSeries = new double[xSeries.length];
System.arraycopy ( xSeries, 0, copiedSeries, 0, xSeries.length );
this.xSeries = copiedSeries;
compressedXSeries = copiedSeries;
compressedIndexes = new int[xSeries.length];
for ( int i = 0; i < xSeries.length; i++ )
{
compressedIndexes[i] = i;
}
compressed = false;
}
/*
* @see ICompress#setYSeries(double[])
*/
public void setYSeries ( double[] ySeries )
{
double[] copiedSeries = new double[ySeries.length];
System.arraycopy ( ySeries, 0, copiedSeries, 0, ySeries.length );
this.ySeries = copiedSeries;
compressedYSeries = copiedSeries;
compressed = false;
}
/*
* @see ICompress#getCompressedXSeries()
*/
public double[] getCompressedXSeries ()
{
double[] copiedSeries = new double[compressedXSeries.length];
System.arraycopy ( compressedXSeries, 0, copiedSeries, 0, compressedXSeries.length );
return copiedSeries;
}
/*
* @see ICompress#getCompressedYSeries()
*/
public double[] getCompressedYSeries ()
{
double[] copiedSeries = new double[compressedYSeries.length];
System.arraycopy ( compressedYSeries, 0, copiedSeries, 0, compressedYSeries.length );
return copiedSeries;
}
/*
* @see ICompress#getCompressedIndexes()
*/
public int[] getCompressedIndexes ()
{
int[] copiedSeries = new int[compressedIndexes.length];
System.arraycopy ( compressedIndexes, 0, copiedSeries, 0, compressedIndexes.length );
return copiedSeries;
}
/*
* @see ICompress#compress(CompressConfig)
*/
final public boolean compress ( CompressConfig compressConfig )
{
if ( ( compressConfig.equals ( prevConfig ) && compressed ) || xSeries == null || ySeries == null )
{
return false;
}
// store the previous configuration
prevConfig = new CompressConfig ( compressConfig );
this.config = compressConfig;
// store into fields to improve performance
xLower = config.getXLowerValue ();
xUpper = config.getXUpperValue ();
yLower = config.getYLowerValue ();
yUpper = config.getYUpperValue ();
isXLogScale = config.isXLogScale ();
isYLogScale = config.isYLogScale ();
widthInPixel = config.getWidthInPixel ();
heightInPixel = config.getHeightInPixel ();
previousXGridIndex = -1;
previousYGridIndex = -1;
ArrayList<Double> xList = new ArrayList<Double> ();
ArrayList<Double> yList = new ArrayList<Double> ();
ArrayList<Integer> indexList = new ArrayList<Integer> ();
// add necessary plots to the array
addNecessaryPlots ( xList, yList, indexList );
compressedXSeries = new double[xList.size ()];
compressedYSeries = new double[yList.size ()];
compressedIndexes = new int[indexList.size ()];
for ( int i = 0; i < xList.size (); i++ )
{
compressedXSeries[i] = xList.get ( i );
compressedYSeries[i] = yList.get ( i );
compressedIndexes[i] = indexList.get ( i );
}
compressed = true;
return true;
}
/**
* Adds the necessary plots.
*
* @param xList
* the array in which x coordinate for necessary plot is stored
* @param yList
* the array in which y coordinate for necessary plot is stored
* @param indexList
* the array in which series index for necessary plot is stored
*/
abstract protected void addNecessaryPlots ( ArrayList<Double> xList, ArrayList<Double> yList, ArrayList<Integer> indexList );
/**
* Adds the given coordinate to list.
*
* @param xList
* the list to store the X coordinate
* @param yList
* the list to store the Y coordinate
* @param indexList
* the list to store the series index
* @param x
* the X coordinate
* @param y
* the Y coordinate
* @param index
* the series index
*/
protected void addToList ( ArrayList<Double> xList, ArrayList<Double> yList, ArrayList<Integer> indexList, double x, double y, int index )
{
xList.add ( x );
yList.add ( y );
indexList.add ( index );
}
/**
* Checks if the given coordinate is in the same grid as previous.
*
* @param x
* the X coordinate
* @param y
* the Y coordinate
* @return true if the given coordinate is in the same grid as previous
*/
protected boolean isInSameGridAsPrevious ( double x, double y )
{
int xGridIndex;
int yGridIndex;
// calculate the X grid index
if ( isXLogScale )
{
double lower = Math.log10 ( xLower );
double upper = Math.log10 ( xUpper );
xGridIndex = (int) ( ( Math.log10 ( x ) - lower ) / ( upper - lower ) * widthInPixel );
}
else
{
xGridIndex = (int) ( ( x - xLower ) / ( xUpper - xLower ) * widthInPixel );
}
// calculate the Y grid index
if ( isYLogScale )
{
double lower = Math.log10 ( yLower );
double upper = Math.log10 ( yUpper );
yGridIndex = (int) ( ( Math.log10 ( y ) - lower ) / ( upper - lower ) * heightInPixel );
}
else
{
yGridIndex = (int) ( ( y - yLower ) / ( yUpper - yLower ) * heightInPixel );
}
// check if the grid index is the same as previous
boolean isInSameGridAsPrevious = ( xGridIndex == previousXGridIndex && yGridIndex == previousYGridIndex );
// store the previous grid index
previousXGridIndex = xGridIndex;
previousYGridIndex = yGridIndex;
return isInSameGridAsPrevious;
}
}