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
|
---|