PropertyContainer.hh 12.1 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
/* ========================================================================= *
Jan Möbius's avatar
Jan Möbius committed
2
3
 *                                                                           *
 *                               OpenMesh                                    *
Jan Möbius's avatar
Jan Möbius committed
4
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
Jan Möbius's avatar
Typo    
Jan Möbius committed
5
 *           Department of Computer Graphics and Multimedia                  *
Jan Möbius's avatar
Jan Möbius committed
6
7
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
Jan Möbius's avatar
Jan Möbius committed
8
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
9
10
11
 *---------------------------------------------------------------------------*
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
Jan Möbius's avatar
Jan Möbius committed
12
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
13
14
15
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
Jan Möbius's avatar
Jan Möbius committed
16
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
17
18
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
Jan Möbius's avatar
Jan Möbius committed
19
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
20
21
22
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
Jan Möbius's avatar
Jan Möbius committed
23
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
24
25
26
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
27
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
28
29
30
31
32
33
34
35
36
37
38
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
40
 *                                                                           *
 * ========================================================================= */
41

42

Jan Möbius's avatar
Jan Möbius committed
43
44
45
46
47

#ifndef OPENMESH_PROPERTYCONTAINER
#define OPENMESH_PROPERTYCONTAINER

#include <OpenMesh/Core/Utils/Property.hh>
48
#include <OpenMesh/Core/Utils/TypeName.hh>
Jan Möbius's avatar
Jan Möbius committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

//-----------------------------------------------------------------------------
namespace OpenMesh
{
//== FORWARDDECLARATIONS ======================================================
  class BaseKernel;

//== CLASS DEFINITION =========================================================
/// A a container for properties.
class PropertyContainer
{
public:

  //-------------------------------------------------- constructor / destructor

  PropertyContainer() {}
65
  virtual ~PropertyContainer() { std::for_each(properties_.begin(), properties_.end(), Delete()); }
Jan Möbius's avatar
Jan Möbius committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81


  //------------------------------------------------------------- info / access

  typedef std::vector<BaseProperty*> Properties;
  const Properties& properties() const { return properties_; }
  size_t size() const { return properties_.size(); }



  //--------------------------------------------------------- copy / assignment

  PropertyContainer(const PropertyContainer& _rhs) { operator=(_rhs); }

  PropertyContainer& operator=(const PropertyContainer& _rhs)
  {
82
83
    // The assignment below relies on all previous BaseProperty* elements having been deleted
    std::for_each(properties_.begin(), properties_.end(), Delete());
Jan Möbius's avatar
Jan Möbius committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    properties_ = _rhs.properties_;
    Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
    for (; p_it!=p_end; ++p_it)
      if (*p_it)
        *p_it = (*p_it)->clone();
    return *this;
  }



  //--------------------------------------------------------- manage properties

  template <class T>
  BasePropHandleT<T> add(const T&, const std::string& _name="<unknown>")
  {
    Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
    int idx=0;
Jan Möbius's avatar
Jan Möbius committed
101
102
    for ( ; p_it!=p_end && *p_it!=nullptr; ++p_it, ++idx ) {};
    if (p_it==p_end) properties_.push_back(nullptr);
103
    properties_[idx] = new PropertyT<T>(_name, get_type_name<T>() );        // create a new property with requested name and given (system dependent) internal typename
Jan Möbius's avatar
Jan Möbius committed
104
105
106
107
108
109
110
111
112
113
    return BasePropHandleT<T>(idx);
  }


  template <class T>
  BasePropHandleT<T> handle(const T&, const std::string& _name) const
  {
    Properties::const_iterator p_it = properties_.begin();
    for (int idx=0; p_it != properties_.end(); ++p_it, ++idx)
    {
Jan Möbius's avatar
Jan Möbius committed
114
      if (*p_it != nullptr &&
Jan Möbius's avatar
Jan Möbius committed
115
         (*p_it)->name() == _name  //skip deleted properties
116
         && (*p_it)->internal_type_name() == get_type_name<T>()     // new check type
Jan Möbius's avatar
Jan Möbius committed
117
118
119
120
121
122
123
124
125
126
127
128
129
         )
      {
        return BasePropHandleT<T>(idx);
      }
    }
    return BasePropHandleT<T>();
  }

  BaseProperty* property( const std::string& _name ) const
  {
    Properties::const_iterator p_it = properties_.begin();
    for (int idx=0; p_it != properties_.end(); ++p_it, ++idx)
    {
Jan Möbius's avatar
Jan Möbius committed
130
      if (*p_it != nullptr && (*p_it)->name() == _name) //skip deleted properties
Jan Möbius's avatar
Jan Möbius committed
131
132
133
134
      {
        return *p_it;
      }
    }
Jan Möbius's avatar
Jan Möbius committed
135
    return nullptr;
Jan Möbius's avatar
Jan Möbius committed
136
137
138
139
140
  }

  template <class T> PropertyT<T>& property(BasePropHandleT<T> _h)
  {
    assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
Jan Möbius's avatar
Jan Möbius committed
141
    assert(properties_[_h.idx()] != nullptr);
142
143
    assert( properties_[_h.idx()]->internal_type_name() == get_type_name<T>() );
    PropertyT<T> *p = static_cast< PropertyT<T>* > (properties_[_h.idx()]);
Jan Möbius's avatar
Jan Möbius committed
144
    assert(p != nullptr);
Jan Möbius's avatar
Jan Möbius committed
145
146
147
148
149
150
151
    return *p;
  }


  template <class T> const PropertyT<T>& property(BasePropHandleT<T> _h) const
  {
    assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
Jan Möbius's avatar
Jan Möbius committed
152
    assert(properties_[_h.idx()] != nullptr);
153
154
    assert( properties_[_h.idx()]->internal_type_name() == get_type_name<T>() );
    PropertyT<T> *p = static_cast< PropertyT<T>* > (properties_[_h.idx()]);
Jan Möbius's avatar
Jan Möbius committed
155
    assert(p != nullptr);
Jan Möbius's avatar
Jan Möbius committed
156
157
158
159
160
161
162
163
    return *p;
  }


  template <class T> void remove(BasePropHandleT<T> _h)
  {
    assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
    delete properties_[_h.idx()];
Jan Möbius's avatar
Jan Möbius committed
164
    properties_[_h.idx()] = nullptr;
Jan Möbius's avatar
Jan Möbius committed
165
166
167
168
169
  }


  void clear()
  {
170
171
172
173
174
175
176
177
178
179
	// Clear properties vector:
	// Replaced the old version with new one
	// which performs a swap to clear values and
	// deallocate memory.

	// Old version (changed 22.07.09) {
	// std::for_each(properties_.begin(), properties_.end(), Delete());
    // }

	std::for_each(properties_.begin(), properties_.end(), ClearAll());
Jan Möbius's avatar
Jan Möbius committed
180
181
182
183
184
  }


  //---------------------------------------------------- synchronize properties

185
186
187
188
/*
 * In C++11 an beyond we can introduce more efficient and more legible
 * implementations of the following methods.
 */
189
#if ((defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY)
190
191
192
  /**
   * Reserves space for \p _n elements in all property vectors.
   */
193
194
195
196
197
  void reserve(size_t _n) const {
    std::for_each(properties_.begin(), properties_.end(),
            [_n](BaseProperty* p) { if (p) p->reserve(_n); });
  }

198
199
200
  /**
   * Resizes all property vectors to the specified size.
   */
201
202
203
204
205
  void resize(size_t _n) const {
    std::for_each(properties_.begin(), properties_.end(),
            [_n](BaseProperty* p) { if (p) p->resize(_n); });
  }

206
207
208
209
210
211
212
213
  /**
   * Same as resize() but ignores property vectors that have a size larger
   * than \p _n.
   *
   * Use this method instead of resize() if you plan to frequently reduce
   * and enlarge the property container and you don't want to waste time
   * reallocating the property vectors every time.
   */
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
214
215
216
217
218
  void resize_if_smaller(size_t _n) const {
    std::for_each(properties_.begin(), properties_.end(),
            [_n](BaseProperty* p) { if (p && p->n_elements() < _n) p->resize(_n); });
  }

219
220
221
222
  /**
   * Swaps the items with index \p _i0 and index \p _i1 in all property
   * vectors.
   */
223
224
225
226
227
  void swap(size_t _i0, size_t _i1) const {
    std::for_each(properties_.begin(), properties_.end(),
            [_i0, _i1](BaseProperty* p) { if (p) p->swap(_i0, _i1); });
  }
#else
228
229
230
  /**
   * Reserves space for \p _n elements in all property vectors.
   */
Jan Möbius's avatar
Jan Möbius committed
231
232
233
234
  void reserve(size_t _n) const {
    std::for_each(properties_.begin(), properties_.end(), Reserve(_n));
  }

235
236
237
  /**
   * Resizes all property vectors to the specified size.
   */
Jan Möbius's avatar
Jan Möbius committed
238
239
240
241
  void resize(size_t _n) const {
    std::for_each(properties_.begin(), properties_.end(), Resize(_n));
  }

242
243
244
245
246
247
248
249
  /**
   * Same as \sa resize() but ignores property vectors that have a size
   * larger than \p _n.
   *
   * Use this method instead of \sa resize() if you plan to frequently reduce
   * and enlarge the property container and you don't want to waste time
   * reallocating the property vectors every time.
   */
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
250
251
252
253
  void resize_if_smaller(size_t _n) const {
    std::for_each(properties_.begin(), properties_.end(), ResizeIfSmaller(_n));
  }

254
255
256
257
  /**
   * Swaps the items with index \p _i0 and index \p _i1 in all property
   * vectors.
   */
Jan Möbius's avatar
Jan Möbius committed
258
259
260
  void swap(size_t _i0, size_t _i1) const {
    std::for_each(properties_.begin(), properties_.end(), Swap(_i0, _i1));
  }
261
#endif
Jan Möbius's avatar
Jan Möbius committed
262
263
264
265
266
267
268
269
270



protected: // generic add/get

  size_t _add( BaseProperty* _bp )
  {
    Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
    size_t idx=0;
Jan Möbius's avatar
Jan Möbius committed
271
272
    for (; p_it!=p_end && *p_it!=nullptr; ++p_it, ++idx) {};
    if (p_it==p_end) properties_.push_back(nullptr);
Jan Möbius's avatar
Jan Möbius committed
273
274
275
276
277
278
279
    properties_[idx] = _bp;
    return idx;
  }

  BaseProperty& _property( size_t _idx )
  {
    assert( _idx < properties_.size());
Jan Möbius's avatar
Jan Möbius committed
280
    assert( properties_[_idx] != nullptr);
Jan Möbius's avatar
Jan Möbius committed
281
    BaseProperty *p = properties_[_idx];
Jan Möbius's avatar
Jan Möbius committed
282
    assert( p != nullptr );
Jan Möbius's avatar
Jan Möbius committed
283
284
285
286
287
288
    return *p;
  }

  const BaseProperty& _property( size_t _idx ) const
  {
    assert( _idx < properties_.size());
Jan Möbius's avatar
Jan Möbius committed
289
    assert( properties_[_idx] != nullptr);
Jan Möbius's avatar
Jan Möbius committed
290
    BaseProperty *p = properties_[_idx];
Jan Möbius's avatar
Jan Möbius committed
291
    assert( p != nullptr );
Jan Möbius's avatar
Jan Möbius committed
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    return *p;
  }


  typedef Properties::iterator       iterator;
  typedef Properties::const_iterator const_iterator;
  iterator begin() { return properties_.begin(); }
  iterator end()   { return properties_.end(); }
  const_iterator begin() const { return properties_.begin(); }
  const_iterator end() const   { return properties_.end(); }

  friend class BaseKernel;

private:

  //-------------------------------------------------- synchronization functors

#ifndef DOXY_IGNORE_THIS
  struct Reserve
  {
Jan Möbius's avatar
Jan Möbius committed
312
    explicit Reserve(size_t _n) : n_(_n) {}
Jan Möbius's avatar
Jan Möbius committed
313
314
315
316
317
318
    void operator()(BaseProperty* _p) const { if (_p) _p->reserve(n_); }
    size_t n_;
  };

  struct Resize
  {
Jan Möbius's avatar
Jan Möbius committed
319
    explicit Resize(size_t _n) : n_(_n) {}
Jan Möbius's avatar
Jan Möbius committed
320
321
322
323
    void operator()(BaseProperty* _p) const { if (_p) _p->resize(n_); }
    size_t n_;
  };

Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
324
325
  struct ResizeIfSmaller
  {
Jan Möbius's avatar
Jan Möbius committed
326
    explicit ResizeIfSmaller(size_t _n) : n_(_n) {}
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
327
328
329
330
    void operator()(BaseProperty* _p) const { if (_p && _p->n_elements() < n_) _p->resize(n_); }
    size_t n_;
  };

331
332
333
334
335
336
  struct ClearAll
  {
    ClearAll() {}
    void operator()(BaseProperty* _p) const { if (_p) _p->clear(); }
  };

Jan Möbius's avatar
Jan Möbius committed
337
338
339
340
341
342
343
344
345
346
  struct Swap
  {
    Swap(size_t _i0, size_t _i1) : i0_(_i0), i1_(_i1) {}
    void operator()(BaseProperty* _p) const { if (_p) _p->swap(i0_, i1_); }
    size_t i0_, i1_;
  };

  struct Delete
  {
    Delete() {}
347
    void operator()(BaseProperty* _p) const { if (_p) delete _p; }
Jan Möbius's avatar
Jan Möbius committed
348
349
350
351
352
353
354
355
356
357
  };
#endif

  Properties   properties_;
};

}//namespace OpenMesh

#endif//OPENMESH_PROPERTYCONTAINER