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

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

#ifndef IA_NO_RCS_STATIC_DATA
static char copyright[] = "Copyright 1993, Center for Computer Vision and Visualization,\nUniversity of Florida.  All rights reserved.\n";

static char rcsid[] = "$Id: DblPS.c,v 1.13 1994/11/10 19:53:56 ljr Exp thoth $";
#endif

// 
// $Log: DblPS.c,v $
// Revision 1.13  1994/11/10  19:53:56  ljr
// Added IA_NO_RCS_STATIC_DATA guard.
//
// Revision 1.12  1994/11/10  18:49:52  fjsoria
// *** empty log message ***
//
// Revision 1.11  1994/10/06  17:39:00  fjsoria
// commented rscid[] line
//
// Revision 1.10  1994/08/18  23:39:28  thoth
// DOS-inspired filename rework
//
// Revision 1.9  1994/07/25  16:58:52  thoth
// \Name sanitization
//
// Revision 1.8  1994/04/26  18:10:49  thoth
// White and Black Hole have been renamed to universal and empty _pset
//
// Revision 1.7  1994/01/31  16:36:00  thoth
// Resurrected the int(*)(Point) constructor.
//
// Revision 1.6  1993/11/17  18:03:31  thoth
// Pointcmp is now pointcmp
//
// Revision 1.5  1993/10/20  15:48:39  thoth
// New naming scheme.  Closures are named Closure.
//
// Revision 1.4  1993/09/15  12:31:12  thoth
// Certain functions are necessary for Continuous images,
// we will implement them later.
//
// Revision 1.3  93/08/08  13:13:09  thoth
// Parametrization of the pointsets on the point type using
// template specialization.
// The extensive FloatPointSet representations seem to work.
// 
// Revision 1.2  93/05/26  16:57:35  thoth
// Copyright Notices
// 
// Revision 1.1  93/05/10  08:33:39  thoth
// Initial revision
// 

#include "DblPS.h"
#include "MondoPS.h"
#include "ClosurePS.h"
#include "LazyPS.h"
#include "ListFPS.h"
#include "BasePSIter.h"

IA_Set<IA_Point<double> > IA_empty_fpset(unsigned dim)
{
    return IA_Set<IA_Point<double> >(IA_BlackHole_<IA_Point<double> >::s_type(), dim);
}

IA_Set<IA_Point<double> > IA_universal_fpset(unsigned dim)
{
    return IA_Set<IA_Point<double> >(IA_WhiteHole_<IA_Point<double> >::s_type(), dim);
}

void IA_Set<IA_Point<double> >::associate(IA_BasePS<IA_Point<double> > *fps)
{
    ps = fps;
    ps->enref();
}

void IA_Set<IA_Point<double> >::disassociate()
{
    hash_managed_delete(ps);
    
    ps = 0;
}


IA_Set<IA_Point<double> >::IA_Set()
{
    associate(new IA_BlackHole_<IA_Point<double> >(0));
}


IA_Set<IA_Point<double> >::IA_Set(const IA_Point<double> &p)
{
    associate(new IA_ListPS<IA_Point<double> >(p));
}

IA_Set<IA_Point<double> >::IA_Set
(unsigned dimen, const IA_Point<double> *afp, unsigned len)
{
    for (int i=0; i<len; i++) {
	if (afp[i].dim() != dimen) {
	    ia_throw(Pointset_DimensionMismatch_Exception(__FILE__, __LINE__));
	    associate(new IA_BlackHole_<IA_Point<double> >(0));
	    return;
	}
    }

    associate(new IA_ListPS<IA_Point<double> >(dimen, afp, len));
}

IA_Set<IA_Point<double> >::IA_Set(IA::Type t, unsigned dim)
{
    if (t==IA_WhiteHole_<IA_Point<double> >::s_type())
	associate(new IA_WhiteHole_<IA_Point<double> >(dim));
    else if (t == IA_BlackHole_<IA_Point<double> >::s_type())
	associate(new IA_BlackHole_<IA_Point<double> >(dim));
    else {
	IA::internal_error(__FILE__, __LINE__);
	associate(new IA_BlackHole_<IA_Point<double> >(0));
    }
}

IA_Set<IA_Point<double> >::IA_Set(unsigned dimen,
				   int(*f)(const IA_Point<double>&))
{
    associate(new IA_PredicatePS_CR<IA_Point<double> >(dimen, f));
}

IA_Set<IA_Point<double> >::IA_Set(unsigned dimen,
				   int(*f)(IA_Point<double>))
{
    associate(new IA_PredicatePS_V<IA_Point<double> >(dimen, f));
}

IA_Set<IA_Point<double> >::IA_Set(const IA_ClosurePS<IA_Point<double> >&ps)
{
    associate(ps.clone_self());
}

IA_Set<IA_Point<double> >::IA_Set(const IA_Set<IA_Point<double> > &fps)
{
    associate(fps.ps);
}

#ifndef __NO_INLINE_DESTRUCTORS

IA_Set<IA_Point<double> >::~IA_Set()
{
    disassociate();
}

#endif

IA_Set<IA_Point<double> > & IA_Set<IA_Point<double> >::operator=(const IA_Set<IA_Point<double> > &fps)
{
    IA_BasePS<IA_Point<double> >	*temp;
    temp = fps.ps;
    temp->enref();
    this->disassociate();
    ps = temp;

    return *this;
}

IA_Set<IA_Point<double> > union_with_structure(const IA_Set<IA_Point<double> >&lhs,const IA_Set<IA_Point<double> >&,IA_SetStructure*) {
  cerr << "union_with_structure(fps,fps,ss), NYI\n";
  exit(1);
  return lhs;
}

IA_Set<IA_Point<int> > operator&(const IA_Set<IA_Point<int> >&lhs,
			      const IA_Set<IA_Point<double> >&){
    cerr << "ips&fps, NYI\n";
    exit(1);
    return lhs;
}

IA_Set<IA_Point<double> > operator+(const IA_Set<IA_Point<double> >&lhs,
			      const IA_Point<double>&){
    cerr << "fps+fp, NYI\n";
    exit(1);
    return lhs;
}


extern "C"
/*static*/ int fpcmp(const void *a, const void *b)
{
  return pointcmp(*(IA_Point<double>*)a,*(IA_Point<double>*)b);
}

void SortDoublePointArray(IA_Point<double> *aip, unsigned len)
{
  // We can use qsort because a swap of the bytes in
  // two DoublePoints does not do any damage.
  qsort((char*)aip, len, sizeof(*aip), fpcmp);
}

#ifdef IA_NO_AUTOINST_OF_STATIC_DATA
char IA_ListPS<IA_Point<double> >:: dummy;
char IA_WhiteHole_<IA_Point<double> >::type_;
char IA_BlackHole_<IA_Point<double> >::type_;
#endif

void hash_managed_delete(IA_BasePS<IA_Point<double> > * ps)
{
    if (ps->unref()<=0) {
	delete ps;
    }
}
