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

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

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

static char rcsid[] = "$Id: FloatPointSet.c,v 1.7 1994/01/31 16:36:00 thoth Exp $";

// 
// $Log: FloatPointSet.c,v $
// 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 "FloatPointSet.h"
#include "MondoPS.h"
#include "ClosurePS.h"
#include "LazyPS.h"
#include "ListFPS.h"

typedef IA_ListPS<IA_FloatPoint> IA_ListFPS;

IA_Set<IA_FloatPoint> IA_CBlackHole(unsigned dim)
{
    return IA_Set<IA_FloatPoint>(IA_BlackHole_<IA_FloatPoint>::s_type(), dim);
}

IA_Set<IA_FloatPoint> IA_CWhiteHole(unsigned dim)
{
    return IA_Set<IA_FloatPoint>(IA_WhiteHole_<IA_FloatPoint>::s_type(), dim);
}

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

void IA_Set<IA_FloatPoint>::disassociate()
{
    if (ps->unref() <=0)
	delete ps;
    
    ps = 0;
}


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


IA_Set<IA_FloatPoint>::IA_Set(const IA_FloatPoint &p)
{
    associate(new IA_ListFPS(p));
}

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

    associate(new IA_ListFPS(dimen, afp, len));
}

IA_Set<IA_FloatPoint>::IA_Set(IA_PointSetType t, unsigned dim)
{
    if (t==IA_WhiteHole_<IA_FloatPoint>::s_type())
	associate(new IA_WhiteHole_<IA_FloatPoint>(dim));
    else if (t == IA_BlackHole_<IA_FloatPoint>::s_type())
	associate(new IA_BlackHole_<IA_FloatPoint>(dim));
    else {
	ia_throw(IA::TYPE_MISMATCH, __FILE__, __LINE__);
	associate(new IA_BlackHole_<IA_FloatPoint>(0));
    }
}

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

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

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

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

IA_Set<IA_FloatPoint>::~IA_Set()
{
    disassociate();
}

IA_Set<IA_FloatPoint> & IA_Set<IA_FloatPoint>::operator=(const IA_Set<IA_FloatPoint> &fps)
{
    IA_BasePS<IA_FloatPoint>	*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_IntPoint> operator&(const IA_Set<IA_IntPoint>&lhs,
			      const IA_FloatPointSet&){
    cerr << "ips&fps, NYI\n";
    exit(1);
    return lhs;
}

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


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

void SortFloatPointArray(IA_FloatPoint *aip, unsigned len)
{
  // We can use qsort because a swap of the bytes in
  // two FloatPoints does not do any damage.
  qsort((char*)aip, len, sizeof(*aip), fpcmp);
}
