Tulip  5.4.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  VectorGraphProperty &operator=(const VectorGraphProperty &) = default;
144 
145  ValuesImpl *_values; /**< TODO */
146  VectorGraph *_graph; /**< TODO */
147 };
148 
149 /**
150  * @class EdgeProperty
151  * @brief That class enables to define a property/attribute on edges on a VectorGraph.
152  *
153  * Using EdgeProperty you can assign any kind of attribute to edges. To use that class
154  * you must first create an instance of EdgeProperty and then connect it to your graph.
155  * NodeProperty can be copied in another EdgeProperty, however the to NodeProperty will
156  * share the same content. You can consider that EdgeProperty is just a pointer on a stl:vector.
157  * to free memory used by a EdgeProperty connected to a graph you must use the free function.
158  * @warning After the call to free all The copy of the original EdgeProperty are no more valid
159  *
160  * Using EdgeProperty you can store and access to values with the same efficiency as if
161  * you created manually a vector. EdgeProperty manage for you the resize, etc... when the
162  * graph is modified.
163  *
164  * Furthemrore, in DEBUG mode, operator[] check if one try to access outside of the Array Bound.
165  * in DEBUG mode, the validy of the Property is also checked (if it has been free/alloc etc...)
166  *
167  * @code
168  * VectorGraph g;
169  * EdgeProperty<double> weight;
170  * g.alloc(weight); //connect weight to g, g allocate memory for that attribute
171  * for (const edge &e : g.edges()) {
172  * weight[n] = g.deg(g.target(e)) + g.deg(g.source(e));
173  * }
174  * EdgeProperty<double> weight2 = weight; //weight2 and weight are pointing on the same memory
175  * address
176  * weight2[g[0]] = 3;
177  * tlp::debug() << weight[g[0]]; //output 3
178  * g.free(weight2); //free the memory, weight and weight2 are no more valid.
179  * @endcode
180  * @see VectorGraph alloc(EdgeProperty)
181  * @see VectorGraph free(EdgeProperty)
182  * @see VectorGraph
183  */
184 template <typename TYPE>
185 class EdgeProperty : public VectorGraphProperty<TYPE> {
186  friend class VectorGraph;
187 
188 public:
189  EdgeProperty() : VectorGraphProperty<TYPE>() {}
190  EdgeProperty(const EdgeProperty &obj) : VectorGraphProperty<TYPE>(obj) {}
191  EdgeProperty &operator=(const EdgeProperty &) = default;
192 #ifndef NDEBUG
193  bool isValid() const;
194 #endif
195 
196 private:
197  EdgeProperty(typename VectorGraphProperty<TYPE>::ValuesImpl *values, VectorGraph *graph)
198  : VectorGraphProperty<TYPE>(values, graph) {}
199 };
200 /**
201  * @class NodeProperty
202  * @brief That class enables to define a property/attribute on nodes on a VectorGraph.
203  *
204  * Using NodeProperty you can assign any kind of attribute to nodes. To use that class
205  * you must first create an instance of NodeProperty and then connect it to your graph.
206  * NodeProperty can be copied in another NodeProperty, however the to NodeProperty will
207  * share the same content. You can consider that NodeProperty is just a pointer on a stl:vector.
208  * to free memory used by a NodeProperty connected to a graph you must use the free function.
209  * @warning After the call to free all The copy of the original NodeProperty are no more valid
210  *
211  * Using NodeProperty you can store and access to values with the same efficiency as if
212  * you created manually a vector. NodeProperty manage for you the resize, etc... when the
213  * graph is modified.
214  *
215  * Furthemrore, in DEBUG mode, operator[] check if one try to access outside of the Array Bound.
216  * in DEBUG mode, the validy of the Property is also checked (if it has been free/alloc etc...)
217  *
218  * @code
219  * VectorGraph g;
220  * NodeProperty<double> weight;
221  * g.alloc(weight); //connect weight to g, g allocate memory for that attribute
222  * for(const node &n : g.nodes()) {
223  * weight[n] = g.deg(n);
224  * }
225  * NodeProperty<double> weight2 = weight; //weight2 and weight are pointing on the same memory
226  * address
227  * weight2[g[0]] = 3;
228  * tlp::debug() << weight[g[0]]; //output 3
229  * g.free(weight2); //free the memory, weight and weight2 are no more valid.
230  * @endcode
231  * @see VectorGraph alloc(NodeProperty)
232  * @see VectorGraph free(NodeProperty)
233  */
234 template <typename TYPE>
235 class NodeProperty : public VectorGraphProperty<TYPE> {
236  friend class VectorGraph;
237 
238 public:
239  NodeProperty() : VectorGraphProperty<TYPE>() {}
240  NodeProperty(const NodeProperty &obj) : VectorGraphProperty<TYPE>(obj) {}
241  NodeProperty &operator=(const NodeProperty &) = default;
242 #ifndef NDEBUG
243  bool isValid() const;
244 #endif
245 
246 private:
247  NodeProperty(typename VectorGraphProperty<TYPE>::ValuesImpl *values, VectorGraph *graph)
248  : VectorGraphProperty<TYPE>(values, graph) {}
249 };
250 } // namespace tlp
251 #endif // VECTORGRAPHPROPERTY_H
252 ///@endcond