rsvs3D  0.0.0
Codes for the c++ implementation of the 3D RSVS
snakeengine.cpp
1 #include "snakeengine.hpp"
2 
3 #include <cmath>
4 #include <ctime>
5 #include <iostream>
6 #include <unordered_map>
7 #include <vector>
8 
9 #include "mesh.hpp"
10 #include "snake.hpp"
11 #include "warning.hpp"
12 
13 using namespace std;
14 
15 void ConnecRemv::disp()
16 {
17  cout << "connrmv: ki " << keepind << " | tobj " << typeobj << " | rmvind ";
18  DisplayVector(rmvind);
19  cout << endl;
20 }
21 
22 // Snake Spawning at Vertex.
23 void SpawnAtVertex(snake &snakein, int indVert)
24 {
25  snake newsnake;
26  int subVert, nVert, nEdge, nSurf, nVolu;
27  bool is3D;
28  vector<int> edgeInds, surfInds, voluInds;
29  vector<int> edgeSubs, surfSubs, voluSubs;
30  // vector<int> vertSubsTemp,edgeSubsTemp,surfSubsTemp,voluSubsTemp;
31  // vector<int>::iterator itVecInt;
32  unordered_multimap<int, int> hashEdgeInds, hashVoluInds, hashSurfInds;
33 
34  is3D = snakein.snakemesh()->volus.size() > 0;
35  // Extract Data corresponding to vertex from Mesh
36  subVert = snakein.snakemesh()->verts.find(indVert);
37 
38  edgeInds = snakein.snakemesh()->verts(subVert)->edgeind;
39  edgeSubs = snakein.snakemesh()->edges.find_list(edgeInds);
40  surfInds = ConcatenateVectorField(snakein.snakemesh()->edges, &edge::surfind, edgeSubs);
41  sort(surfInds);
42  unique(surfInds);
43 
44  surfSubs = snakein.snakemesh()->surfs.find_list(surfInds);
45  voluInds = ConcatenateVectorField(snakein.snakemesh()->surfs, &surf::voluind, surfSubs);
46  sort(voluInds);
47  unique(voluInds);
48  if (is3D)
49  {
50  voluSubs = snakein.snakemesh()->volus.find_list(voluInds);
51  }
52  else
53  {
54  voluSubs = snakein.snakemesh()->volus.find_list(voluInds);
55  }
56  // OperArrayStructMethod(snakein.snakemesh()->surfs, surfSubs, &surf::isready,
57  // ii, std::logical_and<bool>());
58  nVert = edgeInds.size();
59  nEdge = surfInds.size();
60  nSurf = voluInds.size();
61  nVolu = int(is3D);
62 
63  newsnake.Init(snakein.snakemesh(), nVert, nEdge, nSurf, nVolu);
64  newsnake.VertIsIn(indVert);
65  // Generates snaxels and vertices
66  SpawnAtVertexVert(newsnake, nVert, indVert, subVert, surfInds, edgeInds, edgeSubs, hashSurfInds);
67  // Generate snake edges
68  SpawnAtVertexEdge(newsnake, nEdge, surfInds, edgeInds, voluInds, surfSubs, hashEdgeInds, hashVoluInds);
69  // Generate Snake surfaces
70  if (is3D)
71  {
72  SpawnAtVertexSurf3D(newsnake, nSurf, surfInds, voluInds, voluSubs, hashSurfInds);
73  // Generate Volume
74  SpawnAtVertexVolu(newsnake, nSurf);
75  }
76  else
77  {
78  SpawnAtVertexSurf2D(newsnake, nEdge, voluInds);
79  }
80 
81  snakein.SetMaxIndexNM();
82 
83  snakein.MakeCompatible_inplace(newsnake);
84 
85  // DO NOT RUN TO MAITAIN orederedge newsnake.PrepareForUse();
86  snakein.Concatenate(newsnake);
87 }
88 
89 void SpawnAtVertexVert(snake &newsnake, int nVert, int indVert, int subVert, const vector<int> &surfInds,
90  const vector<int> &edgeInds, const vector<int> &edgeSubs,
91  unordered_multimap<int, int> &hashSurfInds)
92 {
93  int ii, jj;
94  vector<int> edgeSubsTemp;
95 
96  newsnake.snakeconn.verts.PopulateIndices();
97  newsnake.snaxs.PopulateIndices();
98  for (ii = 0; ii < nVert; ++ii)
99  {
100  // Finds the to vertex
101  jj = int(newsnake.snakemesh()->edges(edgeSubs[ii])->vertind[0] == indVert);
102  newsnake.snaxs[ii].set(newsnake.snaxs(ii)->index, 0.0, 0.5, indVert,
103  newsnake.snakemesh()->edges(edgeSubs[ii])->vertind[jj], edgeInds[ii], 0, -1);
104 
105  edgeSubsTemp = FindSubList(newsnake.snakemesh()->edges(edgeSubs[ii])->surfind, surfInds, hashSurfInds);
106  newsnake.snakeconn.verts[ii].edgeind = edgeSubsTemp;
107  newsnake.snakeconn.verts[ii].coord = newsnake.snakemesh()->verts(subVert)->coord;
108  }
109  newsnake.snakeconn.verts.ChangeIndices(0, 1, 0, 0);
110 }
111 
112 void SpawnAtVertexEdge(snake &newsnake, int nEdge, const vector<int> &surfInds, const vector<int> &edgeInds,
113  const vector<int> &voluInds, const vector<int> &surfSubs,
114  unordered_multimap<int, int> &hashEdgeInds, unordered_multimap<int, int> &hashVoluInds)
115 {
116  int ii, jj, kk;
117  vector<int> surfSubsTemp, vertSubsTemp;
118 
119  newsnake.snakeconn.edges.PopulateIndices();
120  newsnake.snaxedges.PopulateIndices();
121 
122  for (ii = 0; ii < nEdge; ++ii)
123  {
124  newsnake.snaxedges[ii].surfind = surfInds[ii];
125  if (newsnake.Check3D())
126  {
127  surfSubsTemp = FindSubList(newsnake.snakemesh()->surfs(surfSubs[ii])->voluind, voluInds, hashVoluInds);
128  newsnake.snakeconn.edges[ii].surfind = surfSubsTemp;
129  for (jj = 0; jj < int(surfSubsTemp.size()); ++jj)
130  {
131  newsnake.snakeconn.edges[ii].surfind[jj]++;
132  }
133  }
134  // Assign vertind (can be done WAY more efficiently the other way round)
135  // But liek this we can check the logic
136  vertSubsTemp = FindSubList(newsnake.snakemesh()->surfs(surfSubs[ii])->edgeind, edgeInds, hashEdgeInds);
137  kk = 0;
138  for (jj = 0; jj < int(vertSubsTemp.size()); ++jj)
139  {
140  if (vertSubsTemp[jj] >= 0)
141  {
142  newsnake.snakeconn.edges[ii].vertind[kk] = vertSubsTemp[jj];
143  kk++;
144  }
145  }
146  }
147 
148  newsnake.snakeconn.edges.ChangeIndices(1, 0, 0, 0);
149  if (!newsnake.Check3D())
150  {
151  for (ii = 0; ii < nEdge; ++ii)
152  {
153  newsnake.snakeconn.edges[ii].surfind.assign(2, 0);
154  newsnake.snakeconn.edges[ii].surfind[0] = 1;
155  newsnake.snakeconn.edges[ii].surfind[1] = 0;
156  }
157  }
158 }
159 void SpawnAtVertexSurf3D(snake &newsnake, int nSurf, const vector<int> &surfInds, const vector<int> &voluInds,
160  const vector<int> &voluSubs, unordered_multimap<int, int> &hashSurfInds)
161 {
162  int ii, jj;
163  vector<int> surfSubsTemp;
164 
165  newsnake.snakeconn.surfs.PopulateIndices();
166  newsnake.snaxsurfs.PopulateIndices();
167  for (ii = 0; ii < nSurf; ++ii)
168  {
169  newsnake.snaxsurfs[ii].voluind = voluInds[ii];
170  newsnake.snakeconn.surfs[ii].voluind[0] = 1;
171  // Assign edgeind (can be done WAY more efficiently the other way round)
172  // But like this we can check the logic
173  surfSubsTemp = FindSubList(newsnake.snakemesh()->volus(voluSubs[ii])->surfind, surfInds, hashSurfInds);
174  // Needs to be modified to work with 2D (surfSubsTemps does not come out
175  // right)
176  for (jj = 0; jj < int(surfSubsTemp.size()); ++jj)
177  {
178  if (surfSubsTemp[jj] >= 0)
179  {
180  newsnake.snakeconn.surfs[ii].edgeind.push_back(surfSubsTemp[jj]);
181  }
182  }
183  }
184  newsnake.snakeconn.surfs.ChangeIndices(0, 1, 0, 0);
185 }
186 
187 void SpawnAtVertexSurf2D(snake &newsnake, int nEdge, const vector<int> &voluInds)
188 {
189  int ii, jj;
190  // vector<int> surfSubsTemp;
191 
192  newsnake.snakeconn.surfs.PopulateIndices();
193  newsnake.snaxsurfs.PopulateIndices();
194  ii = 0;
195  newsnake.snaxsurfs[ii].voluind = voluInds[ii];
196  newsnake.snakeconn.surfs[ii].voluind[0] = 0;
197 
198  for (jj = 0; jj < int(nEdge); ++jj)
199  {
200  newsnake.snakeconn.surfs[ii].edgeind.push_back(jj + 1);
201  }
202 
203  // newsnake.snakeconn.surfs.ChangeIndices(0,1,0,0);
204 }
205 
206 void SpawnAtVertexVolu(snake &newsnake, int nSurf)
207 {
208  int ii;
209 
210  newsnake.snakeconn.volus.PopulateIndices();
211  newsnake.snakeconn.volus[0].surfind.reserve(nSurf);
212  for (ii = 0; ii < nSurf; ++ii)
213  {
214  newsnake.snakeconn.volus[0].surfind.push_back(ii + 1);
215  }
216 }
217 
218 // Merge vertices in contact
219 
220 void MergeAllContactVertices(snake &fullsnake, vector<int> &isImpact)
221 {
222  // in isImpact needs to be hashed to rapidly check
223  int ii, jj, nImpacts;
224  vector<int> snaxToRemove, vertSameSub, subVelTo0;
225  vector<bool> isImpactDone;
226  HashedVector<int, snax> impactInd, impactTarg;
227 
228  nImpacts = isImpact.size() / 2;
229  impactInd.vec.reserve(nImpacts);
230  impactTarg.vec.reserve(nImpacts);
231  snaxToRemove.reserve(nImpacts);
232  isImpactDone.assign(nImpacts, false);
233 
234  for (ii = 0; ii < int(isImpact.size()); ii = ii + 2)
235  {
236  impactInd.vec.push_back(isImpact[ii]);
237  }
238  for (ii = 1; ii < int(isImpact.size()); ii = ii + 2)
239  {
240  impactTarg.vec.push_back(isImpact[ii]);
241  }
242  impactInd.GenerateHash();
243  impactTarg.GenerateHash();
244 
245  for (ii = 0; ii < nImpacts; ++ii)
246  {
247  if (!isImpactDone[ii])
248  {
249  isImpactDone[ii] = true;
250  if (impactTarg.vec[ii] > 0)
251  {
252  fullsnake.snakeconn.SwitchIndex(1, impactInd.vec[ii], impactTarg.vec[ii]);
253  subVelTo0.push_back(fullsnake.snaxs.find(impactTarg.vec[ii]));
254 
255  snaxToRemove.push_back(impactInd.vec[ii]);
256  vertSameSub = ReturnDataEqualRange(impactTarg.vec[ii], impactInd.hashTable);
257 
258  for (jj = 0; jj < int(vertSameSub.size()); jj++)
259  {
260  isImpactDone[vertSameSub[jj]] = true;
261  }
262  vertSameSub = ReturnDataEqualRange(impactTarg.vec[ii], impactTarg.hashTable);
263  for (jj = 0; jj < int(vertSameSub.size()); jj++)
264  {
265  isImpactDone[vertSameSub[jj]] = true;
266  }
267  }
268  }
269  }
270  for (ii = 0; ii < int(subVelTo0.size()); ii++)
271  {
272  fullsnake.snaxs[subVelTo0[ii]].v = 0.0;
273  }
274  fullsnake.snaxs.remove(snaxToRemove);
275  fullsnake.snakeconn.verts.remove(snaxToRemove);
276 }
277 
278 void SpawnArrivedSnaxels(snake &fullsnake, const vector<int> &isImpact)
279 {
280  snake fwdSnake, bwdSnake;
281  HashedVector<int, int> vertNoSpawn;
282 
283  fwdSnake.Init(fullsnake.snakemesh(), 0, 0, 0, 0);
284  bwdSnake.Init(fullsnake.snakemesh(), 0, 0, 0, 0);
285 
286  // Generate fwd spawn
287 
288  vertNoSpawn.vec.push_back(0);
289  vertNoSpawn.GenerateHash();
290  SpawnArrivedSnaxelsDir(fullsnake, bwdSnake, isImpact, -1, vertNoSpawn);
291  SpawnArrivedSnaxelsDir(fullsnake, fwdSnake, isImpact, -2, vertNoSpawn);
292 
293  bwdSnake.Flip();
294  /* Old process incompatible with internal vertex tracking
295  fwdSnake.SetMaxIndexNM();
296  fwdSnake.MakeCompatible_inplace(bwdSnake);
297  // DO NOT RUN TO MAITAIN orederedge newsnake.PrepareForUse();
298  fwdSnake.Concatenate(bwdSnake);
299 
300  fullsnake.SetMaxIndexNM();
301  fullsnake.MakeCompatible_inplace(fwdSnake);
302  // DO NOT RUN TO MAITAIN orederedge newsnake.PrepareForUse();
303  fullsnake.Concatenate(fwdSnake);
304  */
305 
306  fullsnake.SetMaxIndexNM();
307  fullsnake.MakeCompatible_inplace(bwdSnake);
308  // DO NOT RUN TO MAITAIN orederedge newsnake.PrepareForUse();
309  fullsnake.Concatenate(bwdSnake);
310 
311  fullsnake.SetMaxIndexNM();
312  fullsnake.MakeCompatible_inplace(fwdSnake);
313  // DO NOT RUN TO MAITAIN orederedge newsnake.PrepareForUse();
314  fullsnake.Concatenate(fwdSnake);
315 
316  fullsnake.PrepareForUse();
317 }
318 
319 void SpawnArrivedSnaxelsDir(snake &fullsnake, snake &partSnake, const vector<int> &isImpact, int dir,
320  HashedVector<int, int> &vertNoSpawn)
321 {
322  int nVert, nEdge, nSurf, nVolu, ii, jj, kk;
323  bool isReady;
324  vector<int> vertSpawn, subList;
325  int snax::*mp = NULL;
326 
327  nVert = 0;
328  nEdge = 0;
329  nSurf = 0;
330  nVolu = 0;
331  jj = -1;
332 
333  if (dir == -1)
334  {
335  mp = &snax::fromvert;
336  }
337  else if (dir == -2)
338  {
339  mp = &snax::tovert;
340  }
341  else
342  {
343  cerr << "Error: Direction of arrived snaxel is invalid " << endl;
344  cerr << " in function:" << __PRETTY_FUNCTION__ << endl;
345  RSVS3D_ERROR_ARGUMENT("direction was invalid");
346  }
347  isReady = fullsnake.snaxs.checkready();
348 
349  for (ii = 0; ii < int(isImpact.size()); ii = ii + 2)
350  {
351  if (isImpact[ii + 1] == dir)
352  {
353  jj = fullsnake.snaxs.find(isImpact[ii]);
354  if (!fullsnake.snakemesh()->verts.isearch(fullsnake.snaxs(jj)->*mp)->isBorder)
355  {
356  jj = fullsnake.snaxs.find(isImpact[ii]);
357  vertSpawn.push_back(fullsnake.snaxs(jj)->*mp);
358  nVolu++;
359  nVert = nVert + fullsnake.snakemesh()->verts.isearch(fullsnake.snaxs(jj)->*mp)->edgeind.size();
360 
361  subList = fullsnake.snakemesh()->edges.find_list(
362  fullsnake.snakemesh()->verts.isearch(fullsnake.snaxs(jj)->*mp)->edgeind);
363 
364  for (kk = 0; kk < int(subList.size()); kk++)
365  {
366  nEdge = nEdge + fullsnake.snakemesh()->edges(subList[kk])->surfind.size();
367  }
368  }
369  else
370  {
371  fullsnake.snaxs[jj].isfreeze = 1;
372  if (isReady)
373  {
374  fullsnake.snaxs.ForceArrayReady();
375  }
376  }
377  }
378  }
379 
380  nSurf = nEdge;
381  partSnake.reserve(nVert, nEdge, nSurf, nVolu);
382 
383  sort(vertSpawn);
384  unique(vertSpawn);
385  /*
386  cout << endl;
387  DisplayVector(vertSpawn);
388  cout << endl;
389  */
390  kk = int(vertSpawn.size());
391 
392  for (ii = 0; ii < kk; ++ii)
393  {
394  if (vertNoSpawn.find(vertSpawn[ii]) == -1)
395  {
396  SpawnAtVertex(partSnake, vertSpawn[ii]);
397  }
398  // else {
399  // cout << endl << "vertex ignored for spawn " <<endl;
400  // }
401  }
402  vertNoSpawn.vec.insert(vertNoSpawn.vec.end(), vertSpawn.begin(), vertSpawn.end());
403  vertNoSpawn.GenerateHash();
404  // DisplayVector(vertNoSpawn.vec);
405 }
406 
407 void dispconnrmv(vector<ConnecRemv> conn)
408 {
409  for (int i = 0; i < int(conn.size()); ++i)
410  {
411  conn[i].disp();
412  }
413 }
414 
415 void SnaxEdgeConnecDetection(snake &snakein, vector<ConnecRemv> &connecEdit)
416 {
417  int ii, snaxSub1, snaxSub2, nSnaxEdge;
418  ConnecRemv tempConnec, tempConnec2;
419  nSnaxEdge = snakein.snaxedges.size();
420 
421  tempConnec.typeobj = 1;
422  tempConnec2.typeobj = 2;
423 
424  for (ii = 0; ii < nSnaxEdge; ++ii)
425  {
426  if (snakein.snakeconn.edges(ii)->vertind.size() > 0)
427  {
428  snaxSub1 = snakein.snaxs.find(snakein.snakeconn.edges(ii)->vertind[0]);
429  snaxSub2 = snakein.snaxs.find(snakein.snakeconn.edges(ii)->vertind[1]);
430  if (snaxSub1 == -1 && snaxSub2 == -1)
431  {
432  // tempConnec2.rmvind.clear();
433  // tempConnec2.keepind=snakein.snaxedges(ii)->index;
434  // tempConnec2.rmvind.push_back(snakein.snaxedges(ii)->index);
435  // connecEdit.push_back(tempConnec2);
436  cout << "SnaxEdgeConnecDetection invalid edge 2 snaxel inexistant:";
437  snakein.snakeconn.edges(ii)->disp();
438  }
439  else if (snaxSub1 == -1)
440  {
441  cout << "SnaxEdgeConnecDetection invalid edge 1(1) snaxel inexistant:";
442  snakein.snakeconn.edges(ii)->disp();
443  }
444  else if (snaxSub2 == -1)
445  {
446  cout << "SnaxEdgeConnecDetection invalid edge 1(2) snaxel inexistant:";
447  snakein.snakeconn.edges(ii)->disp();
448  }
449  else if (snakein.snaxs(snaxSub1)->edgeind == snakein.snaxs(snaxSub2)->edgeind)
450  {
451  if (snaxSub1 != snaxSub2)
452  {
453  tempConnec.rmvind.clear();
454  tempConnec.keepind = snakein.snaxs(snaxSub1)->index;
455  tempConnec.rmvind.push_back(snakein.snaxs(snaxSub2)->index);
456  connecEdit.push_back(tempConnec);
457  } // else {cout << __PRETTY_FUNCTION__<< endl;}
458  tempConnec2.rmvind.clear();
459  tempConnec2.keepind = snakein.snaxedges(ii)->index;
460  tempConnec2.rmvind.push_back(snakein.snaxedges(ii)->index);
461  connecEdit.push_back(tempConnec2);
462 
463  // edit vertices in place but not edges
464  // snakein.snakeconn.SwitchIndex(tempConnec.typeobj,tempConnec.rmvind[0],
465  // tempConnec.keepind,tempConnec.scopeind);
466  // snakein.snakeconn.RemoveIndex(tempConnec2.typeobj,tempConnec2.rmvind[0]);
467  // snakein.snaxedges.DeHashParent(snakein.snaxedges.find(tempConnec2.rmvind[0]));
468  }
469  }
470  }
471 }
472 
473 void SnaxNoConnecDetection(const mesh &snakeconn, vector<ConnecRemv> &connecEdit)
474 {
475  int ii, nSnax;
476  ConnecRemv tempConnec;
477  nSnax = snakeconn.verts.size();
478 
479  tempConnec.typeobj = 1;
480 
481  for (ii = 0; ii < nSnax; ++ii)
482  {
483  if (snakeconn.verts(ii)->edgeind.size() == 0)
484  {
485  tempConnec.rmvind.clear();
486  tempConnec.keepind = snakeconn.verts(ii)->index;
487  tempConnec.rmvind.push_back(snakeconn.verts(ii)->index);
488 
489  connecEdit.push_back(tempConnec);
490  }
491  }
492 }
493 
494 void MergeCleanSnake(snake &fullsnake, vector<int> &isImpact)
495 {
496  /*
497  Perform one merge per clean operations
498  */
499  int ii, nI, kk;
500  bool cond;
501  vector<int> temp;
502  fullsnake.SnaxImpactDetection(isImpact);
503  fullsnake.PrepareForUse();
504  temp.reserve(2);
505 
506  cond = true;
507  while (cond)
508  {
509  kk = 0;
510  fullsnake.SnaxImpactDetection(isImpact);
511  nI = isImpact.size() / 2;
512  for (ii = 0; ii < nI; ++ii)
513  {
514  temp.clear();
515  temp.push_back(isImpact[ii * 2]);
516  temp.push_back(isImpact[ii * 2 + 1]);
517  if (temp[0] >= 0 && temp[1] >= 0)
518  {
519  MergeAllContactVertices(fullsnake, temp);
520  CleanupSnakeConnec(fullsnake);
521  fullsnake.PrepareForUse();
522  break;
523  }
524  else
525  {
526  kk++;
527  }
528  }
529  if (kk == nI)
530  {
531  cond = false;
532  }
533  }
534  fullsnake.PrepareForUse();
535 }
536 
537 void CleanupSnakeConnec(snake &snakein)
538 {
539  vector<ConnecRemv> connecEdit;
540  ConnecRemv tempConnec;
541  vector<int> indRmvVert, indRmvEdge, indRmvSurf, indRmvVolu, indDelSurf;
542 
543  int ii, jj, kk, nEdgeConn, nSurfConn, nEdgeSurfConn, nVertConn, nSnaxConn, nEdgeSameSurfConn, nAboveN;
544  // int nStartConn;
545  // int count=0;
546  bool flag, iterFlag, contFlag;
547  HashedVector<int, int> indDelEdge;
548  iterFlag = true;
549  contFlag = true;
550  // indRmvEdge.reserve(snakein.snakeconn.edges.size());
551  // indRmvSurf.reserve(snakein.snakeconn.surfs.size());
552  auto itVert = indRmvVert.begin();
553  auto itEdge = indRmvEdge.begin();
554  auto itSurf = indRmvSurf.begin();
555  auto itVolu = indRmvVolu.begin();
556 
557  snakein.snakeconn.TightenConnectivity();
558  snakein.HashParent();
559 #ifdef SAFE_ALGO
560  if (snakein.Check3D())
561  {
562  snakein.snakeconn.TestConnectivityBiDir(__PRETTY_FUNCTION__);
563  }
564 #endif
565  while (iterFlag)
566  {
567  indRmvVert.clear();
568  indRmvEdge.clear();
569  indRmvSurf.clear();
570  indRmvVolu.clear();
571  connecEdit.clear();
572  indDelSurf.clear();
573  indDelEdge.vec.clear();
574 
575  snakein.PrepareForUse(false);
576  itVert = indRmvVert.begin();
577  itEdge = indRmvEdge.begin();
578  itSurf = indRmvSurf.begin();
579  itVolu = indRmvVolu.begin();
580  // Identify invalid vertex connections
581  // count=0;
582  // nVertConn=0;
583  SnaxNoConnecDetection(snakein.snakeconn, connecEdit);
584  // do {
585  nSnaxConn = int(connecEdit.size());
586  // nStartConn=nVertConn;
587  // cout << ++count << endl;
588  SnaxEdgeConnecDetection(snakein, connecEdit);
589  nVertConn = int(connecEdit.size());
590  // Identify Edge Connections
591  for (ii = nSnaxConn; ii < nVertConn; ++ii)
592  {
593  if (connecEdit[ii].typeobj == 1)
594  {
595  // Skipping the edges which are marked here for removal.
596  snakein.snakeconn.SwitchIndex(connecEdit[ii].typeobj, connecEdit[ii].rmvind[0], connecEdit[ii].keepind,
597  connecEdit[ii].scopeind);
598  // edit the connectivity editing to reflect the removal of vertices
599  for (jj = ii + 1; jj < nVertConn; ++jj)
600  {
601  if (connecEdit[jj].typeobj == 1)
602  {
603  if (connecEdit[jj].keepind != connecEdit[jj].rmvind[0] &&
604  (connecEdit[jj].rmvind[0] == connecEdit[ii].rmvind[0] ||
605  connecEdit[jj].rmvind[0] == connecEdit[ii].keepind ||
606  connecEdit[jj].keepind == connecEdit[ii].rmvind[0] ||
607  connecEdit[jj].keepind == connecEdit[ii].keepind))
608  {
609  connecEdit[jj].keepind = connecEdit[ii].keepind;
610  connecEdit[jj].rmvind[0] = connecEdit[ii].rmvind[0];
611  // connecEdit[jj+1].keepind=-1; //connecEdit[ii+1].keepind;
612  // if 2 edges connect the same 2 vertices (in different surface)
613  // only want to remove those that match
614  connecEdit[jj + 1].keepind = connecEdit[ii + 1].keepind;
615  connecEdit[jj + 1].rmvind[0] = -1; // connecEdit[ii+1].rmvind[0];
616 
617  // connecEdit[jj].rmvind[0]=connecEdit[ii].keepind;
618  }
619  }
620  }
621  }
622  }
623  // cout << endl << nVertConn << endl;
624  // removes edges which are degenerate
625 
626  for (ii = nSnaxConn; ii < nVertConn; ++ii)
627  {
628  if (connecEdit[ii].typeobj == 2)
629  {
630  if (connecEdit[ii].rmvind[0] > 0)
631  {
632  snakein.snakeconn.RemoveIndex(2, connecEdit[ii].rmvind[0]);
633  snakein.snaxedges.DeHashParent(snakein.snaxedges.find(connecEdit[ii].rmvind[0]));
634  }
635  else
636  {
637  connecEdit[ii].rmvind[0] = connecEdit[ii].keepind;
638  // snakein.snakeconn.RemoveIndex(2,connecEdit[ii].rmvind[0]);
639  }
640  }
641  }
642  // cout << endl << ++count << " " << nStartConn << " " << nVertConn ;
643  // } while(nStartConn!=nVertConn);
644  jj = snakein.snakeconn.edges.size();
645  for (ii = 0; ii < jj; ++ii)
646  { // remove edges connected to the same vertex twice.
647  if (snakein.snakeconn.edges(ii)->vertind.size() > 1 &&
648  (snakein.snakeconn.edges(ii)->vertind[0] == snakein.snakeconn.edges(ii)->vertind[1]))
649  {
650  // cout << "is useful" << endl;
651  snakein.snakeconn.RemoveIndex(2, snakein.snakeconn.edges(ii)->index);
652  snakein.snaxedges.DeHashParent(snakein.snaxedges.find(snakein.snakeconn.edges(ii)->index));
653  tempConnec.typeobj = 2;
654  tempConnec.keepind = snakein.snakeconn.edges(ii)->index;
655  tempConnec.rmvind.clear();
656  tempConnec.rmvind.push_back(tempConnec.keepind);
657  connecEdit.push_back(tempConnec);
658  }
659  }
660  nVertConn = int(connecEdit.size());
661  // This block of code aims to fix the issue of edges in the same parent
662  // surface connected to the same surface It performs a merge for these
663  // surfaces but does not automatically delete the vertex
664  IdentifyMergEdgeSameSurfConnec(snakein, connecEdit);
665  nEdgeSameSurfConn = int(connecEdit.size());
666  for (ii = nVertConn; ii < nEdgeSameSurfConn; ++ii)
667  {
668  for (jj = 0; jj < int(connecEdit[ii].rmvind.size()); ++jj)
669  {
670  snakein.snakeconn.SwitchIndex(connecEdit[ii].typeobj, connecEdit[ii].rmvind[jj], connecEdit[ii].keepind,
671  connecEdit[ii].scopeind);
672  if (connecEdit[ii].typeobj == 2)
673  {
674  snakein.snaxedges.DeHashParent(snakein.snaxedges.find(connecEdit[ii].rmvind[jj]));
675  }
676 
677  // for(jj=ii+2;jj<nEdgeSameSurfConn;jj=jj+2){
678  // if (connecEdit[jj].rmvind[0]==connecEdit[ii].keepind &&
679  // connecEdit[jj].keepind==connecEdit[ii].rmvind[0]){
680 
681  // }
682  // }
683  }
684  }
685 
686  // cout << " nEdgeSameSurfConn=" << nEdgeSameSurfConn-nVertConn << endl;
687  // End Same surf merge
688 
689  IdentifyMergEdgeConnec(snakein, connecEdit);
690  nEdgeConn = int(connecEdit.size());
691  iterFlag = int(nEdgeConn) > 0;
692  if (contFlag || iterFlag)
693  {
694  for (ii = nEdgeSameSurfConn; ii < nEdgeConn; ++ii)
695  {
696  for (jj = 0; jj < int(connecEdit[ii].rmvind.size()); ++jj)
697  {
698  snakein.snakeconn.SwitchIndex(connecEdit[ii].typeobj, connecEdit[ii].rmvind[jj],
699  connecEdit[ii].keepind, connecEdit[ii].scopeind);
700  }
701  }
702  SnaxNoConnecDetection(snakein.snakeconn, connecEdit);
703  nEdgeConn = int(connecEdit.size());
704  // Identify surface connections
705  if (snakein.Check3D())
706  {
707  IdentifyMergSurfConnec(snakein, connecEdit);
708 
709  nSurfConn = int(connecEdit.size());
710  for (ii = nEdgeConn; ii < nSurfConn; ++ii)
711  {
712  for (jj = 0; jj < int(connecEdit[ii].rmvind.size()); ++jj)
713  {
714  snakein.snakeconn.SwitchIndex(connecEdit[ii].typeobj, connecEdit[ii].rmvind[jj],
715  connecEdit[ii].keepind, connecEdit[ii].scopeind);
716  }
717  }
718  }
719 
720  // Build removal ind of objects
721  for (ii = 0; ii < nEdgeConn; ++ii)
722  {
723  if (connecEdit[ii].typeobj == 2)
724  {
725  indRmvEdge.insert(itEdge, connecEdit[ii].rmvind.begin(), connecEdit[ii].rmvind.end());
726  itEdge = indRmvEdge.end();
727  }
728  else if (connecEdit[ii].typeobj == 3)
729  {
730  cerr << "Should not be here " << endl;
731  }
732  else if (connecEdit[ii].typeobj == 5 || connecEdit[ii].typeobj == 1)
733  {
734  indRmvVert.insert(itVert, connecEdit[ii].rmvind.begin(), connecEdit[ii].rmvind.end());
735  itVert = indRmvVert.end();
736  }
737  }
738 
739  sort(indRmvVert);
740  sort(indRmvEdge);
741  unique(indRmvVert);
742  unique(indRmvEdge);
743  // Identify Volumes from vertices
744  if (snakein.Check3D())
745  {
746  ModifyMergVoluConnec(snakein, connecEdit, indRmvVert);
747  }
748  else
749  {
750  // ModifyMergSurf2DConnec(snakein, connecEdit,indRmvVert);
751  ModifyMergSurf2DConnec(snakein, connecEdit);
752  }
753 
754  nEdgeSurfConn = int(connecEdit.size());
755  for (ii = nEdgeConn; ii < nEdgeSurfConn; ++ii)
756  {
757  if (connecEdit[ii].typeobj == 3)
758  {
759  indRmvSurf.insert(itSurf, connecEdit[ii].rmvind.begin(), connecEdit[ii].rmvind.end());
760  itSurf = indRmvSurf.end();
761  }
762  else if (connecEdit[ii].typeobj == 4)
763  {
764  indRmvVolu.insert(itVolu, connecEdit[ii].rmvind.begin(), connecEdit[ii].rmvind.end());
765  itVolu = indRmvVolu.end();
766  }
767  else if (connecEdit[ii].typeobj == 2)
768  {
769  cerr << "Should not be Here " << endl;
770  }
771  else if (connecEdit[ii].typeobj == 5)
772  {
773  cerr << "Should not be Here " << endl;
774  }
775  }
776 
777  sort(indRmvSurf);
778  unique(indRmvSurf);
779  sort(indRmvVolu);
780  unique(indRmvVolu);
781  // Identify collapsed edges from vertind
782  // Remove these like the switch index
783  // Look for edges attached to a deleted vertex and delete them as well
784  indDelEdge.vec.reserve(nEdgeConn);
785  for (ii = 0; ii < nEdgeConn; ++ii)
786  {
787  if (connecEdit[ii].typeobj == 2)
788  {
789  if (snakein.snakeconn.edges.isearch(connecEdit[ii].keepind)->vertind[0] ==
790  snakein.snakeconn.edges.isearch(connecEdit[ii].keepind)->vertind[1])
791  {
792  indDelEdge.vec.push_back(connecEdit[ii].keepind);
793  }
794  }
795  }
796  indDelEdge.GenerateHash();
797 
798  kk = indDelEdge.vec.size();
799  for (ii = 0; ii < kk; ++ii)
800  {
801  snakein.snakeconn.RemoveIndex(2, indDelEdge.vec[ii]);
802  }
803 
804  kk = int(snakein.snakeconn.surfs.size());
805  indDelSurf.reserve(nEdgeSurfConn - nEdgeConn);
806  for (ii = 0; ii < kk; ++ii)
807  {
808  flag = int(snakein.snakeconn.surfs(ii)->edgeind.size()) == 0;
809  if (flag)
810  {
811  indDelSurf.push_back(snakein.snakeconn.surfs(ii)->index);
812  }
813  }
814 
815  kk = indDelSurf.size();
816  for (ii = 0; ii < kk; ++ii)
817  {
818  snakein.snakeconn.RemoveIndex(3, indDelSurf[ii]);
819  }
820  kk = connecEdit.size();
821  SnaxNoConnecDetection(snakein.snakeconn, connecEdit);
822  nEdgeSurfConn = connecEdit.size();
823  itVert = indRmvVert.end();
824  for (ii = kk; ii < nEdgeSurfConn; ++ii)
825  {
826  if (connecEdit[ii].typeobj == 5 || connecEdit[ii].typeobj == 1)
827  {
828  indRmvVert.insert(itVert, connecEdit[ii].rmvind.begin(), connecEdit[ii].rmvind.end());
829  itVert = indRmvVert.end();
830  }
831  }
832  sort(indRmvVert);
833  unique(indRmvVert);
834  // kk=indRmvSurf.size()+indDelSurf.size()+2;
835  // indRmvSurf.reserve(kk);
836  indRmvSurf.insert(indRmvSurf.end(), indDelSurf.begin(), indDelSurf.end());
837 
838  // kk=indRmvEdge.size()+indDelEdge.vec.size()+2;
839  // indRmvEdge.reserve(kk);
840  indRmvEdge.insert(indRmvEdge.end(), indDelEdge.vec.begin(), indDelEdge.vec.end());
841 
842  sort(indRmvEdge);
843  sort(indRmvSurf);
844  unique(indRmvEdge);
845  unique(indRmvSurf);
846 
847  // nAbove3=0;
848  nAboveN = 0;
849  snakein.snakeconn.TightenConnectivity();
850  if (false)
851  {
852  for (ii = 0; ii < int(indRmvVert.size()); ii++)
853  {
854  // nAbove3+=int(int(snakein.snakeconn.verts.isearch(indRmvVert[ii])->edgeind.size())>2);
855  // if(int(snakein.snakeconn.verts.isearch(indRmvVert[ii])->edgeind.size())>2){
856  // snakein.snakeconn.verts.isearch(indRmvVert[ii])->disp();
857  // }
858  if (snakein.snakemesh()
859  ->edges.isearch(snakein.snaxs.isearch(indRmvVert[ii])->edgeind)
860  ->surfind.size() == snakein.snakeconn.verts.isearch(indRmvVert[ii])->edgeind.size())
861  {
862  if (nAboveN == 0)
863  {
864  cout << endl << "displaying vertices about to be removed by nAboveN cond:" << endl;
865  // dispconnrmv(connecEdit);
866  }
867  snakein.snakeconn.verts.isearch(indRmvVert[ii])->disp();
868  indRmvVert.erase(indRmvVert.begin() + ii);
869  ii--;
870  nAboveN++;
871  }
872  }
873  }
874 
875  CheckSnakeRemovalsEdge(snakein, indRmvEdge);
876 
877  snakein.snakeconn.surfs.remove(indRmvSurf);
878  snakein.snakeconn.edges.remove(indRmvEdge);
879  snakein.snakeconn.verts.remove(indRmvVert);
880  snakein.snakeconn.volus.remove(indRmvVolu);
881  snakein.snaxs.remove(indRmvVert);
882  snakein.snaxedges.remove(indRmvEdge);
883  snakein.snaxsurfs.remove(indRmvSurf);
884 
885  snakein.snakeconn.TightenConnectivity();
886  snakein.HashArrayNM();
887  // snakein.ForceCloseContainers();
888 
889 #ifdef SAFE_ALGO
890  if (snakein.Check3D())
891  {
892  ii = snakein.snakeconn.TestConnectivityBiDir(__PRETTY_FUNCTION__, false);
893  if (ii > 0)
894  {
895  dispconnrmv(connecEdit);
896  }
897  }
898 #endif
899 
900  // Change iteration termination condition
901  iterFlag = int(connecEdit.size()) > 0;
902  if (!iterFlag)
903  {
904  contFlag = false;
905  iterFlag = true;
906  }
907  else
908  {
909  contFlag = true;
910  }
911  }
912  else
913  { // Only executes at the end
914 
915  snakein.HashArrayNM();
916  snakein.CheckConnectivity();
917  snakein.OrderEdges();
918  snakein.ForceCloseContainers();
919  snakein.snakeconn.TightenConnectivity();
920 #ifdef SAFE_ALGO
921  if (snakein.Check3D())
922  {
923  snakein.snakeconn.TestConnectivityBiDir(__PRETTY_FUNCTION__);
924  }
925 #endif
926  }
927  }
928  snakein.PrepareForUse();
929 }
930 /*
931 void ConnecForwardEdit(vector<ConnecRemv> &connecEdit,int oldInd, int newInd,int
932 startInd, int step, int finalInd){ int ii,jj,kk;
933 
934  for(ii=startInd;ii<finalInd;++ii){
935 
936  }
937 }*/
938 
939 void IdentifyMergEdgeSameSurfConnec(const snake &snakein, vector<ConnecRemv> &connecEdit)
940 {
941  vector<bool> isObjDone;
942  bool isAnyDone;
943  vector<int> tempSub, tempSub2, tempSub3, tempCount, tempCount2;
944  HashedVector<int, int> tempIndHash;
945  HashedVector<int, int> edge2Surf, tempIndHash2;
946  // vector<int> objSub;
947  int nSnaxEdge, ii, jj, nParent, stepCheck, nSurf, nTemp; // nSnax, nSnaxSurf,
948  ConnecRemv tempConnec, tempConnec2;
949  if (snakein.Check3D())
950  {
951  // nSnax=snakein.snaxs.size();
952  nSnaxEdge = snakein.snaxedges.size();
953  // nSnaxSurf=snakein.snaxsurfs.size();
954 
955  isObjDone.reserve(nSnaxEdge);
956 
957  isObjDone.assign(nSnaxEdge, false);
958  for (ii = 0; ii < nSnaxEdge; ++ii)
959  {
960  if (!isObjDone[ii])
961  {
962  if (snakein.snaxedges.memberIsHashParent(ii))
963  {
964  nParent = snakein.snaxedges.countparent(snakein.snaxedges(ii)->KeyParent());
965  if (nParent > 1)
966  {
967  nSurf = int(snakein.snakeconn.edges(ii)->surfind.size());
968  stepCheck = 0;
969  // for (stepCheck=0;stepCheck<nSurf;stepCheck++){
970 
971  IndentifyEdgeSameSurf(snakein, ii, stepCheck, tempSub, tempSub2, tempSub3, tempIndHash2,
972  edge2Surf, tempCount2);
973  isAnyDone = false;
974  nTemp = tempSub2.size();
975  for (jj = 0; jj < nTemp; ++jj)
976  {
977  isAnyDone = isAnyDone || isObjDone[tempSub2[jj]];
978  }
979  if (stepCheck < nSurf && !isAnyDone)
980  {
981  IdentifyMergeEdgeGeneral(snakein, isObjDone, connecEdit, tempConnec, tempConnec2, tempSub2,
982  tempSub3, tempCount, tempIndHash);
983  }
984  //}
985  }
986  }
987  isObjDone[ii] = true;
988  }
989  }
990  }
991 }
992 
993 void IndentifyEdgeSameSurf(const snake &snakein, int currSub, int &stepCheck, vector<int> &tempSub,
994  vector<int> &tempSub2, vector<int> &tempSub3, HashedVector<int, int> &tempIndHash,
995  HashedVector<int, int> &edge2Surf, vector<int> tempCount)
996 {
997  // Identifies edges which share a surface and
998  int ii, jj, nTemp;
999 
1000  if (stepCheck == 0)
1001  {
1002  snakein.snaxedges.findsiblings(snakein.snaxedges(currSub)->KeyParent(), tempSub);
1003  edge2Surf.vec.clear();
1004  tempIndHash.vec = ConcatenateVectorField(snakein.snakeconn.edges, &edge::surfind, tempSub);
1005  // tempIndHash is a hashed vector of concatenate (surfs(tempSub).edgeind)
1006  for (ii = 0; ii < int(tempSub.size()); ++ii)
1007  {
1008  for (jj = 0; jj < int(snakein.snakeconn.edges(tempSub[ii])->surfind.size()); ++jj)
1009  {
1010  edge2Surf.vec.push_back(ii);
1011  }
1012  }
1013  // edge2Surf is a hashed vector of the subscripts into tempSub of the surf
1014  // matching the edges in tempHashInd
1015 
1016  tempIndHash.GenerateHash();
1017  edge2Surf.GenerateHash();
1018  tempCount = tempIndHash.count(snakein.snakeconn.edges(currSub)->surfind);
1019  tempCount.push_back(0);
1020  }
1021  // tempCount is the vector counting the number of occurences of each edge at
1022  // each edges location
1023  nTemp = tempCount.size() - 1;
1024 
1025  while (tempCount[stepCheck] < 2 && stepCheck <= nTemp)
1026  {
1027  stepCheck++;
1028  }
1029 
1030  if (stepCheck < nTemp)
1031  { // Build the temoSub corresponding to that surface
1032  tempSub3 = tempIndHash.findall(snakein.snakeconn.edges(currSub)->surfind[stepCheck]);
1033  tempSub2.clear();
1034  for (ii = 0; ii < int(tempSub3.size()); ++ii)
1035  {
1036  tempSub2.push_back(tempSub[edge2Surf.vec[tempSub3[ii]]]);
1037  }
1038  }
1039 }
1040 
1041 void IdentifyMergEdgeConnec(const snake &snakein, vector<ConnecRemv> &connecEdit)
1042 {
1043  vector<bool> isObjDone;
1044  vector<int> tempSub, tempSub2, tempCount;
1045  HashedVector<int, int> tempIndHash;
1046  // vector<int> objSub;
1047  int nSnaxEdge, ii, nParent; // nSnax, nSnaxSurf,
1048  ConnecRemv tempConnec, tempConnec2;
1049 
1050  // nSnax=snakein.snaxs.size();
1051  nSnaxEdge = snakein.snaxedges.size();
1052  // nSnaxSurf=snakein.snaxsurfs.size();
1053 
1054  isObjDone.reserve(nSnaxEdge);
1055 
1056  isObjDone.assign(nSnaxEdge, false);
1057  for (ii = 0; ii < nSnaxEdge; ++ii)
1058  {
1059  if (!isObjDone[ii])
1060  {
1061  nParent = snakein.snaxedges.countparent(snakein.snaxedges(ii)->KeyParent());
1062  if (nParent > 1)
1063  {
1064  snakein.snaxedges.findsiblings(snakein.snaxedges(ii)->KeyParent(), tempSub);
1065  IdentifyMergeEdgeGeneral(snakein, isObjDone, connecEdit, tempConnec, tempConnec2, tempSub, tempSub2,
1066  tempCount, tempIndHash);
1067  }
1068  isObjDone[ii] = true;
1069  }
1070  }
1071 }
1072 
1073 void IdentifyMergeEdgeGeneral(const snake &snakein, vector<bool> &isObjDone, vector<ConnecRemv> &connecEdit,
1074  ConnecRemv &tempConnec, ConnecRemv &tempConnec2, vector<int> &tempSub,
1075  vector<int> &tempSub2, vector<int> &tempCount, HashedVector<int, int> &tempIndHash)
1076 {
1077  int jj, jjStart, nTemp;
1078 
1079  // check if the edges are connected
1080  tempIndHash.vec.clear();
1081  tempCount.clear();
1082  tempIndHash.vec = ConcatenateVectorField(snakein.snakeconn.edges, &edge::vertind, tempSub);
1083  tempIndHash.GenerateHash();
1084  tempCount = tempIndHash.count(tempIndHash.vec);
1085  tempCount.push_back(0);
1086  nTemp = tempCount.size() - 1;
1087 
1088  tempConnec2.scopeind.clear();
1089  for (jj = 0; jj < int(tempSub.size()); ++jj)
1090  {
1091  tempConnec2.scopeind.push_back(snakein.snaxedges(tempSub[jj])->index);
1092  }
1093  // perform all chains starting at a 1
1094  jjStart = 0;
1095  while (tempCount[jjStart] != 1 && jjStart < nTemp)
1096  {
1097  jjStart++;
1098  }
1099  while (jjStart < nTemp)
1100  {
1101  IdentifyMergeEdgeGeneralChain(snakein, isObjDone, connecEdit, tempConnec, tempConnec2, tempSub, tempSub2,
1102  tempCount, tempIndHash, jjStart);
1103 
1104  jjStart = 0;
1105  while (tempCount[jjStart] != 1 && jjStart < nTemp)
1106  {
1107  jjStart++;
1108  }
1109  }
1110  // perform all loops starting at a 2
1111  jjStart = 0;
1112 
1113  while (tempCount[jjStart] != 2 && jjStart < nTemp)
1114  {
1115  jjStart++;
1116  }
1117  while (jjStart < nTemp)
1118  {
1119  IdentifyMergeEdgeGeneralChain(snakein, isObjDone, connecEdit, tempConnec, tempConnec2, tempSub, tempSub2,
1120  tempCount, tempIndHash, jjStart);
1121  /*cout << endl;
1122  tempConnec.disp();
1123  tempConnec2.disp();*/
1124  jjStart = 0;
1125  while (tempCount[jjStart] != 2 && jjStart < nTemp)
1126  {
1127  jjStart++;
1128  }
1129  }
1130 }
1131 
1132 void IdentifyMergeEdgeGeneralChain(const snake &snakein, vector<bool> &isObjDone, vector<ConnecRemv> &connecEdit,
1133  ConnecRemv &tempConnec, ConnecRemv &tempConnec2, vector<int> &tempSub,
1134  vector<int> &tempSub2, vector<int> &tempCount, HashedVector<int, int> &tempIndHash,
1135  int jjStart)
1136 {
1137  int jj, jjNext;
1138  bool flagMoved, flag3;
1139  jj = jjStart;
1140  tempConnec.rmvind.clear();
1141  tempConnec2.rmvind.clear();
1142  tempConnec.typeobj = 2;
1143  tempConnec2.typeobj = 5;
1144 
1145  tempCount[jjStart] = 0;
1146  tempConnec.keepind = snakein.snaxedges(tempSub[jjStart / 2])->index;
1147  isObjDone[tempSub[jjStart / 2]] = true;
1148  // if second part of an edge check the other part
1149  jjNext = jj + (1 - ((jj % 2) * 2)); // equivalend of jj+ (jj%2 ? -1 : 1)
1150  flagMoved = false;
1151  while (tempCount[jjNext] > 1)
1152  {
1153  // Builds one group
1154  flagMoved = true;
1155 #ifdef SAFE_ALGO
1156  if (tempCount[jjNext] > 2)
1157  {
1158  cerr << endl;
1159  DisplayVector(tempCount);
1160  DisplayVector(tempIndHash.vec);
1161  cerr << endl;
1162  for (int i = 0; i < int(tempSub.size()); ++i)
1163  {
1164  snakein.snakeconn.edges(tempSub[i])->disp();
1165  }
1166  for (int i = 0; i < int(tempSub.size()); ++i)
1167  {
1168  snakein.snaxedges(tempSub[i])->disp();
1169  }
1170  for (int i = 0; i < int(tempIndHash.vec.size()); ++i)
1171  {
1172  snakein.snakeconn.verts.isearch(tempIndHash.vec[i])->disp();
1173  }
1174  for (int i = 0; i < int(tempIndHash.vec.size()); ++i)
1175  {
1176  snakein.snaxs.isearch(tempIndHash.vec[i])->disp();
1177  }
1178  // dispconnrmv(connecEdit);
1179  cerr << "Error: Algorithm not conceived for this case " << endl;
1180  cerr << " snake has more than 2 edges connected to the same snaxel "
1181  "inside the same surface "
1182  << endl;
1183  cerr << " in function:" << __PRETTY_FUNCTION__ << endl;
1184  // RSVS3D_ERROR_ARGUMENT("Unexpected algorithmic behaviour");
1185  }
1186 #endif // SAFE_ALGO
1187  flag3 = tempCount[jjNext] == 3;
1188  if (!flag3)
1189  {
1190  tempConnec2.rmvind.push_back(tempIndHash.vec[jjNext]);
1191  }
1192 
1193  tempCount[jjNext] = 0;
1194  tempSub2 = tempIndHash.findall(tempIndHash.vec[jjNext]);
1195  jj = 0;
1196  if (!flag3)
1197  {
1198  while (jj < 4 && tempSub2[jj] == jjNext)
1199  {
1200  ++jj;
1201  }
1202  }
1203  else
1204  {
1205  while ((tempSub2[jj] == jjNext || tempCount[tempSub2[jj]] < 3) && jj < 4)
1206  {
1207  ++jj;
1208  }
1209  tempCount[tempSub2[jj]] = 1;
1210  while ((tempSub2[jj] == jjNext || tempCount[tempSub2[jj]] < 3) && jj < 4)
1211  {
1212  ++jj;
1213  }
1214  }
1215 
1216 #ifdef SAFE_ALGO
1217  if (jj > (2))
1218  {
1219  cerr << "Error: Algorithm not conceived for this case " << endl;
1220  cerr << " jj>3 Unsafe read has happened " << endl;
1221  cerr << " in function:" << __PRETTY_FUNCTION__ << endl;
1222  RSVS3D_ERROR_ARGUMENT("Unexpected algorithmic behaviour");
1223  }
1224 #endif // SAFE_ALGO
1225 
1226  jj = tempSub2[jj];
1227  tempCount[jj] = 0;
1228  tempConnec.rmvind.push_back(snakein.snaxedges(tempSub[jj / 2])->index);
1229  isObjDone[tempSub[jj / 2]] = true;
1230 
1231  jjNext = jj + (1 - ((jj % 2) * 2));
1232  }
1233  tempConnec2.keepind = tempIndHash.vec[jjNext];
1234  if (flagMoved)
1235  {
1236  connecEdit.push_back(tempConnec);
1237  connecEdit.push_back(tempConnec2);
1238  }
1239 }
1240 
1241 void IdentifyMergSurfConnec(const snake &snakein, vector<ConnecRemv> &connecEdit)
1242 {
1243  vector<bool> isObjDone;
1244  vector<int> tempSub, tempSub2, tempCount;
1245  HashedVector<int, int> tempIndHash, edge2Surf;
1246  // vector<int> objSub;
1247  int nSnaxSurf, ii, nParent; // nSnax, nSnaxSurf,
1248  ConnecRemv tempConnec, tempConnec2;
1249 
1250  // nSnax=snakein.snaxs.size();
1251  nSnaxSurf = snakein.snaxsurfs.size();
1252  // nSnaxSurf=snakein.snaxsurfs.size();
1253 
1254  isObjDone.reserve(nSnaxSurf);
1255 
1256  isObjDone.assign(nSnaxSurf, false);
1257  for (ii = 0; ii < nSnaxSurf; ++ii)
1258  {
1259  if (!isObjDone[ii])
1260  {
1261  nParent = snakein.snaxsurfs.countparent(snakein.snaxsurfs(ii)->KeyParent());
1262  if (nParent > 1)
1263  {
1264  tempSub.clear();
1265  snakein.snaxsurfs.findsiblings(snakein.snaxsurfs(ii)->KeyParent(), tempSub);
1266  IdentifyMergeSurfGeneral(snakein, isObjDone, connecEdit, tempConnec, tempSub, tempSub2, tempCount,
1267  edge2Surf, tempIndHash);
1268  }
1269  isObjDone[ii] = true;
1270  }
1271  }
1272 }
1273 
1274 void IdentifyMergeSurfGeneral(const snake &snakein, vector<bool> &isObjDone, vector<ConnecRemv> &connecEdit,
1275  ConnecRemv &tempConnec, vector<int> &tempSub, vector<int> &tempSub2,
1276  vector<int> &tempCount, HashedVector<int, int> &edge2Surf,
1277  HashedVector<int, int> &tempIndHash)
1278 {
1279  // tempSub is the sub of surfaces in snakeconn that are in the same volume
1280  int ii, jj, jjStart, nTemp;
1281 
1282  edge2Surf.vec.clear();
1283  tempIndHash.vec = ConcatenateVectorField(snakein.snakeconn.surfs, &surf::edgeind, tempSub);
1284  // tempIndHash is a hashed vector of concatenate (surfs(tempSub).edgeind)
1285  for (ii = 0; ii < int(tempSub.size()); ++ii)
1286  {
1287  for (jj = 0; jj < int(snakein.snakeconn.surfs(tempSub[ii])->edgeind.size()); ++jj)
1288  {
1289  edge2Surf.vec.push_back(ii);
1290  }
1291  }
1292  // edge2Surf is a hashed vector of the subscripts into tempSub of the surf
1293  // matching the edges in tempHashInd
1294 
1295  tempIndHash.GenerateHash();
1296  edge2Surf.GenerateHash();
1297  tempCount = tempIndHash.count(tempIndHash.vec);
1298  tempCount.push_back(0);
1299  // tempCount is the vector counting the number of occurences of each edge at
1300  // each edges location
1301  nTemp = tempCount.size() - 1;
1302 
1303  jjStart = 0;
1304  while (tempCount[jjStart] <= 1 && jjStart < nTemp)
1305  {
1306  jjStart++;
1307  }
1308  // jjStart must start at a point were tempCount[jjStart] > 1 otherwise there
1309  // is no merging needed in the cell
1310 
1311  if (jjStart < nTemp)
1312  {
1313  do
1314  {
1315  // if can't find a count above 1 we're done
1316  tempConnec.rmvind.clear();
1317 
1318  tempSub2 = tempIndHash.findall(tempIndHash.vec[jjStart]);
1319  // tempSub2 is the position of edges matching that detected by jjStart
1320  tempConnec.typeobj = 3;
1321  isObjDone[tempSub[edge2Surf.vec[jjStart]]] = true;
1322  tempConnec.keepind = snakein.snakeconn.surfs(tempSub[edge2Surf.vec[jjStart]])->index;
1323  // Kept index is the last surf to be detected as having the edge of
1324  // jjStart
1325  tempCount[jjStart] = 0; // To ensure this edge is not set again set tempCount to 0
1326 
1327  IdentifyMergeSurfRecursive(snakein, isObjDone, tempCount, edge2Surf, tempIndHash, tempConnec, tempSub,
1328  tempSub2, jjStart);
1329  if (tempConnec.rmvind.size() > 0)
1330  {
1331  sort(tempConnec.rmvind);
1332  unique(tempConnec.rmvind);
1333  connecEdit.push_back(tempConnec);
1334 
1335  // cout << " " << tempConnec.rmvind.size() << " " << tempSub.size() << "
1336  // ; ";
1337  }
1338 
1339  while (tempCount[jjStart] <= 1 && jjStart < nTemp)
1340  {
1341  jjStart++;
1342  }
1343  } while (jjStart < nTemp);
1344  }
1345  // Note:
1346  // Check for surface collapse
1347  // if all of the edges are "collapsed edges" the surfaces need to be assembled
1348  // in a single surface and made a collapsed surface ie marked for deletion.
1349 }
1350 
1351 void IdentifyMergeSurfRecursive(const snake &snakein, vector<bool> &isObjDone, vector<int> &tempCount,
1352  const HashedVector<int, int> &edge2Surf, const HashedVector<int, int> &tempIndHash,
1353  ConnecRemv &tempConnec, const vector<int> &tempSub, const vector<int> &tempSub2,
1354  int excludeSub)
1355 {
1356  // tempSub2 is the position of edges matching that detected by jjStart
1357  // excludeSub is used to not recurse into the caller edge
1358  int ii, jj;
1359  vector<int> tempSurf, tempRecur;
1360 
1361  for (ii = 0; ii < int(tempSub2.size()); ++ii)
1362  {
1363  if (tempSub2[ii] != excludeSub)
1364  {
1365  if (!isObjDone[tempSub[edge2Surf.vec[tempSub2[ii]]]])
1366  {
1367  tempConnec.rmvind.push_back(snakein.snakeconn.surfs(tempSub[edge2Surf.vec[tempSub2[ii]]])->index);
1368 
1369  isObjDone[tempSub[edge2Surf.vec[tempSub2[ii]]]] = true;
1370  tempCount[tempSub2[ii]] = 0;
1371  // this edge is explored set to 0;
1372  // add all edges detected on the same edge as merge targets
1373  tempSurf = edge2Surf.findall(edge2Surf.vec[tempSub2[ii]]);
1374 
1375  // find all the occurences of that surf
1376  for (jj = 0; jj < int(tempSurf.size()); ++jj)
1377  {
1378  if (tempCount[tempSurf[jj]] > 1)
1379  {
1380  // for each edge of that cell which is tempCount>1 recurs
1381  tempCount[tempSurf[jj]] = 0;
1382  tempRecur = tempIndHash.findall(tempIndHash.vec[tempSurf[jj]]);
1383  IdentifyMergeSurfRecursive(snakein, isObjDone, tempCount, edge2Surf, tempIndHash, tempConnec,
1384  tempSub, tempRecur, tempSurf[jj]);
1385  }
1386  }
1387  }
1388  }
1389  }
1390 }
1391 
1392 void ModifyMergVoluConnec(snake &snakein, vector<ConnecRemv> &connecEdit, const vector<int> &indRmvVert)
1393 {
1394  vector<int> tempSub, tempSub2; // vector<int> objSub;
1395  int ii, jj, kk; // nSnax, nSnaxSurf,
1396  ConnecRemv tempConnec;
1397 
1398  for (ii = 0; ii < int(indRmvVert.size()); ++ii)
1399  {
1400  // find edges connected to vertex
1401  tempSub = snakein.snakeconn.edges.find_list(snakein.snakeconn.verts.isearch(indRmvVert[ii])->edgeind);
1402 
1403  tempSub2 = ConcatenateVectorField(snakein.snakeconn.edges, &edge::surfind, tempSub);
1404  tempSub = ConcatenateVectorField(snakein.snakeconn.surfs, &surf::voluind,
1405  snakein.snakeconn.surfs.find_list(tempSub2));
1406 
1407  sort(tempSub);
1408  unique(tempSub);
1409 
1410  if (int(tempSub.size()) > 1)
1411  {
1412  tempConnec.typeobj = 4;
1413  kk = 0;
1414  if (tempSub[kk] == 0)
1415  {
1416  kk++;
1417  }
1418  if (int(tempSub.size()) > (kk + 1))
1419  {
1420  tempConnec.keepind = tempSub[kk];
1421  tempConnec.rmvind.clear();
1422  for (jj = kk + 1; jj < int(tempSub.size()); ++jj)
1423  {
1424  if (tempSub[jj] > 0)
1425  {
1426  tempConnec.rmvind.push_back(tempSub[jj]);
1427  }
1428  }
1429  if (int(tempConnec.rmvind.size()) > 0)
1430  {
1431  for (jj = 0; jj < int(tempConnec.rmvind.size()); jj++)
1432  {
1433  snakein.snakeconn.SwitchIndex(tempConnec.typeobj, tempConnec.rmvind[jj], tempConnec.keepind,
1434  tempConnec.scopeind);
1435  }
1436  connecEdit.push_back(tempConnec);
1437  }
1438  }
1439  }
1440  }
1441 }
1442 
1443 void ModifyMergSurf2DConnec(snake &snakein, vector<ConnecRemv> &connecEdit)
1444 {
1445  /*
1446  Relies on on surfaces only. If they are connected by an edge they need to be
1447  merged.
1448  */
1449 
1450  int ii, jj, ni, nj, nAbove0; // nSnax, nSnaxSurf,
1451  ConnecRemv tempConnec;
1452 
1453  tempConnec.typeobj = 3;
1454  // kk = 0;
1455  ni = snakein.snakeconn.edges.size();
1456  // cout << endl;
1457  for (ii = 0; ii < ni; ++ii)
1458  {
1459  nj = snakein.snakeconn.edges(ii)->surfind.size();
1460  if (nj > 1)
1461  {
1462  nAbove0 = 0;
1463  for (jj = 0; jj < nj; ++jj)
1464  {
1465  nAbove0 += (snakein.snakeconn.edges(ii)->surfind[jj] > 0);
1466  }
1467  if (nAbove0 > 1)
1468  {
1469  nAbove0 = 0;
1470  tempConnec.keepind = -1;
1471  tempConnec.rmvind.clear();
1472 
1473  for (jj = 0; jj < nj; ++jj)
1474  {
1475  if (nAbove0 == 0)
1476  {
1477  tempConnec.keepind = snakein.snakeconn.edges(ii)->surfind[jj];
1478  }
1479  else if (snakein.snakeconn.edges(ii)->surfind[jj] != 0 &&
1480  snakein.snakeconn.edges(ii)->surfind[jj] != tempConnec.keepind)
1481  {
1482  tempConnec.rmvind.push_back(snakein.snakeconn.edges(ii)->surfind[jj]);
1483  }
1484  nAbove0 += (snakein.snakeconn.edges(ii)->surfind[jj] > 0);
1485  }
1486 
1487  for (jj = 0; jj < int(tempConnec.rmvind.size()); jj++)
1488  {
1489  snakein.snakeconn.SwitchIndex(tempConnec.typeobj, tempConnec.rmvind[jj], tempConnec.keepind,
1490  tempConnec.scopeind);
1491  // kk++;
1492  // cout << tempConnec.keepind << " " << tempConnec.rmvind[jj] << "|";
1493  }
1494  connecEdit.push_back(tempConnec);
1495  }
1496  }
1497  }
1498  // cout << " " << ni << endl;
1499 }
1500 
1501 // Checks before removal by snake engine
1502 // Most of these checks have to be performed on the remaining objects
1503 
1504 #pragma GCC diagnostic push
1505 #pragma GCC diagnostic ignored "-Wunused-parameter"
1506 void CheckSnakeRemovalsVert(const snake &snakein, const vector<int> &indRmvVert)
1507 {
1508  /*
1509  Vertex can be removed if
1510  */
1511 }
1512 void CheckSnakeRemovalsEdge(const snake &snakein, const vector<int> &indRmvEdge)
1513 {
1514  /*
1515  Edge can be removed if it is connected to one surface or one vertex.
1516  */
1517  int ii, jj, kk, ni, nj, ne, sub;
1518  bool cond1vert, cond1surf;
1519  ni = indRmvEdge.size();
1520  ne = 0;
1521  for (ii = 0; ii < ni; ++ii)
1522  {
1523  sub = snakein.snakeconn.edges.find(indRmvEdge[ii]);
1524  cond1vert = false;
1525  cond1surf = false;
1526 
1527  nj = snakein.snakeconn.edges(sub)->vertind.size();
1528  if (nj > 1)
1529  {
1530  jj = 0;
1531  kk = snakein.snakeconn.edges(sub)->vertind[jj];
1532  for (jj = 0; jj < nj; ++jj)
1533  {
1534  cond1vert = kk != snakein.snakeconn.edges(sub)->vertind[jj];
1535  if (cond1vert)
1536  {
1537  break;
1538  }
1539  }
1540  }
1541  else
1542  {
1543  cond1vert = true;
1544  }
1545 
1546  nj = snakein.snakeconn.edges(sub)->surfind.size();
1547  if (nj > 1)
1548  {
1549  jj = 0;
1550  kk = snakein.snakeconn.edges(sub)->surfind[jj];
1551  for (jj = 0; jj < nj; ++jj)
1552  {
1553  cond1surf = kk != snakein.snakeconn.edges(sub)->surfind[jj];
1554  if (cond1surf)
1555  {
1556  break;
1557  }
1558  }
1559  }
1560 
1561  if (!(cond1surf || cond1vert))
1562  {
1563  if (ne == 0)
1564  {
1565  cerr << endl;
1566  }
1567  snakein.snakeconn.edges(sub)->disptree(snakein.snakeconn, 2);
1568  cerr << endl
1569  << "Edge was marked for deletion but is connected"
1570  << " to more than 1 Surface and edge." << endl;
1571  ne++;
1572  }
1573  }
1574 
1575  // I don't think this error makes sense its a side effect of the cleanup.
1576  // ni = snakein.snakeconn.edges.size();
1577  // for (ii = 0; ii < ni; ++ii){
1578  // if (snakein.snakeconn.edges(ii)->surfind.size()>2){
1579  // // snakein.snakeconn.edges(ii)->disptree(snakein.snakeconn,1);
1580  // // cerr << endl << "Edge is connected to too many surfaces" <<
1581  // endl; if(ne==0){cerr<< endl;} cerr << "Edge error " << ne << " edge should
1582  // connect to single surface (surfind:)";
1583  // DisplayVector(snakein.snakeconn.edges(ii)->surfind);
1584  // cerr << endl;
1585  // ne++;
1586  // }
1587  // }
1588  if (ne > 0)
1589  {
1590  cerr << endl << "There were " << ne << " Edge deletion errors:";
1591  cerr << endl << __PRETTY_FUNCTION__ << endl;
1592  }
1593 }
1594 void CheckSnakeRemovalsSurf(const snake &snakein, const vector<int> &indRmvSurf)
1595 {
1596  /*
1597  Surf can be removed if
1598  */
1599 }
1600 void CheckSnakeRemovalsVolu(const snake &snakein, const vector<int> &indRmvVolu)
1601 {
1602  /*
1603  Vertex can be removed if
1604  */
1605 }
1606 #pragma GCC diagnostic pop
Class containing the information needed to trim objects from a mesh.
Definition: mesh.hpp:514
Class for mesh handling.
Definition: mesh.hpp:592
Definition: snake.hpp:83
Definition: snake.hpp:192
Provides all the mesh tools used for the generation of 3D grids and geometries.
Provides the core restricted surface snake container.
Functions needed to evolve the r-surface snake.
Provides the error and warning system used by the RSVS3D project.
#define RSVS3D_ERROR_ARGUMENT(M)
Throw a invalid_argument.
Definition: warning.hpp:148