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

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


//
// $Log: BaseI.c,v $
// Revision 1.3  1993/12/29  17:03:16  thoth
// Improved error handling.
//
// Revision 1.2  1993/11/17  18:10:45  thoth
// IPSIter is now PSIter<IntPoint>
// LazyXlationI is in a separate .c file now.
// The default iterators are now in a separate file.
//
// Revision 1.1  1993/09/15  12:50:14  thoth
// Initial revision
//

#include "PSIter.h"
#include "BaseI.h"
//#include "OtherIIter.h"
#include "VectorI.h"
#include "BaseImageIter.h"


template < class P,class T>
T& IA_BaseImage<P,T>::operator[](const P&)
{
    ia_throw( IA::IMAGE_REQUIRE_EXTENSIVE, __FILE__, __LINE__);
    IA::internal_error(__FILE__,__LINE__);
    return *(T*)0;
}

template < class P,class T>
IA_BaseImage<P,T>* IA_BaseImage<P,T>::clone_self_extensively() const
{
    // This will throw if the pointset is comprehensive, but
    // we can\'t clone extensively if our domain is comprehensive.
    const unsigned sz = ps.card();

    // We will build a VectorI
    T *const dest = new T[sz];

    {
	// Iterate over the domain.
	IA_PSIter<P>	iter(ps);
	// For each point
	P	ip;
	T *scan = dest;

	while (iter(ip))
	    // evaluate the image at that point and place it in the
	    // proper slot of the vector.
	    *(scan++) = (*this)(ip);
    }

    // Build a VectorI and give away the value vector.
    return new IA_VectorI<P,T>(ps, dest, sz, 1);
}

#if 1
template < class P,class T>
IA_ValueSet<T> IA_BaseImage<P,T>::range() const
{
    // This will throw if the pointset is comprehensive, but
    // we can\'t compute the range if our domain is comprehensive.
    const unsigned sz = ps.card();

    // We will build a vector of values
    T *const dest = new T[sz];

    {
	// Iterate over the domain.
	IA_PSIter<P>	iter(ps);
	// For each point
	P	ip;
	T *scan = dest;

	while (iter(ip))
	    // evaluate the image at that point and place it in the vector.
	    *(scan++) = (*this)(ip);
    }

    IA_ValueSet<T>	rval(dest, sz);
    delete[] dest;

    return rval;
}
#else
template < class P,class T>
T* IA_BaseImage<P,T>::range(unsigned *sz) const
{
    // This will throw if the pointset is comprehensive, but
    // we can\'t compute the range if our domain is comprehensive.
    *sz = ps.card();

    // We will build a vector of values
    T *const dest = new T[*sz];

    {
	// Iterate over the domain.
	IA_PSIter<P>	iter(ps);
	// For each point
	P	ip;
	T *scan = dest;

	while (iter(ip))
	    // evaluate the image at that point and place it in the vector.
	    *(scan++) = (*this)(ip);
    }

    return dest;
}
#endif

template < class P,class T>
IA_Array<T> IA_BaseImage<P,T>::value_array() const
{
    // This will throw if the pointset is comprehensive, but
    // we can\'t compute the value_array if our domain is comprehensive.
    const unsigned sz = ps.card();

    // We will build a vector of values
    T *const dest = new T[sz];

    {
	// Iterate over the domain.
	IA_PSIter<P>	iter(ps);
	// For each point
	P	ip;
	T *scan = dest;

	while (iter(ip))
	    // evaluate the image at that point and place it in the vector.
	    *(scan++) = (*this)(ip);
    }

    return IA_Array<T>(dest, sz, 1);
}


//
// restriction.  We have a LOT of problems with CFront
//

#include "restrict.h"

template <class P, class T>
IA_BaseImage<IA_Point<int>,T> *IA_BaseImage<P,T>::restricted_to(const IA_Set<IA_Point<int> > &ips) const
{
    return restrict_toD(this, ips);
}

template <class P, class T>
IA_BaseImage<P,T> *IA_BaseImage<P,T>::restricted_to(const IA_Set<IA_Point<double> > &/*fps*/) const
{
    return 0;			// NYI
}


//
//
//

#include "LazyXlationI.h"

template < class P,class T>
IA_BaseImage<P,T> *IA_BaseImage<P,T>::xlated_by(const P &p) const
{
    return new IA_LazyXlationI<P,T>(this, p);
}

//
//  iterator support below
//

#include "OtherImageIter.h"

template < class P,class T>
IA_BaseIVIter<P,T> *IA_BaseImage<P,T>::value_iterator() const
{
    return new IA_OtherIVIter<P,T>(this);
}

template < class P,class T>
IA_BaseIPIter<P,T> *IA_BaseImage<P,T>::pixel_iterator() const
{
    return new IA_OtherIPIter<P,T>(this);
}

//
//
//

template < class P,class T>
ostream& operator<<(ostream& o, const IA_BaseImage<P,T>& bdi)
{
    o << "**Image**\n";
    bdi.print_this(o);
    return o << "\n******************\n" ;
}

