1 /****************************************************************************
2 **
3 ** Copyright (c) 2009-2020 C.B. Barber. All rights reserved.
4 ** $Id: //main/2019/qhull/src/libqhullcpp/QhullPoints.h#6 $$Change: 3001 $
5 ** $DateTime: 2020/07/24 20:43:28 $$Author: bbarber $
6 **
7 ****************************************************************************/
8 
9 #ifndef QHULLPOINTS_H
10 #define QHULLPOINTS_H
11 
12 #include "libqhull_r/qhull_ra.h"
13 #include "libqhullcpp/QhullPoint.h"
14 
15 #include <cstddef>  // ptrdiff_t, size_t
16 #include <ostream>
17 
18 namespace orgQhull {
19 
20 #//!\name Defined here
21     class QhullPoints;          //!< One or more points Coordinate pointers with dimension and iterators
22     class QhullPointsIterator;  //!< Java-style iterator
23 
24 //! QhullPoints are an array of QhullPoint as pointers into an array of coordinates.
25 //! For Qhull/QhullQh, QhullPoints must use hull_dim.  Can change QhullPoint to input_dim if needed for Delaunay input site
26 class QhullPoints {
27 
28 private:
29 #//!\name Fields
30     coordT *            point_first; //!< First coordinate of an array of points of point_dimension
31     coordT *            point_end;   //!< End of point coordinates (end>=first).  Trailing coordinates ignored
32     QhullQh *           qh_qh;       //!< Maybe initialized NULL to allow ownership by RboxPoints
33                                      //!< qh_qh used for QhullPoint() and qh_qh->hull_dim in constructor
34     int                 point_dimension;  //!< Dimension, >=0
35 
36 public:
37 #//!\name Subtypes
38     class const_iterator;
39     class iterator;
40     typedef QhullPoints::const_iterator ConstIterator;
41     typedef QhullPoints::iterator       Iterator;
42 
43 #//!\name Construct
44     //! QhullPoint, PointCoordinates, and QhullPoints have similar constructors
45     //! If Qhull/QhullQh is not initialized, then QhullPoints.dimension() is zero unless explicitly set
46     //! Cannot define QhullPoints(int pointDimension) since it is ambiguous with QhullPoints(QhullQh *qqh)
QhullPoints()47                         QhullPoints() : point_first(0), point_end(0), qh_qh(0), point_dimension(0) { }
QhullPoints(int pointDimension,countT coordinateCount2,coordT * c)48                         QhullPoints(int pointDimension, countT coordinateCount2, coordT *c) : point_first(c), point_end(c+coordinateCount2), qh_qh(0), point_dimension(pointDimension) { QHULL_ASSERT(pointDimension>=0); }
49     explicit            QhullPoints(const Qhull &q);
50                         QhullPoints(const Qhull &q, countT coordinateCount2, coordT *c);
51                         QhullPoints(const Qhull &q, int pointDimension, countT coordinateCount2, coordT *c);
QhullPoints(QhullQh * qqh)52     explicit            QhullPoints(QhullQh *qqh) : point_first(0), point_end(0), qh_qh(qqh), point_dimension(qqh ? qqh->hull_dim : 0) { }
QhullPoints(QhullQh * qqh,countT coordinateCount2,coordT * c)53                         QhullPoints(QhullQh *qqh, countT coordinateCount2, coordT *c) : point_first(c), point_end(c+coordinateCount2), qh_qh(qqh), point_dimension(qqh ? qqh->hull_dim : 0) { QHULL_ASSERT(qqh && qqh->hull_dim>0); }
54                         QhullPoints(QhullQh *qqh, int pointDimension, countT coordinateCount2, coordT *c);
55                         //! Copy constructor copies pointers but not contents.  Needed for return by value and parameter passing.
QhullPoints(const QhullPoints & other)56                         QhullPoints(const QhullPoints &other)  : point_first(other.point_first), point_end(other.point_end), qh_qh(other.qh_qh), point_dimension(other.point_dimension) {}
57     QhullPoints &       operator=(const QhullPoints &other) { point_first= other.point_first; point_end= other.point_end; qh_qh= other.qh_qh; point_dimension= other.point_dimension; return *this; }
~QhullPoints()58                         ~QhullPoints() {}
59 
60 public:
61 
62 #//!\name Conversion
63 
64 #ifndef QHULL_NO_STL
65     std::vector<QhullPoint> toStdVector() const;
66 #endif //QHULL_NO_STL
67 #ifdef QHULL_USES_QT
68     QList<QhullPoint>   toQList() const;
69 #endif //QHULL_USES_QT
70 
71 #//!\name GetSet
72     // Constructs QhullPoint.  Cannot return reference.
at(countT idx)73     const QhullPoint    at(countT idx) const { /* point_first==0 caught by point_end assert */ coordT *p= point_first+idx*point_dimension; QHULL_ASSERT(p<point_end); return QhullPoint(qh_qh, point_dimension, p); }
74     // Constructs QhullPoint.  Cannot return reference.
back()75     const QhullPoint    back() const { return last(); }
back()76     QhullPoint          back() { return last(); }
begin()77     ConstIterator       begin() const { return ConstIterator(*this); }
begin()78     Iterator            begin() { return Iterator(*this); }
constBegin()79     ConstIterator       constBegin() const { return ConstIterator(*this); }
constData()80     const coordT *      constData() const { return point_first; }
constEnd()81     ConstIterator       constEnd() const { return ConstIterator(qh_qh, point_dimension, point_end); }
coordinates()82     coordT *            coordinates() const { return point_first; }
coordinateCount()83     countT              coordinateCount() const { return static_cast<countT>(point_end-point_first); } // WARN64
count()84     countT              count() const { return static_cast<countT>(size()); } // WARN64
data()85     const coordT *      data() const { return point_first; }
data()86     coordT *            data() { return point_first; }
defineAs(int pointDimension,countT coordinatesCount,coordT * c)87     void                defineAs(int pointDimension, countT coordinatesCount, coordT *c) { QHULL_ASSERT(pointDimension>=0 && coordinatesCount>=0 && c!=0); point_first= c; point_end= c+coordinatesCount; point_dimension= pointDimension; }
defineAs(countT coordinatesCount,coordT * c)88     void                defineAs(countT coordinatesCount, coordT *c) { QHULL_ASSERT((point_dimension>0 && coordinatesCount>=0 && c!=0) || (c==0 && coordinatesCount==0)); point_first= c; point_end= c+coordinatesCount; }
defineAs(const QhullPoints & other)89     void                defineAs(const QhullPoints &other) { point_first= other.point_first; point_end= other.point_end; qh_qh= other.qh_qh; point_dimension= other.point_dimension; }
dimension()90     int                 dimension() const { return point_dimension; }
end()91     ConstIterator       end() const { return ConstIterator(qh_qh, point_dimension, point_end); }
end()92     Iterator            end() { return Iterator(qh_qh, point_dimension, point_end); }
extraCoordinates()93     coordT *            extraCoordinates() const { return (extraCoordinatesCount() ? (point_end-extraCoordinatesCount()) : 0); }
94     countT              extraCoordinatesCount() const;  // WARN64
95     // Constructs QhullPoint.  Cannot return reference.
first()96     const QhullPoint    first() const { return QhullPoint(qh_qh, point_dimension, point_first); }
first()97     QhullPoint          first() { return QhullPoint(qh_qh, point_dimension, point_first); }
98     // Constructs QhullPoint.  Cannot return reference.
front()99     const QhullPoint    front() const { return first(); }
front()100     QhullPoint          front() { return first(); }
includesCoordinates(const coordT * c)101     bool                includesCoordinates(const coordT *c) const { return (c>=point_first && c<point_end); }
isEmpty()102     bool                isEmpty() const { return (point_end==point_first || point_dimension==0); }
103     // Constructs QhullPoint.  Cannot return reference.
last()104     const QhullPoint    last() const { QHULL_ASSERT(point_first!=0); return QhullPoint(qh_qh, point_dimension, point_end - point_dimension); }
last()105     QhullPoint          last() { QHULL_ASSERT(point_first!=0); return QhullPoint(qh_qh, point_dimension, point_end - point_dimension); }
106     bool                operator==(const QhullPoints &other) const;
107     bool                operator!=(const QhullPoints &other) const { return (! operator==(other)); }
108     QhullPoint          operator[](countT idx) const { return at(idx); }
qh()109     QhullQh *           qh() const { return qh_qh; }
110     void                resetQhullQh(QhullQh *qqh);
setDimension(int d)111     void                setDimension(int d) { point_dimension= d; }
size()112     size_t              size() const { return (point_dimension ? (point_end-point_first)/point_dimension : 0); }
113     QhullPoint          value(countT idx) const;
114     QhullPoint          value(countT idx, QhullPoint &defaultValue) const;
115 
116 #//!\name Methods
117     bool                contains(const QhullPoint &t) const;
118     countT              count(const QhullPoint &t) const;
119     countT              indexOf(const coordT *pointCoordinates) const;
120     countT              indexOf(const coordT *pointCoordinates, int noThrow) const;
121     countT              indexOf(const QhullPoint &t) const;
122     countT              lastIndexOf(const QhullPoint &t) const;
123     //! Returns a subset of the points, not a copy
124     QhullPoints         mid(countT idx, countT length= -1) const;
125 
126 #//!\name QhullPoints::iterator
127     // Modeled on qlist.h w/o QT_STRICT_ITERATORS
128     // before const_iterator for conversion with comparison operators
129     // See: QhullSet.h
130     class iterator : public QhullPoint {
131 
132     public:
133         typedef std::random_access_iterator_tag  iterator_category;
134         typedef QhullPoint      value_type;
135         typedef value_type *    pointer;
136         typedef value_type &    reference;
137         typedef ptrdiff_t       difference_type;
138 
iterator(const QhullPoints & ps)139         explicit        iterator(const QhullPoints &ps) : QhullPoint(ps.qh(), ps.dimension(), ps.coordinates()) {}
iterator(const int pointDimension,coordT * c)140                         iterator(const int pointDimension, coordT *c): QhullPoint(pointDimension, c) {}
iterator(const Qhull & q,coordT * c)141                         iterator(const Qhull &q, coordT *c): QhullPoint(q, c) {}
iterator(const Qhull & q,int pointDimension,coordT * c)142                         iterator(const Qhull &q, int pointDimension, coordT *c): QhullPoint(q, pointDimension, c) {}
iterator(QhullQh * qqh,coordT * c)143                         iterator(QhullQh *qqh, coordT *c): QhullPoint(qqh, c) {}
iterator(QhullQh * qqh,int pointDimension,coordT * c)144                         iterator(QhullQh *qqh, int pointDimension, coordT *c): QhullPoint(qqh, pointDimension, c) {}
iterator(const iterator & other)145                         iterator(const iterator &other): QhullPoint(*other) {}
146         iterator &      operator=(const iterator &other) { defineAs( const_cast<iterator &>(other)); return *this; }
147 
148         // Need 'const QhullPoint' to maintain const
149         const QhullPoint & operator*() const { return *this; }
150         QhullPoint &    operator*() { return *this; }
151         const QhullPoint * operator->() const { return this; }
152         QhullPoint *    operator->() { return this; }
153         // value instead of reference since advancePoint() modifies self
154         QhullPoint      operator[](countT idx) const { QhullPoint result= *this; result.advancePoint(idx); return result; }
155         bool            operator==(const iterator &o) const { QHULL_ASSERT(qh_qh==o.qh_qh); return (point_coordinates==o.point_coordinates && point_dimension==o.point_dimension); }
156         bool            operator!=(const iterator &o) const { return (! operator==(o)); }
157         bool            operator<(const iterator &o) const  { QHULL_ASSERT(qh_qh==o.qh_qh); return point_coordinates < o.point_coordinates; }
158         bool            operator<=(const iterator &o) const { QHULL_ASSERT(qh_qh==o.qh_qh); return point_coordinates <= o.point_coordinates; }
159         bool            operator>(const iterator &o) const  { QHULL_ASSERT(qh_qh==o.qh_qh); return point_coordinates > o.point_coordinates; }
160         bool            operator>=(const iterator &o) const { QHULL_ASSERT(qh_qh==o.qh_qh); return point_coordinates >= o.point_coordinates; }
161         // reinterpret_cast to break circular dependency
162         bool            operator==(const QhullPoints::const_iterator &o) const { QHULL_ASSERT(qh_qh==reinterpret_cast<const iterator &>(o).qh_qh); return (point_coordinates==reinterpret_cast<const iterator &>(o).point_coordinates && point_dimension==reinterpret_cast<const iterator &>(o).point_dimension); }
163         bool            operator!=(const QhullPoints::const_iterator &o) const { return (! operator==(reinterpret_cast<const iterator &>(o))); }
164         bool            operator<(const QhullPoints::const_iterator &o) const  { QHULL_ASSERT(qh_qh==reinterpret_cast<const iterator &>(o).qh_qh); return point_coordinates < reinterpret_cast<const iterator &>(o).point_coordinates; }
165         bool            operator<=(const QhullPoints::const_iterator &o) const { QHULL_ASSERT(qh_qh==reinterpret_cast<const iterator &>(o).qh_qh); return point_coordinates <= reinterpret_cast<const iterator &>(o).point_coordinates; }
166         bool            operator>(const QhullPoints::const_iterator &o) const  { QHULL_ASSERT(qh_qh==reinterpret_cast<const iterator &>(o).qh_qh); return point_coordinates > reinterpret_cast<const iterator &>(o).point_coordinates; }
167         bool            operator>=(const QhullPoints::const_iterator &o) const { QHULL_ASSERT(qh_qh==reinterpret_cast<const iterator &>(o).qh_qh); return point_coordinates >= reinterpret_cast<const iterator &>(o).point_coordinates; }
168         iterator &      operator++() { advancePoint(1); return *this; }
169         iterator        operator++(int) { iterator n= *this; operator++(); return iterator(n); }
170         iterator &      operator--() { advancePoint(-1); return *this; }
171         iterator        operator--(int) { iterator n= *this; operator--(); return iterator(n); }
172         iterator &      operator+=(countT idx) { advancePoint(idx); return *this; }
173         iterator &      operator-=(countT idx) { advancePoint(-idx); return *this; }
174         iterator        operator+(countT idx) const { iterator n= *this; n.advancePoint(idx); return n; }
175         iterator        operator-(countT idx) const { iterator n= *this; n.advancePoint(-idx); return n; }
176         difference_type operator-(iterator o) const { QHULL_ASSERT(qh_qh==o.qh_qh && point_dimension==o.point_dimension); return (point_dimension ? (point_coordinates-o.point_coordinates)/point_dimension : 0); }
177     };//QhullPoints::iterator
178 
179 #//!\name QhullPoints::const_iterator
180     //!\todo QH11018 FIX: const_iterator same as iterator.  SHould have a common definition
181     class const_iterator : public QhullPoint {
182 
183     public:
184         typedef std::random_access_iterator_tag  iterator_category;
185         typedef QhullPoint          value_type;
186         typedef const value_type *  pointer;
187         typedef const value_type &  reference;
188         typedef ptrdiff_t           difference_type;
189 
const_iterator(const QhullPoints::iterator & o)190                         const_iterator(const QhullPoints::iterator &o) : QhullPoint(*o) {}
const_iterator(const QhullPoints & ps)191         explicit        const_iterator(const QhullPoints &ps) : QhullPoint(ps.qh(), ps.dimension(), ps.coordinates()) {}
const_iterator(const int pointDimension,coordT * c)192                         const_iterator(const int pointDimension, coordT *c): QhullPoint(pointDimension, c) {}
const_iterator(const Qhull & q,coordT * c)193                         const_iterator(const Qhull &q, coordT *c): QhullPoint(q, c) {}
const_iterator(const Qhull & q,int pointDimension,coordT * c)194                         const_iterator(const Qhull &q, int pointDimension, coordT *c): QhullPoint(q, pointDimension, c) {}
const_iterator(QhullQh * qqh,coordT * c)195                         const_iterator(QhullQh *qqh, coordT *c): QhullPoint(qqh, c) {}
const_iterator(QhullQh * qqh,int pointDimension,coordT * c)196                         const_iterator(QhullQh *qqh, int pointDimension, coordT *c): QhullPoint(qqh, pointDimension, c) {}
const_iterator(const const_iterator & o)197                         const_iterator(const const_iterator &o) : QhullPoint(*o) {}
198         const_iterator &operator=(const const_iterator &o) { defineAs(const_cast<const_iterator &>(o)); return *this; }
199 
200         // value/non-const since advancePoint(1), etc. modifies self
201         const QhullPoint & operator*() const { return *this; }
202         const QhullPoint * operator->() const { return this; }
203         // value instead of reference since advancePoint() modifies self
204         const QhullPoint operator[](countT idx) const { QhullPoint n= *this; n.advancePoint(idx); return n; }
205         bool            operator==(const const_iterator &o) const { QHULL_ASSERT(qh_qh==o.qh_qh); return (point_coordinates == o.point_coordinates && point_dimension==o.point_dimension); }
206         bool            operator!=(const const_iterator &o) const { return (! operator==(o)); }
207         bool            operator<(const const_iterator &o) const  { QHULL_ASSERT(qh_qh==o.qh_qh); return (point_coordinates < o.point_coordinates); }
208         bool            operator<=(const const_iterator &o) const { QHULL_ASSERT(qh_qh==o.qh_qh); return (point_coordinates <= o.point_coordinates); }
209         bool            operator>(const const_iterator &o) const  { QHULL_ASSERT(qh_qh==o.qh_qh); return (point_coordinates > o.point_coordinates); }
210         bool            operator>=(const const_iterator &o) const { QHULL_ASSERT(qh_qh==o.qh_qh); return (point_coordinates >= o.point_coordinates); }
211         const_iterator &operator++() { advancePoint(1); return *this; }
212         const_iterator  operator++(int) { const_iterator n= *this; operator++(); return const_iterator(n); }
213         const_iterator &operator--() { advancePoint(-1); return *this; }
214         const_iterator  operator--(int) { const_iterator n= *this; operator--(); return const_iterator(n); }
215         const_iterator &operator+=(countT idx) { advancePoint(idx); return *this; }
216         const_iterator &operator-=(countT idx) { advancePoint(-idx); return *this; }
217         const_iterator  operator+(countT idx) const { const_iterator n= *this; n.advancePoint(idx); return n; }
218         const_iterator  operator-(countT idx) const { const_iterator n= *this; n.advancePoint(-idx); return n; }
219         difference_type operator-(const_iterator o) const { QHULL_ASSERT(qh_qh==o.qh_qh && point_dimension==o.point_dimension); return (point_dimension ? (point_coordinates-o.point_coordinates)/point_dimension : 0); }
220     };//QhullPoints::const_iterator
221 
222 #//!\name IO
223     struct PrintPoints{
224         const QhullPoints  *points;
225         const char *    point_message;
226         bool            with_identifier;
PrintPointsPrintPoints227         PrintPoints(const char *message, bool withIdentifier, const QhullPoints &ps) : points(&ps), point_message(message), with_identifier(withIdentifier) {}
228     };//PrintPoints
print(const char * message)229     PrintPoints          print(const char *message) const { return PrintPoints(message, false, *this); }
printWithIdentifier(const char * message)230     PrintPoints          printWithIdentifier(const char *message) const { return PrintPoints(message, true, *this); }
231 };//QhullPoints
232 
233 
234 //! QhullPointsIterator is a Java-style iterator.  It may be used on temporary results.  It copies the pointers in QhullPoints
235 //! Did not use QHULL_DECLARE_SEQUENTIAL_ITERATOR because next(),etc cannot return a reference to a temporary
236 class QhullPointsIterator
237 {
238     typedef QhullPoints::const_iterator const_iterator;
239 
240 #//!\name Fields
241 private:
242     QhullPoints         ps;
243     const_iterator      i;
244 
245 public:
QhullPointsIterator(const QhullPoints & other)246                         QhullPointsIterator(const QhullPoints &other) : ps(other), i(ps.constBegin()) {}
247     QhullPointsIterator &operator=(const QhullPoints &other) { ps= other; i= ps.constBegin(); return *this; }
248 
249     bool                findNext(const QhullPoint &t);
250     bool                findPrevious(const QhullPoint &t);
hasNext()251     bool                hasNext() const { return i != ps.constEnd(); }
hasPrevious()252     bool                hasPrevious() const { return i != ps.constBegin(); }
next()253     QhullPoint          next() { return *i++; }
peekNext()254     QhullPoint          peekNext() const { return *i; }
peekPrevious()255     QhullPoint          peekPrevious() const { const_iterator p= i; return *--p; }
previous()256     QhullPoint          previous() { return *--i; }
toBack()257     void                toBack() { i= ps.constEnd(); }
toFront()258     void                toFront() { i= ps.constBegin(); }
259 };//QhullPointsIterator
260 
261 }//namespace orgQhull
262 
263 #//!\name Global
264 
265 std::ostream &          operator<<(std::ostream &os, const orgQhull::QhullPoints &p);
266 std::ostream &          operator<<(std::ostream &os, const orgQhull::QhullPoints::PrintPoints &pr);
267 
268 #endif // QHULLPOINTS_H
269