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

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


static char VectorDIrcsid[] = "$Id: VectorDI.c,v 1.12 93/05/27 11:28:31 thoth Exp $";

// $Log:	VectorDI.c,v $
// Revision 1.12  93/05/27  11:28:31  thoth
// Copyright Notices
// 
// Revision 1.11  93/05/26  17:03:26  thoth
// range is once again ValueSet.
// value_array() is fairly quick.
// 
// Revision 1.10  93/04/17  18:45:11  thoth
// Iterator support is no longer based on a switch statement.  We now
// use a virtual method.  The user can now provide faster iterators.
// 
// Revision 1.9  93/04/08  13:21:12  thoth
// removed cruft.
// new pointset restriction method.
// new translation method.
// 
// Revision 1.8  93/03/10  13:37:00  thoth
// range method no longer returns valueset due to
// difficulties with template implementation.
// 
// Revision 1.7  93/02/20  15:13:16  thoth
// Constructor with no values is not useful yet.
// We only need one vector constructor.
// Generic equality testing is not the domain of the BaseDI derived classes.
// The pointset should go first in an image constructor.
// 
// Revision 1.6  93/02/17  11:04:37  thoth
// minor cleaning up within the constructors.
// 
// Revision 1.5  93/02/08  13:03:42  thoth
// BaseDI takes care of common DI stuff.
// made array constructor consistent with IACC style (giveaway).
// equal method no longer loops infinitely.
// 
// Revision 1.4  93/01/19  14:56:39  jnw
// Modified to support IA_ naming convention
// 
// Revision 1.3  92/12/10  09:58:48  jnw
// Removed ancient debugging code
// 
// Revision 1.2  92/11/12  16:58:39  jnw
// Major modifications
// 
// 
// Revision 1.1  92/10/05  11:43:49  jnw
// Initial revision
// 

#include "VectorDI.h"
#include "IPSIter.h"
#include "VectorDIVIter.h"
#include "VectorDIPIter.h"

template <class T>
char IA_VectorDI<T>::dummy;

template <class T>
IA_VectorDI<T>::IA_VectorDI(IA_IntPointSet pset, T *v, unsigned sz,
			    int giveaway)
: IA_BaseDI<T>(pset), size(pset.card())
{
    if (sz != size) {
	ia_throw( IA::PSET_SIZE_MISMATCH, __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 T>
IA_VectorDI<T>::IA_VectorDI(const IA_IntPointSet &pset, const T& v)
:IA_BaseDI<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 T>
IA_ValueSet<T> IA_VectorDI<T>::range() const {
    return IA_ValueSet<T>(vec, size);
}
#else
template <class T>
T* IA_VectorDI<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 T>
IA_Array<T> IA_VectorDI<T>::value_array() const
{
    return IA_Array<T>(vec, size);
}

template <class T>
ostream& IA_VectorDI<T>::print_this(ostream &o) const
{
    IA_IPSIter iter(this->ps);
    IA_IntPoint p;
    int i;

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

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

}

template <class T>
void IA_VectorDI<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
	}
    }
}

template <class T>
IA_BaseDI<T> * IA_VectorDI<T>::restricted_to(const IA_IntPointSet &ips) const
{
    IA_SetStructure	ss;
    IA_IntPointSet	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_VectorDI<T>(result_domain, dest, sz, 1);
}

//
//
//

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

//
// iterator support below
//

template <class T>
IA_BaseDIVIter<T> *IA_VectorDI<T>::value_iterator() const
{
    return new IA_VectorDIVIter<T>(this);
}

template <class T>
IA_BaseDIPIter<T> *IA_VectorDI<T>::pixel_iterator() const
{
    return new IA_VectorDIPIter<T>(this);
}
