Tulip  5.3.0
Large graphs analysis and drawing
vectorgraphproperty.h
1 /*
2  *
3  * This file is part of Tulip (http://tulip.labri.fr)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 ///@cond DOXYGEN_HIDDEN
20 
21 #ifndef VECTORGRAPHPROPERTY_H
22 #define VECTORGRAPHPROPERTY_H
23 #include <algorithm>
24 #include <cassert>
25 #include <vector>
26 
27 namespace tlp {
28 class VectorGraph;
29 
30 /**
31  * @brief Internal class to access to a stl::vector in VectorGraph
32  * @warning never use that class
33  */
34 class VectorGraphValues {
35  friend class VectorGraph;
36 
37 protected:
38  virtual void addElement(const unsigned int id) = 0;
39  virtual void reserve(const size_t size) = 0;
40  virtual ~VectorGraphValues() {}
41 };
42 
43 /**
44  * @class VectorGraphProperty
45  * @brief That class enables to factorize code for NodeProperty and EdgeProperty in VectorGraph, it
46  * could not be used directly.
47  * @see NodeProperty
48  * @see EdgeProperty
49  * @see VectorGraph
50  */
51 template <typename TYPE>
52 class VectorGraphProperty {
53  friend class VectorGraph;
54 
55 protected:
56  //===========================================
57  /**
58  * @brief Internal class to access to a stl::vector in VectorGraph
59  * @warning never use that class
60  */
61  struct ValuesImpl : public VectorGraphValues, public std::vector<TYPE> {
62 
63  ValuesImpl(const unsigned int size = 0, const unsigned int capacity = 0) {
64  std::vector<TYPE>::reserve(capacity);
65  std::vector<TYPE>::resize(size);
66  }
67  ~ValuesImpl() override {}
68  void addElement(const unsigned int id) override {
69  if (id >= std::vector<TYPE>::size()) {
70  std::vector<TYPE>::resize(id + 1);
71  }
72  }
73  void reserve(const size_t size) override {
74  std::vector<TYPE>::reserve(size);
75  }
76  };
77 
78 public:
79  virtual ~VectorGraphProperty() {}
80  /**
81  * @brief read/write accessor
82  *
83  * return the value of the ith element and enables to modify it.
84  */
85  typename std::vector<TYPE>::reference operator[](const size_t id) {
86  // assert(isValid());
87  assert(id < _values->size());
88  return (*_values)[id];
89  }
90  /**
91  * @brief read accessor
92  *
93  * return the value of the ith element.
94  */
95  typename std::vector<TYPE>::const_reference operator[](const size_t id) const {
96  // assert(isValid());
97  assert(id < _values->size());
98  return (*_values)[id];
99  }
100  /**
101  * @bried Set all the value of the property to the value given in parameter
102  *
103  * That function affect the same value to all elements of the vector, there
104  * is no effect on the future value added in the vector
105  * @warning There is differences between the setAll of the MutableContainer and
106  * the setAll of VectorProperty (NodeProperty or EdgeProperty). The MutableContainer,
107  * ensures that new inserted element will have the value given by the last setAll
108  *
109  * @see MutableContainer
110  */
111  void setAll(const TYPE &obj) {
112  fill(_values->begin(), _values->end(), obj);
113  }
114  /**
115  * @brief write accessor
116  *
117  * change the value of the ith element.
118  */
119  void set(const size_t id, const TYPE &obj) {
120  (*this)[id] = obj;
121  }
122  /**
123  * @brief read accessor
124  *
125  * return the value of the ith element.
126  */
127  typename std::vector<TYPE>::const_reference get(const size_t id) const {
128  return (*this)[id];
129  }
130 #ifndef NDEBUG
131  virtual bool isValid() const = 0;
132 #endif
133 
134  void swap(VectorGraphProperty<TYPE> &v) {
135  assert(_values && (_graph == v._graph));
136  _values->swap(*(v._values));
137  }
138 
139 protected:
140  VectorGraphProperty() : _values(nullptr), _graph(nullptr) {}
141  VectorGraphProperty(const VectorGraphProperty &obj) : _values(obj._values), _graph(obj._graph) {}
142  VectorGraphProperty(ValuesImpl *values, VectorGraph *graph) : _values(values), _graph(graph) {}
143 
144  ValuesImpl *_values; /**< TODO */
145  VectorGraph *_graph; /**< TODO */
146 };
147 
148 /**
149  * @class EdgeProperty
150  * @brief That class enables to define a property/attribute on edges on a VectorGraph.
151  *
152  * Using EdgeProperty you can assign any kind of attribute to edges. To use that class
153  * you must first create an instance of EdgeProperty and then connect it to your graph.
154  * NodeProperty can be copied in another EdgeProperty, however the to NodeProperty will
155  * share the same content. You can consider that EdgeProperty is just a pointer on a stl:vector.
156  * to free memory used by a EdgeProperty connected to a graph you must use the free function.
157  * @warning After the call to free all The copy of the orignal EdgeProperty are no more valid
158  *
159  * Using EdgeProperty you can store and access to values with the same efficiency as if
160  * you created manually a vector. EdgeProperty manage for you the resize, etc... when the
161  * graph is modified.
162  *
163  * Furthemrore, in DEBUG mode, operator[] check if one try to access outside of the Array Bound.
164  * in DEBUG mode, the validy of the Property is also checked (if it has been free/alloc etc...)
165  *
166  * @code
167  * VectorGraph g;
168  * EdgeProperty<double> weight;
169  * g.alloc(weight); //connect weight to g, g allocate memory for that attribute
170  * for (const edge &e : g.edges()) {
171  * weight[n] = g.deg(g.target(e)) + g.deg(g.source(e));
172  * }
173  * EdgeProperty<double> weight2 = weight; //weight2 and weight are pointing on the same memory
174  * addres
175  * weight2[g[0]] = 3;
176  * tlp::debug() << weight[g[0]]; //output 3
177  * g.free(weight2); //free the memory, weight and weight2 are no more valid.
178  * @endcode
179  * @see VectorGraph alloc(EdgeProperty)
180  * @see VectorGraph free(EdgeProperty)
181  * @see VectorGraph
182  */
183 template <typename TYPE>
184 class EdgeProperty : public VectorGraphProperty<TYPE> {
185  friend class VectorGraph;
186 
187 public:
188  EdgeProperty() : VectorGraphProperty<TYPE>() {}
189  EdgeProperty(const EdgeProperty &obj) : VectorGraphProperty<TYPE>(obj) {}
190 #ifndef NDEBUG
191  bool isValid() const;
192 #endif
193 
194 private:
195  EdgeProperty(typename VectorGraphProperty<TYPE>::ValuesImpl *values, VectorGraph *graph)
196  : VectorGraphProperty<TYPE>(values, graph) {}
197 };
198 /**
199  * @class NodeProperty
200  * @brief That class enables to define a property/attribute on nodes on a VectorGraph.
201  *
202  * Using NodeProperty you can assign any kind of attribute to nodes. To use that class
203  * you must first create an instance of NodeProperty and then connect it to your graph.
204  * NodeProperty can be copied in another NodeProperty, however the to NodeProperty will
205  * share the same content. You can consider that NodeProperty is just a pointer on a stl:vector.
206  * to free memory used by a NodeProperty connected to a graph you must use the free function.
207  * @warning After the call to free all The copy of the orignal NodeProperty are no more valid
208  *
209  * Using NodeProperty you can store and access to values with the same efficiency as if
210  * you created manually a vector. NodeProperty manage for you the resize, etc... when the
211  * graph is modified.
212  *
213  * Furthemrore, in DEBUG mode, operator[] check if one try to access outside of the Array Bound.
214  * in DEBUG mode, the validy of the Property is also checked (if it has been free/alloc etc...)
215  *
216  * @code
217  * VectorGraph g;
218  * NodeProperty<double> weight;
219  * g.alloc(weight); //connect weight to g, g allocate memory for that attribute
220  * for(const node &n : g.nodes()) {
221  * weight[n] = g.deg(n);
222  * }
223  * NodeProperty<double> weight2 = weight; //weight2 and weight are pointing on the same memory
224  * addres
225  * weight2[g[0]] = 3;
226  * tlp::debug() << weight[g[0]]; //output 3
227  * g.free(weight2); //free the memory, weight and weight2 are no more valid.
228  * @endcode
229  * @see VectorGraph alloc(NodeProperty)
230  * @see VectorGraph free(NodeProperty)
231  */
232 template <typename TYPE>
233 class NodeProperty : public VectorGraphProperty<TYPE> {
234  friend class VectorGraph;
235 
236 public:
237  NodeProperty() : VectorGraphProperty<TYPE>() {}
238  NodeProperty(const NodeProperty &obj) : VectorGraphProperty<TYPE>(obj) {}
239 #ifndef NDEBUG
240  bool isValid() const;
241 #endif
242 
243 private:
244  NodeProperty(typename VectorGraphProperty<TYPE>::ValuesImpl *values, VectorGraph *graph)
245  : VectorGraphProperty<TYPE>(values, graph) {}
246 };
247 } // namespace tlp
248 #endif // VECTORGRAPHPROPERTY_H
249 ///@endcond