[10207] | 1 | /****************************************************************************
|
---|
| 2 | **
|
---|
| 3 | ** Copyright (c) 2008-2012 C.B. Barber. All rights reserved.
|
---|
| 4 | ** $Id: //main/2011/qhull/src/libqhullcpp/QhullSet.h#7 $$Change: 1464 $
|
---|
| 5 | ** $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
|
---|
| 6 | **
|
---|
| 7 | ****************************************************************************/
|
---|
| 8 |
|
---|
| 9 | #ifndef QhullSet_H
|
---|
| 10 | #define QhullSet_H
|
---|
| 11 |
|
---|
| 12 | #include "QhullError.h"
|
---|
| 13 | extern "C" {
|
---|
| 14 | #include "libqhull/qhull_a.h"
|
---|
| 15 | }
|
---|
| 16 |
|
---|
| 17 |
|
---|
| 18 | #ifndef QHULL_NO_STL
|
---|
| 19 | #include <vector>
|
---|
| 20 | #endif
|
---|
| 21 |
|
---|
| 22 | #ifdef QHULL_USES_QT
|
---|
| 23 | #include <QtCore/QList>
|
---|
| 24 | #endif
|
---|
| 25 |
|
---|
| 26 | namespace orgQhull {
|
---|
| 27 |
|
---|
| 28 | #//Type
|
---|
| 29 | class QhullSetBase; //! Base class for QhullSet<T>
|
---|
| 30 | //! QhullSet<T> -- A read-only wrapper to Qhull's collection class, setT.
|
---|
| 31 | //! QhullSet is similar to STL's <vector> and Qt's QVector.
|
---|
| 32 | //! QhullSet is unrelated to STL and Qt's set and map types (e.g., QSet and QMap)
|
---|
| 33 | //! For STL efficiency, QhullSet caches endPointer()
|
---|
| 34 | //! T must be a pointer type
|
---|
| 35 | //! A QhullSet does not own its contents -- erase(), clear(), removeFirst(), removeLast(), pop_back(), pop_front(), fromStdList() not defined
|
---|
| 36 | //! Qhull's FOREACHelement_() [qset.h] is more efficient than QhullSet. It uses a NULL terminator instead of an end pointer. STL requires an end pointer.
|
---|
| 37 | //! Derived from QhullLinkedList.h and Qt/core/tools/qvector.h
|
---|
| 38 |
|
---|
| 39 | //! QhullSetIterator<T> defined below
|
---|
| 40 | //See: QhullPointSet, QhullLinkedList<T>
|
---|
| 41 |
|
---|
| 42 | class QhullSetBase {
|
---|
| 43 |
|
---|
| 44 | private:
|
---|
| 45 | #//Fields --
|
---|
| 46 | setT *qh_set;
|
---|
| 47 |
|
---|
| 48 | #//Class objects
|
---|
| 49 | static setT s_empty_set; //! Workaround for no setT allocator. Used if setT* is NULL
|
---|
| 50 |
|
---|
| 51 | public:
|
---|
| 52 | #//Class methods
|
---|
| 53 | static int count(const setT *set);
|
---|
| 54 | //s may be null
|
---|
| 55 | static bool isEmpty(const setT *s) { return SETempty_(s); }
|
---|
| 56 |
|
---|
| 57 |
|
---|
| 58 | #//Constructors
|
---|
| 59 | //! Copy constructor copies the pointer but not the set. Needed for return by value and parameter passing.
|
---|
| 60 | QhullSetBase(const QhullSetBase &o) : qh_set(o.qh_set) {}
|
---|
| 61 | explicit QhullSetBase(setT *s) : qh_set(s ? s : &s_empty_set) {}
|
---|
| 62 | ~QhullSetBase() {}
|
---|
| 63 |
|
---|
| 64 | private:
|
---|
| 65 | //!disabled since memory allocation for QhullSet not defined
|
---|
| 66 | QhullSetBase() {}
|
---|
| 67 | //!disabled since qs= qs2 is ambiguous (pointer vs. contents)
|
---|
| 68 | QhullSetBase &operator=(const QhullSetBase &);
|
---|
| 69 | public:
|
---|
| 70 |
|
---|
| 71 | #//Conversions
|
---|
| 72 | //! Not type-safe since setT may contain any type
|
---|
| 73 | void defineAs(setT *s) { qh_set= s ? s : &s_empty_set; }
|
---|
| 74 | setT *getSetT() const { return qh_set; }
|
---|
| 75 | setT **referenceSetT() { return &qh_set; }
|
---|
| 76 |
|
---|
| 77 | #//Read-only
|
---|
| 78 | int count() const { return QhullSetBase::count(qh_set); }
|
---|
| 79 | bool empty() const { return SETfirst_(qh_set)==0; }
|
---|
| 80 | bool isEmpty() const { return empty(); }
|
---|
| 81 | size_t size() const { return count(); }
|
---|
| 82 |
|
---|
| 83 | #//Element
|
---|
| 84 | protected:
|
---|
| 85 | void **beginPointer() const { return &qh_set->e[0].p; }
|
---|
| 86 | void **elementPointer(int idx) const { QHULL_ASSERT(idx>=0 && idx<qh_set->maxsize); return &SETelem_(qh_set, idx); }
|
---|
| 87 | //! Always points to 0
|
---|
| 88 | void **endPointer() const { return qh_setendpointer(qh_set); }
|
---|
| 89 | };//QhullSetBase
|
---|
| 90 |
|
---|
| 91 |
|
---|
| 92 | //! set of pointers to baseT, T.getBaseT()
|
---|
| 93 | template <typename T>
|
---|
| 94 | class QhullSet : public QhullSetBase {
|
---|
| 95 |
|
---|
| 96 | private:
|
---|
| 97 | #//Fields -- see QhullSetBase
|
---|
| 98 |
|
---|
| 99 | #//Class objects
|
---|
| 100 | static setT s_empty_set; //! Workaround for no setT allocator. Used if setT* is NULL
|
---|
| 101 |
|
---|
| 102 | public:
|
---|
| 103 | #//Subtypes
|
---|
| 104 | typedef T *iterator;
|
---|
| 105 | typedef const T *const_iterator;
|
---|
| 106 | typedef typename QhullSet<T>::iterator Iterator;
|
---|
| 107 | typedef typename QhullSet<T>::const_iterator ConstIterator;
|
---|
| 108 |
|
---|
| 109 | #//Class methods
|
---|
| 110 | static int count(const setT *set);
|
---|
| 111 | //s may be null
|
---|
| 112 | static bool isEmpty(const setT *s) { return SETempty_(s); }
|
---|
| 113 |
|
---|
| 114 | #//Constructors
|
---|
| 115 | //Copy constructor copies pointer but not contents. Needed for return by value.
|
---|
| 116 | QhullSet<T>(const QhullSet<T> &o) : QhullSetBase(o) {}
|
---|
| 117 | //Conversion from setT* is not type-safe. Implicit conversion for void* to T
|
---|
| 118 | explicit QhullSet<T>(setT *s) : QhullSetBase(s) { QHULL_ASSERT(sizeof(T)==sizeof(void *)); }
|
---|
| 119 | ~QhullSet<T>() {}
|
---|
| 120 |
|
---|
| 121 | private:
|
---|
| 122 | //!Disable default constructor and copy assignment. See QhullSetBase
|
---|
| 123 | QhullSet<T>();
|
---|
| 124 | QhullSet<T> &operator=(const QhullSet<T> &);
|
---|
| 125 | public:
|
---|
| 126 |
|
---|
| 127 | #//Conversion
|
---|
| 128 |
|
---|
| 129 | #ifndef QHULL_NO_STL
|
---|
| 130 | std::vector<T> toStdVector() const;
|
---|
| 131 | #endif
|
---|
| 132 | #ifdef QHULL_USES_QT
|
---|
| 133 | QList<T> toQList() const;
|
---|
| 134 | #endif
|
---|
| 135 |
|
---|
| 136 | #//Read-only -- see QhullSetBase for count(), empty(), isEmpty(), size()
|
---|
| 137 | using QhullSetBase::count;
|
---|
| 138 | using QhullSetBase::isEmpty;
|
---|
| 139 | // operator== defined for QhullSets of the same type
|
---|
| 140 | bool operator==(const QhullSet<T> &other) const { return qh_setequal(getSetT(), other.getSetT()); }
|
---|
| 141 | bool operator!=(const QhullSet<T> &other) const { return !operator==(other); }
|
---|
| 142 |
|
---|
| 143 | #//Element access
|
---|
| 144 | const T &at(int idx) const { return operator[](idx); }
|
---|
| 145 | T &back() { return last(); }
|
---|
| 146 | T &back() const { return last(); }
|
---|
| 147 | //! end element is NULL
|
---|
| 148 | const T *constData() const { return constBegin(); }
|
---|
| 149 | T *data() { return begin(); }
|
---|
| 150 | const T *data() const { return begin(); }
|
---|
| 151 | T &first() { QHULL_ASSERT(!isEmpty()); return *begin(); }
|
---|
| 152 | const T &first() const { QHULL_ASSERT(!isEmpty()); return *begin(); }
|
---|
| 153 | T &front() { return first(); }
|
---|
| 154 | const T &front() const { return first(); }
|
---|
| 155 | T &last() { QHULL_ASSERT(!isEmpty()); return *(end()-1); }
|
---|
| 156 | const T &last() const { QHULL_ASSERT(!isEmpty()); return *(end()-1); }
|
---|
| 157 | // mid() not available. No setT constructor
|
---|
| 158 | T &operator[](int idx) { T *n= reinterpret_cast<T *>(elementPointer(idx)); QHULL_ASSERT(idx>=0 && n < reinterpret_cast<T *>(endPointer())); return *n; }
|
---|
| 159 | const T &operator[](int idx) const { const T *n= reinterpret_cast<const T *>(elementPointer(idx)); QHULL_ASSERT(idx>=0 && n < reinterpret_cast<T *>(endPointer())); return *n; }
|
---|
| 160 | T &second() { return operator[](1); }
|
---|
| 161 | const T &second() const { return operator[](1); }
|
---|
| 162 | T value(int idx) const;
|
---|
| 163 | T value(int idx, const T &defaultValue) const;
|
---|
| 164 |
|
---|
| 165 | #//Read-write -- Not available, no setT constructor
|
---|
| 166 |
|
---|
| 167 | #//iterator
|
---|
| 168 | iterator begin() { return iterator(beginPointer()); }
|
---|
| 169 | const_iterator begin() const { return const_iterator(beginPointer()); }
|
---|
| 170 | const_iterator constBegin() const { return const_iterator(beginPointer()); }
|
---|
| 171 | const_iterator constEnd() const { return const_iterator(endPointer()); }
|
---|
| 172 | iterator end() { return iterator(endPointer()); }
|
---|
| 173 | const_iterator end() const { return const_iterator(endPointer()); }
|
---|
| 174 |
|
---|
| 175 | #//Search
|
---|
| 176 | bool contains(const T &t) const;
|
---|
| 177 | int count(const T &t) const;
|
---|
| 178 | int indexOf(const T &t) const { /* no qh_qh */ return qh_setindex(getSetT(), t.getBaseT()); }
|
---|
| 179 | int lastIndexOf(const T &t) const;
|
---|
| 180 |
|
---|
| 181 | };//class QhullSet
|
---|
| 182 |
|
---|
| 183 | // FIXUP? can't use QHULL_DECLARE_SEQUENTIAL_ITERATOR because it is not a template
|
---|
| 184 |
|
---|
| 185 | template <typename T>
|
---|
| 186 | class QhullSetIterator {
|
---|
| 187 |
|
---|
| 188 | #//Subtypes
|
---|
| 189 | typedef typename QhullSet<T>::const_iterator const_iterator;
|
---|
| 190 |
|
---|
| 191 | private:
|
---|
| 192 | #//Fields
|
---|
| 193 | const_iterator i;
|
---|
| 194 | const_iterator begin_i;
|
---|
| 195 | const_iterator end_i;
|
---|
| 196 |
|
---|
| 197 | public:
|
---|
| 198 | #//Constructors
|
---|
| 199 | QhullSetIterator<T>(const QhullSet<T> &s) : i(s.begin()), begin_i(i), end_i(s.end()) {}
|
---|
| 200 | QhullSetIterator<T>(const QhullSetIterator<T> &o) : i(o.i), begin_i(o.begin_i), end_i(o.end_i) {}
|
---|
| 201 | QhullSetIterator<T> &operator=(const QhullSetIterator<T> &o) { i= o.i; begin_i= o.begin_i; end_i= o.end_i; return *this; }
|
---|
| 202 |
|
---|
| 203 | #//ReadOnly
|
---|
| 204 | int countRemaining() { return (int)(end_i-begin_i); } // WARN64
|
---|
| 205 |
|
---|
| 206 | #//Search
|
---|
| 207 | bool findNext(const T &t);
|
---|
| 208 | bool findPrevious(const T &t);
|
---|
| 209 |
|
---|
| 210 | #//Foreach
|
---|
| 211 | bool hasNext() const { return i != end_i; }
|
---|
| 212 | bool hasPrevious() const { return i != begin_i; }
|
---|
| 213 | T next() { return *i++; }
|
---|
| 214 | T peekNext() const { return *i; }
|
---|
| 215 | T peekPrevious() const { const_iterator p = i; return *--p; }
|
---|
| 216 | T previous() { return *--i; }
|
---|
| 217 | void toBack() { i = end_i; }
|
---|
| 218 | void toFront() { i = begin_i; }
|
---|
| 219 | };//class QhullSetIterator
|
---|
| 220 |
|
---|
| 221 | #//== Definitions =========================================
|
---|
| 222 |
|
---|
| 223 | #//Conversion
|
---|
| 224 |
|
---|
| 225 | #ifndef QHULL_NO_STL
|
---|
| 226 | template <typename T>
|
---|
| 227 | std::vector<T> QhullSet<T>::
|
---|
| 228 | toStdVector() const
|
---|
| 229 | {
|
---|
| 230 | QhullSetIterator<T> i(*this);
|
---|
| 231 | std::vector<T> vs;
|
---|
| 232 | vs.reserve(i.countRemaining());
|
---|
| 233 | while(i.hasNext()){
|
---|
| 234 | vs.push_back(i.next());
|
---|
| 235 | }
|
---|
| 236 | return vs;
|
---|
| 237 | }//toStdVector
|
---|
| 238 | #endif
|
---|
| 239 |
|
---|
| 240 | #ifdef QHULL_USES_QT
|
---|
| 241 | template <typename T>
|
---|
| 242 | QList<T> QhullSet<T>::
|
---|
| 243 | toQList() const
|
---|
| 244 | {
|
---|
| 245 | QhullSetIterator<T> i(*this);
|
---|
| 246 | QList<T> vs;
|
---|
| 247 | while(i.hasNext()){
|
---|
| 248 | vs.append(i.next());
|
---|
| 249 | }
|
---|
| 250 | return vs;
|
---|
| 251 | }//toQList
|
---|
| 252 | #endif
|
---|
| 253 |
|
---|
| 254 | #//Element
|
---|
| 255 |
|
---|
| 256 | template <typename T>
|
---|
| 257 | T QhullSet<T>::
|
---|
| 258 | value(int idx) const
|
---|
| 259 | {
|
---|
| 260 | // Avoid call to qh_setsize() and assert in elementPointer()
|
---|
| 261 | const T *n= reinterpret_cast<const T *>(&SETelem_(getSetT(), idx));
|
---|
| 262 | return (idx>=0 && n<end()) ? *n : T();
|
---|
| 263 | }//value
|
---|
| 264 |
|
---|
| 265 | template <typename T>
|
---|
| 266 | T QhullSet<T>::
|
---|
| 267 | value(int idx, const T &defaultValue) const
|
---|
| 268 | {
|
---|
| 269 | // Avoid call to qh_setsize() and assert in elementPointer()
|
---|
| 270 | const T *n= reinterpret_cast<const T *>(&SETelem_(getSetT(), idx));
|
---|
| 271 | return (idx>=0 && n<end()) ? *n : defaultValue;
|
---|
| 272 | }//value
|
---|
| 273 |
|
---|
| 274 | #//Search
|
---|
| 275 |
|
---|
| 276 | template <typename T>
|
---|
| 277 | bool QhullSet<T>::
|
---|
| 278 | contains(const T &t) const
|
---|
| 279 | {
|
---|
| 280 | setT *s= getSetT();
|
---|
| 281 | void *e= t.getBaseT(); // contains() is not inline for better error reporting
|
---|
| 282 | int result= qh_setin(s, e);
|
---|
| 283 | return result!=0;
|
---|
| 284 | }//contains
|
---|
| 285 |
|
---|
| 286 | template <typename T>
|
---|
| 287 | int QhullSet<T>::
|
---|
| 288 | count(const T &t) const
|
---|
| 289 | {
|
---|
| 290 | int c= 0;
|
---|
| 291 | const T *i= data();
|
---|
| 292 | const T *e= end();
|
---|
| 293 | while(i<e){
|
---|
| 294 | if(*i==t){
|
---|
| 295 | c++;
|
---|
| 296 | }
|
---|
| 297 | i++;
|
---|
| 298 | }
|
---|
| 299 | return c;
|
---|
| 300 | }//count
|
---|
| 301 |
|
---|
| 302 | template <typename T>
|
---|
| 303 | int QhullSet<T>::
|
---|
| 304 | lastIndexOf(const T &t) const
|
---|
| 305 | {
|
---|
| 306 | const T *b= begin();
|
---|
| 307 | const T *i= end();
|
---|
| 308 | while(--i>=b){
|
---|
| 309 | if(*i==t){
|
---|
| 310 | break;
|
---|
| 311 | }
|
---|
| 312 | }
|
---|
| 313 | return (int)(i-b); // WARN64
|
---|
| 314 | }//lastIndexOf
|
---|
| 315 |
|
---|
| 316 | #//QhullSetIterator
|
---|
| 317 |
|
---|
| 318 | template <typename T>
|
---|
| 319 | bool QhullSetIterator<T>::
|
---|
| 320 | findNext(const T &t)
|
---|
| 321 | {
|
---|
| 322 | while(i!=end_i){
|
---|
| 323 | if(*(++i)==t){
|
---|
| 324 | return true;
|
---|
| 325 | }
|
---|
| 326 | }
|
---|
| 327 | return false;
|
---|
| 328 | }//findNext
|
---|
| 329 |
|
---|
| 330 | template <typename T>
|
---|
| 331 | bool QhullSetIterator<T>::
|
---|
| 332 | findPrevious(const T &t)
|
---|
| 333 | {
|
---|
| 334 | while(i!=begin_i){
|
---|
| 335 | if(*(--i)==t){
|
---|
| 336 | return true;
|
---|
| 337 | }
|
---|
| 338 | }
|
---|
| 339 | return false;
|
---|
| 340 | }//findPrevious
|
---|
| 341 |
|
---|
| 342 | }//namespace orgQhull
|
---|
| 343 |
|
---|
| 344 |
|
---|
| 345 | #//== Global namespace =========================================
|
---|
| 346 |
|
---|
| 347 | template <typename T>
|
---|
| 348 | std::ostream &
|
---|
| 349 | operator<<(std::ostream &os, const orgQhull::QhullSet<T> &qs)
|
---|
| 350 | {
|
---|
| 351 | const T *i= qs.begin();
|
---|
| 352 | const T *e= qs.end();
|
---|
| 353 | while(i!=e){
|
---|
| 354 | os << *i;
|
---|
| 355 | ++i;
|
---|
| 356 | }
|
---|
| 357 | return os;
|
---|
| 358 | }//operator<<
|
---|
| 359 |
|
---|
| 360 | #endif // QhullSet_H
|
---|