modify.cpp 66.9 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1
#include "inmost.h"
Kirill Terekhov's avatar
Kirill Terekhov committed
2
#include "incident_matrix.hpp"
Kirill Terekhov's avatar
Kirill Terekhov committed
3 4 5 6 7 8
#if defined(USE_MESH)

//TODO:
// incident_matrix class should measure for minimal volume,
// possibly check and update from projects/OctreeCutcell/octgrid.cpp

9 10
using namespace std;

Kirill Terekhov's avatar
Kirill Terekhov committed
11 12
namespace INMOST
{
Kirill Terekhov's avatar
Kirill Terekhov committed
13

Kirill Terekhov's avatar
Kirill Terekhov committed
14
	
Kirill Terekhov's avatar
Kirill Terekhov committed
15
	void Face::SwapCells() const
Kirill Terekhov's avatar
Kirill Terekhov committed
16
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
17 18 19
		Mesh * m = GetMeshLink();
		MarkerType hm = m->HideMarker();
		adj_type & hc = m->HighConn(GetHandle());
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
20
		if( m->Count(hc.data(),static_cast<enumerator>(hc.size()),hm) == 2 )
Kirill Terekhov's avatar
Kirill Terekhov committed
21
		{
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
22 23 24
			enumerator k1 = ENUMUNDEF, k2;
			k1 = m->getNext(hc.data(),static_cast<enumerator>(hc.size()),k1,hm);
			k2 = m->getNext(hc.data(),static_cast<enumerator>(hc.size()),k1,hm);
Kirill Terekhov's avatar
Kirill Terekhov committed
25 26 27
			HandleType temp = hc[k1];
			hc[k1] = hc[k2];
			hc[k2] = temp;
Kirill Terekhov's avatar
Kirill Terekhov committed
28
			//FixNormalOrientation(); //maybe should change orientation?
Kirill Terekhov's avatar
Kirill Terekhov committed
29 30
		}
	}
31 32 33 34 35

	void Edge::SwapEnds()
	{
		Mesh * m = GetMeshLink();
		MarkerType hm = m->HideMarker();
36 37
		adj_type & lc = m->LowConn(GetHandle());
		if( m->Count(lc.data(),static_cast<enumerator>(lc.size()),hm) == 2 )
38 39
		{
			enumerator k1 = ENUMUNDEF, k2;
40 41 42 43 44 45 46 47
			k1 = m->getNext(lc.data(),static_cast<enumerator>(lc.size()),k1,hm);
			k2 = m->getNext(lc.data(),static_cast<enumerator>(lc.size()),k1,hm);
			//std::cout << "k " << k1 << " " << k2 << std::endl;
			//std::cout << "was " << lc[k1] << " " << lc[k2] << std::endl;
			HandleType temp = lc[k1];
			lc[k1] = lc[k2];
			lc[k2] = temp;
			//std::cout << "now " << lc[k1] << " " << lc[k2] << std::endl;
48 49
		}
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
50
	
Kirill Terekhov's avatar
Kirill Terekhov committed
51
	void Element::Disconnect(bool del_upper) const
Kirill Terekhov's avatar
Kirill Terekhov committed
52
	{
53
		
Kirill Terekhov's avatar
Kirill Terekhov committed
54 55
		dynarray<adj_type::size_type,64> del;
		Mesh * m = GetMeshLink();
Kirill Terekhov's avatar
Kirill Terekhov committed
56 57 58 59
		//BEGIN NEW CODE - CHECK
		//Reorder face edges, so that they always apear in right direction
		if( GetElementType() == CELL ) //This is a cell
		{
60 61
			getAsCell()->SwapBackCell();
			/*
Kirill Terekhov's avatar
Kirill Terekhov committed
62
			MarkerType hm = m->HideMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
63
			adj_type & lc = m->LowConn(GetHandle());
64
			for( adj_type::size_type it = 0; it < lc.size(); it++) //if( !m->GetMarker(lc[it],hm) ) //iterator over unhidden faces
Kirill Terekhov's avatar
Kirill Terekhov committed
65
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
66
				adj_type & hc = m->HighConn(lc[it]);
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
67
				if( !hc.empty() && m->Count(hc.data(),static_cast<enumerator>(hc.size()),hm) == 2 ) //there are two cells connected to face
Kirill Terekhov's avatar
Kirill Terekhov committed
68
				{
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
69 70
					enumerator k1 = ENUMUNDEF, k2;
					k1 = m->getNext(hc.data(),static_cast<enumerator>(hc.size()),k1,hm);
Kirill Terekhov's avatar
Kirill Terekhov committed
71
					if( hc[k1] == GetHandle() ) //the first cell is current
Kirill Terekhov's avatar
Kirill Terekhov committed
72
					{
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
73
						k2 = m->getNext(hc.data(),static_cast<enumerator>(hc.size()),k1,hm);
Kirill Terekhov's avatar
Kirill Terekhov committed
74 75 76 77
						hc[k1] = hc[k2];
						//hc[k2] = GetHandle(); //cannot use the cell because virtualization table is already destroyed and FixNormalOrientation will do bad things
						hc.resize(1); //just remove element, we will do this anyway later
						Face(m,lc[it])->FixNormalOrientation(); //restore orientation
Kirill Terekhov's avatar
Kirill Terekhov committed
78 79 80
					}
				}
			}
81
			*/
Kirill Terekhov's avatar
Kirill Terekhov committed
82 83
		}
		//END NEW CODE - CHECK
Kirill Terekhov's avatar
Kirill Terekhov committed
84
		adj_type & hc = m->HighConn(GetHandle());
85
		adj_type::size_type i = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
86
		for( adj_type::size_type it = 0; it < hc.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
87 88
		{
			int flag = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
89 90 91
			adj_type & ilc = m->LowConn(hc[it]);
			adj_type::iterator jt = ilc.begin();
			while (jt != ilc.end())
Kirill Terekhov's avatar
Kirill Terekhov committed
92
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
93
				if(*jt == GetHandle())
Kirill Terekhov's avatar
Kirill Terekhov committed
94 95
				{
					flag = 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
96
					jt = ilc.erase(jt);
Kirill Terekhov's avatar
Kirill Terekhov committed
97 98 99 100 101 102 103 104 105 106
				}
				else ++jt;
			}
			if( flag ) del.push_back(i);
			i++;
		}
		if( del_upper )
		{
			if( GetElementType() < CELL ) 
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
107 108 109
				if( Hidden() ) 
				{
					for(dynarray<adj_type::size_type,64>::iterator it = del.begin(); it != del.end(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
110
						if( m->GetMarker(hc[*it],m->HideMarker()) ) m->Delete(hc[*it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
111 112 113 114
				}
				else 
				{
					for(dynarray<adj_type::size_type,64>::iterator it = del.begin(); it != del.end(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
115
						m->Delete(hc[*it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
116
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
117 118
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
119 120 121
		hc.clear();
		adj_type & lc = m->LowConn(GetHandle());
		for(adj_type::size_type it = 0; it < lc.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
122
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
123 124 125
			adj_type & ihc = m->HighConn(lc[it]);
			adj_type::iterator jt = ihc.begin();
			while (jt != ihc.end())
Kirill Terekhov's avatar
Kirill Terekhov committed
126
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
127
				if(*jt == GetHandle()) jt = ihc.erase(jt);
Kirill Terekhov's avatar
Kirill Terekhov committed
128 129 130
				else ++jt;
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
131
		lc.clear();
Kirill Terekhov's avatar
Kirill Terekhov committed
132 133
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
134
	Cell Cell::UniteCells(const ElementArray<Cell> & unite, MarkerType del_protect)
Kirill Terekhov's avatar
Kirill Terekhov committed
135
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
136 137 138 139 140
		Mesh * m = unite.GetMeshLink();
		if( unite.empty() ) return Cell(m,InvalidHandle());
		tiny_map<HandleType, int, 64> face_visit; // we check all edges of faces, inner edges are visited several times, outer - once
		ElementArray<Face> faces(m); 
		dynarray<HandleType,64> inner_faces;
Kirill Terekhov's avatar
Kirill Terekhov committed
141
		bool doexit = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
142
		MarkerType hm = m->HideMarker();
143 144
		//Compute which faces of the provided cells lay on boundary (1 visit) and
		//inside of the set of cells (2 visits)
Kirill Terekhov's avatar
Kirill Terekhov committed
145
		for(ElementArray<Cell>::size_type j = 0; j < unite.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
146
		{
147 148
			if( unite[j]->GetMarker(del_protect) ) doexit = true;
			//access faces
Kirill Terekhov's avatar
Kirill Terekhov committed
149
			adj_type const & lc = m->LowConn(unite.at(j));
150 151
			for(adj_type::size_type it = 0; it < lc.size(); it++)
				if( !m->GetMarker(lc[it],hm) ) face_visit[lc[it]]++;
Kirill Terekhov's avatar
Kirill Terekhov committed
152
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
153
		if( doexit ) return Cell(m,InvalidHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
154
		MarkerType visited = m->CreateMarker(), rem = m->CreateMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
155 156
		dynarray<HandleType,64> edges;
		dynarray<HandleType,64> nodes;
157 158 159
		//gather boundary faces into set that will be used to create new cell
		//mark internal faces to be deleted. For internal faces find out
		//all internal edges that should be deleted as well.
Kirill Terekhov's avatar
Kirill Terekhov committed
160 161
		for(tiny_map<HandleType,int,64>::iterator it = face_visit.begin(); it != face_visit.end(); it++)
		{
162
			if( it->second == 1 ) //boundary faces, use for new cell
Kirill Terekhov's avatar
Kirill Terekhov committed
163
				faces.push_back(it->first);
164
			else //internal faces
Kirill Terekhov's avatar
Kirill Terekhov committed
165
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
166
				if( m->GetMarker(it->first,del_protect) ) doexit = true;
167
				//mark face to be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
168
				m->SetMarker(it->first,rem);
169
				//access edges of the face, gather into array
Kirill Terekhov's avatar
Kirill Terekhov committed
170 171 172
				adj_type const & lc = m->LowConn(it->first);
				for(adj_type::size_type jt = 0; jt < lc.size(); jt++) if( !m->GetMarker(lc[jt],hm) )
					if( !m->GetMarker(lc[jt],visited) )
Kirill Terekhov's avatar
Kirill Terekhov committed
173
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
174 175
						m->SetMarker(lc[jt],visited);
						edges.push_back(lc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
176
					}
177
				//gather internal faces
Kirill Terekhov's avatar
Kirill Terekhov committed
178 179
				inner_faces.push_back(it->first);
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
180
		}
181 182 183
		//for edges of internal faces gather their nodes,
		//for each edge check if all it's faces are to be deleted,
		//then the edge should be deleted, otherwise keep the edge
Kirill Terekhov's avatar
Kirill Terekhov committed
184
		for(dynarray<HandleType,64>::size_type i = 0; i < edges.size(); i++) 
Kirill Terekhov's avatar
Kirill Terekhov committed
185
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
186
			m->RemMarker(edges[i],visited);
187
			//access nodes of the edge, gather into array
Kirill Terekhov's avatar
Kirill Terekhov committed
188 189
			adj_type const & lc = m->LowConn(edges[i]);
			for(adj_type::size_type jt = 0; jt < lc.size(); jt++) if( !m->GetMarker(lc[jt],hm) )
Kirill Terekhov's avatar
Kirill Terekhov committed
190
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
191
				if( !m->GetMarker(lc[jt],visited) )
Kirill Terekhov's avatar
Kirill Terekhov committed
192
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
193 194
					m->SetMarker(lc[jt],visited);
					nodes.push_back(lc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
195 196
				}
			}
197 198
			//access faces of the edge, check is there any
			//face that would not be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
199 200 201 202 203 204
			int nonzero = 0;
			adj_type const & hc = m->HighConn(edges[i]);
			for(adj_type::size_type jt = 0; jt < hc.size(); jt++) if( !m->GetMarker(hc[jt],hm) )//iterate over faces
				if( !m->GetMarker(hc[jt],rem) ) nonzero++; // check if it is not deleted
			if( nonzero == 0 ) //all faces should be deleted, edge to remove
			{
205
				//mark edge to be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
206 207 208
				m->SetMarker(edges[i],rem);
				if( m->GetMarker(edges[i],del_protect) ) doexit = true;
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
209
		}
210 211
		//for nodes of internal faces check is there any edges
		//that should not be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
212
		for(dynarray<HandleType,64>::size_type i = 0; i < nodes.size(); i++) 
Kirill Terekhov's avatar
Kirill Terekhov committed
213
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
214
			m->RemMarker(nodes[i],visited);
215 216 217 218 219 220 221
			int nonzero = 0;
			//acces edges of the node, check is there any
			//edge that would not be deleted
			adj_type const & hc = m->HighConn(nodes[i]);
			for(adj_type::size_type jt = 0; jt < hc.size(); jt++) if( !m->GetMarker(hc[jt],hm) )
				if( !m->GetMarker(hc[jt],rem) ) nonzero++;
			if( nonzero == 0 ) //all edges should be deleted, node to remove
Kirill Terekhov's avatar
Kirill Terekhov committed
222
			{
223 224 225
				//mark node to be deleted
				m->SetMarker(nodes[i],rem);
				if( m->GetMarker(nodes[i],del_protect) ) doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
226 227 228
			}
		}
		m->ReleaseMarker(visited);
229 230
		if( doexit )
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
231 232 233
			m->RemMarkerArray(inner_faces.data(),(enumerator)inner_faces.size(),rem);
			m->RemMarkerArray(edges.data(), (enumerator)edges.size(), rem);
			m->RemMarkerArray(nodes.data(), (enumerator)nodes.size(), rem);
234 235 236
			m->ReleaseMarker(rem);
			return Cell(m,InvalidHandle());
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
237
		//delete cells
Kirill Terekhov's avatar
Kirill Terekhov committed
238
		for(ElementArray<Cell>::size_type j = 0; j < unite.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
239
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
240 241
			if( m->GetMarker(unite.at(j),del_protect) )
				std::cout << __FUNCTION__ << " deleted protected cells, united " << unite.size() << " cells " << std::endl;
242 243 244 245
			if( m->HideMarker() )
				m->Hide(unite.at(j));
			else
				m->Delete(unite.at(j));
Kirill Terekhov's avatar
Kirill Terekhov committed
246 247
		}
		//delete inner faces
Kirill Terekhov's avatar
Kirill Terekhov committed
248
		for(dynarray<HandleType,64>::size_type j = 0; j < inner_faces.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
249
		{
250 251 252 253 254 255 256 257 258 259
			if( m->GetMarker(inner_faces[j],rem) )
			{
				m->RemMarker(inner_faces[j],rem);
				if( m->GetMarker(inner_faces[j],del_protect) )
					std::cout << __FUNCTION__ << " deleted protected faces, united " << unite.size() << " cells " << std::endl;
				if( m->HideMarker() )
					m->Hide(inner_faces[j]);
				else
					m->Delete(inner_faces[j]);
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
260
		}
261 262
		//delete unused edges
		for(dynarray<HandleType,64>::size_type j = 0; j < edges.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
263
		{
264
			if( m->GetMarker(edges[j],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
265
			{
266
				m->RemMarker(edges[j],rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
267 268
				if( m->GetMarker(edges[j],del_protect) )
					std::cout << __FUNCTION__ << " deleted protected edge, united " << unite.size() << " cells " << std::endl;
269 270 271 272
				if( m->HideMarker() )
					m->Hide(edges[j]);
				else
					m->Delete(edges[j]);
Kirill Terekhov's avatar
Kirill Terekhov committed
273
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
274
		}
275 276
		//delete unused nodes
		for(dynarray<HandleType,64>::size_type j = 0; j < nodes.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
277 278
		{

279
			if( m->GetMarker(nodes[j],rem) ) //there are no edges that use this edge
Kirill Terekhov's avatar
Kirill Terekhov committed
280
			{
281
				m->RemMarker(nodes[j],rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
282 283 284 285
				// there must be no cells that use this node
				assert( m->LowConn(nodes[j]).empty() || m->Count(m->LowConn(nodes[j]).data(),static_cast<integer>(m->LowConn(nodes[j]).size()),hm) == 0 );
				if( m->GetMarker(nodes[j],del_protect) )
					std::cout << __FUNCTION__ << " deleted protected node, united " << unite.size() << " cells " << std::endl;
286 287 288 289
				if( m->HideMarker() )
					m->Hide(nodes[j]);
				else
					m->Delete(nodes[j]);
Kirill Terekhov's avatar
Kirill Terekhov committed
290 291 292 293
				//disconnect node from cell
				//we don't need this algorithm, because all dependent cells should be deleted
				//if( !nodes[j]->Hide() )
				//{					
Kirill Terekhov's avatar
Kirill Terekhov committed
294 295
					//adj_iterator it = nodes[j]->LowConn().begin();
					//while(it != nodes[j]->LowConn().end()) if( !(*it)->GetMarker(hm) ) //iterate through cells of the node
Kirill Terekhov's avatar
Kirill Terekhov committed
296
					//{
Kirill Terekhov's avatar
Kirill Terekhov committed
297 298
					//	adj_iterator jt =(*it)->HighConn().begin();
					//	while(jt != (*it)->HighConn().end() ) if( !(*jt)->GetMarker(hm) ) // iterate through nodes of the cell
Kirill Terekhov's avatar
Kirill Terekhov committed
299 300
					//	{
					//		if( *jt == nodes[j] )
Kirill Terekhov's avatar
Kirill Terekhov committed
301
					//			jt = (*it)->HighConn().erase(jt); //erase link to node
Kirill Terekhov's avatar
Kirill Terekhov committed
302 303 304 305 306 307 308 309
					//		else ++jt;
					//	}
					//  ++it;
					//}
					//nodes[j]->Disconnect();
					//nodes[j]->Delete();
				//}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
310
		}
311
		m->ReleaseMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
312
		//reconstruct cell by outer faces
Kirill Terekhov's avatar
Kirill Terekhov committed
313
		return m->CreateCell(faces).first;
Kirill Terekhov's avatar
Kirill Terekhov committed
314 315 316
	}
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
317
	bool Cell::TestUniteCells(const ElementArray<Cell> & unite, MarkerType del_protect)
Kirill Terekhov's avatar
Kirill Terekhov committed
318
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
319 320 321
		if( unite.empty() ) return false;
		Mesh * m = unite.GetMeshLink();
		tiny_map<HandleType,int,64> face_visit; // we check all edges of faces, inner edges are visited several times, outer - once
Kirill Terekhov's avatar
Kirill Terekhov committed
322
		bool doexit = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
323 324
		MarkerType hm = m->HideMarker();			
		for(ElementArray<Cell>::size_type j = 0; j < unite.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
325
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
326 327 328 329
			if( m->GetMarker(unite.at(j),del_protect) ) doexit = true; 
			adj_type const & lc = m->LowConn(unite.at(j));
			for(adj_type::size_type it = 0; it < lc.size(); it++) if( !m->GetMarker(lc[it],hm) )
				face_visit[lc[it]]++;
Kirill Terekhov's avatar
Kirill Terekhov committed
330 331
		}
		if( doexit ) return false;
Kirill Terekhov's avatar
Kirill Terekhov committed
332
		MarkerType rem = m->CreateMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
333 334 335 336
		dynarray<HandleType,64> edges;
		dynarray<HandleType,64> nodes;		
		for(tiny_map<HandleType,int,64>::iterator it = face_visit.begin(); it != face_visit.end(); it++)
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
337 338
			if( it->second != 1 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
339 340 341 342 343
				if( m->GetMarker(it->first,del_protect) ) doexit = true;
				m->SetMarker(it->first,rem);
				adj_type const & lc = m->LowConn(it->first);
				for(adj_type::size_type jt = 0; jt < lc.size(); jt++) if( !m->GetMarker(lc[jt],hm) )
					if( !m->GetMarker(lc[jt],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
344
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
345 346
						m->SetMarker(lc[jt],rem);
						edges.push_back(lc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
347 348
					}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
349 350
		}
		for(dynarray<HandleType,64>::size_type i = 0; i < edges.size(); i++) 
Kirill Terekhov's avatar
Kirill Terekhov committed
351
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
352 353 354
			m->RemMarker(edges[i],rem);
			adj_type const & lc = m->LowConn(edges[i]);
			for(adj_type::size_type jt = 0; jt < lc.size(); jt++) if( !m->GetMarker(lc[jt],hm) )
Kirill Terekhov's avatar
Kirill Terekhov committed
355
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
356
				if( !m->GetMarker(lc[jt],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
357
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
358 359
					m->SetMarker(lc[jt],rem);
					nodes.push_back(lc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
360 361
				}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
362
			int nonzero = 0;
363 364
			//access faces of the edge, check is there any
			//that would not be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
365 366 367
			adj_type const & hc = m->HighConn(edges[i]);
			for(adj_type::size_type jt = 0; jt < hc.size(); jt++) if( !m->GetMarker(hc[jt],hm) ) //iterate over faces
				if( !m->GetMarker(hc[jt],rem) ) nonzero++; // check if it is not deleted
368 369 370
			//all faces should be deleted, edge to remove
			if( nonzero == 0 && m->GetMarker(edges[i],del_protect) )
				doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
371
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
372
		for(dynarray<HandleType,64>::size_type i = 0; i < nodes.size(); i++) 
Kirill Terekhov's avatar
Kirill Terekhov committed
373
		{
374 375 376 377 378 379 380 381 382
			int nonzero = 0;
			//access edges of the node, check is there
			//any that would not be deleted
			adj_type const & hc = m->HighConn(nodes[i]);
			for(adj_type::size_type jt = 0; jt < hc.size(); jt++) if( !m->GetMarker(hc[jt],hm) )
				if( !m->GetMarker(hc[jt],rem) ) nonzero++;
			//all edges should be deleted, node to remove
			if( nonzero == 0 && m->GetMarker(edges[i],del_protect) )
				doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
383
		}
384
		for(tiny_map<HandleType,int,64>::iterator it = face_visit.begin(); it != face_visit.end(); it++) m->RemMarker(it->first,rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
385 386
		m->RemMarkerArray(edges.data(), (enumerator)edges.size(),rem);
		m->RemMarkerArray(nodes.data(), (enumerator)nodes.size(), rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
387 388 389 390 391 392
		m->ReleaseMarker(rem);
		if( doexit ) return false;
		return true;
	}
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
393
	Face Face::UniteFaces(const ElementArray<Face> & unite, MarkerType del_protect)
Kirill Terekhov's avatar
Kirill Terekhov committed
394
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
395
		Mesh * m = const_cast<Mesh *>(unite.GetMeshLink());
396
		assert(m != NULL);
Kirill Terekhov's avatar
Kirill Terekhov committed
397
		if( unite.empty() ) return Face(m,InvalidHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
398
		MarkerType hm = m->HideMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
399
		bool doexit = false, dothrow = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
400 401 402
		for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
			if( m->GetMarker(unite.at(j),del_protect) ) doexit = true;
		if( doexit ) return Face(m,InvalidHandle());
403
		dynarray<HandleType,64> cells;
Kirill Terekhov's avatar
Kirill Terekhov committed
404 405
		MarkerType edge_set = m->CreateMarker();
		MarkerType rem = m->CreateMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
406
		
407
		//gather cells adjacent to united faces
Kirill Terekhov's avatar
Kirill Terekhov committed
408 409 410 411 412 413
		for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
		{
			adj_type const & hc = m->HighConn(unite.at(j));
			for(adj_type::size_type it = 0; it < hc.size(); it++) if( !m->GetMarker(hc[it],hm) )
			{
				if( !m->GetMarker(hc[it],edge_set) )
Kirill Terekhov's avatar
Kirill Terekhov committed
414
				{
415
					cells.push_back(hc[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
416
					m->SetMarker(hc[it],edge_set);
Kirill Terekhov's avatar
Kirill Terekhov committed
417
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
418
			}
419
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
420
		m->RemMarkerArray(cells.data(), (enumerator)cells.size(), edge_set);
421 422 423 424
		assert(cells.size() <= 2);
		//check is there a topological problem
		//new face should be adjacent to no more then two cells
		if( m->GetTopologyCheck(TRIPLE_SHARED_FACE) && cells.size() > 2 )
Kirill Terekhov's avatar
Kirill Terekhov committed
425 426 427 428 429 430
		{
			m->SetTopologyError(TRIPLE_SHARED_FACE);
			if( m->GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(TRIPLE_SHARED_FACE) << std::endl;
			if( m->GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
		}
		
Kirill Terekhov's avatar
Kirill Terekhov committed
431 432 433
		dynarray<HandleType,64> nodes;
		tiny_map<HandleType, int,64> edge_visit;
		ElementArray<Edge> edges(m);
434
		//compute how many times each edge is visited
Kirill Terekhov's avatar
Kirill Terekhov committed
435
		for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
436
		{
437
			//access edges of the face
Kirill Terekhov's avatar
Kirill Terekhov committed
438
			adj_type const & lc = m->LowConn(unite.at(j));
439 440
			for(adj_type::size_type it = 0; it < lc.size(); it++)
				if( !m->GetMarker(lc[it],hm) ) edge_visit[lc[it]]++;
Kirill Terekhov's avatar
Kirill Terekhov committed
441
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
442 443
		HandleType first = InvalidHandle(); //first edge
		HandleType prev = InvalidHandle(); //prev node
444 445 446
		//Mark all the edges on boundary to recreate the face,
		//assemble set of nodes
		int expect_q = 0; //used to test for consistency of the loop of edges
Kirill Terekhov's avatar
Kirill Terekhov committed
447
		for(tiny_map<HandleType,int,64>::iterator it = edge_visit.begin(); it != edge_visit.end(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
448 449 450
		{
			if( it->second == 1 )
			{
451
				expect_q++;
Kirill Terekhov's avatar
Kirill Terekhov committed
452 453
				m->SetMarker(it->first,edge_set);
				if( first == InvalidHandle() ) first = it->first;
Kirill Terekhov's avatar
Kirill Terekhov committed
454 455 456
			}
			else if( it->second == 2 )
			{
457 458 459
				//edge is protected
				if( m->GetMarker(it->first,del_protect) ) doexit = true;
				//mark edge to be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
460
				m->SetMarker(it->first,rem);
461
				//access nodes of the edge
Kirill Terekhov's avatar
Kirill Terekhov committed
462 463 464 465
				adj_type const & lc = m->LowConn(it->first);
				for(adj_type::size_type jt = 0; jt < lc.size(); jt++) if( !m->GetMarker(lc[jt],hm) )
				{
					if( !m->GetMarker(lc[jt],edge_set) )
Kirill Terekhov's avatar
Kirill Terekhov committed
466
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
467 468
						m->SetMarker(lc[jt],edge_set);
						nodes.push_back(lc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
469
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
470
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
471 472 473 474 475 476 477
			}
			else 
			{
				doexit = true; //the faces we unite would not appear as one surface
				dothrow = true;
			}
		}
478
		//Find out set of nodes to be deleted
Kirill Terekhov's avatar
Kirill Terekhov committed
479
		for(dynarray<HandleType,64>::size_type j = 0; j < nodes.size(); j++) 
Kirill Terekhov's avatar
Kirill Terekhov committed
480
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
481
			m->RemMarker(nodes[j],edge_set);
482 483 484 485 486 487 488
			int nonzero = 0;
			//access edges of the nodes, find out whether all
			//of them are deleted
			adj_type const & hc = m->HighConn(nodes[j]);
			for(adj_type::size_type it = 0; it < hc.size(); it++) if( !m->GetMarker(hc[it],hm) ) //iterate through edges of the node
				if( !m->GetMarker(hc[it],rem) ) nonzero++; // check if edge should not be deleted
			if( nonzero == 0 ) //all edges are deleted but the node is protected
Kirill Terekhov's avatar
Kirill Terekhov committed
489
			{
490 491
				m->SetMarker(nodes[j],rem);
				if( m->GetMarker(nodes[j],del_protect) ) doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
492 493 494 495 496
			}
		}
			
		if( doexit )
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
497 498
			for(tiny_map<HandleType,int,64>::iterator it = edge_visit.begin(); it != edge_visit.end(); it++)
			{
499 500 501
				m->RemMarker(it->first,rem);
				m->RemMarker(it->first,edge_set);
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
502
			m->RemMarkerArray(nodes.data(), (enumerator)nodes.size(), rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
503 504
			m->ReleaseMarker(edge_set);
			m->ReleaseMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
505 506
			assert( !dothrow ); //report the situation, because user need to debug the input
			return Face(m,InvalidHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
507
		}
508
		//Order edges on the boundary of united faces into loop
Kirill Terekhov's avatar
Kirill Terekhov committed
509 510 511
		edges.push_back(first);
		edges.back()->RemMarker(edge_set);
		bool done = false;
512
		int q = 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
513 514
		while( !done )
		{
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
515
			enumerator k1 = ENUMUNDEF,k2;
516
			//access nodes of the last pushed edge
Kirill Terekhov's avatar
Kirill Terekhov committed
517
			adj_type const & lc = m->LowConn(edges.atback());
518
			//find out first node
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
519
			k1 = m->getNext(lc.data(),static_cast<enumerator>(lc.size()),k1,hm);
520
			//find out second node
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
521
			k2 = m->getNext(lc.data(),static_cast<enumerator>(lc.size()),k1,hm);
522 523
			//find out which of the nodes should connect to the next edge
			//at the begining we can select any of the two
Kirill Terekhov's avatar
Kirill Terekhov committed
524 525
			if( lc[k1] != prev ) 
				prev = lc[k1]; 
Kirill Terekhov's avatar
Kirill Terekhov committed
526
			else 
Kirill Terekhov's avatar
Kirill Terekhov committed
527
				prev = lc[k2];
528 529
			//find out the next edge connected to the privious node
			bool found = false; //detect that edge was found, otherwise there is no loop
Kirill Terekhov's avatar
Kirill Terekhov committed
530 531
			adj_type const & hc = m->HighConn(prev);
			for(adj_type::size_type it = 0; it < hc.size(); ++it) if( !m->GetMarker(hc[it],hm) )
Kirill Terekhov's avatar
Kirill Terekhov committed
532
			{
533 534
				//we came back to the first edge, the loop is closed
				if( hc[it] == first && q != 1)
Kirill Terekhov's avatar
Kirill Terekhov committed
535 536 537 538
				{
					found = done = true;
					break;
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
539
				if( m->GetMarker(hc[it],edge_set) )
Kirill Terekhov's avatar
Kirill Terekhov committed
540 541 542
				{
					q++;
					found = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
543 544
					edges.push_back(hc[it]);
					m->RemMarker(hc[it],edge_set);
Kirill Terekhov's avatar
Kirill Terekhov committed
545 546 547
					break;
				}
			}
548
			assert(found); //there is no loop
Kirill Terekhov's avatar
Kirill Terekhov committed
549
			//if( !found ) throw Failure;
Kirill Terekhov's avatar
Kirill Terekhov committed
550 551 552
		}
		m->ReleaseMarker(edge_set);
		
553 554
		//number of edges collected matches number of edges expected
		assert(expect_q == q);
Kirill Terekhov's avatar
Kirill Terekhov committed
555 556 557 558
		

		
		
Kirill Terekhov's avatar
Kirill Terekhov committed
559 560
		if( !m->HideMarker() ) //we can't hide elements
		{
561 562 563
			unite.SetMarker(rem);
			//untie every face from the cell
			for(dynarray<HandleType,64>::size_type it = 0; it < cells.size(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
564
			{
565
				adj_type & lc = m->LowConn(cells[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
566 567 568 569
				adj_type::iterator jt = lc.begin();
				while( jt != lc.end()) //don't need to check is it hidden
					if( m->GetMarker(*jt,rem) )
						jt = lc.erase(jt);
Kirill Terekhov's avatar
Kirill Terekhov committed
570 571
					else jt++;
			}
572
			unite.RemMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
573
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
574
		
575
		//delete old faces
Kirill Terekhov's avatar
Kirill Terekhov committed
576
		if( m->HideMarker() )
577 578
			for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
				m->Hide(unite.at(j));
Kirill Terekhov's avatar
Kirill Terekhov committed
579
		else
Kirill Terekhov's avatar
Kirill Terekhov committed
580
		{
581 582
			// delete all faces
			for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
583
			{
584 585
				//untie cells from face
				m->HighConn(unite.at(j)).clear();
Kirill Terekhov's avatar
Kirill Terekhov committed
586 587 588
				if( m->GetMarker(unite.at(j),del_protect) )
					std::cout << __FUNCTION__ << " deleted protected face, united " << unite.size() << " faces " << std::endl;
				m->Delete(unite.at(j)); 
Kirill Terekhov's avatar
Kirill Terekhov committed
589 590
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
591 592

		for(tiny_map<HandleType,int,64>::iterator it = edge_visit.begin(); it != edge_visit.end(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
593 594
			if( it->second != 1 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
595 596 597 598
				m->RemMarker(it->first,rem);
				assert( m->HighConn(it->first).empty() || m->Count(m->HighConn(it->first).data(),static_cast<integer>(m->HighConn(it->first).size()),hm) == 0 ); //it's connected to face somewhere
				if( m->GetMarker(it->first,del_protect) )
					std::cout << __FUNCTION__ << " deleted protected edge, united " << unite.size() << " faces " << std::endl;
599 600 601 602
				if( m->HideMarker() )
					m->Hide(it->first);
				else
					m->Delete(it->first);
Kirill Terekhov's avatar
Kirill Terekhov committed
603 604
			}
			
605
		
Kirill Terekhov's avatar
Kirill Terekhov committed
606

Kirill Terekhov's avatar
Kirill Terekhov committed
607
		for(dynarray<HandleType,64>::size_type it = 0; it < nodes.size(); it++) //delete nodes inside the face
Kirill Terekhov's avatar
Kirill Terekhov committed
608
		{
609
			//adj_type const & hc = m->HighConn(nodes[it]);
610
			if( m->GetMarker(nodes[it],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
611
			{
612 613 614
				assert( m->HighConn(nodes[it]).empty() || m->Count(m->HighConn(nodes[it]).data(),static_cast<integer>(m->HighConn(nodes[it]).size()),hm) == 0 );
				m->RemMarker(nodes[it],rem);
				if( !m->HideMarker() )
Kirill Terekhov's avatar
Kirill Terekhov committed
615
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
616 617 618
					adj_type & lc = m->LowConn(nodes[it]);
					adj_type::iterator jt = lc.begin();
					while(jt != lc.end() ) // iterate through cells of the node
Kirill Terekhov's avatar
Kirill Terekhov committed
619
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
620 621 622
						adj_type & ihc = m->HighConn(*jt);
						adj_type::iterator qt = ihc.begin(); //iterate through nodes of the cell
						while( qt != ihc.end() )
Kirill Terekhov's avatar
Kirill Terekhov committed
623
						{
Kirill Terekhov's avatar
Kirill Terekhov committed
624 625
							if( *qt == nodes[it] ) 
								qt = ihc.erase(qt); //remove links from the cell to the node
Kirill Terekhov's avatar
Kirill Terekhov committed
626 627 628 629
							else ++qt;
						}
						++jt;
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
630 631 632 633
					lc.clear(); // remove links to cells
					if( m->GetMarker(nodes[it],del_protect) )
						std::cout << __FUNCTION__ << " deleted protected node, united " << unite.size() << " faces " << std::endl;
					m->Destroy(nodes[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
634
				}
635
				else m->Hide(nodes[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
636 637
			}
		}
638 639
		
		m->ReleaseMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
640
				
Kirill Terekhov's avatar
Kirill Terekhov committed
641
		Face ret = m->CreateFace(edges).first;
Kirill Terekhov's avatar
Kirill Terekhov committed
642
		
643
		
Kirill Terekhov's avatar
Kirill Terekhov committed
644
		assert( ret->GetGeometricType() != MultiLine );
Kirill Terekhov's avatar
Kirill Terekhov committed
645
		
646
		
Kirill Terekhov's avatar
Kirill Terekhov committed
647
		adj_type & hc = m->HighConn(ret->GetHandle());
648
		for(dynarray<HandleType,64>::size_type it = 0; it < cells.size(); it++)  //tie new face to old cells
Kirill Terekhov's avatar
Kirill Terekhov committed
649
		{
650 651
			hc.push_back(cells[it]); // connect new face to cells
			m->LowConn(cells[it]).push_back(ret.GetHandle()); // connect cells to new face
Kirill Terekhov's avatar
Kirill Terekhov committed
652 653
			
		}
654 655 656
		
		
		for(dynarray<HandleType,64>::size_type it = 0; it < cells.size(); it++)  //tie new face to old cells
Kirill Terekhov's avatar
Kirill Terekhov committed
657
		{
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
			assert(m->Count(m->LowConn(cells[it]).data(),m->LowConn(cells[it]).size(),hm) >= 4);
			//compute geometric data
			m->ComputeGeometricType(cells[it]);
			assert(m->GetGeometricType(cells[it]) != MultiPolygon);
			//change nodes of the cell according to ordering
			ElementArray<Node> nodes(m);
			m->RestoreCellNodes(cells[it],nodes);
			adj_type & hc = m->HighConn(cells[it]);
			assert(nodes.size() == m->Count(hc.data(),hc.size(),hm));
			//should keep hidden nodes of the cell
			//todo: think about how we should order them
			for(adj_type::size_type k = 0; k < hc.size(); ++k)
				if( m->Hidden(hc[k]) ) nodes.push_back(hc[k]);
			hc.replace(hc.begin(),hc.end(),nodes.begin(),nodes.end());
			//recompute geometric data
			m->RecomputeGeometricData(cells[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
674 675 676 677 678 679
		}
		
		return ret;
	}
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
680
	bool Face::TestUniteFaces(const ElementArray<Face> & unite, MarkerType del_protect)
Kirill Terekhov's avatar
Kirill Terekhov committed
681
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
682
		Mesh * m = const_cast<Mesh *>(unite.GetMeshLink());
Kirill Terekhov's avatar
Kirill Terekhov committed
683
		if( unite.size() == 0 ) return false;
Kirill Terekhov's avatar
Kirill Terekhov committed
684
		bool doexit = false, dothrow = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
685 686
		for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
			if( m->GetMarker(unite.at(j),del_protect) ) doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
687
		MarkerType hm = m->HideMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
688
		if( doexit ) return false;
689
		dynarray<HandleType,64> cells;
Kirill Terekhov's avatar
Kirill Terekhov committed
690
		MarkerType rem = m->CreateMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
691 692 693 694 695
		for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
		{
			adj_type const & hc = m->HighConn(unite.at(j));
			for(adj_type::size_type it = 0; it < hc.size(); it++) if( !m->GetMarker(hc[it],hm) )
				if( !m->GetMarker(hc[it],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
696
				{
697
					cells.push_back(hc[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
698
					m->SetMarker(hc[it],rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
699
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
700
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
701
		m->RemMarkerArray(cells.data(), (enumerator)cells.size(), rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
702 703 704
		dynarray<HandleType,64> nodes;
		tiny_map<HandleType, int,64> edge_visit;
		for(ElementArray<Face>::size_type j = 0; j < unite.size(); j++)
Kirill Terekhov's avatar
Kirill Terekhov committed
705
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
706 707 708
			adj_type const & lc = m->LowConn(unite.at(j));
			for(adj_type::size_type it = 0; it < lc.size(); it++) if( !m->GetMarker(lc[it],hm) )
				edge_visit[lc[it]]++;
Kirill Terekhov's avatar
Kirill Terekhov committed
709
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
710
		for(tiny_map<HandleType,int,64>::iterator it = edge_visit.begin(); it != edge_visit.end(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
711 712 713
		{
			if( it->second == 2 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
714 715 716 717 718 719
				if( m->GetMarker(it->first,del_protect) ) doexit = true; // edge is protected
				m->SetMarker(it->first,rem);
				adj_type const & lc = m->LowConn(it->first);
				for(adj_type::size_type jt = 0; jt < lc.size(); jt++) if( !m->GetMarker(lc[jt],hm) )
				{
					if( !m->GetMarker(lc[jt],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
720
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
721 722
						m->SetMarker(lc[jt],rem);
						nodes.push_back(lc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
723
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
724
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
725 726 727 728 729 730 731
			}
			else if( it->second != 1 )
			{
				doexit = true;
				dothrow = true;
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
732
		for(dynarray<HandleType,64>::size_type j = 0; j < nodes.size(); j++) 
Kirill Terekhov's avatar
Kirill Terekhov committed
733
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
734
			m->RemMarker(nodes[j],rem);
735 736 737 738 739 740
			int nonzero = 0;
			adj_type const & hc = m->HighConn(nodes[j]);
			for(adj_type::size_type it = 0; it < hc.size(); it++) if( !m->GetMarker(hc[it],hm) )//iterate through edges of the node
				if( !m->GetMarker(hc[it],rem) ) nonzero++; // check if edge should not be deleted
			//all edges are deleted but the node is protected
			if( nonzero == 0 && m->GetMarker(nodes[j],del_protect)) doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
741
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
742 743
		for(tiny_map<HandleType,int,64>::iterator it = edge_visit.begin(); it != edge_visit.end(); it++)
			if( it->second != 1 ) m->RemMarker(it->first,rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
744 745 746
		m->ReleaseMarker(rem);
		if( doexit )
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
747 748
			assert(!dothrow);
			//if( dothrow ) throw Impossible; //something went the way it shouldn't, possibly bad input
Kirill Terekhov's avatar
Kirill Terekhov committed
749 750 751 752 753
			return false;
		}
		return true;
	}

Kirill Terekhov's avatar
Kirill Terekhov committed
754
	Edge Edge::UniteEdges(const ElementArray<Edge> & edges, MarkerType del_protect)
Kirill Terekhov's avatar
Kirill Terekhov committed
755
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
756
		Mesh * m = const_cast<Mesh *>(edges.GetMeshLink());
Kirill Terekhov's avatar
Kirill Terekhov committed
757 758
		if( edges.size() == 0 ) return Edge(m,InvalidHandle());
		
Kirill Terekhov's avatar
Kirill Terekhov committed
759
		bool doexit = false, dothrow = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
760 761
		MarkerType hm = m->HideMarker();
		MarkerType rem = m->CreateMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
762
		dynarray<HandleType,64> cells;
763
		dynarray<HandleType,64> faces;
Kirill Terekhov's avatar
Kirill Terekhov committed
764 765 766
		tiny_map<HandleType,int,64> nodes;
		ElementArray<Node> build_nodes(m);
		for(ElementArray<Edge>::size_type it = 0; it < edges.size(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
767
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
768
			if( m->GetMarker(edges.at(it),del_protect) )
Kirill Terekhov's avatar
Kirill Terekhov committed
769
				doexit = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
770 771
			adj_type const & hc = m->HighConn(edges.at(it));
			for(adj_type::size_type jt = 0; jt != hc.size(); ++jt) if( !m->GetMarker(hc[jt],hm) )
Kirill Terekhov's avatar
Kirill Terekhov committed
772
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
773
				if( !m->GetMarker(hc[jt],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
774
				{
775
					faces.push_back(hc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
776
					m->SetMarker(hc[jt],rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
777 778
				}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
779 780 781
			adj_type const & lc = m->LowConn(edges.at(it));
			for(adj_type::size_type jt = 0; jt < lc.size(); ++jt) if( !m->GetMarker(lc[jt],hm) )
				nodes[lc[jt]]++;
Kirill Terekhov's avatar
Kirill Terekhov committed
782 783
		}
		
784
		for(dynarray<HandleType,64>::size_type it = 0; it < faces.size(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
785
		{
786 787
			m->RemMarker(faces[it],rem);
			adj_type const & hc = m->HighConn(faces[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
788 789 790
			for(adj_type::size_type jt = 0; jt < hc.size(); ++jt)
			{
				if( !m->GetMarker(hc[jt],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
791
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
792 793
					m->SetMarker(hc[jt],rem);
					cells.push_back(hc[jt]);
Kirill Terekhov's avatar
Kirill Terekhov committed
794
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
795
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
796
		}
797
		
Kirill Terekhov's avatar
Kirill Terekhov committed
798
		m->RemMarkerArray(cells.data(), (enumerator)cells.size(), rem);
799 800
		
		
Kirill Terekhov's avatar
Kirill Terekhov committed
801 802 803 804

		if( doexit )
		{
			m->ReleaseMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
805
			return Edge(m,InvalidHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
806 807
		}
		
Kirill Terekhov's avatar
Kirill Terekhov committed
808
		for(tiny_map<HandleType,int,64>::iterator it = nodes.begin(); it != nodes.end(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
809
		{
810
			
Kirill Terekhov's avatar
Kirill Terekhov committed
811 812 813 814
			if( it->second == 1 )
				build_nodes.push_back(it->first);
			else if( it->second == 2 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
815
				if( m->GetMarker(it->first,del_protect) )
Kirill Terekhov's avatar
Kirill Terekhov committed
816 817 818 819
					doexit = true;
			}
			else 
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
820
				doexit = true; //edges have some loop
Kirill Terekhov's avatar
Kirill Terekhov committed
821 822 823
				dothrow = true;
			}
		}
824 825 826
		
		
		assert(build_nodes.size() == 2);
Kirill Terekhov's avatar
Kirill Terekhov committed
827 828 829 830

		if( doexit )
		{
			m->ReleaseMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
831 832 833
			assert(!dothrow);
			//if( dothrow ) throw Impossible; // bad input
			return Edge(m,InvalidHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
834 835 836
		}


Kirill Terekhov's avatar
Kirill Terekhov committed
837
		dynarray<adj_type::size_type,64> insert_pos; //position where we insert new edge
Kirill Terekhov's avatar
Kirill Terekhov committed
838

839 840
		for(ElementArray<Edge>::size_type it = 0; it < edges.size(); ++it)
			m->SetMarker(edges.at(it),rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
841

842
		for(dynarray<HandleType,64>::size_type it = 0; it < faces.size(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
843
		{
844 845
			adj_type const & lc = m->LowConn(faces[it]); //edges of face
			bool found_rem = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
846 847 848
			for(adj_type::size_type k = 0; k < lc.size(); k++) //insert new edge to the first position where we delete old edge
			{
				if( m->GetMarker(lc[k],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
849 850
				{
					//all united edges should appear in consecutive order in deleted face
Kirill Terekhov's avatar
Kirill Terekhov committed
851
					/*
Kirill Terekhov's avatar
Kirill Terekhov committed
852
					adj_type::size_type sum = 0, j = k;
Kirill Terekhov's avatar
Kirill Terekhov committed
853
					while( j < lc.size() && !m->GetMarker(lc[j],hm) && m->GetMarker(lc[j],rem) )
Kirill Terekhov's avatar
Kirill Terekhov committed
854 855 856
					{
						sum++; j++;
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
857
					if( sum != static_cast<adj_type::size_type>(edges.size()) ) //not all edges belong to current face - face will be broken!
Kirill Terekhov's avatar
Kirill Terekhov committed
858 859 860 861
					{
						doexit = true;
						dothrow = true;
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
862
					 */
Kirill Terekhov's avatar
Kirill Terekhov committed
863
					insert_pos.push_back(k);
864
					found_rem = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
865 866
					break;
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
867
			}
868 869 870 871 872
			if( !found_rem )
			{
				doexit = true;
				dothrow = true;
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
873
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
874 875 876

		if( doexit )
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
877
			m->RemMarkerArray(edges.data(), (enumerator)edges.size(), rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
878
			m->ReleaseMarker(rem);
Kirill Terekhov's avatar
Kirill Terekhov committed
879 880 881
			assert(!dothrow);
			//if( dothrow ) throw Impossible; // bad input
			return Edge(m,InvalidHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
882 883
		}

Kirill Terekhov's avatar
Kirill Terekhov committed
884
		if( !m->HideMarker() ) //disconnect if cannot hide
Kirill Terekhov's avatar
Kirill Terekhov committed
885
		{
886
			for(dynarray<HandleType,64>::size_type it = 0; it < faces.size(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
887
			{
888
				adj_type & lc = m->LowConn(faces[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
889 890
				adj_iterator jt = lc.begin(); //iterate over edges of faces
				while( jt != lc.end())
Kirill Terekhov's avatar
Kirill Terekhov committed
891
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
892 893
					if( m->GetMarker(*jt,rem) )
						jt = lc.erase(jt);
Kirill Terekhov's avatar
Kirill Terekhov committed
894 895 896 897 898 899
					else ++jt;
				}
			}
		}


Kirill Terekhov's avatar
Kirill Terekhov committed
900
		for(ElementArray<Edge>::size_type it = 0; it < edges.size(); ++it)//delete edges
Kirill Terekhov's avatar
Kirill Terekhov committed
901
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
902 903
			m->RemMarker(edges.at(it),rem);
			if( !m->Hide(edges.at(it)) ) //cannot hide
Kirill Terekhov's avatar
Kirill Terekhov committed
904
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
905 906
				m->HighConn(edges.at(it)).clear(); //remove connection from edge to faces
				m->Destroy(edges.at(it));
Kirill Terekhov's avatar
Kirill Terekhov committed
907 908 909 910 911
			}
		}

		m->ReleaseMarker(rem);

Kirill Terekhov's avatar
Kirill Terekhov committed
912 913
		for(tiny_map<HandleType,int,64>::iterator it = nodes.begin(); it != nodes.end(); it++)
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
914 915
			if( it->second != 1 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
916
				if( !m->Hide(it->first) ) //cannot hide, we have to untie cells from nodes
Kirill Terekhov's avatar
Kirill Terekhov committed
917
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
918 919
					adj_type & lc = m->LowConn(it->first);
					for(adj_type::size_type qt = 0; qt < lc.size(); ++qt) //iterate through cells of the node
Kirill Terekhov's avatar
Kirill Terekhov committed
920
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
921 922 923
						adj_type & hc = m->HighConn(lc[qt]);
						adj_iterator jt = hc.begin();
						while(jt != hc.end() ) // iterate through nodes of the cell
Kirill Terekhov's avatar
Kirill Terekhov committed
924 925
						{
							if( *jt == it->first )
926
							{
Kirill Terekhov's avatar
Kirill Terekhov committed
927
								jt = hc.erase(jt); //erase link to node
928
							}
Kirill Terekhov's avatar
Kirill Terekhov committed
929 930 931
							else ++jt;
						}
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
932
					m->Destroy(it->first);
Kirill Terekhov's avatar
Kirill Terekhov committed
933 934
				}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
935 936 937 938
		}
			
		Edge e = m->CreateEdge(build_nodes).first;
		adj_type & ehc = m->HighConn(e->GetHandle());
Kirill Terekhov's avatar
Kirill Terekhov committed
939

Kirill Terekhov's avatar
Kirill Terekhov committed
940
		for(dynarray<adj_type::size_type,64>::size_type k = 0; k < insert_pos.size(); k++)
Kirill Terekhov's avatar
Kirill Terekhov committed
941
		{
942
			adj_type & lc = m->LowConn(faces[k]);
Kirill Terekhov's avatar
Kirill Terekhov committed
943
			lc.insert(lc.begin()+insert_pos[k],e->GetHandle());
944 945 946
			ehc.push_back(faces[k]);
			m->ComputeGeometricType(faces[k]);
			m->RecomputeGeometricData(faces[k]);
Kirill Terekhov's avatar
Kirill Terekhov committed
947 948
		}

Kirill Terekhov's avatar
Kirill Terekhov committed
949
		for(dynarray<HandleType,64>::size_type it = 0; it < cells.size(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
950
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
951
			m->ComputeGeometricType(cells[it]);
952 953 954 955 956 957 958 959 960 961 962
			//change nodes of the cell according to ordering
			ElementArray<Node> nodes(m);
			m->RestoreCellNodes(cells[it],nodes);
			adj_type & hc = m->HighConn(cells[it]);
			assert(nodes.size() == m->Count(hc.data(),hc.size(),hm));
			//should keep hidden nodes of the cell
			//todo: think about how we should order them
			for(adj_type::size_type k = 0; k < hc.size(); ++k)
				if( m->Hidden(hc[k]) ) nodes.push_back(hc[k]);
			hc.replace(hc.begin(),hc.end(),nodes.begin(),nodes.end());
			//update centroid, volume, orientation, etc
Kirill Terekhov's avatar
Kirill Terekhov committed
963
			m->RecomputeGeometricData(cells[it]);
Kirill Terekhov's avatar
Kirill Terekhov committed
964
		}
965 966
		
		
Kirill Terekhov's avatar
Kirill Terekhov committed
967 968 969

		return e;
	}