// -*- C++ -*-
#ifndef RISPECTRALCURVE_H
#define RISPECTRALCURVE_H
/* Copyright 1996 
 * Tue Apr 15 13:51:16 1997  Brian Edward Smits  (bes@burn.cs.utah.edu)
 * 
 * RiSpectralCurve.H
 * 
 *	
 * 
 * $Id: RiSpectralCurve.H,v 1.4 1997/05/22 17:36:39 bes Exp $ 
 * 
 */
#ifndef RICOMMON_H
#include <RiCommon.H>
#endif

// The includes should be reversed...
#ifndef RISPECTRUM_H
#include <RiSpectrum.H>
#endif


/***************************************************************
CLASS
    RiSpectralCurve
    An abstract class that represents a function over the visible
    spectrum. RI_SPECTRUM_MIN_LAMBDA to RI_SPECTRUM_MAX_LAMBDA

DESCRIPTION
    This class allows us to represent any spectral data.  RiSpectrum
    can then use this interface to convert any arbitrary spectral data
    to an RiSpectrum.  There are minimal restrictions on this class.
    It will be used to represent energy, sensitivity curves, and
    possibly reflectances.

PATTERN
    abstract function

WARNING
    The conversion operator to RiSpectrum samples the spectral function
    at 1nm increments.  If you have data that contains higher frequencies,
    (sodium vapor lamp maybe, lazer) either smooth it a little or
    write your own conversion operator if you want to get an RiSpectrum out of it.
    Obviously, an RiSpectrum is a really bad represenation of the original
    data.
****************************************************************/

class RiSpectralCurve {
  public:
				//// Virtual destructor so everything works fine for derived classes
    virtual ~RiSpectralCurve() {}
				//// Conversion operator to RiSpectrum
    virtual operator RiSpectrum() const;
				//// Return the value of the function at lambda
    virtual RiReal GetValue(RiReal lambda) const = 0;
				//// overload the function call operator for convenience
    RiReal operator()(RiReal lambda) const {return GetValue(lambda);}
  protected:
				//// allow a little efficiency into the conversion to Spectrum
    RiSpectrum Integrate(RiReal stepSize) const;
};


/***************************************************************
CLASS
    RiRegularSpectralCurve
    A spectral curve from regularly spaced samples

DESCRIPTION
     This class takes a set of numSamples regularly spaced samples from a
     minLambda to a maxLambda represented as an array of RiReals.  

WARNINGS
     The user is responsible for deleting the array passed in.  RiRegularSpectralCurve
     makes it's own internal copy.
****************************************************************/

class RiRegularSpectralCurve : public RiSpectralCurve {
  public:
				// GROUP: Constructors and assignment
				//// Constructor [in] data Array of values
				//               [in] minLambda  starting lambda for the data
				//               [in] maxLambda  ending lambda for the data
				//               [in] numSamples total number of samples
    RiRegularSpectralCurve(const RiReal *data, RiReal minLambda, RiReal maxLambda,
			    int numSamples);
				//// Destructor deletes the internal data array
    ~RiRegularSpectralCurve();
				// GROUP: Members
				//// returns the linearly interpolated value of the function at lambda
    virtual RiReal GetValue(RiReal lambda) const;
private:
				//// Copy constructor 
    RiRegularSpectralCurve(const RiRegularSpectralCurve &);
				//// Assignment 
    RiRegularSpectralCurve& operator=( const RiRegularSpectralCurve &);
    RiReal 	*data;
    RiReal 	 minLambda, maxLambda;
    int	 	 numSamples;
    RiReal	 width;
};


/***************************************************************
CLASS
    RiIrregularSpectralCurve
     A RiSpectralCurve represented by irregular data points

DESCRIPTION
     A RiSpectralCurve represented by irregular data points.  The user passes in two arrays,
     one representing the values of the spectral curve, the other representing the wavelengths
     corresponding to those values.

WARNINGS
     The user is responsible for deleting the array passed in.  RiRegularSpectralCurve
     makes it's own internal copy.
     The wavelength samples (lambda) must be strictly increasing.
****************************************************************/

class RiIrregularSpectralCurve : public RiSpectralCurve {
  public:
				// GROUP: Constructors and assignment
				//// Default Constructor
    RiIrregularSpectralCurve(const RiReal *data, const RiReal *lambda, int numSamples);
				//// Constructor for incremental creation
    RiIrregularSpectralCurve(int numSamples);
				//// Destructor
    ~RiIrregularSpectralCurve();
				//// Build the data incrementally (useful for reading)
    void SetSample(int sample, RiReal value, RiReal lambda);
				// GROUP: Members
				//// returns the linearly interpolated value of the function at lambda
    virtual RiReal GetValue(RiReal lambda) const;
  private:
				//// Copy constructor makes sure adoptData isn't passed along
    RiIrregularSpectralCurve(const RiIrregularSpectralCurve &);
				//// Assignment  makes sure adoptData isn't passed along.
    RiIrregularSpectralCurve& operator=( const RiIrregularSpectralCurve &);
    RiReal 	*data;
    RiReal	*lambda;
    int	 	 numSamples;
};



/***************************************************************
CLASS
    RiCombinedSpectralCurve
     Create a RiSpectralCurve that is the linear combination of some other
     set of RiSpectralCurve.

DESCRIPTION
     Takes 2,3, or 4 RiSpectralCurve and weights, and returns the weighted
     sum of the curves at each lambda.  

WARNINGS
      The user is responsible for deleting the RiSpectralCurves when done with
      the RiCombinedSpectralCurve.  The user must not delete them before then.
****************************************************************/

class RiCombinedSpectralCurve : public RiSpectralCurve {
  public:
				// GROUP: Constructors and assignment
				//// Default Constructor
    RiCombinedSpectralCurve();
				//// Linearly combine 2 curves
    RiCombinedSpectralCurve(const RiSpectralCurve *c0, RiReal w0, const RiSpectralCurve *c1, RiReal w1);
				//// Linearly combine 3 curves
    RiCombinedSpectralCurve(const RiSpectralCurve *c0, RiReal w0, const RiSpectralCurve *c1, RiReal w1,
			    const RiSpectralCurve *c2, RiReal w2);
				//// Linearly combine 4 curves
    RiCombinedSpectralCurve(const RiSpectralCurve *c0, RiReal w0, const RiSpectralCurve *c1, RiReal w1,
			    const RiSpectralCurve *c2, RiReal w2, const RiSpectralCurve *c3, RiReal w3);
				////Copy Constructor
    RiCombinedSpectralCurve(const RiCombinedSpectralCurve &);
				//// Assignment
    RiCombinedSpectralCurve &operator=(const RiCombinedSpectralCurve &);
				// GROUP: Members
				//// Return the weighted sum of the curves
    virtual RiReal GetValue(RiReal lambda) const;
  private:
    const RiSpectralCurve  	*curve[4];
    RiReal		 	 weight[4];
    int			 	 numCurves;
};



#endif /* RISPECTRALCURVE_H */

