inmost_mesh.h 221 KB
Newer Older
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1

Kirill Terekhov's avatar
Kirill Terekhov committed
2 3 4 5
#ifndef INMOST_MESH_H_INCLUDED
#define INMOST_MESH_H_INCLUDED

#include "inmost_common.h"
Kirill Terekhov's avatar
Kirill Terekhov committed
6
#include "inmost_data.h"
Kirill Terekhov's avatar
Kirill Terekhov committed
7 8 9

#if defined(USE_MESH)

Kirill Terekhov's avatar
Kirill Terekhov committed
10

Kirill Terekhov's avatar
Kirill Terekhov committed
11 12 13

namespace INMOST
{
Kirill Terekhov's avatar
Kirill Terekhov committed
14

15
    std::string ro();
Kirill Terekhov's avatar
Kirill Terekhov committed
16

Kirill Terekhov's avatar
Kirill Terekhov committed
17 18 19 20 21 22 23 24
	class Mesh;
	class Storage;
	class Element;
	class TagManager;
	class Node;
	class Edge;
	class Face;
	class Cell;
Kirill Terekhov's avatar
Kirill Terekhov committed
25
	class ElementSet;
Kirill Terekhov's avatar
Kirill Terekhov committed
26

Kirill Terekhov's avatar
Kirill Terekhov committed
27

Kirill Terekhov's avatar
Kirill Terekhov committed
28 29
	
	typedef INMOST_DATA_BULK_TYPE GeometricData;
Kirill Terekhov's avatar
Kirill Terekhov committed
30 31 32 33 34
	static const GeometricData CENTROID    = 0;
	static const GeometricData NORMAL      = 1;
	static const GeometricData ORIENTATION = 2;
	static const GeometricData MEASURE     = 3;
	static const GeometricData BARYCENTER  = 4;
Kirill Terekhov's avatar
Kirill Terekhov committed
35
	
Kirill Terekhov's avatar
Kirill Terekhov committed
36
	typedef INMOST_DATA_BULK_TYPE SyncBitOp; //< This type is used for marker synchronization
Kirill Terekhov's avatar
Kirill Terekhov committed
37
	static const SyncBitOp SYNC_BIT_SET = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
38 39 40 41
	static const SyncBitOp SYNC_BIT_OR  = 1;
	static const SyncBitOp SYNC_BIT_XOR = 2;
	static const SyncBitOp SYNC_BIT_AND = 3;

42
    
Kirill Terekhov's avatar
Kirill Terekhov committed
43

Kirill Terekhov's avatar
Kirill Terekhov committed
44
	///Definition for data type of topology error or event. This type may be extended later to 64 bits
Kirill Terekhov's avatar
Kirill Terekhov committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
	/// to accomodate more topological errors or events.
	typedef INMOST_DATA_ENUM_TYPE         TopologyCheck;
	///Throw TopologyError exception on error.
	static const TopologyCheck            THROW_EXCEPTION        = 0x00000001;
	///Print topology notify to std::cerr.
	static const TopologyCheck            PRINT_NOTIFY           = 0x00000002;
	///Element should be deleted if there is an error in EndTopologyCheck.
	static const TopologyCheck            DELETE_ON_ERROR        = 0x00000004;
	///Bitwise OR of errors is recorded to sparse integer tag of element (if not deleted), availible
	/// by TopologyErrorTag().
	static const TopologyCheck            MARK_ON_ERROR          = 0x00000008;
	///Check that edge already exists, on occurance CreateEdge silently returns existant edge.
	static const TopologyCheck            DUPLICATE_EDGE         = 0x00000010;
	///Check that face already exists, on occurance CreateFace silently returns existant face.
	static const TopologyCheck            DUPLICATE_FACE         = 0x00000020;
	///Check that cell already exists, on occurance CreateCell silently returns existant cell.
	static const TopologyCheck            DUPLICATE_CELL         = 0x00000040;
	///Check that edge have more then two nodes (no support for this kind of object).
	static const TopologyCheck            DEGENERATE_EDGE        = 0x00000080;
	///Produce error if face consists of less then 3 edges.
	static const TopologyCheck            DEGENERATE_FACE        = 0x00000100;
	///Produce error if cell consists of less then 4 faces.
	static const TopologyCheck            DEGENERATE_CELL        = 0x00000200;
	///Produce error if face have wrong orientation of edges, for star-shaped elements only.
	static const TopologyCheck            FACE_ORIENTATION       = 0x00000400;
	///Produce error if face is non planar.
	static const TopologyCheck            FACE_PLANARITY         = 0x00000800;
	///Produce error if there is another face that already uses same nodes.
	static const TopologyCheck            INTERLEAVED_FACES      = 0x00001000;
	///Check that every face have exectly two neighbours, if DUPLICATE_CELL is activated, then checks
	/// for cell duplication.
Kirill Terekhov's avatar
Kirill Terekhov committed
76
	static const TopologyCheck            TRIPLE_SHARED_FACE     = 0x00002000;
Kirill Terekhov's avatar
Kirill Terekhov committed
77
	///Produce error if one of the faces of the cell contains all the nodes of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
78
	static const TopologyCheck            FLATTENED_CELL         = 0x00004000;
Kirill Terekhov's avatar
Kirill Terekhov committed
79
	///Produce error if provided array of elements for construction contain duplications.
Kirill Terekhov's avatar
Kirill Terekhov committed
80
	static const TopologyCheck            ADJACENT_DUPLICATE     = 0x00008000;
Kirill Terekhov's avatar
Kirill Terekhov committed
81 82 83 84 85 86 87 88
	///Hidden elements should not be used when new elements are created.
	static const TopologyCheck            ADJACENT_HIDDEN        = 0x00010000;
	///Check that all handles are valid.
	static const TopologyCheck            ADJACENT_VALID         = 0x00020000;
	///Produce error if provided array of elements have wrong geometric dimension.
	static const TopologyCheck            ADJACENT_DIMENSION     = 0x00040000;
	///Produce error if edges of faces are not closed, or face is folded.
	/// \warning This check needs NEED_TEST_CLOSURE to be activated.
Kirill Terekhov's avatar
Kirill Terekhov committed
89
	static const TopologyCheck            PROHIBIT_MULTILINE     = 0x00080000;
Kirill Terekhov's avatar
Kirill Terekhov committed
90
	/// Allow only known types of elements: Tet, Quad, Line.
Kirill Terekhov's avatar
Kirill Terekhov committed
91
	static const TopologyCheck            PROHIBIT_POLYGON       = 0x00100000;
Kirill Terekhov's avatar
Kirill Terekhov committed
92 93 94 95 96 97 98 99 100 101 102 103
	///Produce error if faces of cell are not closed, or cell is folded.
	/// \warning This check needs NEED_TEST_CLOSURE to be activated.
	static const TopologyCheck            PROHIBIT_MULTIPOLYGON  = 0x00200000;
	///Allow only known types of elements: Tet,Hex,Prism,Pyramid.
	static const TopologyCheck            PROHIBIT_POLYHEDRON    = 0x00400000;
	///Edges of the face should form one closed loop.
	static const TopologyCheck            FACE_EDGES_ORDER       = 0x00800000;
	///Don't allow concave face.
	/// \warning Not implemented.
	static const TopologyCheck            PROHIBIT_CONCAVE_FACE  = 0x01000000;
	///Don't allow concave cell.
	/// \warning Not implemented.
Kirill Terekhov's avatar
Kirill Terekhov committed
104
	static const TopologyCheck            PROHIBIT_CONCAVE_CELL  = 0x02000000;
Kirill Terekhov's avatar
Kirill Terekhov committed
105 106
	///Don't allow non-star shaped face.
	/// \warning Not implemented.
Kirill Terekhov's avatar
Kirill Terekhov committed
107
	static const TopologyCheck            PROHIBIT_NONSTAR_FACE  = 0x04000000;
Kirill Terekhov's avatar
Kirill Terekhov committed
108 109
	///Don't allow non-star shaped concave cell.
	/// \warning Not implemented.
Kirill Terekhov's avatar
Kirill Terekhov committed
110
	static const TopologyCheck            PROHIBIT_NONSTAR_CELL  = 0x08000000;
Kirill Terekhov's avatar
Kirill Terekhov committed
111 112
	///Edges of the face don't cross each other.
	/// \warning Not implemented.
Kirill Terekhov's avatar
Kirill Terekhov committed
113
	static const TopologyCheck            FACE_SELF_INTERSECTION = 0x10000000;
Kirill Terekhov's avatar
Kirill Terekhov committed
114 115 116 117 118 119 120
	///Faces of the cell don't cross each other.
	/// \warning Not implemented.
	static const TopologyCheck            CELL_SELF_INTERSECTION = 0x20000000;
	///Silent, test's for closure in ComputeGeometricType, needed to detect MultiLine and
	/// MultiPolygon.
	static const TopologyCheck            NEED_TEST_CLOSURE      = 0x40000000;
	///Don't allow 2d grids, where edges appear to be vertexes, faces are edges and cells are faces
Kirill Terekhov's avatar
Kirill Terekhov committed
121
	static const TopologyCheck            DISABLE_2D             = 0x80000000;
Kirill Terekhov's avatar
Kirill Terekhov committed
122
	///A shortcut to test for grid conformity.
Kirill Terekhov's avatar
Kirill Terekhov committed
123 124 125 126 127
	static const TopologyCheck            GRID_CONFORMITY        = NEED_TEST_CLOSURE 
                                                               | PROHIBIT_MULTILINE 
                                                               | PROHIBIT_MULTIPOLYGON  
                                                               | INTERLEAVED_FACES 
                                                               | TRIPLE_SHARED_FACE;
Kirill Terekhov's avatar
Kirill Terekhov committed
128
	///Default set of options.
Kirill Terekhov's avatar
Kirill Terekhov committed
129 130 131 132 133
	static const TopologyCheck            DEFAULT_CHECK          = THROW_EXCEPTION 
                                                               | DUPLICATE_EDGE 
                                                               | DUPLICATE_FACE 
                                                               | DUPLICATE_CELL 
                                                               | PRINT_NOTIFY;
Kirill Terekhov's avatar
Kirill Terekhov committed
134 135
	///Returns a string explaining each topology check. Implemented in mesh.cpp.
	/// @param c Single topology check.
Kirill Terekhov's avatar
Kirill Terekhov committed
136 137 138
	const char * TopologyCheckNotifyString(TopologyCheck c);
  
 
Kirill Terekhov's avatar
Kirill Terekhov committed
139
	
Kirill Terekhov's avatar
Kirill Terekhov committed
140 141
	template <typename StorageType>
	class ElementArray
Kirill Terekhov's avatar
Kirill Terekhov committed
142
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
143 144 145
	public:
		typedef dynarray<HandleType,64>      cont_t;
		typedef cont_t::size_type            size_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
146
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
147 148
		Mesh *                               m_link;
		cont_t                               container;
Kirill Terekhov's avatar
Kirill Terekhov committed
149
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
150 151 152 153 154 155 156 157 158 159 160 161
		const cont_t & GetContainer() {return container;}
		~ElementArray() {}
		ElementArray() : m_link(NULL) {}
		ElementArray(Mesh * m_link) : m_link(m_link) {}
		ElementArray(Mesh * m_link, size_type n, HandleType h = InvalidHandle())  : m_link(m_link), container(n,h) {}
		ElementArray(Mesh * m_link, const cont_t & c)  : m_link(m_link), container(c) {}
		ElementArray(const ElementArray & other) : m_link(other.m_link), container(other.container) {}
		template<class InputIterator>
		ElementArray(Mesh * m_link, InputIterator first, InputIterator last) :m_link(m_link), container(first,last) {}
		ElementArray & operator=(ElementArray const & other) {m_link = other.m_link; container = other.container; return *this;}
	public:
		class iterator : public cont_t::iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
162
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
163
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
164
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
165 166
			iterator(Mesh * m, const cont_t::iterator & other ) : cont_t::iterator(other) , m_link(m){assert(m_link);}
			iterator(const iterator & other ) : cont_t::iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
167
			ptrdiff_t     operator -(const iterator & other) const {return static_cast<const cont_t::iterator>(*this)-static_cast<const cont_t::iterator>(other);}
Kirill Terekhov's avatar
Kirill Terekhov committed
168 169
			iterator      operator +(size_t n) const{return iterator(m_link,cont_t::iterator::operator +(n));}
			iterator      operator -(size_t n) const{return iterator(m_link,cont_t::iterator::operator -(n));}
Kirill Terekhov's avatar
Kirill Terekhov committed
170 171 172 173 174 175
			iterator &    operator ++() {cont_t::iterator::operator++(); return *this;}
			iterator      operator ++(int) {iterator ret(*this); cont_t::iterator::operator++(); return ret;}
			iterator &    operator --() {cont_t::iterator::operator--(); return *this;}
			iterator      operator --(int) {iterator ret(*this); cont_t::iterator::operator--(); return ret;}
			iterator &    operator =(iterator const & other) {m_link = other.m_link; cont_t::iterator::operator=(static_cast<cont_t::iterator const &>(other)); return *this; }
			HandleType &  operator *() { return cont_t::iterator::operator *(); }
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
176
			StorageType   operator->() { return StorageType(m_link,&cont_t::iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
177
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
178
		class reverse_iterator : public cont_t::reverse_iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
179
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
180
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
181
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
182 183
			reverse_iterator(Mesh * m, const cont_t::reverse_iterator & other ) : cont_t::reverse_iterator(other), m_link(m) {assert(m_link);}
			reverse_iterator(const reverse_iterator & other ) : cont_t::reverse_iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
184
			ptrdiff_t             operator -(const reverse_iterator & other) const {return static_cast<const cont_t::reverse_iterator>(*this)-static_cast<const cont_t::reverse_iterator>(other);}
Kirill Terekhov's avatar
Kirill Terekhov committed
185 186
			reverse_iterator      operator +(size_t n) const {return reverse_iterator(m_link,cont_t::reverse_iterator::operator+(n));}
			reverse_iterator      operator -(size_t n) const {return reverse_iterator(m_link,cont_t::reverse_iterator::operator-(n));}
Kirill Terekhov's avatar
Kirill Terekhov committed
187 188 189 190 191 192
			reverse_iterator &    operator ++() {cont_t::reverse_iterator::operator++(); return *this;}
			reverse_iterator      operator ++(int) {reverse_iterator ret(*this); cont_t::reverse_iterator::operator++(); return ret;}
			reverse_iterator &    operator --() {cont_t::reverse_iterator::operator--(); return *this;}
			reverse_iterator      operator --(int) {reverse_iterator ret(*this); cont_t::reverse_iterator::operator--(); return ret;}
			reverse_iterator & operator =(reverse_iterator const & other) {m_link = other.m_link; cont_t::reverse_iterator::operator=(static_cast<cont_t::reverse_iterator const &>(other)); return *this; }
			HandleType &       operator *() { return cont_t::reverse_iterator::operator *(); }
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
193
			StorageType        operator->() { return StorageType(m_link,&cont_t::reverse_iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
194
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
195
		class const_iterator : public cont_t::const_iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
196
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
197
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
198
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
199 200
			const_iterator(Mesh * m, const cont_t::const_iterator & other ) : cont_t::const_iterator(other), m_link(m) {assert(m_link);}
			const_iterator(const const_iterator & other ) : cont_t::const_iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
201
			ptrdiff_t     operator -(const const_iterator & other) const {return static_cast<const cont_t::const_iterator>(*this)-static_cast<const cont_t::const_iterator>(other);}
Kirill Terekhov's avatar
Kirill Terekhov committed
202 203 204 205 206 207 208
			const_iterator &    operator ++() {cont_t::const_iterator::operator++(); return *this;}
			const_iterator      operator ++(int) {const_iterator ret(*this); cont_t::const_iterator::operator++(); return ret;}
			const_iterator &    operator --() {cont_t::const_iterator::operator--(); return *this;}
			const_iterator      operator --(int) {const_iterator ret(*this); cont_t::const_iterator::operator--(); return ret;}
			const_iterator &    operator =(const_iterator const & other) {m_link = other.m_link; cont_t::const_iterator::operator=(static_cast<cont_t::const_iterator const &>(other)); return *this; }
			const HandleType &  operator *() { return cont_t::const_iterator::operator *(); }
			StorageType         operator->() { return StorageType(m_link,cont_t::const_iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
209
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
210
		class const_reverse_iterator : public cont_t::const_reverse_iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
211
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
212
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
213
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
214 215
			const_reverse_iterator(Mesh * m, const cont_t::const_reverse_iterator & other) : cont_t::const_reverse_iterator(other), m_link(m) {assert(m_link);}
			const_reverse_iterator(const const_reverse_iterator & other ) : cont_t::const_reverse_iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
216
			ptrdiff_t     operator -(const const_reverse_iterator & other) const {return static_cast<const cont_t::const_reverse_iterator>(*this)-static_cast<const cont_t::const_reverse_iterator>(other);}
Kirill Terekhov's avatar
Kirill Terekhov committed
217 218 219 220 221 222 223
			const_reverse_iterator &    operator ++() {cont_t::const_reverse_iterator::operator++(); return *this;}
			const_reverse_iterator      operator ++(int) {const_reverse_iterator ret(*this); cont_t::const_reverse_iterator::operator++(); return ret;}
			const_reverse_iterator &    operator --() {cont_t::const_reverse_iterator::operator--(); return *this;}
			const_reverse_iterator      operator --(int) {const_reverse_iterator ret(*this); cont_t::const_reverse_iterator::operator--(); return ret;}
			const_reverse_iterator & operator =(const_reverse_iterator const & other) { cont_t::const_reverse_iterator::operator=(static_cast<cont_t::const_reverse_iterator const &>(other)); return *this; }
			const HandleType &       operator *() { return cont_t::const_reverse_iterator::operator *(); }
			StorageType              operator->() { return StorageType(m_link,cont_t::const_reverse_iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
224
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
225
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
226
		template<class InputIterator>
Kirill Terekhov's avatar
Kirill Terekhov committed
227 228 229 230 231 232 233 234 235 236 237 238
		__INLINE void             insert      (iterator pos,InputIterator pbeg, InputIterator pend) {container.insert(static_cast<cont_t::iterator>(pos),pbeg,pend);}
		__INLINE iterator         erase       (iterator pos) {return iterator(m_link,container.erase(static_cast<cont_t::iterator>(pos)));}

		__INLINE iterator         begin       () { return iterator(m_link,container.begin()); }
		__INLINE iterator         end         () { return iterator(m_link,container.end()); }
		__INLINE reverse_iterator rbegin      () { return reverse_iterator(m_link,container.rbegin()); }
		__INLINE reverse_iterator rend        () { return reverse_iterator(m_link,container.rend()); }
		__INLINE const_iterator         begin () const { return const_iterator(m_link,container.begin()); }
		__INLINE const_iterator         end   () const { return const_iterator(m_link,container.end()); }
		__INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(m_link,container.rbegin()); }
		__INLINE const_reverse_iterator rend  () const { return const_reverse_iterator(m_link,container.rend()); }
		
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
239
		__INLINE StorageType      operator [] (size_type n) {assert(m_link); return StorageType(m_link,&container[n]);}
Kirill Terekhov's avatar
Kirill Terekhov committed
240
		__INLINE StorageType      operator [] (size_type n) const {assert(m_link); return StorageType(m_link,container[n]);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
241
		__INLINE StorageType      front       () {assert(m_link); return StorageType(m_link,&container.front()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
242
		__INLINE StorageType      front       () const {assert(m_link); return StorageType(m_link,container.front()); }
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
243
		__INLINE StorageType      back        ()  {assert(m_link); return StorageType(m_link,&container.back()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
244 245 246 247 248 249 250 251
		__INLINE StorageType      back        () const {assert(m_link); return StorageType(m_link,container.back()); }
		__INLINE HandleType       atfront     () const { return container.front(); }
		__INLINE HandleType       atback      () const { return container.back(); }
		__INLINE HandleType &     atfront     () { return container.front(); }
		__INLINE HandleType &     atback      () { return container.back(); }
		__INLINE HandleType &     at          (size_type n) { return container.at(n); }
		__INLINE HandleType       at          (size_type n) const { return container.at(n); }
		__INLINE void             swap        (ElementArray<StorageType> & other) {Mesh * t = m_link; m_link = other.m_link; other.m_link = t; container.swap(other.container);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
252
		__INLINE void             push_back   (const Storage & x) {if( m_link == NULL ) m_link = x.GetMeshLink(); assert(x.GetMeshLink() == m_link); container.push_back(x.GetHandle());}
Kirill Terekhov's avatar
Kirill Terekhov committed
253
		//__INLINE void             push_back   (const StorageType & x) {container.push_back(x.GetHandle());}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
254
		__INLINE void             push_back   (HandleType x) {assert(m_link != NULL); container.push_back(x);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
255
		__INLINE void             pop_back    () {container.pop_back();}
Kirill Terekhov's avatar
Kirill Terekhov committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
		__INLINE void             resize      (size_type n) {container.resize(n);}
		__INLINE bool             empty       () const {return container.empty();}
		__INLINE void             clear       () {container.clear();}
		__INLINE void             reserve     (size_type n) {container.reserve(n);}
		__INLINE size_type        size        () const {return container.size(); }
		__INLINE HandleType *     data        () {return container.data();}
		__INLINE const HandleType*data        () const {return container.data();}
		__INLINE Mesh *           GetMeshLink () const {assert(m_link); return m_link;}
		__INLINE void             SetMeshLink (Mesh * m) {m_link = m;}
		//implemented in mesh_array.cpp
		void                      Unite       (const HandleType * h, INMOST_DATA_ENUM_TYPE num);
		void                      Subtract    (const HandleType * h, INMOST_DATA_ENUM_TYPE num);
		void                      Intersect   (const HandleType * h, INMOST_DATA_ENUM_TYPE num);
		template<typename EType>
		void                      Unite       (const ElementArray<EType> & other) {Unite(other.data(),static_cast<INMOST_DATA_ENUM_TYPE>(other.size()));}
		template<typename EType>
		void                      Subtract    (const ElementArray<EType> & other) {Subtract(other.data(),static_cast<INMOST_DATA_ENUM_TYPE>(other.size()));}
		template<typename EType>
		void                      Intersect   (const ElementArray<EType> & other) {Intersect(other.data(),static_cast<INMOST_DATA_ENUM_TYPE>(other.size()));}
		void                      SetMarker   (MarkerType n) const;
		void                      RemMarker   (MarkerType n) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
277
		void                      SetPrivateMarker   (MarkerType n) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
278
		void                      RemPrivateMarker   (MarkerType n) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
279 280
		template<typename Etype>
		ElementArray<Etype>       Convert() {return ElementArray<Etype>(m_link,container);}
Kirill Terekhov's avatar
Kirill Terekhov committed
281 282 283 284 285 286
	};
	
			
	class Element : public Storage //implemented in element.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300
		typedef INMOST_DATA_BULK_TYPE GeometricType;
		static const GeometricType Unset        = 0;
		static const GeometricType Vertex       = 1;
		static const GeometricType Line         = 2;
		static const GeometricType MultiLine    = 3;
		static const GeometricType Tri          = 4;
		static const GeometricType Quad         = 5;
		static const GeometricType Polygon      = 6;
		static const GeometricType MultiPolygon = 7;
		static const GeometricType Tet          = 8;
		static const GeometricType Hex          = 9;
		static const GeometricType Prism        = 10;
		static const GeometricType Pyramid      = 11;
		static const GeometricType Polyhedron   = 12;
Kirill Terekhov's avatar
Kirill Terekhov committed
301 302 303
		static const GeometricType Set          = 253;
		static const GeometricType MeshPart     = 254;
		static const GeometricType MaxType      = 255;
Kirill Terekhov's avatar
Kirill Terekhov committed
304
		//enum GeometricType {Unset,Vertex,Line,MultiLine,Tri,Quad,Polygon,MultiPolygon,Tet,Hex,Prism,Pyramid,Polyhedron,Set};
Kirill Terekhov's avatar
Kirill Terekhov committed
305
		static const char *       GeometricTypeName(GeometricType t);
Kirill Terekhov's avatar
Kirill Terekhov committed
306
		static integer            GetGeometricDimension(GeometricType m_type);
Kirill Terekhov's avatar
Kirill Terekhov committed
307 308 309 310 311 312 313
		typedef INMOST_DATA_BULK_TYPE Status;
		static const Status Owned  = 1;
		static const Status Shared = 2;
		static const Status Ghost  = 4;
		static const Status Any    = 0;
		static const char * StatusName(Status s);
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
314
		typedef inner_reference_array            adj_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
315 316 317 318
		typedef adj_type::iterator               adj_iterator;
		typedef adj_type::const_iterator         const_adj_iterator;
		typedef adj_type::reverse_iterator       adj_reverse_iterator;
		typedef adj_type::const_reverse_iterator const_adj_reverse_iterator;
Kirill Terekhov's avatar
Kirill Terekhov committed
319 320 321
	public:
		//adj_type &                  HighConn                () const;
		//adj_type &                  LowConn                 () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
322
	protected:
Kirill Terekhov's avatar
Kirill Terekhov committed
323 324 325 326
		void                        SetGeometricType        (GeometricType t);
	public:
		Element() : Storage(NULL,InvalidHandle()) {}
		Element(Mesh * m, HandleType h) : Storage(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
327
		Element(Mesh * m, HandleType * h) : Storage(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
328 329 330 331 332 333
		Element(const Element & other) : Storage(other) {}
		Element & operator =(Element const & other) {Storage::operator =(other); return *this;}
		Element * operator ->() {return this;}
		const Element * operator ->() const {return this;}
		Element & self() {return *this;}
		const Element & self() const {return *this;}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
334
		virtual ~Element() {}
Kirill Terekhov's avatar
Kirill Terekhov committed
335
	public:
Igor Konshin's avatar
Igor Konshin committed
336
		/// Retrieve number of adjacent elements.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
337 338
		/// For etype you can either pass one type as CELL,
		/// or several types as bitwise mask: NODE | CELL.
Kirill Terekhov's avatar
Kirill Terekhov committed
339 340 341
		/// @param etype bitwise mask of element types
		/// @return number of adjacent elements.
		virtual enumerator                nbAdjElements           (ElementType etype) const;
Igor Konshin's avatar
Igor Konshin committed
342
		/// Retrieve unordered array of adjacent elements.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
343 344 345
		/// If you care about orderness of nodes for face you should you Face::getNodes() instead.
		/// If you want faster access you may use direct access to handles stored in memory
		/// through Mesh::HighConn for upper adjacencies and Mesh::LowConn for lower adjacencies.
Kirill Terekhov's avatar
Kirill Terekhov committed
346 347 348
		/// @param etype bitwise mask of element types
		/// @return array of elements
		virtual ElementArray<Element>     getAdjElements          (ElementType etype) const;  //unordered
Igor Konshin's avatar
Igor Konshin committed
349
		/// Retrieve number of adjacent elements with marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
350 351 352 353 354 355 356
		/// As etype you can either pass one type as CELL,
		/// or several types as bitwise mask: NODE | CELL
		/// @param etype bitwise mask of element types
		/// @param mask marker to be set 
		/// @param invert_mask if true then those are selected on wich marker is not set
		/// @return number of adjacent elements.
		virtual enumerator                nbAdjElements           (ElementType etype, MarkerType mask, bool invert_mask = false) const;
Igor Konshin's avatar
Igor Konshin committed
357
		/// Retrieve unordered array of adjacent elements with marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
358 359 360 361 362
		/// @param etype bitwise mask of element types
		/// @param mask marker to be set 
		/// @param invert_mask if true then those are selected on wich marker is not set
		/// @return array of elements
		virtual ElementArray<Element>     getAdjElements          (ElementType etype, MarkerType mask, bool invert_mask = false) const;  //unordered
363 364 365 366 367
		ElementArray<Element>       BridgeAdjacencies       (ElementType Bridge, ElementType Dest, MarkerType bridge_mask = 0, bool bridge_invert = false, MarkerType target_mask = 0, bool target_invert = false) const;
		ElementArray<Node>          BridgeAdjacencies2Node  (ElementType Bridge, MarkerType bridge_mask = 0, bool bridge_invert = false, MarkerType target_mask = 0, bool target_invert = false) const;
		ElementArray<Edge>          BridgeAdjacencies2Edge  (ElementType Bridge, MarkerType bridge_mask = 0, bool bridge_invert = false, MarkerType target_mask = 0, bool target_invert = false) const;
		ElementArray<Face>          BridgeAdjacencies2Face  (ElementType Bridge, MarkerType bridge_mask = 0, bool bridge_invert = false, MarkerType target_mask = 0, bool target_invert = false) const;
		ElementArray<Cell>          BridgeAdjacencies2Cell  (ElementType Bridge, MarkerType bridge_mask = 0, bool bridge_invert = false, MarkerType target_mask = 0, bool target_invert = false) const;
Igor Konshin's avatar
Igor Konshin committed
368
		/// Retrieve all the nodes of the element.
369
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
370
		/// For a node returns itself.
371
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
372
		/// For an edge returns ordered pair of nodes. The order of nodes in the edge is preserved from the first construction.
373
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
374 375 376
		/// For a face returns ordered set of nodes. In the case Face::CheckNormalOrientation returns true the
		/// order of nodes will follow right hand side rule with respect to normal vector, otherwise it follows
		/// left hand side rule with respect to normal vector.
377
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
378 379 380 381
		/// For a cell returns the same order that was provided through suggest_nodes_oreder in Mesh::CreateCell.
		/// In the case suggest_nodes_order was not provided, the order of nodes follows VTK format for known types
		/// of elements such as Element::Tet, Element::Prism, Element::Hex, Element::Pyramid. For a general polyhedron
		/// the order is unspecified.
382
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
383 384 385
		/// @return array of elements
		/// @see Face::CheckNormalOrientation
		/// @see Face::FaceOrientedOutside
Kirill Terekhov's avatar
Kirill Terekhov committed
386
		virtual ElementArray<Node>  getNodes                () const; //unordered
Igor Konshin's avatar
Igor Konshin committed
387
		/// Retrieve all the edges of the element.
388
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
389
		/// For a node returns unordered set of edges.
390
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
391
		/// For an edge returns itself.
392
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
393
		/// For a face returns ordered set of edges.
394
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
395
		/// For a cell returns unordered set of edges.
396
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
397
		/// @return array of elements
Kirill Terekhov's avatar
Kirill Terekhov committed
398
		virtual ElementArray<Edge>  getEdges                () const; //unordered
Igor Konshin's avatar
Igor Konshin committed
399
		/// Retrieve all the faces of the element.
400
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
401
		/// For a node returns unordered set of faces.
402
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
403
		/// For an edge returns unordered set of faces.
404
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
405
		/// For a face returns itself.
406
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
407
		/// For a cell return ordered set of faces. The order of faces in the cell is preserved from the first construction.
408
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
409
		/// @return array of elements
Kirill Terekhov's avatar
Kirill Terekhov committed
410
		virtual ElementArray<Face>  getFaces                () const; //unordered
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
411
		/// Return all the cells of the element.
412
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
413
		/// For a node returns unordered set of cells.
414
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
415
		/// For an edge returns unordered set of cells.
416
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
417 418
		/// For a face returns a pair of cells. In the case Face::CheckNormalOrientation returns true
		/// then the normal points from the first cell to the second and in oppisite direction otherwise.
419
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
420
		/// For a cell returns itself.
421
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
422 423
		/// @return array of elements
		/// @see Face::FaceOrientedOutside
Kirill Terekhov's avatar
Kirill Terekhov committed
424 425 426 427 428 429 430 431 432 433 434 435 436
		virtual ElementArray<Cell>  getCells                () const; //unordered
		virtual ElementArray<Node>  getNodes                (MarkerType mask,bool invert_mask = false) const; //unordered
		virtual ElementArray<Edge>  getEdges                (MarkerType mask,bool invert_mask = false) const; //unordered
		virtual ElementArray<Face>  getFaces                (MarkerType mask,bool invert_mask = false) const; //unordered
		virtual ElementArray<Cell>  getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
		GeometricType               GetGeometricType        () const;
		unsigned int                GetElementDimension     () const {return GetGeometricDimension(GetGeometricType());}
		Status                      GetStatus               () const;
		void                        SetStatus               (Status status) const;
		Storage::integer &          GlobalID                () const;
		bool                        CheckElementConnectivity() const;
		void                        PrintElementConnectivity() const;
		static bool                 CheckConnectivity       (Mesh * m);
Kirill Terekhov's avatar
Kirill Terekhov committed
437
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
438
		void                        CastRay                 (const real * pos, const real * dir, tiny_map<HandleType, real, 16> & hits) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
439 440 441 442
		void                        ComputeGeometricType    () const;
		void                        Centroid                (real * cnt) const;
		void                        Barycenter              (real * cnt) const;
		Storage::real               Mean                    (real (*func)(real* x,real t),real time) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
443 444 445 446 447 448 449 450
		/// Determine that the element is on the boundary.
		/// \warning This function does not involve communication
		/// for distributed mesh and works only for local partition
		/// of the mesh. It cannot correctly determine boundary elements
		/// of the global mesh. For this purpose you should use
		/// Mesh::MarkBoundaryFaces
		/// @return True if the element is on the boundary, otherwise false.
		/// @see Mesh::MarkBoundaryFaces
Kirill Terekhov's avatar
Kirill Terekhov committed
451 452
		bool                        Boundary                () const;
		bool                        Planarity               () const; // check that all nodes lay on one plane
Kirill Terekhov's avatar
Kirill Terekhov committed
453
		//implemented in modify.cpp
454 455 456
		/// If the function returns true then element was hidden,
		/// works only inside BeginModification and EndModification,
		/// on EndModification all Hidden elements are deleted.
Kirill Terekhov's avatar
Kirill Terekhov committed
457 458
		/// \todo Probably have to check normal orientation after
		/// hiding a back cell for a face.
459 460 461 462
		bool                        Hide                    () const;
		/// If the function returns true then element was recovered
		/// from hidden state, works only inside BeginModification
		/// and EndModification.
Kirill Terekhov's avatar
Kirill Terekhov committed
463 464
		/// \todo Probably have to check normal orientation after
		/// recovering a back cell for a face.
Kirill Terekhov's avatar
Kirill Terekhov committed
465
		bool                        Show                    () const; // if true then element was recovered
Kirill Terekhov's avatar
Kirill Terekhov committed
466 467 468 469 470 471 472
		/// Remove element from mesh.
		/// If you call this function inside modification phase, see Mesh::BeginModification and Mesh::EndModification,
		/// and the element was not created during modification phase (not marked as Element::New),
		/// then the element will not be actually destroyed but hidden. 
		/// You can restore all the hidden elements by using Mesh::ToggleModification.
		/// \warning This function will not resolve an ierarchical strucutre of ElementSet, use ElemnetSet::DeleteSet instead.
		/// @return Returns true if the element was actually destroyed. Returns false if the element was hidden.
Kirill Terekhov's avatar
Kirill Terekhov committed
473 474 475 476
		bool                        Delete                  (); // if true then element was deleted, otherwise it was hidden
		bool                        Hidden                  () const;
		bool                        New                     () const;
		void                        Disconnect              (bool delete_upper_adjacent) const; //disconnect all elements, delete upper dependent
477
		/// Disconnect element.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
478 479
		/// Disconnects nodes from this edge, edges from this face, faces from this cell, cannot disconnect cells from this node; \n
		/// Disconnects edges from this node, faces from this edge, cells from this face, cannot disconnect nodes from this cell; \n
Kirill Terekhov's avatar
Kirill Terekhov committed
480
		/// Updates geometric data and cell nodes automatically.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
481
		void                        Disconnect              (const HandleType * adjacent, INMOST_DATA_ENUM_TYPE num) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
482 483 484
		/// \brief Connects lower adjacencies to current element.
		/// Geometric data and cell nodes are updated automatically.
		///
485
		/// \todo
Kirill Terekhov's avatar
Kirill Terekhov committed
486 487 488
		///	  1. Asserts in this function should be replaced by Topography checks.
		///	  2. This function should be used for construction of elements instead of current implementation.
		///	  3. Should correctly account for order of edges (may be implemented through CheckEdgeOrder, FixEdgeOrder).
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
489
		void                        Connect                 (const HandleType * adjacent, INMOST_DATA_ENUM_TYPE num) const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
490
		/// Update geometric data for element, calls RecomputeGeometricData from Mesh.
Kirill Terekhov's avatar
Kirill Terekhov committed
491
		void                        UpdateGeometricData     () const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
492 493
	};
	
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
494 495
	__INLINE const Element & InvalidElement() {static Element ret(NULL,InvalidHandle()); return ret;}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
496 497 498
	class Node : public Element //implemented in node.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
499 500 501
		Node() : Element() {}
		Node(const Node & other) : Element(other) {}
		Node(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
502
		Node(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
503 504 505 506 507 508 509 510 511
		Node & operator =(Node const & other) {Element::operator =(other); return *this;}
		Node * operator ->() {return this;}
		const Node * operator ->() const {return this;}
		Node & self() {return *this;}
		const Node & self() const {return *this;}
	public:
		ElementArray<Edge>          getEdges                () const; //unordered
		ElementArray<Face>          getFaces                () const; //unordered
		ElementArray<Cell>          getCells                () const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
512

Kirill Terekhov's avatar
Kirill Terekhov committed
513 514 515
		ElementArray<Edge>          getEdges                (MarkerType mask,bool invert_mask = false) const; //unordered
		ElementArray<Face>          getFaces                (MarkerType mask,bool invert_mask = false) const; //unordered
		ElementArray<Cell>          getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
516

Kirill Terekhov's avatar
Kirill Terekhov committed
517
		Storage::real_array         Coords                  () const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
518
	};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
519 520

	__INLINE const Node & InvalidNode() {static Node ret(NULL,InvalidHandle()); return ret;}
Kirill Terekhov's avatar
Kirill Terekhov committed
521 522 523 524
	
	class Edge : public Element //implemented in edge.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
525 526 527
		Edge() : Element() {}
		Edge(const Edge & other) : Element(other) {}
		Edge(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
528
		Edge(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
529 530 531 532 533 534
		Edge & operator =(Edge const & other) {Element::operator =(other); return *this;}
		Edge * operator ->() {return this;}
		const Edge * operator ->() const {return this;}
		Edge & self() {return *this;}
		const Edge & self() const {return *this;}
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
535
		
Kirill Terekhov's avatar
Kirill Terekhov committed
536 537 538
		ElementArray<Node>          getNodes                () const; //ordered
		ElementArray<Face>          getFaces                () const; //unordered
		ElementArray<Cell>          getCells                () const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
539

Kirill Terekhov's avatar
Kirill Terekhov committed
540 541 542
		ElementArray<Node>          getNodes                (MarkerType mask,bool invert_mask = false) const; //ordered
		ElementArray<Face>          getFaces                (MarkerType mask,bool invert_mask = false) const; //unordered
		ElementArray<Cell>          getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
543

Kirill Terekhov's avatar
Kirill Terekhov committed
544 545
		Node                        getBeg                  () const;
		Node                        getEnd                  () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
546
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
547
		static Edge                 UniteEdges              (const ElementArray<Edge> & edges, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
548 549 550
		static bool                 TestUniteEdges          (const ElementArray<Edge> & edges, MarkerType del_protect);
		static ElementArray<Edge>   SplitEdge               (Edge e, const ElementArray<Node> & nodes, MarkerType del_protect); //provide ordered array of nodes, that lay between former nodes of the edge
		static bool                 TestSplitEdge           (Edge e, const ElementArray<Node> & nodes, MarkerType del_protect);
551
		static Node                 CollapseEdge            (Edge e, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
552
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
553
		Storage::real               Length                  () const;
554 555
		///Swap positions of first node and last node
		void                        SwapEnds                ();
Kirill Terekhov's avatar
Kirill Terekhov committed
556
	};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
557 558

	__INLINE const Edge & InvalidEdge() {static Edge ret(NULL,InvalidHandle()); return ret;}
Kirill Terekhov's avatar
Kirill Terekhov committed
559
	
Kirill Terekhov's avatar
Kirill Terekhov committed
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580

	/// \brief An interface for elements of type FACE.
	///
	/// This interface carry the link to the mesh and the element's handle that
	/// represents position of the element's data in the mesh. 
	///
	/// Interface provides some operations that can be done uniquely on the object of class 
	/// Element for which Element::GetElementType retruns FACE.
	///
	/// For the basic set of operations on all of the elements check class Element.
	///
	/// For the basic set of operations on the data of the element check class Storage.
	///
	/// You can obtain object of class Face from Mesh::iteratorFace,
	/// in this case obtained object is always valid.
	/// Also you can get it through Mesh::FaceByLocalID, check with Element::isValid to see whether you
	/// have obtained a valid object.
	/// You can convert an object of class Element into an object of class Face by Element::getAsFace. In debug
	/// mode it will internally check that the element is of type FACE.
	/// You may compose an object of class Face by using constructor and specifing pointer to the mesh
	/// and providing element's handle. You can make a handle with ComposeHandle(FACE,local_id) function.
Kirill Terekhov's avatar
Kirill Terekhov committed
581 582 583
	class Face : public Element //implemented in face.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
584 585 586
		Face() : Element() {}
		Face(const Face & other) : Element(other) {}
		Face(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
587
		Face(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
588 589 590 591 592 593
		Face & operator =(Face const & other) {Element::operator =(other); return *this;}
		Face * operator ->() {return this;}
		const Face * operator ->() const {return this;}
		Face & self() {return *this;}
		const Face & self() const {return *this;}
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
594
		
Kirill Terekhov's avatar
Kirill Terekhov committed
595 596 597
		ElementArray<Node>          getNodes                () const; //ordered
		ElementArray<Edge>          getEdges                () const; //ordered
		ElementArray<Cell>          getCells                () const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
598

Kirill Terekhov's avatar
Kirill Terekhov committed
599 600 601
		ElementArray<Node>          getNodes                (MarkerType mask,bool invert_mask = false) const; //ordered
		ElementArray<Edge>          getEdges                (MarkerType mask,bool invert_mask = false) const; //ordered
		ElementArray<Cell>          getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
602 603

		//this is for 2d case when the face is represented by segment
Kirill Terekhov's avatar
Kirill Terekhov committed
604 605
		Node                        getBeg                  () const;
		Node                        getEnd                  () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
606 607
		/// \brief Retrieve the cell for which the normal points outwards.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
608
		/// \warning Depending on the grid construction the normal may incorrectly point inwards.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
609
		/// You can resolve this situation by Face::FixNormalOrientation.
Kirill Terekhov's avatar
Kirill Terekhov committed
610
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
611 612
		/// @return the cell for which normal points outwards.
		/// @see Face::FixNormalOrientation
Kirill Terekhov's avatar
Kirill Terekhov committed
613
		Cell                        BackCell                () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
614 615
		/// \brief Retrieve the cell for which the normal points inwards.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
616
		/// \warning Depending on the grid construction the normal may incorrectly point outwards.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
617
		/// You can resolve this situation by Face::FixNormalOrientation.
Kirill Terekhov's avatar
Kirill Terekhov committed
618
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
619 620
		/// @return the cell for which normal points inwards.
		/// @see Face::FixNormalOrientation
Kirill Terekhov's avatar
Kirill Terekhov committed
621 622 623 624 625
		Cell                        FrontCell               () const;
		bool                        FaceOrientedOutside     (Cell c) const;
		void                        ReorderEdges            () const;
		bool                        CheckEdgeOrder          () const; //not implemented// returns true if edges of face form an ordered closed loop
		bool                        FixEdgeOrder            () const; //not implemented// returns true if edges were successfully reordered to form a closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
626
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
627
		static Face                 UniteFaces              (const ElementArray<Face> & faces, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
628 629
		static bool                 TestUniteFaces          (const ElementArray<Face> & faces,  MarkerType del_protect);
		static ElementArray<Face>   SplitFace               (Face face, const ElementArray<Edge> & edges, MarkerType del_protect); //provide all edges that lay inside face
Kirill Terekhov's avatar
Kirill Terekhov committed
630 631 632 633 634
		static bool                 TestSplitFace           (Face face, const ElementArray<Edge> & edges, MarkerType del_protect);
		///This function changes Face::BackCell() with Face::FrontCell().
		/// \warning Function does not modify normal orientation. You may have
		/// to call Face::FixNormalOrientation().
		void                        SwapCells               () const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
635
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
636 637 638 639 640 641 642 643
		Storage::real               Area                    () const;
		void                        Normal                  (real * nrm) const;
		void                        UnitNormal              (real * nrm) const;
		void                        OrientedNormal          (Cell c, real * nrm) const;
		void                        OrientedUnitNormal      (Cell c, real * nrm) const;
		bool                        FixNormalOrientation    () const;  //returns true if orientation was corrected, otherwise returns false
		bool                        CheckNormalOrientation  () const; //returns true if orientation is correct, otherwise returns false
		bool                        Closure                 () const; // test integrity of polygon
Kirill Terekhov's avatar
Kirill Terekhov committed
644
	};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
645 646

	__INLINE const Face & InvalidFace() {static Face ret(NULL,InvalidHandle()); return ret;}
Kirill Terekhov's avatar
Kirill Terekhov committed
647
	
Kirill Terekhov's avatar
Kirill Terekhov committed
648 649 650 651 652 653
	//implemented in cell.cpp
	/// \brief An interface for elements of type CELL.
	///
	/// This interface carry the link to the mesh and the element's handle that
	/// represents position of the element's data in the mesh. 
	///
Kirill Terekhov's avatar
Kirill Terekhov committed
654 655
	/// Interface provides some operations that can be done uniquely on the object of class 
	/// Element for which Element::GetElementType retruns CELL.
Kirill Terekhov's avatar
Kirill Terekhov committed
656 657 658 659 660 661 662 663 664
	///
	/// For the basic set of operations on all of the elements check class Element.
	///
	/// For the basic set of operations on the data of the element check class Storage.
	///
	/// You can obtain object of class Cell from Mesh::iteratorCell,
	/// in this case obtained object is always valid.
	/// Also you can get it through Mesh::CellByLocalID, check with Element::isValid to see whether you
	/// have obtained valid object.
Kirill Terekhov's avatar
Kirill Terekhov committed
665 666 667 668
	/// You can convert an object of class Element into an object of class Cell by Element::getAsCell. In debug
	/// mode it will internally check that the element is of type CELL.
	/// You may compose an object of class Cell by using constructor and specifing pointer to the mesh
	/// and providing element's handle. You can make a handle with ComposeHandle(CELL,local_id) function.
Kirill Terekhov's avatar
Kirill Terekhov committed
669
	class Cell : public Element
Kirill Terekhov's avatar
Kirill Terekhov committed
670 671
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
672 673 674 675 676 677 678 679 680 681
		/// \brief Basic constructor.
		///
		/// Constructs invalid cell.
		Cell() : Element() {} 
		/// \brief Basic constructor with fixed handle.
		///
		/// When constructed this way, only handle within object may change.
		///
		/// @param m Pointer to the mesh to which the element belongs.
		/// @param h Unique handle that describes position of the element within the mesh.
Kirill Terekhov's avatar
Kirill Terekhov committed
682
		Cell(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
683 684 685 686 687
		/// \brief Basic constructor with an assignable handle.
		///
		/// When constructed this way, the provided memory location for handle
		/// will be modified on assignment.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
688
		/// The purpose of this function is to be used in various non-constant iterators
Kirill Terekhov's avatar
Kirill Terekhov committed
689 690 691 692
		/// of containers that allow underlaying contents to be changed.
		///
		/// @param m Pointer to the mesh to which the element belongs.
		/// @param h Pointer to the handle that describes position of the element within mesh.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
693
		Cell(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
694 695 696 697 698
		/// \brief Copy constructor.
		///
		/// New object will inherit the assignment behavior of the initial object.
		///
		/// @param other Object of type Cell to be duplicated.
Kirill Terekhov's avatar
Kirill Terekhov committed
699
		Cell(const Cell & other) : Element(other) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
		/// \brief Assignment operator
		///
		/// Assigned object will inherit the asignment behavior of the initial object only
		/// in case it was constructed without pointer to a handle. Otherwise it will
		/// only modify the memory location to which it points.
		///
		/// @param other Object of type Cell to be duplicated.
		/// @return Reference to the current object.
		Cell & operator =(Cell const & other) {Element::operator =(other); return *this;} ///< Assignment Operator.
		/// \brief Operator of dereference to pointer.
		///
		/// This is needed for iterators to work properly.
		///
		/// @return Pointer to the current object.
		Cell * operator ->() {return this;} 
		/// \brief Operator of dereference to constant pointer. 
		///
		/// This is needed for const_iterators to work properly.
		///
		/// @return Constant pointer to the current object.
Kirill Terekhov's avatar
Kirill Terekhov committed
720
		const Cell * operator ->() const {return this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
721 722 723 724 725 726 727 728 729 730 731
		/// \brief Get self-reference.
		///
		/// Main purpose is to convert iterators into elements and to pass them as arguments of functions.
		///
		/// @return Constant reference to the current object.
		Cell & self() {return *this;} 
		/// \brief Get constant self-reference.
		///
		/// Main purpose is to convert iterators into elements and to pass them as arguments of functions.
		///
		/// @return Reference to the current object.
Kirill Terekhov's avatar
Kirill Terekhov committed
732 733
		const Cell & self() const {return *this;}
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
734 735 736 737
		/// \brief Get all the nodes of the current cell.
		///
		/// This function traverses up the adjacency graph by one level.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
738
		/// The order of nodes will be preserved from the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
		/// When suggest_nodes array is not supplied into the Mesh::CreateCell functions, then
		/// for known types the order of nodes follows VTK convention. For polyhedral cells
		/// the order is unspecified. When suggest_nodes_order was provided into Mesh::CreateCell
		/// then the order follows provided order.
		///
		/// @return Set of nodes that compose current cell.
		ElementArray<Node>          getNodes                () const;
		/// \brief Get all the edges of the current cell.
		///
		/// This function traverses down the adjacency graph by two levels.
		///
		/// The order of the edges is unspecified.
		///
		/// @return Set of edges that compose current cell.
		///
		/// \todo
		/// One should thoroughly check three scenarios of function execution in shared parallel environment
		/// for different types of cells (simple tet/hex cells as well as complex polyhedral cells) and
		/// draw a conclusion on the best scenario for each condition. One of the development versions
		/// contains all the algorithms, ask for the files.
		///  1. Use of markers (current wariant).
		///  2. Put all elements into array with duplications, then run std::sort and std::unique.
		///  3. Put all elements into array, check for duplication by running through array.
Kirill Terekhov's avatar
Kirill Terekhov committed
762 763 764 765 766 767 768
		///
		/// \warning Note that this function uses markers to check for duplication of edges
		/// in output array. This allows for faster algorithm, but will lead to penalties
		/// in shared parallel execution, since operations on markers are declared atomic.
		/// For atomic declaration to work you have to define USE_OMP during CMake configuration
		/// or in inmost_common.h. If you attempt to use this function in shared parallel execution
		/// without USE_OMP you may expect side effects.
Kirill Terekhov's avatar
Kirill Terekhov committed
769 770 771 772 773 774
		ElementArray<Edge>          getEdges                () const;
		/// \brief Get all the faces of the current cell.
		///
		/// This function traverses down the adjacency graph by one level.
		///
		/// The order of the faces returned by this function is preserved from 
Kirill Terekhov's avatar
Kirill Terekhov committed
775
		/// the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
776 777 778 779 780 781 782
		///
		/// @return Set of faces that compose current cell.
		ElementArray<Face>          getFaces                () const;
		/// \brief Get the subset of the nodes of the current cell that are (not) marked by provided marker.
		///
		/// This function traverses up the adjacency graph by one level.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
783
		/// The order of nodes will be preserved from the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
784 785 786 787 788 789 790 791 792
		/// When suggest_nodes array is not supplied into the Mesh::CreateCell functions, then
		/// for known types the order of nodes follows VTK convention. For polyhedral cells
		/// the order is unspecified. When suggest_nodes_order was provided into Mesh::CreateCell
		/// then the order follows provided order.
		///
		/// @param mask Marker that should be used to filter elements.
		/// @param invert_mask If false then those elements that are marked will be taken, otherwise
		///                    elements that are not marked will be taken.
		/// @return Set of the nodes that compose current cell and (not) marked by marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
793 794 795
		///
		/// \warning To work correctly in shared parallel environment this function requires
		/// USE_OMP to be defined in CMake or in inmost_common.h.
Kirill Terekhov's avatar
Kirill Terekhov committed
796 797 798 799 800 801 802 803 804 805 806
		ElementArray<Node>          getNodes                (MarkerType mask,bool invert_mask = false) const;
		/// \brief Get the subset of the edges of the current cell that are (not) marked by provided marker.
		///
		/// This function traverses down the adjacency graph by two levels.
		///
		/// The order of the edges is unspecified.
		///
		/// @param mask Marker that should be used to filter elements.
		/// @param invert_mask If false then those elements that are marked will be taken, otherwise
		///                    elements that are not marked will be taken.
		/// @return Set of the edges that compose current cell and (not) marked by marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
807 808 809
		///
		/// \warning To work correctly in shared parallel environment this function requires
		/// USE_OMP to be defined in CMake or in inmost_common.h.
Kirill Terekhov's avatar
Kirill Terekhov committed
810 811 812 813 814 815
		ElementArray<Edge>          getEdges                (MarkerType mask,bool invert_mask = false) const;
		/// \brief Get the subset of the faces of the current cell that are (not) marked by provided marker.
		///
		/// This function traverses down the adjacency graph by one level.
		///
		/// The order of the faces returned by this function is preserved from 
Kirill Terekhov's avatar
Kirill Terekhov committed
816
		/// the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
817 818 819 820 821
		///
		/// @param mask Marker that should be used to filter elements.
		/// @param invert_mask If false then those elements that are marked will be taken, otherwise
		///                    elements that are not marked will be taken.
		/// @return Set of the faces that compose current cell and (not) marked by marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
822 823 824
		///
		/// \warning To work correctly in shared parallel environment this function requires
		/// USE_OMP to be defined in CMake or in inmost_common.h.
Kirill Terekhov's avatar
Kirill Terekhov committed
825 826 827
		ElementArray<Face>          getFaces                (MarkerType mask,bool invert_mask = false) const;
		/// \brief Check that sequence of edges form a closed loop and each edge have a node that matches one of the nodes at the next edge.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
828
		/// This function works for cells for which Element::GetElementDimension returns 2.
Kirill Terekhov's avatar
Kirill Terekhov committed
829 830 831 832 833 834 835
		///
		/// @return True if edges form the correct closed loop.
		///
		/// \todo
		///   1. Implement.
		///   2. Use in topology check algorithms.
		///   3. Use in Element::Connect.
Kirill Terekhov's avatar
Kirill Terekhov committed
836
		bool                        CheckEdgeOrder          () const; //not implemented//2D only, returns true if edges of face form an ordered closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
837 838 839 840 841 842 843 844 845 846 847 848
		/// \brief Repair the sequence of edges so that each edge have node that matches one of the nodes at the next edge.
		///
		/// This function works for cells for which Element::GetGeometricDimension returns 2.
		///
		/// This function may fail if all the edges does not form a closed loop.
		///
		/// @return True if edges were successfully reordered to form a closed loop.
		///
		/// \todo
		///   1. Implement.
		///   2. Use in topology check algorithms.
		///   3. Use in Element::Connect.
Kirill Terekhov's avatar
Kirill Terekhov committed
849
		bool                        FixEdgeOrder            () const; //not implemented//2D only, returns true if edges were successfully reordered to form a closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
850
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
851 852 853 854 855 856 857 858 859
		/// \brief Unite a set of given cells into one cell.
		///
		/// This will create a cell whose faces are formed by symmetric difference
		/// of faces of given cells.
		/// If you specify a nonzero marker then the procedure will fail 
		/// if any marked element have to be deleted during union.
		/// @param cells A set of cells to be united.
		/// @param del_protect A marker that protects elements from deletion. Zero means no check.
		/// @return A new cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
860
		static Cell                 UniteCells              (const ElementArray<Cell> & cells, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
861 862 863 864
		/// \brief Test that no marked element will be deleted during union of given cells.
		/// @param cells A set of cells to be united.
		/// @param del_protect A marker that protects elements from deletion. Zero means no check.
		/// @return True if no element deleted, false otherwise.
Kirill Terekhov's avatar
Kirill Terekhov committed
865
		static bool                 TestUniteCells          (const ElementArray<Cell> & cells, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
		/// \brief Separate a cell according to the set of provided faces.
		///
		/// You should first separate all edges with new nodes by Edge::SplitEdge, then faces with new edges by Face::SplitFace
		/// and then create faces using new edges from faces of initial cell and optionally edges from inside of the cell. 
		/// All faces are supposed to be internal with respect to the current cell. 
		/// Internally this function will resolve geometry of new cells inside of the 
		/// current cell by running through adjacency graph.
		///
		/// @param cell A cell to be split.
		/// @param faces A set of faces, internal for current cell, that will be used for construction of new cells.
		/// @param del_protect Marker that may be used to protect some elements from deletion by algorithm. 
		///        Zero means no check.
		/// @return A set of new cells.
		/// @see Edge::SplitEdge
		/// @see Face::SplitFace
		///
		/// \todo
		///   1. The algorithm inside is minimizing the size of the adjacency graph for each new cell.
		///      The correct behavior is to calculate volume of the cell for each adjacency graph and choose the graph with minimal volume.
		///      This requires calculation of volume for non-convex cells. For correct calculation of volume on non-convex cells one should 
		///      find one face for which normal orientation can be clearly determined and then orient all edges of the cell with respect to
		///      the orientation of edges of this face and establish normals for all faces. Once the algorithm is implemented here it should 
		///      be implemented in geometrical services or vice verse.
		///   2. Probably the algorithm should minimize the volume and adjacency graph size altogether. Between the cells with smallest volume
		///      within some tolerance select those that have smallest adjacency graph.
Kirill Terekhov's avatar
Kirill Terekhov committed
891
		static ElementArray<Cell>   SplitCell               (Cell cell, const ElementArray<Face> & faces, MarkerType del_protect); //provide all faces, that lay inside cell
Kirill Terekhov's avatar
Kirill Terekhov committed
892 893 894 895 896 897
		/// \brief This functions checks is it possible to split the cell by the given set of faces without deleting marked elements.
		///
		/// @param cell A cell to be split.
		/// @param faces Set of faces, internal for current cell, that will be used for new cells.
		/// @param del_protect Marker that may be used to protect some elements from deletion by algorithm. Zero means no check.
		/// @return True if possible, otherwise false.
Kirill Terekhov's avatar
Kirill Terekhov committed
898
		static bool                 TestSplitCell           (Cell cell, const ElementArray<Face> & faces, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
899
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
900 901 902 903 904 905 906 907 908 909
		/// \brief Get a cell that share a face with the current cell.
		///
		/// Don't forget to check that the returned cell is valid.
		/// It would return invalid cell for boundary face.
		///
		/// @param face A face of current cell for which neighbouring cell is determined.
		/// @return A cell that shares a given face with the current cell.
		Cell                        Neighbour               (Face face) const;
		/// \brief Get all cells that share the face with the current cell.
		/// @return Set of cells that share a face with the current cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
910
		ElementArray<Cell>          NeighbouringCells       () const; // get all cells that share any face with current
Kirill Terekhov's avatar
Kirill Terekhov committed
911 912
		/// \brief Determine, if point lies inside element.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
913 914 915 916 917 918
		/// Now it works only for 3-dimensional elements, at future it will be
		/// extended to support polygons and segments.
		/// @param point coordinates of the point, it is assumed that number of the
		/// coordinates is the same as the number of dimensions in the mesh.
		/// @return returns true if points inside element, false otherwise
		/// @see Mesh::GetDimensions
Kirill Terekhov's avatar
Kirill Terekhov committed
919 920 921 922 923 924 925 926 927
		///
		/// \todo
		///   1. Should be checked or extended for 2d cells. (done, testing)
		bool                        Inside                  (const real * point) const; //is point inside cell, check for 2d case
		/// \brief Return volume of the cell.
		///
		/// Note that currently the volume for non-convex cells may be calculated incorrectly.
		/// \todo
		///   1. Geometric services should correctly resolve volume for non-convex cells.
Kirill Terekhov's avatar
Kirill Terekhov committed
928
		real                        Volume                  () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
929 930 931 932
		/// \brief Test that faces of the cell form the closed set.
		///
		/// This is automatically checked for if you activate NEED_TEST_CLOSURE
		/// in Mesh::SetTopologyCheck.
Kirill Terekhov's avatar
Kirill Terekhov committed
933
		/// @return True if faces of the cell form the closed set, false otherwise.
934 935 936
		bool                        Closure                 () const;
		/// For each adjacent cell make me a front cell and fix normal orientation accordingly.
		void                        SwapBackCell            () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
937 938
	};

Kirill Terekhov's avatar
Kirill Terekhov committed
939
	///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
940 941
	__INLINE const Cell & InvalidCell() {static Cell ret(NULL,InvalidHandle()); return ret;}

Kirill Terekhov's avatar
Kirill Terekhov committed
942 943 944
	class ElementSet : public Element //implemented in eset.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
945 946 947 948 949 950
		///Number of reserved positions in HighConn array.
		///The first position is the handle to parent set.
		///The second position is handle to sibling set.
		///The third position is handle to child set.
		///The fourth position is number of sorted elements in the set.
		///All the rest are positions of deleted elements.
Kirill Terekhov's avatar
Kirill Terekhov committed
951
		static const enumerator             high_conn_reserved  = 4;
Kirill Terekhov's avatar
Kirill Terekhov committed
952
		__INLINE static HandleType &        hParent             (Element::adj_type & arr) {return arr[0];}
Kirill Terekhov's avatar
Kirill Terekhov committed
953 954 955
		__INLINE static HandleType &        hSibling            (Element::adj_type & arr) {return arr[1];}
		__INLINE static HandleType &        hChild              (Element::adj_type & arr) {return arr[2];}
		__INLINE static HandleType &        hSorted             (Element::adj_type & arr) {return arr[3];}
Kirill Terekhov's avatar
Kirill Terekhov committed
956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
		typedef INMOST_DATA_BULK_TYPE       ComparatorType;
		static const ComparatorType         UNSORTED_COMPARATOR = 0;
		static const ComparatorType         GLOBALID_COMPARATOR = 1;
		static const ComparatorType         CENTROID_COMPARATOR = 2;
		static const ComparatorType         HIERARCHY_COMPARATOR  = 3;
		static const ComparatorType         HANDLE_COMPARATOR   = 4;
		                                    ElementSet          () : Element() {}
		                                    ElementSet          (Mesh * m, HandleType h) : Element(m,h) {}
		                                    ElementSet          (Mesh * m, HandleType * h) : Element(m,h) {}
		                                    ElementSet          (const ElementSet & other) : Element(other) {}
		__INLINE ElementSet &               operator =          (ElementSet const & other) {Element::operator =(other); return *this;}
		__INLINE ElementSet *               operator ->         () {return this;}
		__INLINE const ElementSet *         operator ->         () const {return this;}
		__INLINE ElementSet &               self                ()              {return *this;}
		__INLINE const ElementSet &         self                () const        {return *this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
971 972 973
	public:
		/// Get name of the set
		std::string                 GetName() const;
Igor Konshin's avatar
Igor Konshin committed
974
		/// Retrieve parent of the set
Kirill Terekhov's avatar
Kirill Terekhov committed
975
		ElementSet                  GetParent() const;
Igor Konshin's avatar
Igor Konshin committed
976
		/// Retrieve sibling set of the set, this will be next child for the parent
Kirill Terekhov's avatar
Kirill Terekhov committed
977
		ElementSet                  GetSibling() const;
978
		/// Retrieve child set of the set.
Kirill Terekhov's avatar
Kirill Terekhov committed
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
		/// Following example shows how to iterate through children of current set:
		/// for(ElementSet it = set->GetChild(); it->isValid(); it = it->GetSibling()) ...
		ElementSet                  GetChild() const;
		
		/// This will create new child for the parent
		void                        AddSibling(const ElementSet & sibling) const;
		/// Add child to current set
		void                        AddChild(const ElementSet & child) const;

		/// This will erase sibling or parent's child
		void                        RemSibling(const ElementSet & sibling) const;
		/// This will erase my child
		void                        RemChild(const ElementSet & child) const;
		/// How many there are siblings to the right of me including me
		enumerator                  CountSiblings() const;
		/// How many children I have 
		enumerator                  CountChildren() const;

		bool                        HaveSibling() const;
		bool                        HaveParent() const;
		bool                        HaveChild() const;

		/// Direct raw access to stored elements, no copy involved.
		/// The actual pointer may change when you add new elements due to reallocation of memory.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1003
		/// Modify at your own risk.
Kirill Terekhov's avatar
Kirill Terekhov committed
1004
		HandleType *                getHandles() const;
1005 1006
		/// Retrieve number of stored handles, including invalid.
		/// If you want to get number of valid elements use ElementSet::Size
Kirill Terekhov's avatar
Kirill Terekhov committed
1007
		enumerator                  nbHandles() const;
1008
		/// Retrieve position after last sorted element. This does not correctly
Kirill Terekhov's avatar
Kirill Terekhov committed
1009 1010
		/// represent total number of sorted elements, since some of them may be deleted
		enumerator                  nbSorted() const;
Igor Konshin's avatar
Igor Konshin committed
1011
		/// Retrieve all elements by type
Kirill Terekhov's avatar
Kirill Terekhov committed
1012 1013
		enumerator                  nbAdjElements(ElementType etype) const;
		enumerator                  nbAdjElements(ElementType etype, MarkerType select, bool invert = false) const;
Igor Konshin's avatar
Igor Konshin committed
1014
		/// Retrieve all elements by type
Kirill Terekhov's avatar
Kirill Terekhov committed
1015 1016 1017
		ElementArray<Element>       getAdjElements(ElementType etype) const;
		ElementArray<Element>       getAdjElements(ElementType etype, MarkerType select, bool invert = false) const;
		
Igor Konshin's avatar
Igor Konshin committed
1018
		/// Retrieve only nodes
Kirill Terekhov's avatar
Kirill Terekhov committed
1019 1020
		ElementArray<Node>          getNodes() const;
		ElementArray<Node>          getNodes(MarkerType select, bool invert = false) const;
Igor Konshin's avatar
Igor Konshin committed
1021
		/// Retrieve only edges
Kirill Terekhov's avatar
Kirill Terekhov committed
1022 1023
		ElementArray<Edge>          getEdges() const;
		ElementArray<Edge>          getEdges(MarkerType select, bool invert = false) const;
Igor Konshin's avatar
Igor Konshin committed
1024
		/// Retrieve only faces
Kirill Terekhov's avatar
Kirill Terekhov committed
1025 1026
		ElementArray<Face>          getFaces() const;
		ElementArray<Face>          getFaces(MarkerType select, bool invert = false) const;
Igor Konshin's avatar
Igor Konshin committed
1027
		/// Retrieve only cells
Kirill Terekhov's avatar
Kirill Terekhov committed
1028 1029
		ElementArray<Cell>          getCells() const;
		ElementArray<Cell>          getCells(MarkerType select, bool invert = false) const;
1030 1031
		/// Put one element without checking of the existance of duplicate.
		/// For sorted set new element will appear at unsorted part.
Kirill Terekhov's avatar
Kirill Terekhov committed
1032
		void                        PutElement(HandleType e) const;
1033
		/// Put one element without checking of the existance of duplicate.
Kirill Terekhov's avatar
Kirill Terekhov committed
1034 1035 1036 1037
		/// For sorted set new element will appear at unsorted part
		void                        PutElement(const Storage & e) const {PutElement(e->GetHandle());}
		/// Put multiple handles without checking of the existance of duplicate
		void                        PutElements(const HandleType * handles, enumerator num) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1038 1039
		/// Put multiple handles of the other set without checking of the existance of duplicate
		void                        PutElements(const ElementSet & other) const {PutElements(other->getHandles(),other->nbHandles());}
Kirill Terekhov's avatar
Kirill Terekhov committed
1040 1041
		/// Put multiple handles without checking
		template<typename EType>
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1042
		void                        PutElements(const ElementArray<EType> & elems) const {PutElements(elems.data(),static_cast<enumerator>(elems.size()));}
1043
		/// Put one element with checking of the existance of duplicate.
Kirill Terekhov's avatar
Kirill Terekhov committed
1044
		/// Preserves order for sorted set, thus may be expensive.
Kirill Terekhov's avatar
Kirill Terekhov committed
1045
		void                        AddElement(HandleType e) const;
1046
		/// Put one element with checking of the existance of duplicate.
Kirill Terekhov's avatar
Kirill Terekhov committed
1047
		/// Preserves order for sorted set, thus may be expensive.
Kirill Terekhov's avatar
Kirill Terekhov committed
1048
		void                        AddElement(const Storage & e) const {AddElement(e->GetHandle());}
1049 1050
		/// Add multiple elements with checking of the existance of duplicate.
		/// Preserves order for sorted set, thus may be expensive.
Kirill Terekhov's avatar
Kirill Terekhov committed
1051 1052 1053
		/// This will also remove any duplicates in unsorted part of the set.
		/// If you inserted duplicated elements through PutElements into previously sorted array
		/// then this operation does not guarantee that those duplications will be stored.
Kirill Terekhov's avatar
Kirill Terekhov committed
1054
		/// \todo Recheck usage of markers.
Kirill Terekhov's avatar
Kirill Terekhov committed
1055
		void                        AddElements(const HandleType * handles, enumerator num) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1056 1057 1058
		/// Add elements of other set
		void                        AddElements(const ElementSet & other) {Unite(other);}
		/// Add multiple elements with checking of the existance of duplicate
Kirill Terekhov's avatar
Kirill Terekhov committed
1059 1060 1061 1062 1063 1064 1065 1066 1067
		template<typename EType>
		void                        AddElements(const ElementArray<EType> & elems) const {AddElements(elems.data(),static_cast<enumerator>(elems.size()));}

		void                        RemoveElement(const Storage & e) const;
		void                        RemoveElements(const HandleType * handles, enumerator num) const;
		/// Remove multiple elements from the set
		template<typename EType>
		void                        RemoveElements(const ElementArray<EType> & elems) const {RemoveElements(elems.data(),static_cast<enumerator>(elems.size()));}

Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1068
		/// Compute and return union with other set.
Kirill Terekhov's avatar
Kirill Terekhov committed
1069
		/// Result is unordered.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1070
		/// All elements will be unique.
Kirill Terekhov's avatar
Kirill Terekhov committed
1071
		ElementArray<Element> Union(const ElementSet & other) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1072
		/// Compute and return union with raw handles.
Kirill Terekhov's avatar
Kirill Terekhov committed
1073
		/// Result is unordered.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1074
		/// All elements will be unique.
Kirill Terekhov's avatar
Kirill Terekhov committed
1075 1076 1077 1078 1079 1080
		ElementArray<Element> Union(const HandleType * handles, enumerator num) const;
		/// Compute and return union with elements
		template<typename EType>
		ElementArray<Element> Union(const ElementArray<EType> & elems) const {return Union(elems.data(),static_cast<enumerator>(elems.size()));}

		ElementArray<Element> Difference(const ElementSet & other) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1081 1082 1083
		/// Compute and return difference with raw handles.
		/// If initial set was ordered, result will preserve the order.
		/// All elements will be unique.
Kirill Terekhov's avatar
Kirill Terekhov committed
1084 1085 1086 1087 1088 1089
		ElementArray<Element> Difference(const HandleType * handles, enumerator num) const;
		/// Compute and return difference with elements
		template<typename EType>
		ElementArray<Element> Difference(const ElementArray<EType> & elems) const {return Difference(elems.data(),static_cast<enumerator>(elems.size()));}

		ElementArray<Element> Intersection(const ElementSet & other) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1090 1091 1092
		/// Compute and return intersection with raw handles.
		/// If initial set was ordered, result will preserve the order.
		/// All elements will be unique.
Kirill Terekhov's avatar
Kirill Terekhov committed
1093
		ElementArray<Element> Intersection(const HandleType * handles, enumerator num) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1094
		/// Compute and return intersection with elements.
Kirill Terekhov's avatar
Kirill Terekhov committed
1095 1096 1097
		template<typename EType>
		ElementArray<Element> Intersection(const ElementArray<EType> & elems) const {return Intersection(elems.data(),static_cast<enumerator>(elems.size()));}
		
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1098
		/// Compute and store union with raw handles.
Kirill Terekhov's avatar
Kirill Terekhov committed
1099
		void Unite(const ElementSet & other) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1100
		/// Compute and store union with raw handles.
Kirill Terekhov's avatar
Kirill Terekhov committed
1101
		void Unite(const HandleType * handles, enumerator num) const;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1102
		/// Compute and store union with elements.
Kirill Terekhov's avatar
Kirill Terekhov committed
1103 1104 1105
		template<typename EType>
		void Unite(const ElementArray<EType> & elems) const {Unite(elems.data(),static_cast<enumerator>(elems.size()));}

1106
		/// Compute and store difference with raw handles.
1107
		/// \todo
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1108
		///   If other and current sets are sorted in same way, may perform narrowing traversal by retriving
Kirill Terekhov's avatar
Kirill Terekhov committed
1109
		///   mutual lower_bound/higher_bound O(log(n)) operations for detecting common subsets in sorted sets.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1110
		///   May work good when deleting handles by small chunks, ApplyModification may greatly benefit.
Kirill Terekhov's avatar
Kirill Terekhov committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
		void Subtract(const ElementSet & other) const;
		/// Compute and store difference with raw handles
		void Subtract(const HandleType * handles, enumerator num) const;
		/// Compute and store difference with elements
		template<typename EType>
		void Subtract(const ElementArray<EType> & elems) const {Subtract(elems.data(),static_cast<enumerator>(elems.size()));}


		/// Compute and store intersection with raw handles
		void Intersect(const ElementSet & other) const;
		/// Compute and store intersection with raw handles
		void Intersect(const HandleType * handles, enumerator num) const;
		/// Compute and store intersection with elements
		template<typename EType>
		void Intersect(const ElementArray<EType> & elems) const {Intersect(elems.data(),static_cast<enumerator>(elems.size()));}
1126
		/// Performs sort of the set of elements. If the set was previously sorted but
Kirill Terekhov's avatar
Kirill Terekhov committed
1127 1128 1129
		/// have unsorted part, then unsorted part will be sorted and two parts will be merged.
		/// If you need all the set to be resorted (for example in the case global ids were changed)
		/// then invoke SortSet with UNSORTED_COMPARATOR first and then with needed comparator.
1130
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
1131
		/// Internally it uses:
1132
		/// - std::sort with Mesh::CentroidComparator for CENTROID_COMPARATOR
Kirill Terekhov's avatar
Kirill Terekhov committed
1133
		/// - std::sort with Mesh::IerarhyComparator  for  HIERARCHY_COMPARATOR
1134 1135 1136 1137
		/// - radix sort starting from certain size for   GLOBALID_COMPARATOR
		/// - radix sort starting from certain size for     HANDLE_COMPARATOR
		/// - only changes state, no sort performed for   UNSORTED_COMPARATOR 
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
1138 1139 1140 1141 1142 1143 1144 1145 1146
		/// After the set was sorted all the invalid handles should appear at the end of the set
		/// and then removed from array, so it will implicitly work as ReorderEmpty function.
		/// No checks that elements are hidden performed (Maybe this checks should be done in comparators)
		/// In the case you formed the set by running over all mesh elements from NODE to ESET in 
		/// increasing order then your set will be automatically sorted by handles, in this case
		/// you are encouraged to override Mesh::SetComparatorTag with HANDLE_COMPARATOR on the set
		/// without invoking SortSet, so that SortSet does not redundantly perform any work.
		/// You are encouraged to do so even if you are not going to use this information -
		/// some internal algorithms may benefit from it.
1147
		///
1148
		/// \todo
Kirill Terekhov's avatar
Kirill Terekhov committed
1149 1150 1151 1152
		/// !TODO 52 - check radix sort on big endian computer
		/// @param comp one of the comparators from description
		/// @see Mesh::SetComparatorTag
		void SortSet(ComparatorType comp) const;
1153
		/// Perform binary search by global id. In set sorted with GLOBALID_COMPARATOR in O(log(n)) time
Kirill Terekhov's avatar
Kirill Terekhov committed
1154 1155
		/// otherwise search needs O(n) comparisons
		Element FindElementByGlobalID(integer global_id) const;
1156
		/// Perform binary search by centroid. In set sorted with CENTROID_COMPARATOR in O(log(n)) time
Kirill Terekhov's avatar
Kirill Terekhov committed
1157 1158
		/// otherwise search needs O(n) comparisons
		Element FindElementByCentroid(real * centroid) const;