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

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


//
// $Log: VectorI.c,v $
// Revision 1.3.1.1  1994/12/28  16:56:06  thoth
// Conversion to classes for throw.
//
// Revision 1.3  1994/03/14  15:48:33  thoth
// ValueSet has been replaced by container class Set.
//
// Revision 1.2  1993/11/17  18:29:07  thoth
// IPSIter is now PSIter<IntPoint>.
//
// Revision 1.1  1993/09/15  12:57:38  thoth
// Initial revision
//

#include "VectorI.h"
#include "PSIter.h"
#include "VectorImageIter.h"
#include "image_errors.h"

template < class P,class T>
char IA_VectorI<P,T>::dummy;

template < class P,class T>
IA_VectorI<P,T>::IA_VectorI(IA_Set<P> pset, T *v, unsigned sz,
			    int giveaway)
: IA_BaseImage<P,T>(pset), size(pset.card())
{
    if (sz != size) {
	ia_throw( Image_VectorConstructorSizeMismatch_Exception(__FILE__, __LINE__));
	abort();		// unrecoverable error
    }

    if (giveaway) {
	this->vec = v;
    } else {
	this->vec = new T [this->size];
	for(int j=0; j<this->size; j++){
	    this->vec[j] = v[j];
	}
    }
}

template < class P,class T>
IA_VectorI<P,T>::IA_VectorI(const IA_Set<P> &pset, const T& v)
:IA_BaseImage<P,T>(pset), size(pset.card())
{
    this->vec = new T [this->size];
    for( int j=0; j<this->size; j++){
	this->vec[j] = v;
    }
}

#if 1
template < class P,class T>
IA_Set<T> IA_VectorI<P,T>::range() const {
    return IA_Set<T>(vec, size);
}
#else
template < class P,class T>
T* IA_VectorI<P,T>::range(unsigned *sz) const {
    T	*temp = new T[*sz = size];
    for (unsigned i=0; i<size; i++)
	temp[i] = vec[i];
    return temp;
}
#endif

template < class P,class T>
IA_Array<T> IA_VectorI<P,T>::value_array() const
{
    return IA_Array<T>(vec, size);
}

template < class P,class T>
ostream& IA_VectorI<P,T>::print_this(ostream &o) const
{
    IA_PSIter<P> iter(this->ps);
    P p;
    int i;

    o << "VectorI - (point,value) pairs follow:\n";
    i = 0;
    while(iter(p)) {
	o << "(" << p << "," << this->vec[i++] << ") ";
    }
    return o << "\n";
}

template < class P,class T>
IA_BaseImage<P,T>* IA_VectorI<P,T>::clone_self_extensively() const
{
    return (IA_BaseImage<P,T> *) new IA_VectorI<P,T>
	( this->ps, this->vec, this->size, 0);

}

template < class P,class T>
void IA_VectorI<P,T>::vec_2_vec_structcopy
(const T** source_vec, T** dest_vec, const IA_SetStructure &ss)
//
// Copies values provided by the source vector into the
// vector pointed at by dest_vec according to the SetStructure ss.
//
// *source_vec	  MODIFIED
// *dest_vec	  MODIFIED
// ss		UNmodified
//
{
    int i,j;

    // for each interval in the current set structure, do the appropriate
    //	copying.
    for(i=0; i<ss.nintervals(); i++){
	const IA_ss_interval &ssi = ss.retrieve_interval(i);

	if (ssi.substructure == IA_SetStructure::BOTH) {
	    // These pixels are in the intersection -- copy them!
	    for(j=0; j < ssi.count; j++)
		*((*dest_vec)++) = *((*source_vec)++);

	} else if (ssi.substructure == IA_SetStructure::FIRST_ONLY) {
	    // These pixels aren\'t in the intersection -- skip them!
	    (*source_vec) += ssi.count;

	} else if (ssi.substructure != IA_SetStructure::SECOND_ONLY) {
	    // Make recursive calls on complicated structure
	    for(j=0; j<ssi.count; j++)
		vec_2_vec_structcopy(source_vec, dest_vec, ssi.substructure);

	} else { // ssi.substructure == IA_SetStructure::SECOND_ONLY
	    // These points aren\'t in the image being restricted
	}
    }
}

#if 0
template < class P,class T>
IA_BaseImage<P,T> * IA_VectorI<P,T>::restricted_to(const IA_Set<P> &ips) const
{
    IA_SetStructure	ss;
    IA_Set<P>	result_domain =
	intersect_with_structure(this->domain(), ips, &ss);
    if (result_domain == this->domain())
	// clue to reuse this object
	return 0;

    const unsigned	sz = result_domain.card();
    T * const	dest = new T[sz];
    {
	const T	*src = this->vec;
	T	*scan = dest;
	vec_2_vec_structcopy(&src,&scan,ss);
    }

    return new IA_VectorI<P,T>(result_domain, dest, sz, 1);
}
#endif

//
//
//

template < class P,class T>
IA_BaseImage<P,T> * IA_VectorI<P,T>::xlated_by(const P & p) const
{
    // the constructor will copy the vector of values
    return new IA_VectorI<P,T>(this->domain()+p, vec, size, 0);
}

//
// iterator support below
//

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

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