Line data Source code
1 : /*
2 : * Copyright (c) 2009-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__LIB_GRID__GEOMETRIC_BASE_OBJECTS__
34 : #define __H__LIB_GRID__GEOMETRIC_BASE_OBJECTS__
35 :
36 : #include <list>
37 : #include <cassert>
38 : #include <iostream>
39 : #include <utility>
40 : #include "common/types.h"
41 : #include "common/common.h"
42 : #include "common/assert.h"
43 : #include "lib_grid/attachments/attachment_pipe.h"
44 : #include "lib_grid/attachments/attached_list.h"
45 : #include "common/util/hash_function.h"
46 : #include "common/allocators/small_object_allocator.h"
47 : #include "common/math/ugmath_types.h"
48 : #include "common/util/pointer_const_array.h"
49 :
50 : namespace ug
51 : {
52 : ////////////////////////////////////////////////////////////////////////
53 : ////////////////////////////////////////////////////////////////////////
54 : // CONSTANTS
55 :
56 : ////////////////////////////////////////////////////////////////////////
57 : /// enumeration of the GridBaseObjects that make up a grid.
58 : enum GridBaseObjectId
59 : {
60 : VERTEX = 0,
61 : EDGE,
62 : FACE,
63 : VOLUME,
64 : NUM_GEOMETRIC_BASE_OBJECTS //always last!!!
65 : };
66 :
67 : extern const char* GRID_BASE_OBJECT_SINGULAR_NAMES[];
68 : extern const char* GRID_BASE_OBJECT_PLURAL_NAMES[];
69 :
70 : ////////////////////////////////////////////////////////////////////////
71 : // Reference-Object IDs
72 : /// these ids are used to identify the shape of a geometric object.
73 : enum ReferenceObjectID
74 : {
75 : ROID_UNKNOWN = -1,
76 : ROID_VERTEX,
77 : ROID_EDGE,
78 : ROID_TRIANGLE,
79 : ROID_QUADRILATERAL,
80 : ROID_TETRAHEDRON,
81 : ROID_HEXAHEDRON,
82 : ROID_PRISM,
83 : ROID_PYRAMID,
84 : ROID_OCTAHEDRON,
85 : NUM_REFERENCE_OBJECTS
86 : };
87 :
88 : inline
89 : ReferenceObjectID operator++(ReferenceObjectID& roid, int)
90 : {
91 : int tmp = roid;
92 0 : return roid = static_cast<ReferenceObjectID>(++tmp);
93 : };
94 :
95 : ////////////////////////////////////////////////////////////////////////
96 : inline
97 0 : std::ostream& operator<< (std::ostream& outStream, ReferenceObjectID type)
98 : {
99 0 : switch(type)
100 : {
101 0 : case ROID_UNKNOWN: outStream << "(invalid)"; break;
102 0 : case ROID_VERTEX: outStream << "Vertex"; break;
103 0 : case ROID_EDGE: outStream << "Edge"; break;
104 0 : case ROID_TRIANGLE: outStream << "Triangle"; break;
105 0 : case ROID_QUADRILATERAL: outStream << "Quadrilateral"; break;
106 0 : case ROID_TETRAHEDRON: outStream << "Tetrahedron"; break;
107 0 : case ROID_OCTAHEDRON: outStream << "Octahedron"; break;
108 0 : case ROID_HEXAHEDRON: outStream << "Hexahedron"; break;
109 0 : case ROID_PRISM: outStream << "Prism"; break;
110 0 : case ROID_PYRAMID: outStream << "Pyramid"; break;
111 0 : default: throw(UGError("Unknown ReferenceObjectID in operator<<"));
112 : }
113 0 : return outStream;
114 : };
115 :
116 :
117 : ////////////////////////////////////////////////////////////////////////
118 : // PREDECLARATIONS
119 : class Grid;
120 : template<class TElem> class ElementStorage;
121 :
122 : class GridObject; // geometric base object
123 : class Vertex; // base for all 0-dimensional grid objects.
124 : class Edge; // base for all 1-dimensional grid objects.
125 : class Face; // base for all 2-dimensional grid objects.
126 : class Volume; // base for all 3-dimensional grid objects.
127 :
128 : class EdgeDescriptor; // describes an edge.
129 : class FaceDescriptor; // describes a face.
130 : class VolumeDescriptor; // describes a volume.
131 :
132 : class EdgeVertices; // manages the vertices of an edge. Base for Edge and EdgeDescriptor.
133 : class FaceVertices; // manages the vertices of a face. Base for Face and FaceDescriptor.
134 : class VolumeVertices; // manages the vertices of a volume. Base for Volume and VolumeDescriptor.
135 :
136 : template<> class attachment_traits<Vertex*, ElementStorage<Vertex> >;
137 : template<> class attachment_traits<Edge*, ElementStorage<Edge> >;
138 : template<> class attachment_traits<Face*, ElementStorage<Face> >;
139 : template<> class attachment_traits<Volume*, ElementStorage<Volume> >;
140 :
141 : /**
142 : * \brief Geometric objects are the building blocks of a grid.
143 : *
144 : * \defgroup lib_grid_grid_objects geometric objects
145 : * \ingroup lib_grid
146 : */
147 : ////////////////////////////////////////////////////////////////////////
148 : // GridObject
149 : /// The base class for all geometric objects, such as vertices, edges, faces, volumes, ...
150 : /**
151 : * In order to be used by libGrid, all derivatives of GridObject
152 : * have to specialize geometry_traits<GeomObjectType>.
153 : *
154 : * \ingroup lib_grid_grid_objects
155 : */
156 : class UG_API GridObject/* : public SmallObject<>*/
157 : {
158 : friend class Grid;
159 : friend class attachment_traits<Vertex*, ElementStorage<Vertex> >;
160 : friend class attachment_traits<Edge*, ElementStorage<Edge> >;
161 : friend class attachment_traits<Face*, ElementStorage<Face> >;
162 : friend class attachment_traits<Volume*, ElementStorage<Volume> >;
163 :
164 : public:
165 : virtual ~GridObject() {}
166 :
167 : /// create an instance of the derived type
168 : /** Make sure to overload this method in derivates of this class!*/
169 0 : virtual GridObject* create_empty_instance() const {return NULL;}
170 :
171 : virtual int container_section() const = 0;
172 : virtual int base_object_id() const = 0;
173 : /**
174 : * A reference object represents a class of geometric objects.
175 : * Tetrahedrons, Triangles etc are such classes.
176 : * Reference ids should be defined in the file in which concrete geometric objects are defined.
177 : */
178 : virtual ReferenceObjectID reference_object_id() const = 0;/// returns the id of the reference-object.
179 :
180 : /// returns true if the object constrains other objects.
181 : /** This is normally only the case for special constraining objects.
182 : * The default implementation returns false.*/
183 0 : virtual bool is_constraining() const {return false;}
184 :
185 : /// returns true if the object is constrained by other objects.
186 : /** This is normally only the case for special constrained objects.
187 : * The default implementation returns false.*/
188 0 : virtual bool is_constrained() const {return false;}
189 :
190 : /// removes a constraint link to the grid object.
191 : /** This method is e.g. called on the constraining edges of a constrained
192 : * vertex as soon as the constrained vertex is deleted.
193 : * \{ */
194 0 : virtual void remove_constraint_link(const Vertex* vrt) {}
195 0 : virtual void remove_constraint_link(const Edge* e) {}
196 0 : virtual void remove_constraint_link(const Face* f) {}
197 : /** \} */
198 :
199 : /// Returns the grid attachment data index of a geometric object.
200 : /** Beware that this index is for internal use in the grid management and can
201 : * be changed by some operations (e.g. by Grid::defragment). But this function
202 : * can be used for debugging, when one wants to identify an element at several
203 : * places in the code.
204 : */
205 35 : inline uint grid_data_index() const {return m_gridDataIndex;}
206 :
207 : protected:
208 : /// ATTENTION: Use this method with extreme care!
209 : /** This method is for internal use only and should almost never be called
210 : * by a user of lib_grid. The method sets the attachment data index and is
211 : * mainly used by attachment-traits classes.*/
212 7 : inline void set_grid_data_index(uint index) {m_gridDataIndex = index;}
213 :
214 : protected:
215 : uint m_gridDataIndex;// index to grid-attached data.
216 : };
217 :
218 :
219 :
220 : ////////////////////////////////////////////////////////////////////////////////////////////////
221 : // Vertex
222 : /// Base-class for all vertex-types
223 : /**
224 : * Vertices are required in any grid.
225 : * They are the geometric objects of lowest dimension.
226 : * All other geometric objects of higher dimension reference vertices.
227 : *
228 : * \ingroup lib_grid_grid_objects
229 : */
230 : class UG_API Vertex : public GridObject
231 : {
232 : friend class Grid;
233 : public:
234 : typedef Vertex grid_base_object;
235 :
236 : // lower dimensional Base Object
237 : typedef void lower_dim_base_object;
238 :
239 : // higher dimensional Base Object
240 : typedef Edge higher_dim_base_object;
241 :
242 : /** The side type is obviously wrong. It should be void.
243 : * However, void would cause problems with template instantiations.*/
244 : typedef Vertex side;
245 : typedef Edge sideof;
246 :
247 : static const bool HAS_SIDES = false;
248 : static const bool CAN_BE_SIDE = true;
249 :
250 : /// reference dimension
251 : static const int dim = 0;
252 :
253 : static const int BASE_OBJECT_ID = VERTEX;
254 :
255 : static const size_t NUM_VERTICES = 1;
256 :
257 : public:
258 : inline static bool type_match(GridObject* pObj) {return dynamic_cast<Vertex*>(pObj) != NULL;}
259 :
260 0 : virtual ~Vertex() {}
261 :
262 : inline uint num_sides() const {return 0;}
263 :
264 0 : virtual int container_section() const {return -1;}
265 0 : virtual int base_object_id() const {return VERTEX;}
266 0 : virtual ReferenceObjectID reference_object_id() const {return ROID_UNKNOWN;}
267 :
268 : /// returns a value that can be used for hashing.
269 : /** this value is unique per grid.
270 : * It is only set correctly if the vertex has been created
271 : * by the grid or has been properly registered at it.*/
272 0 : inline uint32 get_hash_value() const {return m_hashValue;}
273 :
274 : protected:
275 : uint32 m_hashValue;// a unique value for each vertex in a grid.
276 : };
277 :
278 :
279 : /// This descriptor is mainly useful to avoid compilation errors in templated code
280 : /** \note Most methods here are only provided to avoid issues with other descriptors
281 : * in templated code.
282 : * \note The only valid index is '0' for any method taking indices. If a higher
283 : * index is passed, the index is ignored and '0' is used instead.
284 : */
285 : class UG_API VertexDescriptor {
286 : public:
287 : typedef Vertex* const* ConstVertexArray;
288 :
289 : VertexDescriptor() {}
290 : VertexDescriptor(Vertex* v) : m_v(v) {}
291 : VertexDescriptor(const VertexDescriptor& d) : m_v (d.m_v) {}
292 :
293 : VertexDescriptor& operator = (const VertexDescriptor& d)
294 : {m_v = d.m_v; return *this;}
295 :
296 : inline void set_vertex(Vertex* v) {m_v = v;}
297 : inline void set_vertex(uint, Vertex* v) {m_v = v;}
298 :
299 : inline Vertex* vertex () const {return m_v;}
300 : virtual Vertex* vertex(size_t) const {return m_v;}
301 : Vertex* operator[](size_t) const {return m_v;}
302 :
303 : virtual ConstVertexArray vertices() const {return &m_v;}
304 : virtual size_t num_vertices() const {return 1;}
305 :
306 : // compatibility with std::vector for some template routines
307 : /// returns the number of vertices.
308 : inline size_t size() const {return 1;}
309 :
310 : private:
311 : Vertex* m_v;
312 : };
313 :
314 :
315 : /// Base class for all classes which consist of a group of vertices
316 : class UG_API IVertexGroup
317 : {
318 : public:
319 : typedef Vertex* const* ConstVertexArray;
320 :
321 : virtual ~IVertexGroup() {};
322 : virtual Vertex* vertex(size_t index) const = 0;
323 : virtual ConstVertexArray vertices() const = 0;
324 : virtual size_t num_vertices() const = 0;
325 :
326 : // compatibility with std::vector for some template routines
327 : /// returns the number of vertices.
328 0 : inline size_t size() const {return num_vertices();}
329 : /// returns the i-th vertex.
330 : inline Vertex* operator[](size_t index) const {return vertex(index);}
331 : };
332 :
333 :
334 : /// this class can be used if one wants to create a custom element from a set of vertices.
335 : class UG_API CustomVertexGroup : public IVertexGroup
336 : {
337 : public:
338 0 : CustomVertexGroup() {}
339 : CustomVertexGroup(size_t numVrts) {m_vrts.resize(numVrts);}
340 0 : virtual ~CustomVertexGroup() {}
341 :
342 0 : virtual Vertex* vertex(size_t index) const {return m_vrts[index];}
343 0 : virtual ConstVertexArray vertices() const {return &m_vrts.front();}
344 0 : virtual size_t num_vertices() const {return m_vrts.size();}
345 :
346 : void set_num_vertices(size_t newSize) {m_vrts.resize(newSize);}
347 0 : void resize(size_t newSize) {m_vrts.resize(newSize);}
348 : void clear() {m_vrts.clear();}
349 : void push_back(Vertex* vrt) {m_vrts.push_back(vrt);}
350 0 : void set_vertex(size_t index, Vertex* vrt) {m_vrts[index] = vrt;}
351 :
352 : private:
353 : std::vector<Vertex*> m_vrts;
354 : };
355 :
356 :
357 :
358 : ////////////////////////////////////////////////////////////////////////////////////////////////
359 : // EdgeVertices
360 : /// holds the vertices of an Edge or an EdgeDescriptor.
361 : class UG_API EdgeVertices : public IVertexGroup
362 : {
363 : friend class Grid;
364 : public:
365 : virtual ~EdgeVertices() {}
366 3 : virtual Vertex* vertex(size_t index) const {return m_vertices[index];}
367 0 : virtual ConstVertexArray vertices() const {return m_vertices;}
368 0 : virtual size_t num_vertices() const {return 2;}
369 :
370 : // compatibility with std::vector for some template routines
371 : /// returns the number of vertices.
372 : inline size_t size() const {return 2;}
373 : /// returns the i-th vertex.
374 : Vertex* operator[](size_t index) const {return m_vertices[index];}
375 :
376 : protected:
377 : inline void assign_edge_vertices(const EdgeVertices& ev)
378 : {
379 0 : m_vertices[0] = ev.m_vertices[0];
380 0 : m_vertices[1] = ev.m_vertices[1];
381 : }
382 :
383 : protected:
384 : Vertex* m_vertices[2];
385 : };
386 :
387 : ////////////////////////////////////////////////////////////////////////////////////////////////
388 : // Edge
389 : /// Base-class for edges
390 : /**
391 : * Edge is the base class of all 1-dimensional geometric objects.
392 : * Edges connect two vertices.
393 : *
394 : * \ingroup lib_grid_grid_objects
395 : */
396 : class UG_API Edge : public GridObject, public EdgeVertices
397 : {
398 : friend class Grid;
399 : public:
400 : typedef Edge grid_base_object;
401 :
402 : // lower dimensional Base Object
403 : typedef Vertex lower_dim_base_object;
404 : // higher dimensional Base Object
405 : typedef Face higher_dim_base_object;
406 :
407 : typedef Vertex side;
408 : typedef Face sideof;
409 :
410 : static const bool HAS_SIDES = true;
411 : static const bool CAN_BE_SIDE = true;
412 :
413 : /// reference dimension
414 : static const int dim = 1;
415 :
416 : static const int BASE_OBJECT_ID = EDGE;
417 :
418 : static const size_t NUM_VERTICES = 2;
419 :
420 : public:
421 : inline static bool type_match(GridObject* pObj) {return dynamic_cast<Edge*>(pObj) != NULL;}
422 :
423 0 : virtual ~Edge() {}
424 :
425 0 : virtual int container_section() const {return -1;}
426 0 : virtual int base_object_id() const {return EDGE;}
427 0 : virtual ReferenceObjectID reference_object_id() const {return ROID_UNKNOWN;}
428 :
429 : inline uint num_sides() const {return 2;}
430 :
431 : /// retrieves the vertex on the opposing side to the specified one.
432 : /** If the specified vertex is not part of the edge, false is returned.
433 : * If it is, then vrtOut is filled with the opposing vertex and true is returned.*/
434 : bool get_opposing_side(Vertex* v, Vertex** vrtOut);
435 :
436 : bool get_opposing_side(Vertex* v, VertexDescriptor& vrtOut);
437 :
438 : /**
439 : * create 2 new edges, connecting the original edges end-points with vrtNew.
440 : * Newly created edges have to be registered at a grid manually by the caller.
441 : * If the caller does not register the edges in vGeomOut at a grid, he is
442 : * responsible to free the associated memory (delete each element in vNewEdgesOut).
443 : * Please note that refining an edge using this method does not automatically
444 : * refine associated elements.
445 : * Be sure to store the new edges in the right order. vNewEdgesOut should contain
446 : * the edge connecting vertex(0) and newVertex first.
447 : *
448 : * You may pass an array of 2 vertices to pSubstituteVrts. If you do so, Those
449 : * vertices will be used instead of the original ones.
450 : */
451 0 : virtual bool refine(std::vector<Edge*>& vNewEdgesOut,
452 : Vertex* newVertex,
453 0 : Vertex** pSubstituteVrts = NULL) {return false;}
454 :
455 : protected:
456 0 : inline void set_vertex(uint index, Vertex* pVrt) {m_vertices[index] = pVrt;}
457 : };
458 :
459 :
460 : ////////////////////////////////////////////////////////////////////////////////////////////////
461 : // EdgeDescriptor
462 : /// Can be used to store information about an edge and to construct an edge.
463 3 : class UG_API EdgeDescriptor : public EdgeVertices
464 : {
465 : public:
466 : EdgeDescriptor();
467 : EdgeDescriptor(const EdgeDescriptor& ed);
468 : EdgeDescriptor(Vertex* vrt1, Vertex* vrt2);
469 :
470 : EdgeDescriptor& operator = (const EdgeDescriptor& ed);
471 :
472 : inline void set_vertex(uint index, Vertex* vrt) {m_vertices[index] = vrt;}
473 : inline void set_vertices(Vertex* vrt1, Vertex* vrt2)
474 : {
475 3 : m_vertices[0] = vrt1;
476 3 : m_vertices[1] = vrt2;
477 0 : }
478 : };
479 :
480 :
481 :
482 : class UG_API FaceVertices : public IVertexGroup
483 : {
484 : public:
485 : virtual ~FaceVertices() {}
486 0 : virtual Vertex* vertex(size_t index) const {UG_ASSERT(0, "SHOULDN'T BE CALLED"); return NULL;}
487 0 : virtual ConstVertexArray vertices() const {UG_ASSERT(0, "SHOULDN'T BE CALLED"); return NULL;}
488 0 : virtual size_t num_vertices() const {UG_ASSERT(0, "SHOULDN'T BE CALLED"); return 0;}
489 :
490 : // compatibility with std::vector for some template routines
491 : /// returns the number of vertices.
492 0 : inline size_t size() const {return num_vertices();}
493 : /// returns the i-th vertex.
494 : inline Vertex* operator[](size_t index) const {return vertex(index);}
495 : };
496 :
497 : ////////////////////////////////////////////////////////////////////////////////////////////////
498 : // Face
499 : /// Faces are 2-dimensional objects.
500 : /**
501 : * Base class for all 2-dimensional objects.
502 : * Faces connect three or more vertices.
503 : * A face should always be flat (if viewed in 3 dimensions).
504 : * You can not create an instance of Face. grids are constructed from derivatives of face.
505 : * The vertices of a face have always to be specified in counterclockwise order!
506 : *
507 : * \ingroup lib_grid_grid_objects
508 : */
509 : class UG_API Face : public GridObject, public FaceVertices
510 : {
511 : friend class Grid;
512 : public:
513 : typedef Face grid_base_object;
514 :
515 : // lower dimensional Base Object
516 : typedef Edge lower_dim_base_object;
517 : // higher dimensional Base Object
518 : typedef Volume higher_dim_base_object;
519 :
520 : typedef Edge side;
521 : typedef Volume sideof;
522 :
523 : static const bool HAS_SIDES = true;
524 : static const bool CAN_BE_SIDE = true;
525 :
526 : /// reference dimension
527 : static const int dim = 2;
528 : static const int BASE_OBJECT_ID = FACE;
529 :
530 : public:
531 : inline static bool type_match(GridObject* pObj) {return dynamic_cast<Face*>(pObj) != NULL;}
532 :
533 0 : virtual ~Face() {}
534 :
535 : /// returns the i-th edge of the face.
536 : /** This default implementation is reimplemented by derived classes for optimal speed.*/
537 0 : virtual EdgeDescriptor edge_desc(int index) const
538 0 : {return EdgeDescriptor(vertex(index), vertex((index+1) % size()));}
539 :
540 : /// returns the i-th edge of the face.
541 : /** This default implementation is reimplemented by derived classes for optimal speed.*/
542 0 : virtual void edge_desc(int index, EdgeDescriptor& edOut) const
543 0 : {edOut.set_vertices(vertex(index), vertex((index+1) % size()));}
544 :
545 1 : inline uint num_edges() const {return (uint)num_vertices();}
546 : inline uint num_sides() const {return num_edges();}
547 :
548 0 : virtual int container_section() const {return -1;}
549 0 : virtual int base_object_id() const {return FACE;}
550 0 : virtual ReferenceObjectID reference_object_id() const {return ROID_UNKNOWN;}
551 :
552 : /** A default implementation is featured to allow empty instances of
553 : * this class. This is required to allow the use of this class
554 : * for compile-time method selection by dummy-parameters.
555 : * It is cruical that derived classes overload this method.*/
556 0 : virtual Edge* create_edge(int index) {return NULL;} ///< create the edge with index i and return it.
557 :
558 :
559 : /// retrieves the edge-descriptor for the opposing side to the specified one.
560 : /** If no opposing side exists false is returned. If an opposing side exists,
561 : * the method returns true and fills the specified descriptor.*/
562 0 : virtual bool get_opposing_side(EdgeVertices* e, EdgeDescriptor& edOut) const {return false;}
563 :
564 : /// returns an index to the obbject, which lies on the opposite side of the face to the given vertex.
565 : /** The method returs a pair <GridBaseObjectId, int>, where GridBaseObjectId
566 : * is either VERTEX or EDGE and where the second entry specifies the local index
567 : * of the object in the given face.*/
568 : virtual std::pair<GridBaseObjectId, int>
569 0 : get_opposing_object(Vertex* vrt) const {UG_THROW("Base method not implemented.");}
570 :
571 : /// returns the local index of the specified edge.
572 : /** If the edge is not part of the face, then -1 is returned.*/
573 : int get_local_side_index(EdgeVertices* e) const;
574 :
575 : /**
576 : * The refine method can be used to create new elements by inserting new vertices
577 : * on the face.
578 : * The user that calls this function is responsible to either register the new
579 : * faces with a grid (the grid from which the vertices are), or to take responsibility
580 : * for deletion of the acquired memory (delete each element in vNewFacesOut).
581 : * - Specify vertices that shall be inserted on edges with newEdgeVertices. Vertices
582 : * are inserted on the edge that corresponds to their index. Use NULL to indicate
583 : * that no vertex shall be inserted on the associated edge. newEdgeVertices has to point
584 : * to an array that holds as many vertices as there are edges in the face.
585 : * - If the method has to create a new inner vertex, it will be returned in newFaceVertexOut.
586 : * - If you specify pvSubstituteVertices, the created faces will reference the vertices in
587 : * pvSubstituteVertices. Note that pvSubstituteVertices has to contain exactly as many
588 : * vertices as the refined Face. Vertices with the same index correlate.
589 : * - You may optionally specify a 'snapPointIndex'. Default is -1. If an index >= 0
590 : * is specifed, then new inner edges will always be created between new edge vertices
591 : * and the vertex specified through the snap-point-index. Note that a snap-point
592 : * must not be a corner of a refined edge.
593 : */
594 0 : virtual bool refine(std::vector<Face*>& vNewFacesOut,
595 : Vertex** newFaceVertexOut,
596 : Vertex** newEdgeVertices,
597 : Vertex* newFaceVertex = NULL,
598 : Vertex** pSubstituteVertices = NULL,
599 0 : int snapPointIndex = -1) {return false;}
600 :
601 :
602 : /// returns true if the specified edgeMarks would lead to a regular refinement
603 : /** A regular refinement leads to new elements which are all similar to the
604 : * original element. I.e. which are of the same type and which have similar
605 : * angles.
606 : *
607 : * \note this method does not perform refinement. Use 'refine' with the
608 : * specified edges instead.
609 : *
610 : * \param edgeMarks If the i-th edge shall be refined, the expression
611 : * 'edgeMarks & (1<<i) != 0' has to be true. You can
612 : * specify multiple refine-edges using or-combinations:
613 : * 'edgeMarks = (1<<i) | (1<<j)' would indicate that the
614 : * i-th and the j-th edge shall be refined.*/
615 0 : virtual bool is_regular_ref_rule(int edgeMarks) const {return false;}
616 :
617 : /**
618 : * The collapse_edge method creates new geometric objects by collapsing the specified edge.
619 : * The user that calls this function is responsible to either register the new
620 : * faces with a grid (the grid from which the vertices are), or to take responsibility
621 : * for deletion of the acquired memory (delete each element in vNewFacesOut).
622 : * - edgeIndex specifies the edge which shall be collapsed. edgeIndex has to lie
623 : * between 0 and this->num_edges().
624 : * - Vertices adjacent to the collapsed edge will be replaced by newVertex.
625 : * - If you specify pvSubstituteVertices, the created faces will reference the vertices in
626 : * pvSubstituteVertices. Note that pvSubstituteVertices has to contain exactly as many
627 : * vertices as the face in which you collapse the edge. Vertices with the same index correlate.
628 : */
629 0 : virtual bool collapse_edge(std::vector<Face*>& vNewFacesOut,
630 : int edgeIndex, Vertex* newVertex,
631 0 : Vertex** pSubstituteVertices = NULL) {return false;}
632 :
633 : /**
634 : * The collapse_edgea method creates new geometric objects by collapsing the specified edges
635 : * simultaneously. This method makes sense only for faces with more than 4 edges.
636 : * The user that calls this function is responsible to either register the new
637 : * faces with a grid (the grid from which the vertices are), or to take responsibility
638 : * for deletion of the acquired memory (delete each element in vNewFacesOut).
639 : * - for each entry in vNewEdgeVertices which is not NULL, the edge with the same index will
640 : * be collapsed and replaced by the specified vertex.
641 : * The size of vNewEdgeVertices has thus to be between 0 and this->num_edges().
642 : * - If you specify pvSubstituteVertices, the created faces will reference the vertices in
643 : * pvSubstituteVertices. Note that pvSubstituteVertices has to contain exactly as many
644 : * vertices as the face in which you collapse the edge. Vertices with the same index correlate.
645 : */
646 0 : virtual bool collapse_edges(std::vector<Face*>& vNewFacesOut,
647 : std::vector<Vertex*>& vNewEdgeVertices,
648 0 : Vertex** pSubstituteVertices = NULL) {return false;}
649 :
650 : // BEGIN Depreciated
651 : /** creates the faces that result from the splitting of the edge with index 'splitEdgeIndex'.
652 : * The user that calls this function is responsible to either register those faces with the
653 : * same grid in which 'this' was registered, or to take over responsibility for deletion of the
654 : * acquired memory.
655 : * With pvSubstituteVertices you can optionally pass a vector of vertices, which will be used
656 : * instead of the original vertices of this face. If specified, pvSubstituteVertices has to
657 : * contain exactly as many vertices as the face itself.
658 : */
659 0 : virtual void create_faces_by_edge_split(int splitEdgeIndex,
660 : Vertex* newVertex,
661 : std::vector<Face*>& vNewFacesOut,
662 0 : Vertex** pSubstituteVertices = NULL) {};
663 : // END Depreciated
664 :
665 : /** creates the faces that result from the collapsing of the edge with index 'splitEdgeIndex'.*/
666 : //virtual void create_faces_by_edge_collapse(int collapseEdgeIndex,
667 : // Vertex* newVertex,
668 : // std::vector<Face*>& vNewFacesOut) = 0;
669 :
670 : protected:
671 0 : virtual void set_vertex(uint index, Vertex* pVrt) {UG_ASSERT(0, "SHOULDN'T BE CALLED");}
672 : };
673 :
674 :
675 : /// constant that defines the maximal number of vertices per face.
676 : /** This constant is mainly used by FaceDescriptor.
677 : * If required, one should be able to increase it without any problems.*/
678 : const int MAX_FACE_VERTICES = 4;
679 :
680 : ////////////////////////////////////////////////////////////////////////////////////////////////
681 : // FaceDescriptor
682 : /// Can be queried for the edges and vertices of a face.
683 : class UG_API FaceDescriptor : public FaceVertices
684 : {
685 : public:
686 : FaceDescriptor();
687 : FaceDescriptor(uint numVertices);
688 : FaceDescriptor(const FaceDescriptor& fd);
689 0 : FaceDescriptor(Vertex* v0, Vertex* v1, Vertex* v2) :
690 0 : m_numVertices(3)
691 0 : {m_vertices[0] = v0; m_vertices[1] = v1; m_vertices[2] = v2;}
692 :
693 0 : FaceDescriptor(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3) :
694 0 : m_numVertices(4)
695 0 : {m_vertices[0] = v0; m_vertices[1] = v1; m_vertices[2] = v2; m_vertices[3] = v3;}
696 :
697 0 : virtual ~FaceDescriptor() {}
698 :
699 : FaceDescriptor& operator = (const FaceDescriptor& fd);
700 :
701 0 : virtual Vertex* vertex(size_t index) const {return m_vertices[index];}
702 0 : virtual ConstVertexArray vertices() const {return m_vertices;}
703 0 : virtual size_t num_vertices() const {return m_numVertices;}
704 :
705 0 : inline void set_num_vertices(uint numVertices) {m_numVertices = numVertices;}
706 : inline void set_vertex(uint index, Vertex* vrt)
707 0 : {m_vertices[index] = vrt;}
708 :
709 : protected:
710 : Vertex* m_vertices[MAX_FACE_VERTICES];
711 : uint m_numVertices;
712 : };
713 :
714 :
715 : ////////////////////////////////////////////////////////////////////////////////////////////////
716 : ////////////////////////////////////////////////////////////////////////////////////////////////
717 : // VOLUMES
718 :
719 : ////////////////////////////////////////////////////////////////////////////////////////////////
720 : // VolumeVertices
721 : /// holds the vertices of a Volume or a VolumeDescriptor
722 : class UG_API VolumeVertices : public IVertexGroup
723 : {
724 : public:
725 : virtual ~VolumeVertices() {}
726 :
727 0 : virtual Vertex* vertex(size_t index) const {UG_ASSERT(0, "SHOULDN'T BE CALLED"); return NULL;}
728 0 : virtual ConstVertexArray vertices() const {UG_ASSERT(0, "SHOULDN'T BE CALLED"); return NULL;}
729 0 : virtual size_t num_vertices() const {UG_ASSERT(0, "SHOULDN'T BE CALLED"); return 0;}
730 :
731 : // compatibility with std::vector for some template routines
732 : /// returns the number of vertices.
733 : inline size_t size() const {return num_vertices();}
734 : /// returns the i-th vertex.
735 : inline Vertex* operator[](size_t index) const {return vertex(index);}
736 : };
737 :
738 : ////////////////////////////////////////////////////////////////////////////////////////////////
739 : // Volume
740 : /// Volumes are 3-dimensional objects.
741 : /**
742 : * Base class for all 3-dimensional objects.
743 : * Volumes connect four or more vertices.
744 : *
745 : * default implementations of all methods are featured to allow
746 : * empty instances of this class.
747 : * This is required to allow the use of this class
748 : * for compile-time method selection by dummy-parameters.
749 : * It is cruical that derived classes overload those methods.
750 : *
751 : * \ingroup lib_grid_grid_objects
752 : */
753 : class UG_API Volume : public GridObject, public VolumeVertices
754 : {
755 : friend class Grid;
756 : public:
757 : typedef Volume grid_base_object;
758 :
759 : // lower dimensional Base Object
760 : typedef Face lower_dim_base_object;
761 : // higher dimensional Base Object
762 : typedef void higher_dim_base_object;
763 :
764 : typedef Face side;
765 : // this is just by convention. Use can_be_side() to stop recursions.
766 : typedef Volume sideof;
767 :
768 : static const bool HAS_SIDES = true;
769 : static const bool CAN_BE_SIDE = false;
770 :
771 : /// reference dimension
772 : static const int dim = 3;
773 : static const int BASE_OBJECT_ID = VOLUME;
774 :
775 : public:
776 : inline static bool type_match(GridObject* pObj) {return dynamic_cast<Volume*>(pObj) != NULL;}
777 :
778 0 : virtual ~Volume() {}
779 :
780 0 : virtual EdgeDescriptor edge_desc(int index) const {return EdgeDescriptor(NULL, NULL);}
781 0 : virtual void edge_desc(int index, EdgeDescriptor& edOut) const {edOut = EdgeDescriptor(NULL, NULL);}
782 0 : virtual uint num_edges() const {return 0;}
783 :
784 0 : virtual FaceDescriptor face_desc(int index) const {return FaceDescriptor(0);}
785 0 : virtual void face_desc(int index, FaceDescriptor& fdOut) const {fdOut = FaceDescriptor(0);}
786 0 : virtual uint num_faces() const {return 0;}
787 0 : inline uint num_sides() const {return num_faces();}
788 :
789 0 : virtual Edge* create_edge(int index) {return NULL;} ///< create the edge with index i and return it.
790 0 : virtual Face* create_face(int index) {return NULL;} ///< create the face with index i and return it.
791 :
792 : /// returns the local indices of an edge of the volume.
793 : /** Default implementation throws a UGError*/
794 0 : virtual void get_vertex_indices_of_edge(size_t& ind1Out,
795 : size_t& ind2Out,
796 : size_t edgeInd) const
797 0 : {UG_THROW("Base method not implemented.");};
798 :
799 : /// returns the local indices of a face of the volume.
800 : /** Default implementation throws a UGError*/
801 0 : virtual void get_vertex_indices_of_face(std::vector<size_t>& indsOut,
802 : size_t side) const
803 0 : {UG_THROW("Base method not implemented.");}
804 :
805 : /// returns the local index of the edge which connects the two vertex indices.
806 : /** Default implementation throws a UGError*/
807 0 : virtual int get_edge_index_from_vertices( const size_t vi0,
808 : const size_t vi1) const
809 0 : {UG_THROW("Base method not implemented.");};
810 :
811 : /// returns the local index of the j-th edge of the i-th face of the volume
812 : /** Default implementation throws a UGError*/
813 0 : virtual int get_face_edge_index ( const size_t faceInd,
814 : const size_t faceEdgeInd) const
815 0 : {UG_THROW("Base method not implemented.");};
816 :
817 : /// retrieves the face-descriptor for the opposing side to the specified one.
818 : /** If no opposing side exists false is returned. If an opposing side exists,
819 : * the method returns true and fills the specified descriptor.*/
820 0 : virtual bool get_opposing_side(FaceVertices* f, FaceDescriptor& fdOut) const {return false;}
821 :
822 : /// returns an index to the obbject, which lies on the opposite side of the volume to the given vertex.
823 : /** The method returs a pair <GridBaseObjectId, int>, where GridBaseObjectId
824 : * is either VERTEX, EDGE, or FACE and where the second entry specifies the local index
825 : * of the object in the given volume.*/
826 : virtual std::pair<GridBaseObjectId, int>
827 0 : get_opposing_object(Vertex* vrt) const
828 0 : {UG_THROW("Base method not implemented.");}
829 :
830 : /// returns the local index of the given face or -1, if the face is not part of the volume.
831 : int get_local_side_index(FaceVertices* f) const;
832 :
833 : /**
834 : * The refine method can be used to create new elements by inserting new vertices
835 : * on the volume.
836 : *
837 : * New volumes will be returned in vNewFacesOut.
838 : * If a new vertex has to be created from the prototypeVertex (this happens in
839 : * more complicated situations) the pointer to the new vertex is returned in
840 : * ppNewVertexOut. ppNewVertexOut contains NULL if no new vertex has been created.
841 : *
842 : * The user that calls this function is responsible to either register the new
843 : * volumes and the new vertex with a grid (the grid from which the referenced
844 : * vertices are), or to take responsibility for deletion of the acquired memory
845 : * (delete each element in vNewVolumesOut and ppNewVertexOut - if it is not NULL).
846 : *
847 : * - Specify vertices that shall be inserted on edges with vNewEdgeVertices. Vertices
848 : * are inserted on the edge that corresponds to its index. Use NULL to indicate
849 : * that no vertex shall be inserted on the associated edge.
850 : * - Specify vertices that shall be inserted on faces with vNewFaceVertices. Vertices
851 : * are inserted on the face that corresponds to its index. Use NULL to indicate
852 : * that no vertex shall be inserted on the associated face.
853 : * - If newVolumeVertex is not NULL, newVolumeVertex will be inserted in the center of
854 : * the volume.
855 : * - via the prototypeVertex you can specify the vertex-type of the vertex that is
856 : * auto-inserted if the refine operation is too complex. In most cases this will be
857 : * an instance of a standard vertex (a concrete type is required. Vertex will not do).
858 : * The prototypeVertex has not to be registered at any grid - it may be a temporary
859 : * instance.
860 : * - If you specify pvSubstituteVertices, the created volumes will reference the vertices
861 : * in pvSubstituteVertices. Note that pvSubstituteVertices has to contain exactly as
862 : * many vertices as the refined Face. Vertices with the same index correlate.
863 : * - You may optionally specify an array containing the corner positions of the element.
864 : * If specified, those corners are used during regular tetrahedron refinement
865 : * only (only if all edges are refined). They are used to choose the best
866 : * refinement rule for interior child tetrahedrons, thus improving interior
867 : * angles.
868 : * - You may optionally specify 'isSnapPoint', a list of booleans of length 'num_vertices()'.
869 : * Each quadrilateral side may contain at most one snap-point. New edges on quadrilateral
870 : * faces will then connect the snap-point and the newly introduced edge-vertex.
871 : * Note that a snap-point must not be a corner of a refined edge.
872 : */
873 0 : virtual bool refine(std::vector<Volume*>& vNewVolumesOut,
874 : Vertex** ppNewVertexOut,
875 : Vertex** newEdgeVertices,
876 : Vertex** newFaceVertices,
877 : Vertex* newVolumeVertex,
878 : const Vertex& prototypeVertex,
879 : Vertex** pSubstituteVertices = NULL,
880 : vector3* corners = NULL,
881 0 : bool* isSnapPoint = NULL) {return false;}
882 :
883 :
884 : /// returns true if the specified edgeMarks would lead to a regular refinement
885 : /** A regular refinement leads to new elements which are all similar to the
886 : * original element. I.e. which are of the same type and which have similar
887 : * angles.
888 : *
889 : * \note this method does not perform refinement. Use 'refine' with the
890 : * specified edges instead.
891 : *
892 : * \param edgeMarks If the i-th edge shall be refined, the expression
893 : * 'edgeMarks & (1<<i) != 0' has to be true. You can
894 : * specify multiple refine-edges using or-combinations:
895 : * 'edgeMarks = (1<<i) | (1<<j)' would indicate that the
896 : * i-th and the j-th edge shall be refined.*/
897 0 : virtual bool is_regular_ref_rule(int edgeMarks) const {return false;}
898 :
899 : /**
900 : * The collapse_edge method creates new geometric objects by collapsing the specified edge.
901 : * The user that calls this function is responsible to either register the new
902 : * volumes with a grid (the grid from which the vertices are), or to take responsibility
903 : * for deletion of the acquired memory (delete each element in vNewFacesOut).
904 : * - edgeIndex specifies the edge which shall be collapsed. edgeIndex has to lie
905 : * between 0 and this->num_edges().
906 : * - Vertices adjacent to the collapsed edge will be replaced by newVertex.
907 : * - If you specify pvSubstituteVertices, the created volumes will reference the vertices in
908 : * pvSubstituteVertices. Note that pvSubstituteVertices has to contain exactly as many
909 : * vertices as the volume in which you collapse the edge. Vertices with the same index correlate.
910 : */
911 0 : virtual bool collapse_edge(std::vector<Volume*>& vNewVolumesOut,
912 : int edgeIndex, Vertex* newVertex,
913 0 : std::vector<Vertex*>* pvSubstituteVertices = NULL) {return false;}
914 :
915 : /**
916 : * Writes vertices to the volume-descriptor so that it defines a volume with
917 : * flipped orientation. If you want to flip the orientation of a volume in a
918 : * grid, please consider using the grids flip_orientation method.
919 : *
920 : * Please note: The default implementation returns the original volume and has
921 : * to be reimplemented by derived classes.
922 : */
923 : virtual void get_flipped_orientation(VolumeDescriptor& vdOut) const;
924 :
925 0 : virtual int container_section() const {return -1;}
926 0 : virtual int base_object_id() const {return VOLUME;}
927 0 : virtual ReferenceObjectID reference_object_id() const {return ROID_UNKNOWN;}
928 :
929 : /** creates the volumes that result from the splitting of the edge with index 'splitEdgeIndex'.*/
930 : //virtual void create_volumes_by_edge_split(int splitEdgeIndex,
931 : // Vertex* newVertex,
932 : // std::vector<Volume*>& vNewFacesOut) = 0;
933 :
934 : /** creates the volumes that result from the collapsing of the edge with index 'splitEdgeIndex'.*/
935 : //virtual void create_Volumes_by_edge_collapse(int collapseEdgeIndex,
936 : // Vertex* newVertex,
937 : // std::vector<Volume*>& vNewFacesOut) = 0;
938 : protected:
939 0 : virtual void set_vertex(uint index, Vertex* pVrt) {UG_ASSERT(0, "SHOULDN'T BE CALLED");}
940 : };
941 :
942 :
943 : /// constant that defines the maximal number of vertices per volume element.
944 : /** This constant is mainly used by VolumeDescriptor.*/
945 : const int MAX_VOLUME_VERTICES = 8;
946 :
947 : ////////////////////////////////////////////////////////////////////////////////////////////////
948 : // VolumeDescriptor
949 : /// Holds a set of vertices which represent the corners of a volume element
950 : class UG_API VolumeDescriptor : public VolumeVertices
951 : {
952 : public:
953 : VolumeDescriptor();
954 : VolumeDescriptor(uint numVertices);
955 : VolumeDescriptor(const VolumeDescriptor& vd);
956 :
957 0 : virtual ~VolumeDescriptor() {}
958 :
959 : VolumeDescriptor& operator = (const VolumeDescriptor& vv);
960 : VolumeDescriptor& operator = (const VolumeVertices& vv);
961 :
962 0 : virtual Vertex* vertex(size_t index) const {return m_vertices[index];}
963 0 : virtual ConstVertexArray vertices() const {return m_vertices;}
964 0 : virtual size_t num_vertices() const {return m_numVertices;}
965 :
966 0 : inline void set_num_vertices(uint numVertices) {m_numVertices = numVertices;}
967 0 : inline void set_vertex(uint index, Vertex* vrt) {m_vertices[index] = vrt;}
968 :
969 : protected:
970 : Vertex* m_vertices[MAX_VOLUME_VERTICES];
971 : uint m_numVertices;
972 : };
973 :
974 :
975 :
976 : ////////////////////////////////////////////////////////////////////////
977 : ////////////////////////////////////////////////////////////////////////
978 : /** Defines the geometric base object type for each dimension.
979 : * \{ */
980 : template <int dim> struct GeomObjBaseTypeByDim;
981 :
982 : template <> struct GeomObjBaseTypeByDim<0>{
983 : typedef Vertex base_obj_type;
984 : };
985 :
986 : template <> struct GeomObjBaseTypeByDim<1>{
987 : typedef Edge base_obj_type;
988 : };
989 :
990 : template <> struct GeomObjBaseTypeByDim<2>{
991 : typedef Face base_obj_type;
992 : };
993 :
994 : template <> struct GeomObjBaseTypeByDim<3>{
995 : typedef Volume base_obj_type;
996 : };
997 :
998 : /** \} */
999 :
1000 :
1001 : ////////////////////////////////////////////////////////////////////////
1002 : ////////////////////////////////////////////////////////////////////////
1003 : /** template helpers that return the geometric base object type
1004 : * given a pointer to a derived class of Vertex, Edge, Face or Volume.
1005 : *
1006 : * e.g. PtrToValueType<RegularVertex*>::base_type = Vertex.
1007 : * \{
1008 : */
1009 : template <class TGeomObjPtrType>
1010 : struct PtrToValueType
1011 : {typedef void base_type;};
1012 :
1013 : template <>
1014 : struct PtrToValueType<Vertex*>
1015 : {typedef Vertex base_type;};
1016 :
1017 : template <>
1018 : struct PtrToValueType<Edge*>
1019 : {typedef Edge base_type;};
1020 :
1021 : template <>
1022 : struct PtrToValueType<Face*>
1023 : {typedef Face base_type;};
1024 :
1025 : template <>
1026 : struct PtrToValueType<Volume*>
1027 : {typedef Volume base_type;};
1028 : /** \} */
1029 :
1030 :
1031 : ////////////////////////////////////////////////////////////////////////
1032 : ////////////////////////////////////////////////////////////////////////
1033 : // hash-funtions for vertices
1034 : /// returns the hash-value of the vertex.
1035 : size_t hash_key(Vertex* key);
1036 :
1037 : ////////////////////////////////////////////////////////////////////////
1038 : // hash-funtions for edges
1039 : /// the hash-key is a function of vertex-hash-values.
1040 : /**
1041 : * The hash value depends on the associated vertices.
1042 : * If an Edge (or EdgeDescriptor) has the same vertices
1043 : * as another Edge (or EdgeDescriptor), the hash-keys
1044 : * are the same.
1045 : */
1046 : size_t hash_key(EdgeVertices* key);
1047 : size_t hash_key(const EdgeVertices* key);
1048 :
1049 : /// the hash-key is a function of vertex-hash-values.
1050 : /** \sa hash_key<PEdgeVertices>*/
1051 : size_t hash_key(Edge* key);
1052 :
1053 : /// the hash-key is a function of vertex-hash-values.
1054 : /** \sa hash_key<PEdgeVertices>*/
1055 : size_t hash_key(EdgeDescriptor* key);
1056 :
1057 : ////////////////////////////////////////////////////////////////////////
1058 : // hash-funtions for faces
1059 : /// the hash-key is a function of vertex-hash-values.
1060 : /**
1061 : * The hash value depends on the associated vertices.
1062 : * If an Face (or FaceDescriptor) has the same vertices
1063 : * as another Face (or FaceDescriptor), the hash-keys
1064 : * are the same.
1065 : */
1066 : size_t hash_key(FaceVertices* key);
1067 : size_t hash_key(const FaceVertices* key);
1068 :
1069 : /// the hash-key is a function of vertex-hash-values.
1070 : /**\sa hash_key<PFaceVertices>*/
1071 : size_t hash_key(Face* key);
1072 :
1073 : /// the hash-key is a function of vertex-hash-values.
1074 : /**\sa hash_key<PFaceVertices>*/
1075 : size_t hash_key(FaceDescriptor* key);
1076 :
1077 : ////////////////////////////////////////////////////////////////////////
1078 : // hash-funtions for volumes
1079 : /// the hash-key is a function of vertex-hash-values.
1080 : /**
1081 : * The hash value depends on the associated vertices.
1082 : * If an Volume (or VolumeDescriptor) has the same vertices
1083 : * as another Volume (or VolumeDescriptor), the hash-keys
1084 : * are the same.
1085 : */
1086 : size_t hash_key(VolumeVertices* key);
1087 : size_t hash_key(const VolumeVertices* key);
1088 :
1089 : /// the hash-key is a function of vertex-hash-values.
1090 : /**\sa hash_key<PVolumeVertices>*/
1091 : size_t hash_key(Volume* key);
1092 :
1093 : /// the hash-key is a function of vertex-hash-values.
1094 : /**\sa hash_key<PVolumeVertices>*/
1095 : size_t hash_key(VolumeDescriptor* key);
1096 :
1097 : }// end of namespace
1098 :
1099 : #endif
|