// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//


//
// $Log:	ContinuousImage.h,v $
// Revision 1.3  93/06/10  17:23:50  thoth
// Workaround for 3.0.1 bug.
// 
// Revision 1.2  93/05/27  11:19:33  thoth
// Copyright Notices
// 
// Revision 1.1  93/05/26  17:15:17  thoth
// Initial revision
// 

#ifndef ContinuousImage_h_
#define ContinuousImage_h_

#include <stream.h>
#include "ia.h"

#include "BaseCI.h"
#include "DiscreteImage.h"

template <class T> class IA_ValueSet;

#if 1
#include "OtherCI.h"
#else
template <class T> class IA_OtherCI;
#endif

template <class T>
friend ostream& operator <<(ostream&, const IA_ContinuousImage<T>&);


template <class T>
class IA_ContinuousImage {
protected:

    // INVARIANT:  bcip has a value in every image.  The uninitialized
    //		   value is errorDI.
    IA_BaseCI<T> *bcip;

    // Places a valid value in bcip and refcounts appropriately.
    void set_and_reference_image(IA_BaseCI<T> *i);

    // Decrement the BaseCI\'s refcount and delete if necessary.
    void disassociate_image();

    // no one else should be tossing BaseCIs around
    IA_ContinuousImage(IA_BaseCI<T> *base) {
	set_and_reference_image(base);
    }

public:
    IA_ContinuousImage();

    // copy constructor
    IA_ContinuousImage(const IA_ContinuousImage&);

    // const image constructor
    IA_ContinuousImage(const IA_FloatPointSet&, const T&);

    // vector image constructor
    IA_ContinuousImage(const IA_FloatPointSet&, T *, unsigned, int giveaway);
    IA_ContinuousImage(const IA_FloatPointSet&, const T *, unsigned);
    IA_ContinuousImage(const IA_OtherCI<T>& i);
    IA_ContinuousImage(const IA_FloatPointSet&, T (*)(const IA_FloatPoint&));

    virtual ~IA_ContinuousImage();

    IA_ContinuousImage& operator =(const IA_ContinuousImage &);

    // keep the domain, but make all values the same
    IA_ContinuousImage& operator =(const T&);

    // what sort of image is this?
    IA_ImageType type() const { return bcip->type(); }

    // retrieve a value from the image
    T operator ()(const IA_FloatPoint& p) const {
	if (!domain().contains(p)) {
	    abort();		// throw
	}
	return (*this->bcip)(p);
    }

    // retrieve a reference to a value in the image
    T& operator [](const IA_FloatPoint&);

    IA_ContinuousImage restrict( const IA_FloatPointSet&) const;
    IA_DiscreteImage<T> restrict( const IA_IntPointSet&) const;
    IA_ContinuousImage restrict( const IA_ValueSet<T>&) const;
    // the next one looks gratuitous --thoth
    //IA_ContinuousImage restrict( int (*)(const IA_FloatPoint&)) const;

    // Image Extension -- NOT ASSOCIATIVE!!!
  public:
    IA_ContinuousImage extend( const IA_ContinuousImage&) const;

    IA_ContinuousImage xlated( const IA_FloatPoint &) const;

    IA_FloatPointSet domain() const { return this->bcip->domain(); }
    
    IA_ValueSet<T> range() const;

//    int card() const { return this->domain().card(); }

    int extensivep() const { return this->bcip->extensivep(); }

    T reduce(T (*)(const T&, const T&),T) const;

    T reduce(T (*) (T, T), T) const;

    friend ostream& operator <<(ostream&, const IA_ContinuousImage<T>&);

    friend zero_extend(const IA_ContinuousImage<T> &, const IA_FloatPointSet&,
		       T*, T);
};

#include "PPComp.h"

template <class T>
IA_ContinuousImage<T> compose
(const IA_ContinuousImage<T>&,
 const IA_PPCompClosure<IA_FloatPoint, IA_FloatPoint> &);

template <class T>
IA_ContinuousImage<T> compose(const IA_ContinuousImage<T>&,
			      IA_FloatPoint (*)(const IA_FloatPoint&));

#endif
