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

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


// 
// $Log: DblPS.h,v $
// Revision 1.12  1994/12/01  15:55:04  fjsoria
// changed gaurd __NO_INLINE_DESTRUCTORS to
// __NO_OUTLINE_DESTRUCTORS
//
// Revision 1.11  1994/10/06  17:37:52  fjsoria
// commented rcsid[]
//
// 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:28  thoth
// Resurrected the int(*)(Point) constructor.
// Added static member functions to construct white and black holes.
//
// Revision 1.6  1993/11/17  18:02:03  thoth
// extensivep() is now extensive()
//
// 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:34  thoth
// Certain functions are necessary for Continuous images,
// we will implement them later.
//
// Revision 1.3  93/08/08  13:14:35  thoth
// Parametrization of the pointsets on the point type using
// template specialization.
// 
// Revision 1.2  93/05/26  16:51:16  thoth
// Copyright Notices
// 
// Revision 1.1  93/05/10  08:33:25  thoth
// Initial revision
// 

#ifndef DoublePointSet_h_
#define DoublePointSet_h_

#define SUPPRESS_INCLUDE
#include "Set.h"
#undef SUPPRESS_INCLUDE

#include "DblPoint.h"
#include "BasePS.h"
#include "SetStructure.h"

template <class P> class IA_ClosurePS;
template <class P> class IA_PSIter;


class IA_Set<IA_Point<double> > {
  private:
    
    IA_BasePS<IA_Point<double> >	*ps;

    void associate(IA_BasePS<IA_Point<double> > *);
    void disassociate();

    IA_Set(IA_BasePS<IA_Point<double> > *fps) { associate(fps); }
    IA_Set(IA::Type t, unsigned dim);
  public:
    IA_Set();
    IA_Set(const IA_Point<double>&p);
    IA_Set(unsigned dimen, int(*f)(const IA_Point<double>&));
    IA_Set(unsigned dimen, int(*f)(IA_Point<double>));
    IA_Set(const IA_ClosurePS<IA_Point<double> >&);
    IA_Set(unsigned dimen, const IA_Point<double> *afp, unsigned len);
    IA_Set(const IA_Set<IA_Point<double> > &fps);
//    IA_Set(const IA_Set<IA_Point<int> > &ips);
#ifdef __NO_OUTLINE_DESTRUCTORS
    ~IA_Set() { disassociate();}
#else
    ~IA_Set();
#endif

    IA_Set<IA_Point<double> > & operator=(const IA_Set<IA_Point<double> >&);

    int operator==(const IA_Set<IA_Point<double> >&fps) const ;
    int operator!=(const IA_Set<IA_Point<double> >&fps) const ;

    // This block NYI
    friend IA_Set<IA_Point<double> > operator|
    (const IA_Set<IA_Point<double> > &,const IA_Set<IA_Point<double> > &);
    friend IA_Set<IA_Point<double> > operator&
    (const IA_Set<IA_Point<double> > &,const IA_Set<IA_Point<double> > &);
    friend IA_Set<IA_Point<double> > operator^
    (const IA_Set<IA_Point<double> > &,const IA_Set<IA_Point<double> > &);
    friend IA_Set<IA_Point<double> > operator/
    (const IA_Set<IA_Point<double> > &,const IA_Set<IA_Point<double> > &);
    //
    friend IA_Set<IA_Point<double> > operator+
    (const IA_Set<IA_Point<double> > &,const IA_Point<double> &);
    IA_Set<IA_Point<double> > operator-() const {
	IA::not_yet_implemented(__FILE__, __LINE__);
	return *this;
    }
    //
    friend IA_Set<IA_Point<double> > intersect_with_structure
    (const IA_Set<IA_Point<double> > &lhs, const IA_Set<IA_Point<double> > &rhs,
     IA_SetStructure *s_struct);
    friend IA_Set<IA_Point<double> > union_with_structure
    (const IA_Set<IA_Point<double> > &lhs, const IA_Set<IA_Point<double> > &rhs, IA_SetStructure *s_struct);
    //

#if 0
    int operator==(const IA_Set<IA_Point<double> >&fps) const;
    int operator!=(const IA_Set<IA_Point<double> >&fps) const
    { return !(*this==fps); }
#endif
    unsigned dim() const { return ps->dim(); }

    int contains(const IA_Point<double> &ip) const { return ps->contains(ip); }
    unsigned index(const IA_Point<double> &fp) const { return ps->index(fp); }
    IA_Point<double> index(unsigned idx) const { return ps->index(idx); }

    unsigned card() const { return ps->card(); }
    int empty() const { return ps->empty(); }
    int extensive() const { return ps->extensive(); }

    // he has to know how to get at the underlying IA_BasePS<IA_Point<double> >*
    friend class IA_PSIter<IA_Point<double> >;

    friend IA_Set<IA_Point<double> > IA_empty_fpset(unsigned dim);
    friend IA_Set<IA_Point<double> > IA_universal_fpset(unsigned dim);

    static IA_Set<IA_Point<double> > WhiteHole(unsigned dim) {
	return IA_universal_fpset(dim);
    }
    static IA_Set<IA_Point<double> > BlackHole(unsigned dim) {
	return IA_empty_fpset(dim);
    }
};


inline IA_Set<IA_Point<double> > IA_CWhiteHole(unsigned dim) {
    return IA_universal_fpset(dim);
}
inline IA_Set<IA_Point<double> > IA_CBlackHole(unsigned dim) {
    return IA_empty_fpset(dim);
}

#include "IntPS.h"	// for the intersection

IA_Set<IA_Point<int> > operator&(const IA_Set<IA_Point<int> >&,
			      const IA_Set<IA_Point<double> >&);
inline IA_Set<IA_Point<int> > operator&(const IA_Set<IA_Point<double> >&lhs,
			      const IA_Set<IA_Point<int> >&rhs) {
    return rhs&lhs;
}

void SortDoublePointArray(IA_Point<double> *afp, unsigned len);

#endif
