/**************************************************************************** ** ** Copyright (c) 2008-2020 C.B. Barber. All rights reserved. ** $Id: //main/2019/qhull/src/libqhullcpp/QhullSet.h#5 $$Change: 3018 $ ** $DateTime: 2020/08/15 19:58:23 $$Author: bbarber $ ** ****************************************************************************/ #ifndef QhullSet_H #define QhullSet_H #include "libqhull_r/qhull_ra.h" #include "libqhullcpp/QhullError.h" #include "libqhullcpp/QhullQh.h" #include // ptrdiff_t, size_t #ifndef QHULL_NO_STL #include #endif #ifdef QHULL_USES_QT #include #endif namespace orgQhull { #//!\name Used here class Qhull; #//!\name Defined here class QhullSetBase; //! Base class for QhullSet //! QhullSet defined below //! QhullSetIterator defined below //! \see QhullPointSet, QhullLinkedList //! QhullSetBase is a wrapper for Qhull's setT of void* pointers //! \see libqhull_r/qset.h class QhullSetBase { private: #//!\name Fields -- setT * qh_set; QhullQh * qh_qh; //! Provides access to setT memory allocator #//!\name Class objects static setT s_empty_set; //! Used if setT* is NULL public: #//!\name Constructors QhullSetBase(const Qhull &q, setT *s); QhullSetBase(QhullQh *qqh, setT *s) : qh_set(s ? s : &s_empty_set), qh_qh(qqh) {} //! Copy constructor copies the pointer but not the set. Needed for return by value and parameter passing. QhullSetBase(const QhullSetBase &other) : qh_set(other.qh_set), qh_qh(other.qh_qh) {} QhullSetBase & operator=(const QhullSetBase &other) { qh_set= other.qh_set; qh_qh= other.qh_qh; return *this; } ~QhullSetBase() {} private: //!disabled since memory allocation for QhullSet not defined QhullSetBase() : qh_set(NULL), qh_qh(NULL) {} public: #//!\name GetSet countT count() const { return QhullSetBase::count(qh_set); } void defineAs(setT *s) { qh_set= s ? s : &s_empty_set; } //!< Not type-safe since setT may contain any type void forceEmpty() { qh_set= &s_empty_set; } setT * getSetT() const { return qh_set; } bool isEmpty() const { return SETempty_(qh_set); } QhullQh * qh() const { return qh_qh; } setT ** referenceSetT() { return &qh_set; } size_t size() const { return QhullSetBase::count(qh_set); } #//!\name Element protected: void ** beginPointer() const { return &qh_set->e[0].p; } void ** elementPointer(countT idx) const { QHULL_ASSERT(idx>=0 && idxmaxsize); return &SETelem_(qh_set, idx); } //! Always points to 0 void ** endPointer() const { return qh_setendpointer(qh_set); } #//!\name Class methods public: static countT count(const setT *set); //s may be null static bool isEmpty(const setT *s) { return SETempty_(s); } };//QhullSetBase //! QhullSet -- A read-only wrapper to Qhull's collection class, setT. //! QhullSet is similar to STL's and Qt's QVector //! QhullSet is unrelated to STL and Qt's set and map types (e.g., QSet and QMap) //! T is a Qhull type that defines 'base_type' and getBaseT() (e.g., QhullFacet with base_type 'facetT *' //! A QhullSet does not own its contents -- erase(), clear(), removeFirst(), removeLast(), pop_back(), pop_front(), fromStdList() not defined //! QhullSetIterator is faster than STL-style iterator/const_iterator //! Qhull's FOREACHelement_() [qset_r.h] maybe more efficient than QhullSet. It uses a NULL terminator instead of an end pointer. STL requires an end pointer. //! Derived from QhullLinkedList.h and Qt/core/tools/qlist.h w/o QT_STRICT_ITERATORS template class QhullSet : public QhullSetBase { private: #//!\name Fields -- see QhullSetBase #//!\name Class objects static setT s_empty_set; //! Workaround for no setT allocator. Used if setT* is NULL public: #//!\name Defined here class iterator; class const_iterator; typedef typename QhullSet::iterator Iterator; typedef typename QhullSet::const_iterator ConstIterator; #//!\name Constructors QhullSet(const Qhull &q, setT *s) : QhullSetBase(q, s) { } QhullSet(QhullQh *qqh, setT *s) : QhullSetBase(qqh, s) { } //Conversion from setT* is not type-safe. Implicit conversion for void* to T //Copy constructor copies pointer but not contents. Needed for return by value. QhullSet(const QhullSet &other) : QhullSetBase(other) {} QhullSet & operator=(const QhullSet &other) { QhullSetBase::operator=(other); return *this; } ~QhullSet() {} private: //!Disable default constructor. See QhullSetBase QhullSet(); public: #//!\name Conversion #ifndef QHULL_NO_STL std::vector toStdVector() const; #endif #ifdef QHULL_USES_QT QList toQList() const; #endif #//!\name GetSet -- see QhullSetBase for count(), empty(), isEmpty(), size() using QhullSetBase::count; using QhullSetBase::isEmpty; // operator== defined for QhullSets of the same type bool operator==(const QhullSet &other) const { return qh_setequal(getSetT(), other.getSetT()); } bool operator!=(const QhullSet &other) const { return !operator==(other); } #//!\name Element access // Constructs T. Cannot return reference. const T at(countT idx) const { return operator[](idx); } // Constructs T. Cannot return reference. const T back() const { return last(); } T back() { return last(); } //! end element is NULL const typename T::base_type * constData() const { return reinterpret_cast(beginPointer()); } typename T::base_type * data() { return reinterpret_cast(beginPointer()); } const typename T::base_type *data() const { return reinterpret_cast(beginPointer()); } typename T::base_type * endData() { return reinterpret_cast(endPointer()); } const typename T::base_type * endData() const { return reinterpret_cast(endPointer()); } // Constructs T. Cannot return reference. const T first() const { QHULL_ASSERT(!isEmpty()); return T(qh(), *data()); } T first() { QHULL_ASSERT(!isEmpty()); return T(qh(), *data()); } // Constructs T. Cannot return reference. const T front() const { return first(); } T front() { return first(); } // Constructs T. Cannot return reference. const T last() const { QHULL_ASSERT(!isEmpty()); return T(qh(), *(endData()-1)); } T last() { QHULL_ASSERT(!isEmpty()); return T(qh(), *(endData()-1)); } // mid() not available. No setT constructor // Constructs T. Cannot return reference. const T operator[](countT idx) const { const typename T::base_type *p= reinterpret_cast(elementPointer(idx)); QHULL_ASSERT(idx>=0 && p < endData()); return T(qh(), *p); } T operator[](countT idx) { typename T::base_type *p= reinterpret_cast(elementPointer(idx)); QHULL_ASSERT(idx>=0 && p < endData()); return T(qh(), *p); } const T second() const { return operator[](1); } T second() { return operator[](1); } T value(countT idx) const; T value(countT idx, const T &defaultValue) const; #//!\name Read-write -- Not available, no setT constructor #//!\name iterator iterator begin() { return iterator(qh(), reinterpret_cast(beginPointer())); } const_iterator begin() const { return const_iterator(qh(), data()); } const_iterator constBegin() const { return const_iterator(qh(), data()); } const_iterator constEnd() const { return const_iterator(qh(), endData()); } iterator end() { return iterator(qh(), endData()); } const_iterator end() const { return const_iterator(qh(), endData()); } #//!\name Search bool contains(const T &t) const; countT count(const T &t) const; countT indexOf(const T &t) const { /* no qh_qh */ return qh_setindex(getSetT(), t.getBaseT()); } countT lastIndexOf(const T &t) const; // before const_iterator for conversion with comparison operators class iterator { friend class const_iterator; private: typename T::base_type * i; // e.g., facetT**, first for debugger QhullQh * qh_qh; public: typedef ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; typedef T value_type; iterator(QhullQh *qqh, typename T::base_type *p) : i(p), qh_qh(qqh) {} iterator(const iterator &o) : i(o.i), qh_qh(o.qh_qh) {} iterator & operator=(const iterator &o) { i= o.i; qh_qh= o.qh_qh; return *this; } // Constructs T. Cannot return reference. T operator*() const { return T(qh_qh, *i); } //operator->() n/a, value-type // Constructs T. Cannot return reference. T operator[](countT idx) const { return T(qh_qh, *(i+idx)); } //!< No error checking bool operator==(const iterator &o) const { return i == o.i; } bool operator!=(const iterator &o) const { return !operator==(o); } bool operator==(const const_iterator &o) const { return (i==reinterpret_cast(o).i); } bool operator!=(const const_iterator &o) const { return !operator==(o); } //! Assumes same point set countT operator-(const iterator &o) const { return static_cast(i-o.i); } //WARN64 bool operator>(const iterator &o) const { return i>o.i; } bool operator<=(const iterator &o) const { return !operator>(o); } bool operator<(const iterator &o) const { return i=(const iterator &o) const { return !operator<(o); } bool operator>(const const_iterator &o) const { return (i > reinterpret_cast(o).i); } bool operator<=(const const_iterator &o) const { return !operator>(o); } bool operator<(const const_iterator &o) const { return (i < reinterpret_cast(o).i); } bool operator>=(const const_iterator &o) const { return !operator<(o); } //! No error checking iterator & operator++() { ++i; return *this; } iterator operator++(int) { iterator o= *this; ++i; return o; } iterator & operator--() { --i; return *this; } iterator operator--(int) { iterator o= *this; --i; return o; } iterator operator+(countT j) const { return iterator(qh_qh, i+j); } iterator operator-(countT j) const { return operator+(-j); } iterator & operator+=(countT j) { i += j; return *this; } iterator & operator-=(countT j) { i -= j; return *this; } };//QhullPointSet::iterator class const_iterator { private: const typename T::base_type * i; // e.g., const facetT**, first for debugger QhullQh * qh_qh; public: typedef ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; typedef T value_type; const_iterator(QhullQh *qqh, const typename T::base_type * p) : i(p), qh_qh(qqh) {} const_iterator(const const_iterator &o) : i(o.i), qh_qh(o.qh_qh) {} const_iterator(const iterator &o) : i(o.i), qh_qh(o.qh_qh) {} const_iterator &operator=(const const_iterator &o) { i= o.i; qh_qh= o.qh_qh; return *this; } // Constructs T. Cannot return reference. Retaining 'const T' return type for consistency with QList/QVector const T operator*() const { return T(qh_qh, *i); } const T operator[](countT idx) const { return T(qh_qh, *(i+idx)); } //!< No error checking //operator->() n/a, value-type bool operator==(const const_iterator &o) const { return i == o.i; } bool operator!=(const const_iterator &o) const { return !operator==(o); } //! Assumes same point set countT operator-(const const_iterator &o) { return static_cast(i-o.i); } //WARN64 bool operator>(const const_iterator &o) const { return i>o.i; } bool operator<=(const const_iterator &o) const { return !operator>(o); } bool operator<(const const_iterator &o) const { return i=(const const_iterator &o) const { return !operator<(o); } //!< No error checking const_iterator &operator++() { ++i; return *this; } const_iterator operator++(int) { const_iterator o= *this; ++i; return o; } const_iterator &operator--() { --i; return *this; } const_iterator operator--(int) { const_iterator o= *this; --i; return o; } const_iterator operator+(int j) const { return const_iterator(qh_qh, i+j); } const_iterator operator-(int j) const { return operator+(-j); } const_iterator &operator+=(int j) { i += j; return *this; } const_iterator &operator-=(int j) { i -= j; return *this; } };//QhullPointSet::const_iterator };//class QhullSet //! QhullSetIterator is a Java-style iterator. It may be used on temporary results. //! QhullSetIterator copies the qh_set and qh_qh pointers in QhullSetBase //! Faster then interator/const_iterator due to T::base_type template class QhullSetIterator { #//!\name Subtypes typedef typename QhullSet::const_iterator const_iterator; private: #//!\name Fields const typename T::base_type * i; // e.g., facetT**, first for debugger const typename T::base_type * begin_i; // must be initialized after i const typename T::base_type * end_i; QhullQh * qh_qh; public: #//!\name Constructors QhullSetIterator(const QhullSet &s) : i(s.data()), begin_i(i), end_i(s.endData()), qh_qh(s.qh()) {} QhullSetIterator(const QhullSetIterator &o) : i(o.i), begin_i(o.begin_i), end_i(o.end_i), qh_qh(o.qh_qh) {} QhullSetIterator &operator=(const QhullSetIterator &o) { i= o.i; begin_i= o.begin_i; end_i= o.end_i; qh_qh= o.qh_qh; return *this; } #//!\name ReadOnly countT countRemaining() { return static_cast(end_i-i); } // WARN64 #//!\name Search bool findNext(const T &t); bool findPrevious(const T &t); #//!\name Foreach bool hasNext() const { return i != end_i; } bool hasPrevious() const { return i != begin_i; } T next() { return T(qh_qh, *i++); } T peekNext() const { return T(qh_qh, *i); } T peekPrevious() const { const typename T::base_type *p= i; return T(qh_qh, *--p); } T previous() { return T(qh_qh, *--i); } void toBack() { i= end_i; } void toFront() { i= begin_i; } };//class QhullSetIterator #//!\name == Definitions ========================================= #//!\name Conversions // See qt-qhull.cpp for QList conversion #ifndef QHULL_NO_STL template std::vector QhullSet:: toStdVector() const { typename QhullSet::const_iterator i= begin(); typename QhullSet::const_iterator e= end(); std::vector vs; while(i!=e){ vs.push_back(*i++); } return vs; }//toStdVector #endif //QHULL_NO_STL #ifdef QHULL_USES_QT template QList QhullSet:: toQList() const { typename QhullSet::const_iterator i= begin(); typename QhullSet::const_iterator e= end(); QList vs; while(i!=e){ vs.append(*i++); } return vs; }//toQList #endif #//!\name Element template T QhullSet:: value(countT idx) const { // Avoid call to qh_setsize() and assert in elementPointer() const typename T::base_type *p= reinterpret_cast(&SETelem_(getSetT(), idx)); return (idx>=0 && p T QhullSet:: value(countT idx, const T &defaultValue) const { // Avoid call to qh_setsize() and assert in elementPointer() const typename T::base_type *p= reinterpret_cast(&SETelem_(getSetT(), idx)); return (idx>=0 && p bool QhullSet:: contains(const T &t) const { setT *s= getSetT(); void *p= t.getBaseT(); // contains() is not inline for better error reporting int result= qh_setin(s, p); return result!=0; }//contains template countT QhullSet:: count(const T &t) const { countT n= 0; const typename T::base_type *i= data(); const typename T::base_type *e= endData(); typename T::base_type p= t.getBaseT(); while(i countT QhullSet:: lastIndexOf(const T &t) const { const typename T::base_type *b= data(); const typename T::base_type *i= endData(); typename T::base_type p= t.getBaseT(); while(--i>=b){ if(*i==p){ break; } } return static_cast(i-b); // WARN64 }//lastIndexOf #//!\name QhullSetIterator template bool QhullSetIterator:: findNext(const T &t) { typename T::base_type p= t.getBaseT(); while(i!=end_i){ if(*(++i)==p){ return true; } } return false; }//findNext template bool QhullSetIterator:: findPrevious(const T &t) { typename T::base_type p= t.getBaseT(); while(i!=begin_i){ if(*(--i)==p){ return true; } } return false; }//findPrevious }//namespace orgQhull #//!\name == Global namespace ========================================= template std::ostream & operator<<(std::ostream &os, const orgQhull::QhullSet &qs) { const typename T::base_type *i= qs.data(); const typename T::base_type *e= qs.endData(); while(i!=e){ os << T(qs.qh(), *i++); } return os; }//operator<< #endif // QhullSet_H