/*********************************************************************************
 JPlotFunctionBase.cc
 
	JPlotFunctionBase class.
 
	Copyright @ 1997 by Glenn W. Bach. All rights reserved.

 ********************************************************************************/

#include <JPlotFunctionBase.h>
#include <J2DPlotWidget.h>
#include <JMinMax.h>
#include <jAssert.h>

const JSize kDefSampleCount = 100;	// # of points for approximating y range

/*********************************************************************************
 Constructor 

 ********************************************************************************/

JPlotFunctionBase::JPlotFunctionBase
	(
	const PlotDataType	type,
	J2DPlotWidget*		plot,
	const JFloat		xMin,
	const JFloat		xMax
	)
	:
	JPlotDataBase(type)
{
	itsPlot = plot;
	itsXMin = JMin(xMin, xMax);
	itsXMax = JMax(xMin, xMax);

	itsValues = new JArray<Point>(kDefSampleCount);	
	assert( itsValues != NULL );

	ListenTo(itsPlot);
}

/*********************************************************************************
 Destructor

 ********************************************************************************/
 
JPlotFunctionBase::~JPlotFunctionBase()
{
	delete itsValues;	
}

/*********************************************************************************
 GetElement (virtual)

 ********************************************************************************/

void
JPlotFunctionBase::GetElement
	(
	const JIndex	index, 
	J2DDataPoint*	data
	) 
	const
{
	const Point pt = itsValues->GetElement(index);
	data->x        = pt.x;
	data->y        = pt.y;
}

/*********************************************************************************
 GetXRange (virtual)

 ********************************************************************************/

void
JPlotFunctionBase::GetXRange
	(
	JFloat* min, 
	JFloat* max
	)
	const
{
	*min = itsXMin;
	*max = itsXMax;
}

/*********************************************************************************
 GetYRange (virtual)

 ********************************************************************************/

JBoolean
JPlotFunctionBase::GetYRange
	(
	const JFloat	xMin, 
	const JFloat	xMax,
	JFloat*			yMin, 
	JFloat*			yMax
	)
	const
{
	const JFloat stepSize = (xMax - xMin)/((JFloat) kDefSampleCount);

	JBoolean firstValue = kTrue;

	Point pt;
	for (JIndex i = 0; i <= kDefSampleCount; i++)
		{
		pt.x = xMin + i*stepSize;
		if (GetYValue(pt.x, &(pt.y)))
			{
			if (pt.y < *yMin || firstValue)
				{
				*yMin = pt.y;
				}
			if (pt.y > *yMax || firstValue)
				{
				*yMax = pt.y;
				}
			firstValue = kFalse;
			}
		}

	return JNegate(firstValue);
}

/*********************************************************************************
 Receive (virtual protected)

 ********************************************************************************/

void 
JPlotFunctionBase::Receive
	(
	JBroadcaster*	sender, 
	const Message&	message
	)
{
	if (sender == itsPlot && message.Is(J2DPlotWidget::kScaleChanged))
		{
		UpdateFunction();
		}
	else
		{
		JPlotDataBase::Receive(sender, message);
		}		
}

/*********************************************************************************
 UpdateFunction (protected)

 ********************************************************************************/

void
JPlotFunctionBase::UpdateFunction()
{
	JFloat min, max, inc;
	itsPlot->GetXScaling(&min, &max, &inc);
	UpdateFunction(min, max, itsPlot->GetSmoothSteps());
}

void
JPlotFunctionBase::UpdateFunction
	(
	const JFloat	min, 
	const JFloat	max, 
	const JSize		stepCount
	)
{
	itsValues->RemoveAll();

	SetElementCount(stepCount+1);

	JFloat stepSize;
	if (itsPlot->XAxisIsLinear())
		{
		stepSize = (max - min)/((JFloat) stepCount);
		} 
	else
		{
		stepSize = (log10(max) - log10(min))/((JFloat) stepCount);
		}
	Point pt;
	for (JIndex i = 0; i <= stepCount; i++)
		{
		if (itsPlot->XAxisIsLinear())
			{
			pt.x = min + i*stepSize;
			}
		else
			{
			pt.x = pow(10, log10(min) + i*stepSize);
			}
		if (GetYValue(pt.x, &(pt.y)))
			{
			itsValues->AppendElement(pt);
			}
		else
			{
			ElementRemoved();
			}
		}
}

#define JTemplateType JPlotFunctionBase::Point
#include <JArray.tmpls>
#undef JTemplateType
