got keys + clicks :)
[engrid.git] / operation.cpp
blobdd9c1c71c481e933d4cee4bd11657d3dae9d6eab
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008,2009 Oliver Gloth +
7 // + +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
12 // + +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
17 // + +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // + +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 #include "operation.h"
24 #include "guimainwindow.h"
25 #include "vtkTriangleFilter.h"
26 #include "vtkInformation.h"
27 #include "vtkInformationVector.h"
28 #include "vtkObjectFactory.h"
29 #include "vtkPointData.h"
30 #include "vtkPolyData.h"
31 #include "vtkPolygon.h"
32 #include "vtkStreamingDemandDrivenPipeline.h"
33 #include "vtkCellArray.h"
34 #include "vtkCellData.h"
35 #include "vtkCellLocator.h"
36 #include "vtkFloatArray.h"
37 #include "vtkMath.h"
38 #include <vtkCharArray.h>
39 #include "egvtkobject.h"
41 #include "geometrytools.h"
42 using namespace GeometryTools;
44 #include <QApplication>
46 QSet<Operation*> Operation::garbage_operations;
48 void Operation::collectGarbage()
50 QSet<Operation*> delete_operations;
51 foreach (Operation *op, garbage_operations) {
52 if (!op->getThread().isRunning()) {
53 delete_operations.insert(op);
54 cout << "deleting Operation " << op << endl;
55 delete op;
58 foreach (Operation *op, delete_operations) {
59 garbage_operations.remove(op);
63 Operation::Operation()
65 grid = NULL;
66 gui = false;
67 err = NULL;
68 autoset = true;
70 //default values for determining node types and for smoothing operations
71 Convergence=0;
72 NumberOfIterations=20;
73 RelaxationFactor=0.01;
74 FeatureEdgeSmoothing=1;//0 by default in VTK, but we need 1 to avoid the "potatoe effect" ^^
75 FeatureAngle=45;
76 EdgeAngle=15;
77 BoundarySmoothing=1;
78 GenerateErrorScalars=0;
79 GenerateErrorVectors=0;
82 Operation::~Operation()
84 if (err) {
85 err->display();
86 delete err;
90 void Operation::del()
92 garbage_operations.insert(this);
95 void OperationThread::run()
97 try {
98 GuiMainWindow::lock();
99 GuiMainWindow::pointer()->setBusy();
100 op->operate();
101 } catch (Error err) {
102 op->err = new Error();
103 *(op->err) = err;
105 GuiMainWindow::unlock();
106 GuiMainWindow::pointer()->setIdle();
109 void Operation::operator()()
111 if (gui) {
112 if (GuiMainWindow::tryLock()) {
113 checkGrid();
114 thread.setOperation(this);
115 GuiMainWindow::unlock();
116 thread.start(QThread::LowPriority);
117 } else {
118 QMessageBox::warning(NULL, "not permitted", "Operation is not permitted while background process is running!");
120 } else {
121 checkGrid();
122 operate();
125 checkGrid();
126 operate();
130 void Operation::setAllCells()
132 QVector<vtkIdType> all_cells;
133 getAllCells(all_cells, grid);
134 setCells(all_cells);
137 void Operation::setAllVolumeCells()
139 QVector<vtkIdType> cells;
140 getAllVolumeCells(cells, grid);
141 setCells(cells);
144 void Operation::setAllSurfaceCells()
146 QVector<vtkIdType> cells;
147 getAllSurfaceCells(cells, grid);
148 setCells(cells);
151 void Operation::initMapping()
153 nodes_map.resize(nodes.size());
154 for (int i_nodes = 0; i_nodes < nodes.size(); ++i_nodes) {
155 nodes_map[i_nodes] = nodes[i_nodes];
157 cells_map.resize(cells.size());
158 for (int i_cells = 0; i_cells < cells.size(); ++i_cells) {
159 cells_map[i_cells] = cells[i_cells];
163 void Operation::checkGrid()
165 if (grid == NULL) {
166 grid = GuiMainWindow::pointer()->getGrid();
168 if ((cells.size() == 0) && autoset) {
169 setAllCells();
173 void Operation::updateActors()
175 mainWindow()->updateActors();
178 GuiMainWindow* Operation::mainWindow()
180 return GuiMainWindow::pointer();
183 void Operation::populateBoundaryCodes(QListWidget *lw)
185 QSet<int> bcs;
186 mainWindow()->getAllBoundaryCodes(bcs);
187 foreach(int bc, bcs) {
188 QListWidgetItem *lwi = new QListWidgetItem(lw);
189 lwi->setCheckState(Qt::Unchecked);
190 QString text = "";
191 QTextStream ts(&text);
192 ts << bc;
193 lwi->setText(text);
194 lwi->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
198 //TODO: Get the EG_BUG error again and figure out where it came from
199 stencil_t Operation::getStencil(vtkIdType id_cell1, int j1)
201 stencil_t S;
202 S.valid = true;
203 S.id_cell1 = id_cell1;
204 if (c2c[_cells[id_cell1]][j1] != -1) {
205 S.id_cell2 = cells[c2c[_cells[id_cell1]][j1]];
206 if (grid->GetCellType(S.id_cell2) != VTK_TRIANGLE) {
207 EG_BUG;
209 vtkIdType N1, N2, *pts1, *pts2;
210 grid->GetCellPoints(S.id_cell1, N1, pts1);
211 grid->GetCellPoints(S.id_cell2, N2, pts2);
212 if (j1 == 0) { S.p[0] = pts1[2]; S.p[1] = pts1[0]; S.p[3] = pts1[1]; }
213 else if (j1 == 1) { S.p[0] = pts1[0]; S.p[1] = pts1[1]; S.p[3] = pts1[2]; }
214 else if (j1 == 2) { S.p[0] = pts1[1]; S.p[1] = pts1[2]; S.p[3] = pts1[0]; };
215 bool p2 = false;
216 if (c2c[_cells[S.id_cell2]][0] != -1) {
217 if (cells[c2c[_cells[S.id_cell2]][0]] == S.id_cell1) {
218 S.p[2] = pts2[2];
219 p2 = true;
222 if (c2c[_cells[S.id_cell2]][1] != -1) {
223 if (cells[c2c[_cells[S.id_cell2]][1]] == S.id_cell1) {
224 S.p[2] = pts2[0];
225 p2 = true;
228 if (c2c[_cells[S.id_cell2]][2] != -1) {
229 if (cells[c2c[_cells[S.id_cell2]][2]] == S.id_cell1) {
230 S.p[2] = pts2[1];
231 p2 = true;
234 if (!p2) {
235 EG_BUG;
237 } else {
238 S.valid = false;
239 S.id_cell2 = -1;
240 vtkIdType N1, *pts1;
241 grid->GetCellPoints(S.id_cell1, N1, pts1);
242 if (j1 == 0) { S.p[0] = pts1[2]; S.p[1] = pts1[0]; S.p[3] = pts1[1]; }
243 else if (j1 == 1) { S.p[0] = pts1[0]; S.p[1] = pts1[1]; S.p[3] = pts1[2]; }
244 else if (j1 == 2) { S.p[0] = pts1[1]; S.p[1] = pts1[2]; S.p[3] = pts1[0]; };
246 return S;
249 ostream& operator<<(ostream &out, stencil_t S)
251 out<<"S.id_cell1="<<S.id_cell1<<" ";
252 out<<"S.id_cell2="<<S.id_cell2<<" ";
253 out<<"S.valid="<<S.valid<<" ";
254 out<<"[";
255 for(int i=0;i<4;i++){
256 out<<S.p[i];
257 if(i!=3) out<<",";
259 out<<"]";
260 return(out);
263 //////////////////////////////////////////////
264 double CurrentVertexAvgDist(vtkIdType a_vertex,QVector< QSet< int > > &n2n,vtkUnstructuredGrid *a_grid)
266 double total_dist=0;
267 double avg_dist=0;
268 int N=n2n[a_vertex].size();
269 vec3_t C;
270 a_grid->GetPoint(a_vertex, C.data());
271 foreach(int i,n2n[a_vertex])
273 vec3_t M;
274 a_grid->GetPoint(i, M.data());
275 total_dist+=(M-C).abs();
277 avg_dist=total_dist/(double)N;
278 return(avg_dist);
281 double CurrentMeshDensity(vtkIdType a_vertex,QVector< QSet< int > > &n2n,vtkUnstructuredGrid *a_grid)
283 double total_dist=0;
284 double avg_dist=0;
285 int N=n2n[a_vertex].size();
286 vec3_t C;
287 a_grid->GetPoint(a_vertex, C.data());
288 foreach(int i,n2n[a_vertex])
290 vec3_t M;
291 a_grid->GetPoint(i, M.data());
292 total_dist+=(M-C).abs();
294 avg_dist=total_dist/(double)N;
295 double avg_density=1./avg_dist;
296 return(avg_density);
299 double DesiredVertexAvgDist(vtkIdType a_vertex,QVector< QSet< int > > &n2n,vtkUnstructuredGrid *a_grid)
301 double total_dist=0;
302 double avg_dist=0;
303 EG_VTKDCN(vtkDoubleArray, node_meshdensity, a_grid, "node_meshdensity");
304 int N=n2n[a_vertex].size();
305 foreach(int i,n2n[a_vertex])
307 total_dist+=1./node_meshdensity->GetValue(i);
309 avg_dist=total_dist/(double)N;
310 return(avg_dist);
313 double DesiredMeshDensity(vtkIdType a_vertex,QVector< QSet< int > > &n2n,vtkUnstructuredGrid *a_grid)
315 double total_density=0;
316 double avg_density=0;
317 EG_VTKDCN(vtkDoubleArray, node_meshdensity, a_grid, "node_meshdensity");
318 int N=n2n[a_vertex].size();
319 foreach(int i,n2n[a_vertex])
321 total_density+=node_meshdensity->GetValue(i);
323 avg_density=total_density/(double)N;
324 return(avg_density);
327 ///////////////////////////////////////////
328 vtkIdType Operation::getClosestNode(vtkIdType a_id_node,vtkUnstructuredGrid* a_grid)
330 vec3_t C;
331 a_grid->GetPoint(a_id_node,C.data());
332 vtkIdType id_minlen=-1;
333 double minlen=-1;
334 foreach(vtkIdType neighbour,n2n[a_id_node])
336 vec3_t M;
337 a_grid->GetPoint(neighbour,M.data());
338 double len=(M-C).abs();
339 if(minlen<0 or len<minlen)
341 minlen=len;
342 id_minlen=neighbour;
345 return(id_minlen);
348 vtkIdType Operation::getFarthestNode(vtkIdType a_id_node,vtkUnstructuredGrid* a_grid)
350 vec3_t C;
351 a_grid->GetPoint(a_id_node,C.data());
352 vtkIdType id_maxlen=-1;
353 double maxlen=-1;
354 foreach(vtkIdType neighbour,n2n[a_id_node])
356 vec3_t M;
357 a_grid->GetPoint(neighbour,M.data());
358 double len=(M-C).abs();
359 if(maxlen<0 or len>maxlen)
361 maxlen=len;
362 id_maxlen=neighbour;
365 return(id_maxlen);
368 bool Operation::SwapCells(vtkUnstructuredGrid* a_grid, stencil_t S)
370 bool swap = false;
371 if (S.valid) {
372 vec3_t x3[4], x3_0(0,0,0);
373 vec2_t x[4];
374 for (int k = 0; k < 4; ++k) {
375 a_grid->GetPoints()->GetPoint(S.p[k], x3[k].data());
376 x3_0 += x3[k];
378 vec3_t n1 = triNormal(x3[0], x3[1], x3[3]);
379 vec3_t n2 = triNormal(x3[1], x3[2], x3[3]);
380 n1.normalise();
381 n2.normalise();
382 if ( (n1*n2) > 0.8) {
383 vec3_t n = n1 + n2;
384 n.normalise();
385 vec3_t ex = orthogonalVector(n);
386 vec3_t ey = ex.cross(n);
387 for (int k = 0; k < 4; ++k) {
388 x[k] = vec2_t(x3[k]*ex, x3[k]*ey);
390 vec2_t r1, r2, r3, u1, u2, u3;
391 r1 = 0.5*(x[0] + x[1]); u1 = turnLeft(x[1] - x[0]);
392 r2 = 0.5*(x[1] + x[2]); u2 = turnLeft(x[2] - x[1]);
393 r3 = 0.5*(x[1] + x[3]); u3 = turnLeft(x[3] - x[1]);
394 double k, l;
395 vec2_t xm1, xm2;
396 bool ok = true;
397 if (intersection(k, l, r1, u1, r3, u3)) {
398 xm1 = r1 + k*u1;
399 if (intersection(k, l, r2, u2, r3, u3)) {
400 xm2 = r2 + k*u2;
401 } else {
402 ok = false;
404 } else {
405 ok = false;
406 swap = true;
408 if (ok) {
409 if ((xm1 - x[2]).abs() < (xm1 - x[0]).abs()) {
410 swap = true;
412 if ((xm2 - x[0]).abs() < (xm2 - x[2]).abs()) {
413 swap = true;
418 if (swap) {
419 vtkIdType new_pts1[3], new_pts2[3];
420 new_pts1[0] = S.p[1];
421 new_pts1[1] = S.p[2];
422 new_pts1[2] = S.p[0];
423 new_pts2[0] = S.p[2];
424 new_pts2[1] = S.p[3];
425 new_pts2[2] = S.p[0];
426 a_grid->ReplaceCell(S.id_cell1, 3, new_pts1);
427 a_grid->ReplaceCell(S.id_cell2, 3, new_pts2);
429 return(swap);
432 void Operation::quad2triangle(vtkUnstructuredGrid* src,vtkIdType quadcell)
434 vtkIdType type_cell = grid->GetCellType(quadcell);
435 cout<<"It's a "<<type_cell<<endl;
436 if(type_cell==VTK_QUAD)
438 cout_grid(cout,src,true,true,true,true);
439 EG_VTKSP(vtkUnstructuredGrid, dst);
440 //src grid info
441 int N_points=src->GetNumberOfPoints();
442 int N_cells=src->GetNumberOfCells();
443 allocateGrid(dst,N_cells+1,N_points);
445 for (vtkIdType id_node = 0; id_node < src->GetNumberOfPoints(); ++id_node) {
446 vec3_t x;
447 src->GetPoints()->GetPoint(id_node, x.data());
448 dst->GetPoints()->SetPoint(id_node, x.data());
449 copyNodeData(src, id_node, dst, id_node);
451 for (vtkIdType id_cell = 0; id_cell < src->GetNumberOfCells(); ++id_cell) {
452 vtkIdType N_pts, *pts;
453 vtkIdType type_cell = src->GetCellType(id_cell);
454 src->GetCellPoints(id_cell, N_pts, pts);
455 vtkIdType id_new_cell;
456 vtkIdType id_new_cell1;
457 vtkIdType id_new_cell2;
458 if(id_cell!=quadcell)
460 id_new_cell = dst->InsertNextCell(type_cell, N_pts, pts);
461 copyCellData(src, id_cell, dst, id_new_cell);
463 else
465 vtkIdType triangle1[3];
466 vtkIdType triangle2[3];
467 triangle1[0]=pts[1];
468 triangle1[1]=pts[3];
469 triangle1[2]=pts[0];
470 triangle2[0]=pts[3];
471 triangle2[1]=pts[1];
472 triangle2[2]=pts[2];
473 id_new_cell1 = dst->InsertNextCell(VTK_TRIANGLE, 3, triangle1);
474 copyCellData(src, id_cell, dst, id_new_cell1);
475 id_new_cell2 = dst->InsertNextCell(VTK_TRIANGLE, 3, triangle2);
476 copyCellData(src, id_cell, dst, id_new_cell2);
477 stencil_t S;
478 S.id_cell1=id_new_cell1;
479 S.id_cell2=id_new_cell2;
480 S.p[0]=pts[0];
481 S.p[1]=pts[1];
482 S.p[2]=pts[2];
483 S.p[3]=pts[3];
484 S.valid=true;
485 SwapCells(dst,S);
488 cout_grid(cout,dst,true,true,true,true);
489 makeCopy(dst, src);
490 }//end of if quad
493 void Operation::quad2triangle(vtkUnstructuredGrid* src,vtkIdType quadcell,vtkIdType MovingPoint)
495 vtkIdType type_cell = grid->GetCellType(quadcell);
496 cout<<"It's a "<<type_cell<<endl;
497 if(type_cell==VTK_QUAD)
499 cout_grid(cout,src,true,true,true,true);
500 EG_VTKSP(vtkUnstructuredGrid, dst);
501 //src grid info
502 int N_points=src->GetNumberOfPoints();
503 int N_cells=src->GetNumberOfCells();
504 allocateGrid(dst,N_cells+1,N_points);
506 for (vtkIdType id_node = 0; id_node < src->GetNumberOfPoints(); ++id_node) {
507 vec3_t x;
508 src->GetPoints()->GetPoint(id_node, x.data());
509 dst->GetPoints()->SetPoint(id_node, x.data());
510 copyNodeData(src, id_node, dst, id_node);
512 for (vtkIdType id_cell = 0; id_cell < src->GetNumberOfCells(); ++id_cell) {
513 vtkIdType N_pts, *pts;
514 src->GetCellPoints(id_cell, N_pts, pts);
515 vtkIdType type_cell = src->GetCellType(id_cell);
516 vtkIdType id_new_cell;
517 vtkIdType id_new_cell1;
518 vtkIdType id_new_cell2;
519 if(id_cell!=quadcell)
521 id_new_cell = dst->InsertNextCell(type_cell, N_pts, pts);
522 copyCellData(src, id_cell, dst, id_new_cell);
524 else
526 vtkIdType triangle1[3];
527 vtkIdType triangle2[3];
528 if(MovingPoint==pts[0] || MovingPoint==pts[2])
530 triangle1[0]=pts[1];
531 triangle1[1]=pts[3];
532 triangle1[2]=pts[0];
533 triangle2[0]=pts[3];
534 triangle2[1]=pts[1];
535 triangle2[2]=pts[2];
537 else
539 triangle1[0]=pts[2];
540 triangle1[1]=pts[0];
541 triangle1[2]=pts[1];
542 triangle2[0]=pts[0];
543 triangle2[1]=pts[2];
544 triangle2[2]=pts[3];
546 id_new_cell1 = dst->InsertNextCell(VTK_TRIANGLE, 3, triangle1);
547 copyCellData(src, id_cell, dst, id_new_cell1);
548 id_new_cell2 = dst->InsertNextCell(VTK_TRIANGLE, 3, triangle2);
549 copyCellData(src, id_cell, dst, id_new_cell2);
552 cout_grid(cout,dst,true,true,true,true);
553 makeCopy(dst, src);
554 }//end of if quad
557 int Operation::NumberOfCommonPoints(vtkIdType node1, vtkIdType node2, bool& IsTetra)
559 // QVector< QSet< int > > n2n
560 QSet <int> node1_neighbours=n2n[node1];
561 QSet <int> node2_neighbours=n2n[node2];
562 QSet <int> intersection=node1_neighbours.intersect(node2_neighbours);
563 int N=intersection.size();
564 IsTetra=false;
565 if(N==2)
567 QSet<int>::const_iterator p1=intersection.begin();
568 QSet<int>::const_iterator p2=p1+1;
569 vtkIdType intersection1=_nodes[*p1];
570 vtkIdType intersection2=_nodes[*p2];
571 if(n2n[intersection1].contains(intersection2))//if there's an edge between intersection1 and intersection2
573 //check if (node1,intersection1,intersection2) and (node2,intersection1,intersection2) are defined as cells!
574 // QVector< QSet< int > > n2c
575 QSet< int > S1=n2c[intersection1];
576 QSet< int > S2=n2c[intersection2];
577 QSet< int > Si=S1.intersect(S2);
578 int counter=0;
579 foreach(vtkIdType C,Si){
580 vtkIdType N_pts, *pts;
581 grid->GetCellPoints(C, N_pts, pts);
582 for(int i=0;i<N_pts;i++)
584 if(pts[i]==node1 || pts[i]==node2) counter++;
587 if(counter>=2) IsTetra=true;
590 return(N);
593 // vtkIdType Operation::FindSnapPoint(vtkUnstructuredGrid *src, vtkIdType DeadNode)
594 // {
595 // return(0);
596 // }
598 bool Operation::DeletePoint(vtkUnstructuredGrid *src, vtkIdType DeadNode)
600 EG_VTKSP(vtkUnstructuredGrid, dst);
602 //src grid info
603 int N_points=src->GetNumberOfPoints();
604 int N_cells=src->GetNumberOfCells();
605 int N_newpoints=-1;
606 int N_newcells=0;
608 if(DeadNode<0 || DeadNode>=N_points)
610 cout<<"Warning: Point out of range: DeadNode="<<DeadNode<<" N_points="<<N_points<<endl;
611 return(false);
614 QSet <vtkIdType> DeadCells;
615 QSet <vtkIdType> MutatedCells;
616 QSet <vtkIdType> MutilatedCells;
618 vtkIdType SnapPoint=-1;
619 //Find closest point to DeadNode
620 // vtkIdType SnapPoint = getClosestNode(DeadNode,src);//DeadNode moves to SnapPoint
622 foreach(vtkIdType PSP, n2n[DeadNode])
624 bool IsValidSnapPoint=true;
626 cout<<"====>PSP="<<PSP<<endl;
627 bool IsTetra=true;
628 if(NumberOfCommonPoints(DeadNode,PSP,IsTetra)>2)//common point check
630 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
631 IsValidSnapPoint=false;
633 if(IsTetra)//tetra check
635 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
636 IsValidSnapPoint=false;
639 //count number of points and cells to remove + analyse cell transformations
640 N_newpoints=-1;
641 N_newcells=0;
642 DeadCells.clear();
643 MutatedCells.clear();
644 MutilatedCells.clear();
645 foreach(vtkIdType C, n2c[DeadNode])//loop through potentially dead cells
647 cout<<"C="<<C<<endl;
648 //get points around cell
649 vtkIdType N_pts, *pts;
650 src->GetCellPoints(C, N_pts, pts);
652 bool ContainsSnapPoint=false;
653 bool invincible=false;
654 for(int i=0;i<N_pts;i++)
656 cout<<"pts["<<i<<"]="<<pts[i]<<" and PSP="<<PSP<<endl;
657 if(pts[i]==PSP) {ContainsSnapPoint=true;}
658 if(pts[i]!=DeadNode && pts[i]!=PSP && n2c[pts[i]].size()<=1) invincible=true;
660 if(ContainsSnapPoint)
662 if(N_pts==3)//dead cell
664 if(invincible)//Check that empty lines aren't left behind when a cell is killed
666 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
667 IsValidSnapPoint=false;
669 else
671 DeadCells.insert(C);
672 N_newcells-=1;
673 cout<<"cell "<<C<<" has been pwned!"<<endl;
676 /* else if(N_pts==4)//mutilated cell
678 MutilatedCells.insert(C);
679 cout<<"cell "<<C<<" has lost a limb!"<<endl;
681 else
683 cout<<"RED ALERT: Xenomorph detected!"<<endl;
684 EG_BUG;
687 else
689 vtkIdType src_N_pts, *src_pts;
690 src->GetCellPoints(C, src_N_pts, src_pts);
692 if(src_N_pts!=3)
694 cout<<"RED ALERT: Xenomorph detected!"<<endl;
695 EG_BUG;
698 vtkIdType OldTriangle[3];
699 vtkIdType NewTriangle[3];
701 for(int i=0;i<src_N_pts;i++)
703 OldTriangle[i]=src_pts[i];
704 NewTriangle[i]=( (src_pts[i]==DeadNode) ? PSP : src_pts[i] );
706 vec3_t Old_N= triNormal(src, OldTriangle[0], OldTriangle[1], OldTriangle[2]);
707 vec3_t New_N= triNormal(src, NewTriangle[0], NewTriangle[1], NewTriangle[2]);
708 double OldArea=Old_N.abs();
709 double NewArea=New_N.abs();
710 double scal=Old_N*New_N;
711 double cross=(Old_N.cross(New_N)).abs();//double-cross on Nar Shadaa B-)
713 cout<<"OldArea="<<OldArea<<endl;
714 cout<<"NewArea="<<NewArea<<endl;
715 cout<<"scal="<<scal<<endl;
716 cout<<"cross="<<cross<<endl;
718 if(Old_N*New_N<Old_N*Old_N*1./100.)//area + inversion check
720 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
721 IsValidSnapPoint=false;
724 /* if(NewArea<OldArea*1./100.)
726 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
727 IsValidSnapPoint=false;
730 if(abs(cross)>10e-4)
732 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
733 IsValidSnapPoint=false;
736 //mutated cell
737 MutatedCells.insert(C);
738 cout<<"cell "<<C<<" has been infected!"<<endl;
742 if(N_cells+N_newcells<=0)//survivor check
744 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
745 IsValidSnapPoint=false;
747 /* if(EmptyVolume(DeadNode,PSP))//simplified volume check
749 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
750 IsValidSnapPoint=false;
752 if(IsValidSnapPoint) {SnapPoint=PSP; break;}
753 }//end of loop through potential SnapPoints
755 cout<<"===>SNAPPOINT="<<SnapPoint<<endl;
756 if(SnapPoint<0) {cout<<"Sorry no possible SnapPoint found."<<endl; return(false);}
758 //allocate
759 cout<<"N_points="<<N_points<<endl;
760 cout<<"N_cells="<<N_cells<<endl;
761 cout<<"N_newpoints="<<N_newpoints<<endl;
762 cout<<"N_newcells="<<N_newcells<<endl;
763 allocateGrid(dst,N_cells+N_newcells,N_points+N_newpoints);
765 //vector used to redefine the new point IDs
766 QVector <vtkIdType> OffSet(N_points);
768 //copy undead points
769 vtkIdType dst_id_node=0;
770 for (vtkIdType src_id_node = 0; src_id_node < N_points; src_id_node++) {//loop through src points
771 if(src_id_node!=DeadNode)//if the node isn't dead, copy it
773 vec3_t x;
774 src->GetPoints()->GetPoint(src_id_node, x.data());
775 dst->GetPoints()->SetPoint(dst_id_node, x.data());
776 copyNodeData(src, src_id_node, dst, dst_id_node);
777 OffSet[src_id_node]=src_id_node-dst_id_node;
778 dst_id_node++;
782 cout<<"DeadCells="<<DeadCells<<endl;
783 cout<<"MutatedCells="<<MutatedCells<<endl;
784 cout<<"MutilatedCells="<<MutilatedCells<<endl;
786 //Copy undead cells
787 for (vtkIdType id_cell = 0; id_cell < src->GetNumberOfCells(); ++id_cell) {//loop through src cells
788 if(!DeadCells.contains(id_cell))//if the cell isn't dead
790 vtkIdType src_N_pts, *src_pts;
791 vtkIdType dst_N_pts, *dst_pts;
792 src->GetCellPoints(id_cell, src_N_pts, src_pts);
794 vtkIdType type_cell = src->GetCellType(id_cell);
795 cout<<"-->id_cell="<<id_cell<<endl;
796 for(int i=0;i<src_N_pts;i++) cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
797 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
798 dst_N_pts=src_N_pts;
799 dst_pts=new vtkIdType[dst_N_pts];
800 if(MutatedCells.contains(id_cell))//mutated cell
802 cout<<"processing mutated cell "<<id_cell<<endl;
803 for(int i=0;i<src_N_pts;i++)
805 if(src_pts[i]==DeadNode) {
806 cout<<"SnapPoint="<<SnapPoint<<endl;
807 cout<<"OffSet[SnapPoint]="<<OffSet[SnapPoint]<<endl;
808 cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
809 dst_pts[i]=SnapPoint-OffSet[SnapPoint];
811 else dst_pts[i]=src_pts[i]-OffSet[src_pts[i]];
813 cout<<"--->dst_pts:"<<endl;
814 for(int i=0;i<dst_N_pts;i++) cout<<"dst_pts["<<i<<"]="<<dst_pts[i]<<endl;
817 else if(MutilatedCells.contains(id_cell))//mutilated cell
819 cout<<"processing mutilated cell "<<id_cell<<endl;
821 if(type_cell==VTK_QUAD) {
822 type_cell=VTK_TRIANGLE;
823 dst_N_pts-=1;
825 else {cout<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl;EG_BUG;}
826 //merge points
827 int j=0;
828 for(int i=0;i<src_N_pts;i++)
830 if(src_pts[i]==SnapPoint) { dst_pts[j]=SnapPoint-OffSet[SnapPoint];j++; }//SnapPoint
831 else if(src_pts[i]!=DeadNode) { dst_pts[j]=src_pts[i]-OffSet[src_pts[i]];j++; }//pre-snap/dead + post-snap/dead
832 //do nothing in case of DeadNode
835 else//normal cell
837 cout<<"processing normal cell "<<id_cell<<endl;
838 for(int i=0;i<src_N_pts;i++)
840 dst_pts[i]=src_pts[i]-OffSet[src_pts[i]];
843 //copy the cell
844 vtkIdType id_new_cell = dst->InsertNextCell(type_cell, dst_N_pts, dst_pts);
845 copyCellData(src, id_cell, dst, id_new_cell);
846 cout<<"===Copying cell "<<id_cell<<" to "<<id_new_cell<<"==="<<endl;
847 cout<<"src_pts:"<<endl;
848 for(int i=0;i<src_N_pts;i++) cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
849 cout<<"dst_pts:"<<endl;
850 for(int i=0;i<dst_N_pts;i++) cout<<"dst_pts["<<i<<"]="<<dst_pts[i]<<endl;
851 cout<<"OffSet="<<OffSet<<endl;
852 cout<<"===Copying cell end==="<<endl;
853 delete dst_pts;
856 // cout_grid(cout,dst,true,true,true,true);
857 makeCopy(dst, src);
858 return(true);
861 bool Operation::EmptyVolume(vtkIdType DeadNode, vtkIdType PSP)
863 c2c[DeadNode];
864 c2c[PSP];
865 return(true);
868 vec3_t Operation::GetCenter(vtkIdType cellId, double& R)
870 vtkIdType *pts, Npts;
871 grid->GetCellPoints(cellId, Npts, pts);
873 vec3_t x(0,0,0);
874 for (vtkIdType i = 0; i < Npts; ++i) {
875 vec3_t xp;
876 grid->GetPoints()->GetPoint(pts[i], xp.data());
877 x += double(1)/Npts * xp;
880 R = 1e99;
881 for (vtkIdType i = 0; i < Npts; ++i) {
882 vec3_t xp;
883 grid->GetPoints()->GetPoint(pts[i], xp.data());
884 R = min(R, 0.25*(xp-x).abs());
887 return(x);
890 bool Operation::getNeighbours(vtkIdType Boss, QVector <vtkIdType>& Peons, int BC)
892 // QVector <vtkIdType> Peons;
894 QSet <int> S1=n2c[Boss];
895 cout<<"S1="<<S1<<endl;
896 foreach(vtkIdType PN,n2n[Boss])
898 cout<<"PN="<<PN<<endl;
899 QSet <int> S2=n2c[PN];
900 cout<<"S2="<<S2<<endl;
901 QSet <int> Si=S2.intersect(S1);
902 cout<<"PN="<<PN<<" Si="<<Si<<endl;
903 if(Si.size()<2)//only one common cell
905 Peons.push_back(PN);
907 else
909 QSet <int> bc_set;
910 foreach(vtkIdType C,Si)
912 EG_VTKDCC(vtkIntArray, cell_code, grid, "cell_code");
913 int bc=cell_code->GetValue(C);
914 cout<<"C="<<C<<" bc="<<bc<<endl;
915 bc_set.insert(bc);
917 if(bc_set.size()>1)//2 different boundary codes
919 Peons.push_back(PN);
923 if(Peons.size()==2)
925 /* Peon1=Peons[0];
926 Peon2=Peons[1];*/
927 return(true);
929 else
931 int N=n2n[Boss].size();
932 QVector <vtkIdType> neighbours(N);
933 qCopy(n2n[Boss].begin(), n2n[Boss].end(), neighbours.begin());
935 double alphamin_value;
936 vtkIdType alphamin_i;
937 vtkIdType alphamin_j;
938 bool first=true;
940 for(int i=0;i<N;i++)
942 for(int j=i+1;j<N;j++)
944 double alpha=deviation(grid,neighbours[i],Boss,neighbours[j]);
945 // cout<<"alpha("<<neighbours[i]<<","<<Boss<<","<<neighbours[j]<<")="<<alpha<<endl;
946 if(first) {
947 alphamin_value=alpha;
948 alphamin_i=i;
949 alphamin_j=j;
950 first=false;
952 else
954 if(alpha<alphamin_value)
956 alphamin_value=alpha;
957 alphamin_i=i;
958 alphamin_j=j;
963 // cout<<"alphamin_value="<<alphamin_value<<endl;
965 Peons.resize(2);
966 Peons[0]=neighbours[alphamin_i];
967 Peons[1]=neighbours[alphamin_j];
968 return(true);
969 /* cout<<"FATAL ERROR: number of neighbours != 2"<<endl;
970 EG_BUG;*/
972 return(false);
975 int Operation::UpdateMeshDensity()
977 cout<<"===UpdateMeshDensity START==="<<endl;
979 getAllSurfaceCells(cells,grid);
980 EG_VTKDCC(vtkIntArray, cell_code, grid, "cell_code");
981 EG_VTKDCN(vtkDoubleArray, node_meshdensity, grid, "node_meshdensity");
982 getNodesFromCells(cells, nodes, grid);
983 setGrid(grid);
984 setCells(cells);
986 if(DebugLevel>5) cout<<"cells.size()="<<cells.size()<<endl;
988 EG_VTKDCN(vtkDoubleArray, node_meshdensity_current, grid, "node_meshdensity_current");
989 foreach(vtkIdType node,nodes)
991 double L=CurrentVertexAvgDist(node,n2n,grid);
992 double D=1./L;
993 node_meshdensity_current->SetValue(node, D);
995 cout<<"===UpdateMeshDensity END==="<<endl;
996 return(0);
999 // Special structure for marking vertices
1000 typedef struct _vtkMeshVertex
1002 char type;
1003 vtkIdList *edges; // connected edges (list of connected point ids)
1004 } vtkMeshVertex, *vtkMeshVertexPtr;
1006 int Operation::UpdateNodeType_all()
1008 cout<<"===UpdateNodeType_all START==="<<endl;
1009 if(DebugLevel>47) cout<<"this->FeatureAngle="<<this->FeatureAngle<<endl;
1010 if(DebugLevel>47) cout<<"this->EdgeAngle="<<this->EdgeAngle<<endl;
1012 getAllSurfaceCells(cells,grid);
1013 if(DebugLevel>5) cout<<"cells.size()="<<cells.size()<<endl;
1015 EG_VTKSP(vtkPolyData, pdata);
1016 // addToPolyData(m_SelectedCells, pdata, grid);
1017 addToPolyData(cells, pdata, grid);
1019 vtkPolyData* input=pdata;
1021 vtkPolyData *source = 0;
1023 vtkIdType numPts, numCells, i, numPolys;
1024 int j, k;
1025 vtkIdType npts = 0;
1026 vtkIdType *pts = 0;
1027 vtkIdType p1, p2;
1028 double x[3], y[3], deltaX[3], xNew[3], conv, maxDist, dist, factor;
1029 double x1[3], x2[3], x3[3], l1[3], l2[3];
1030 double CosFeatureAngle; //Cosine of angle between adjacent polys
1031 double CosEdgeAngle; // Cosine of angle between adjacent edges
1032 double closestPt[3], dist2, *w = NULL;
1033 int iterationNumber, abortExecute;
1034 vtkIdType numSimple=0, numBEdges=0, numFixed=0, numFEdges=0;
1035 vtkPolyData *inMesh, *Mesh;
1036 vtkPoints *inPts;
1037 vtkCellArray *inVerts, *inLines, *inPolys;
1038 vtkPoints *newPts;
1039 vtkMeshVertexPtr Verts;
1040 vtkCellLocator *cellLocator=NULL;
1042 // Check input
1044 numPts=input->GetNumberOfPoints();
1045 numCells=input->GetNumberOfCells();
1046 if (numPts < 1 || numCells < 1)
1048 cout<<"No data to smooth!"<<endl;
1049 return 1;
1052 CosFeatureAngle =
1053 cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle);
1054 CosEdgeAngle = cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle);
1056 if(DebugLevel>5) {
1057 cout<<"Smoothing " << numPts << " vertices, " << numCells
1058 << " cells with:\n"
1059 << "\tConvergence= " << this->Convergence << "\n"
1060 << "\tIterations= " << this->NumberOfIterations << "\n"
1061 << "\tRelaxation Factor= " << this->RelaxationFactor << "\n"
1062 << "\tEdge Angle= " << this->EdgeAngle << "\n"
1063 << "\tBoundary Smoothing " << (this->BoundarySmoothing ? "On\n" : "Off\n")
1064 << "\tFeature Edge Smoothing " << (this->FeatureEdgeSmoothing ? "On\n" : "Off\n")
1065 << "\tError Scalars " << (this->GenerateErrorScalars ? "On\n" : "Off\n")
1066 << "\tError Vectors " << (this->GenerateErrorVectors ? "On\n" : "Off\n")<<endl;
1068 // Peform topological analysis. What we're gonna do is build a connectivity
1069 // array of connected vertices. The outcome will be one of three
1070 // classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or
1071 // VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected
1072 // vertices. FIXED vertices are never smoothed. Edge vertices are smoothed
1073 // using a subset of the attached vertices.
1075 if(DebugLevel>5) cout<<"===>Analyze topology==="<<endl;
1076 if(DebugLevel>5) cout<<"Analyzing topology..."<<endl;
1077 if(DebugLevel>5) cout<<"0:numPts="<<numPts<<endl;
1078 Verts = new vtkMeshVertex[numPts];
1079 for (i=0; i<numPts; i++)
1081 if(DebugLevel>5) cout<<"0:VTK_SIMPLE_VERTEX"<<endl;
1082 Verts[i].type = VTK_SIMPLE_VERTEX; //can smooth
1083 Verts[i].edges = NULL;
1086 inPts = input->GetPoints();
1087 conv = this->Convergence * input->GetLength();
1089 if(DebugLevel>5) cout<<"==polygons and triangle strips=="<<endl;
1090 // now polygons and triangle strips-------------------------------
1091 inPolys=input->GetPolys();
1092 numPolys = inPolys->GetNumberOfCells();
1094 if(DebugLevel>5) cout<<"numPolys="<<numPolys<<endl;
1096 if ( numPolys > 0 )
1097 { //build cell structure
1098 vtkCellArray *polys;
1099 vtkIdType cellId;
1100 int numNei, nei, edge;
1101 vtkIdType numNeiPts;
1102 vtkIdType *neiPts;
1103 double normal[3], neiNormal[3];
1104 vtkIdList *neighbors;
1106 neighbors = vtkIdList::New();
1107 neighbors->Allocate(VTK_CELL_SIZE);
1109 inMesh = vtkPolyData::New();
1110 inMesh->SetPoints(inPts);
1111 inMesh->SetPolys(inPolys);
1112 Mesh = inMesh;
1114 Mesh->BuildLinks(); //to do neighborhood searching
1115 polys = Mesh->GetPolys();
1117 for (cellId=0, polys->InitTraversal(); polys->GetNextCell(npts,pts);
1118 cellId++)
1120 if(DebugLevel>5) cout<<"->cellId="<<cellId<<endl;
1121 for (i=0; i < npts; i++)
1123 if(DebugLevel>5) cout<<"-->i="<<i<<endl;
1124 p1 = pts[i];
1125 p2 = pts[(i+1)%npts];
1127 if ( Verts[p1].edges == NULL )
1129 Verts[p1].edges = vtkIdList::New();
1130 Verts[p1].edges->Allocate(16,6);
1132 if ( Verts[p2].edges == NULL )
1134 Verts[p2].edges = vtkIdList::New();
1135 Verts[p2].edges->Allocate(16,6);
1138 Mesh->GetCellEdgeNeighbors(cellId,p1,p2,neighbors);
1139 numNei = neighbors->GetNumberOfIds();
1140 if(DebugLevel>5) cout<<"-->numNei="<<numNei<<endl;
1142 edge = VTK_SIMPLE_VERTEX;
1143 if ( numNei == 0 )
1145 edge = VTK_BOUNDARY_EDGE_VERTEX;
1148 else if ( numNei >= 2 )
1150 // check to make sure that this edge hasn't been marked already
1151 for (j=0; j < numNei; j++)
1153 if ( neighbors->GetId(j) < cellId )
1155 break;
1158 if ( j >= numNei )
1160 edge = VTK_FEATURE_EDGE_VERTEX;
1164 else if ( numNei == 1 && (nei=neighbors->GetId(0)) > cellId )
1166 vtkPolygon::ComputeNormal(inPts,npts,pts,normal);
1167 Mesh->GetCellPoints(nei,numNeiPts,neiPts);
1168 vtkPolygon::ComputeNormal(inPts,numNeiPts,neiPts,neiNormal);
1170 if ( this->FeatureEdgeSmoothing &&
1171 vtkMath::Dot(normal,neiNormal) <= CosFeatureAngle )
1173 edge = VTK_FEATURE_EDGE_VERTEX;
1176 else // a visited edge; skip rest of analysis
1178 continue;
1181 if ( edge && Verts[p1].type == VTK_SIMPLE_VERTEX )
1183 Verts[p1].edges->Reset();
1184 Verts[p1].edges->InsertNextId(p2);
1185 Verts[p1].type = edge;
1187 else if ( (edge && Verts[p1].type == VTK_BOUNDARY_EDGE_VERTEX) ||
1188 (edge && Verts[p1].type == VTK_FEATURE_EDGE_VERTEX) ||
1189 (!edge && Verts[p1].type == VTK_SIMPLE_VERTEX ) )
1191 Verts[p1].edges->InsertNextId(p2);
1192 if ( Verts[p1].type && edge == VTK_BOUNDARY_EDGE_VERTEX )
1194 Verts[p1].type = VTK_BOUNDARY_EDGE_VERTEX;
1198 if ( edge && Verts[p2].type == VTK_SIMPLE_VERTEX )
1200 Verts[p2].edges->Reset();
1201 Verts[p2].edges->InsertNextId(p1);
1202 Verts[p2].type = edge;
1204 else if ( (edge && Verts[p2].type == VTK_BOUNDARY_EDGE_VERTEX ) ||
1205 (edge && Verts[p2].type == VTK_FEATURE_EDGE_VERTEX) ||
1206 (!edge && Verts[p2].type == VTK_SIMPLE_VERTEX ) )
1208 Verts[p2].edges->InsertNextId(p1);
1209 if ( Verts[p2].type && edge == VTK_BOUNDARY_EDGE_VERTEX )
1211 Verts[p2].type = VTK_BOUNDARY_EDGE_VERTEX;
1217 inMesh->Delete();
1219 neighbors->Delete();
1220 }//if strips or polys
1222 //post-process edge vertices to make sure we can smooth them
1223 for (i=0; i<numPts; i++)
1225 if ( Verts[i].type == VTK_SIMPLE_VERTEX )
1227 numSimple++;
1230 else if ( Verts[i].type == VTK_FIXED_VERTEX )
1232 numFixed++;
1235 else if ( Verts[i].type == VTK_FEATURE_EDGE_VERTEX ||
1236 Verts[i].type == VTK_BOUNDARY_EDGE_VERTEX )
1237 { //see how many edges; if two, what the angle is
1239 if ( !this->BoundarySmoothing &&
1240 Verts[i].type == VTK_BOUNDARY_EDGE_VERTEX )
1242 if(DebugLevel>5) cout<<"Verts[i].type = VTK_FIXED_VERTEX; 4"<<endl;
1243 Verts[i].type = VTK_FIXED_VERTEX;
1244 numBEdges++;
1247 else if ( (npts = Verts[i].edges->GetNumberOfIds()) != 2 )
1249 if(DebugLevel>5) cout<<"Verts["<<i<<"].type = VTK_FIXED_VERTEX; 5"<<endl;
1250 Verts[i].type = VTK_FIXED_VERTEX;
1251 numFixed++;
1254 else //check angle between edges
1256 inPts->GetPoint(Verts[i].edges->GetId(0),x1);
1257 inPts->GetPoint(i,x2);
1258 inPts->GetPoint(Verts[i].edges->GetId(1),x3);
1260 for (k=0; k<3; k++)
1262 l1[k] = x2[k] - x1[k];
1263 l2[k] = x3[k] - x2[k];
1265 if ( vtkMath::Normalize(l1) >= 0.0 &&
1266 vtkMath::Normalize(l2) >= 0.0 &&
1267 vtkMath::Dot(l1,l2) < CosEdgeAngle)
1269 if(DebugLevel>5) cout<<"Verts["<<i<<"].type = VTK_FIXED_VERTEX; 6"<<endl;
1270 Verts[i].type = VTK_FIXED_VERTEX;
1271 numFixed++;
1273 else
1275 if ( Verts[i].type == VTK_FEATURE_EDGE_VERTEX )
1277 numFEdges++;
1279 else
1281 numBEdges++;
1284 }//if along edge
1285 }//if edge vertex
1286 }//for all points
1288 if(DebugLevel>5) {
1289 cout<<"Found\n\t" << numSimple << " simple vertices\n\t"
1290 << numFEdges << " feature edge vertices\n\t"
1291 << numBEdges << " boundary edge vertices\n\t"
1292 << numFixed << " fixed vertices\n\t"<<endl;
1293 cout<<"1:numPts="<<numPts<<endl;
1296 for (i=0; i<numPts; i++)
1298 if(DebugLevel>5) cout<<"Verts["<<i<<"].type="<<VertexType2Str(Verts[i].type)<<endl;
1299 if(Verts[i].edges != NULL && (npts = Verts[i].edges->GetNumberOfIds()) > 0)
1301 for (j=0; j<npts; j++)
1303 if(DebugLevel>5) cout<<"Verts["<<i<<"].edges->GetId("<<j<<")="<<Verts[i].edges->GetId(j)<<endl;
1304 }//for all connected points
1308 //Copy node type info from Verts
1309 EG_VTKDCN(vtkCharArray, node_type, grid, "node_type");
1310 if(DebugLevel>5) cout<<"nodes.size()="<<nodes.size()<<endl;
1311 foreach(vtkIdType node,nodes)
1313 if(DebugLevel>5) cout<<"Verts["<<node<<"].type="<<VertexType2Str(Verts[node].type)<<endl;
1314 node_type->SetValue(node,Verts[node].type);
1317 //free up connectivity storage
1318 for (int i=0; i<numPts; i++)
1320 if ( Verts[i].edges != NULL )
1322 Verts[i].edges->Delete();
1323 Verts[i].edges = NULL;
1326 delete [] Verts;
1328 cout<<"===UpdateNodeType_all END==="<<endl;
1329 return(0);
1331 //End of UpdateNodeType_all
1333 int Operation::UpdateNodeType()
1335 if(DebugLevel>47) cout<<"this->FeatureAngle="<<this->FeatureAngle<<endl;
1336 if(DebugLevel>47) cout<<"this->EdgeAngle="<<this->EdgeAngle<<endl;
1337 cout<<"===UpdateNodeType START==="<<endl;
1339 getAllSurfaceCells(cells,grid);
1340 if(DebugLevel>5) cout<<"cells.size()="<<cells.size()<<endl;
1342 EG_VTKSP(vtkPolyData, pdata);
1343 // addToPolyData(m_SelectedCells, pdata, grid);
1344 addToPolyData(cells, pdata, grid);
1346 vtkPolyData* input=pdata;
1348 vtkPolyData *source = 0;
1350 vtkIdType numPts, numCells, i, numPolys;
1351 int j, k;
1352 vtkIdType npts = 0;
1353 vtkIdType *pts = 0;
1354 vtkIdType p1, p2;
1355 double x[3], y[3], deltaX[3], xNew[3], conv, maxDist, dist, factor;
1356 double x1[3], x2[3], x3[3], l1[3], l2[3];
1357 double CosFeatureAngle; //Cosine of angle between adjacent polys
1358 double CosEdgeAngle; // Cosine of angle between adjacent edges
1359 double closestPt[3], dist2, *w = NULL;
1360 int iterationNumber, abortExecute;
1361 vtkIdType numSimple=0, numBEdges=0, numFixed=0, numFEdges=0;
1362 vtkPolyData *inMesh, *Mesh;
1363 vtkPoints *inPts;
1364 vtkCellArray *inVerts, *inLines, *inPolys;
1365 vtkPoints *newPts;
1366 vtkMeshVertexPtr Verts;
1367 vtkCellLocator *cellLocator=NULL;
1369 // Check input
1371 numPts=input->GetNumberOfPoints();
1372 numCells=input->GetNumberOfCells();
1373 if (numPts < 1 || numCells < 1)
1375 cout<<"No data to smooth!"<<endl;
1376 return 1;
1379 CosFeatureAngle =
1380 cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle);
1381 CosEdgeAngle = cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle);
1383 if(DebugLevel>5) {
1384 cout<<"Smoothing " << numPts << " vertices, " << numCells
1385 << " cells with:\n"
1386 << "\tConvergence= " << this->Convergence << "\n"
1387 << "\tIterations= " << this->NumberOfIterations << "\n"
1388 << "\tRelaxation Factor= " << this->RelaxationFactor << "\n"
1389 << "\tEdge Angle= " << this->EdgeAngle << "\n"
1390 << "\tBoundary Smoothing " << (this->BoundarySmoothing ? "On\n" : "Off\n")
1391 << "\tFeature Edge Smoothing " << (this->FeatureEdgeSmoothing ? "On\n" : "Off\n")
1392 << "\tError Scalars " << (this->GenerateErrorScalars ? "On\n" : "Off\n")
1393 << "\tError Vectors " << (this->GenerateErrorVectors ? "On\n" : "Off\n")<<endl;
1395 // Peform topological analysis. What we're gonna do is build a connectivity
1396 // array of connected vertices. The outcome will be one of three
1397 // classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or
1398 // VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected
1399 // vertices. FIXED vertices are never smoothed. Edge vertices are smoothed
1400 // using a subset of the attached vertices.
1402 if(DebugLevel>5) cout<<"===>Analyze topology==="<<endl;
1403 if(DebugLevel>5) cout<<"Analyzing topology..."<<endl;
1404 if(DebugLevel>5) cout<<"0:numPts="<<numPts<<endl;
1405 Verts = new vtkMeshVertex[numPts];
1406 for (i=0; i<numPts; i++)
1408 if(DebugLevel>5) cout<<"0:VTK_SIMPLE_VERTEX"<<endl;
1409 Verts[i].type = VTK_SIMPLE_VERTEX; //can smooth
1410 Verts[i].edges = NULL;
1413 inPts = input->GetPoints();
1414 conv = this->Convergence * input->GetLength();
1416 if(DebugLevel>5) cout<<"==polygons and triangle strips=="<<endl;
1417 // now polygons and triangle strips-------------------------------
1418 inPolys=input->GetPolys();
1419 numPolys = inPolys->GetNumberOfCells();
1421 if(DebugLevel>5) cout<<"numPolys="<<numPolys<<endl;
1423 if ( numPolys > 0 )
1424 { //build cell structure
1425 vtkCellArray *polys;
1426 vtkIdType cellId;
1427 int numNei, nei, edge;
1428 vtkIdType numNeiPts;
1429 vtkIdType *neiPts;
1430 double normal[3], neiNormal[3];
1431 vtkIdList *neighbors;
1433 neighbors = vtkIdList::New();
1434 neighbors->Allocate(VTK_CELL_SIZE);
1436 inMesh = vtkPolyData::New();
1437 inMesh->SetPoints(inPts);
1438 inMesh->SetPolys(inPolys);
1439 Mesh = inMesh;
1441 Mesh->BuildLinks(); //to do neighborhood searching
1442 polys = Mesh->GetPolys();
1444 for (cellId=0, polys->InitTraversal(); polys->GetNextCell(npts,pts);
1445 cellId++)
1447 if(DebugLevel>5) cout<<"->cellId="<<cellId<<endl;
1448 for (i=0; i < npts; i++)
1450 if(DebugLevel>5) cout<<"-->i="<<i<<endl;
1451 p1 = pts[i];
1452 p2 = pts[(i+1)%npts];
1454 if ( Verts[p1].edges == NULL )
1456 Verts[p1].edges = vtkIdList::New();
1457 Verts[p1].edges->Allocate(16,6);
1459 if ( Verts[p2].edges == NULL )
1461 Verts[p2].edges = vtkIdList::New();
1462 Verts[p2].edges->Allocate(16,6);
1465 Mesh->GetCellEdgeNeighbors(cellId,p1,p2,neighbors);
1466 numNei = neighbors->GetNumberOfIds();
1467 if(DebugLevel>5) cout<<"-->numNei="<<numNei<<endl;
1469 edge = VTK_SIMPLE_VERTEX;
1470 if ( numNei == 0 )
1472 edge = VTK_BOUNDARY_EDGE_VERTEX;
1475 else if ( numNei >= 2 )
1477 // check to make sure that this edge hasn't been marked already
1478 for (j=0; j < numNei; j++)
1480 if ( neighbors->GetId(j) < cellId )
1482 break;
1485 if ( j >= numNei )
1487 edge = VTK_FEATURE_EDGE_VERTEX;
1491 else if ( numNei == 1 && (nei=neighbors->GetId(0)) > cellId )
1493 vtkPolygon::ComputeNormal(inPts,npts,pts,normal);
1494 Mesh->GetCellPoints(nei,numNeiPts,neiPts);
1495 vtkPolygon::ComputeNormal(inPts,numNeiPts,neiPts,neiNormal);
1497 if ( this->FeatureEdgeSmoothing &&
1498 vtkMath::Dot(normal,neiNormal) <= CosFeatureAngle )
1500 edge = VTK_FEATURE_EDGE_VERTEX;
1503 else // a visited edge; skip rest of analysis
1505 continue;
1508 if ( edge && Verts[p1].type == VTK_SIMPLE_VERTEX )
1510 Verts[p1].edges->Reset();
1511 Verts[p1].edges->InsertNextId(p2);
1512 Verts[p1].type = edge;
1514 else if ( (edge && Verts[p1].type == VTK_BOUNDARY_EDGE_VERTEX) ||
1515 (edge && Verts[p1].type == VTK_FEATURE_EDGE_VERTEX) ||
1516 (!edge && Verts[p1].type == VTK_SIMPLE_VERTEX ) )
1518 Verts[p1].edges->InsertNextId(p2);
1519 if ( Verts[p1].type && edge == VTK_BOUNDARY_EDGE_VERTEX )
1521 Verts[p1].type = VTK_BOUNDARY_EDGE_VERTEX;
1525 if ( edge && Verts[p2].type == VTK_SIMPLE_VERTEX )
1527 Verts[p2].edges->Reset();
1528 Verts[p2].edges->InsertNextId(p1);
1529 Verts[p2].type = edge;
1531 else if ( (edge && Verts[p2].type == VTK_BOUNDARY_EDGE_VERTEX ) ||
1532 (edge && Verts[p2].type == VTK_FEATURE_EDGE_VERTEX) ||
1533 (!edge && Verts[p2].type == VTK_SIMPLE_VERTEX ) )
1535 Verts[p2].edges->InsertNextId(p1);
1536 if ( Verts[p2].type && edge == VTK_BOUNDARY_EDGE_VERTEX )
1538 Verts[p2].type = VTK_BOUNDARY_EDGE_VERTEX;
1544 inMesh->Delete();
1546 neighbors->Delete();
1547 }//if strips or polys
1549 //post-process edge vertices to make sure we can smooth them
1550 for (i=0; i<numPts; i++)
1552 if ( Verts[i].type == VTK_SIMPLE_VERTEX )
1554 numSimple++;
1557 else if ( Verts[i].type == VTK_FIXED_VERTEX )
1559 numFixed++;
1562 else if ( Verts[i].type == VTK_FEATURE_EDGE_VERTEX ||
1563 Verts[i].type == VTK_BOUNDARY_EDGE_VERTEX )
1564 { //see how many edges; if two, what the angle is
1566 if ( !this->BoundarySmoothing &&
1567 Verts[i].type == VTK_BOUNDARY_EDGE_VERTEX )
1569 if(DebugLevel>5) cout<<"Verts[i].type = VTK_FIXED_VERTEX; 4"<<endl;
1570 Verts[i].type = VTK_FIXED_VERTEX;
1571 numBEdges++;
1574 else if ( (npts = Verts[i].edges->GetNumberOfIds()) != 2 )
1576 if(DebugLevel>5) cout<<"Verts["<<i<<"].type = VTK_FIXED_VERTEX; 5"<<endl;
1577 Verts[i].type = VTK_FIXED_VERTEX;
1578 numFixed++;
1581 else //check angle between edges
1583 inPts->GetPoint(Verts[i].edges->GetId(0),x1);
1584 inPts->GetPoint(i,x2);
1585 inPts->GetPoint(Verts[i].edges->GetId(1),x3);
1587 for (k=0; k<3; k++)
1589 l1[k] = x2[k] - x1[k];
1590 l2[k] = x3[k] - x2[k];
1592 if ( vtkMath::Normalize(l1) >= 0.0 &&
1593 vtkMath::Normalize(l2) >= 0.0 &&
1594 vtkMath::Dot(l1,l2) < CosEdgeAngle)
1596 if(DebugLevel>5) cout<<"Verts["<<i<<"].type = VTK_FIXED_VERTEX; 6"<<endl;
1597 Verts[i].type = VTK_FIXED_VERTEX;
1598 numFixed++;
1600 else
1602 if ( Verts[i].type == VTK_FEATURE_EDGE_VERTEX )
1604 numFEdges++;
1606 else
1608 numBEdges++;
1611 }//if along edge
1612 }//if edge vertex
1613 }//for all points
1615 if(DebugLevel>5) {
1616 cout<<"Found\n\t" << numSimple << " simple vertices\n\t"
1617 << numFEdges << " feature edge vertices\n\t"
1618 << numBEdges << " boundary edge vertices\n\t"
1619 << numFixed << " fixed vertices\n\t"<<endl;
1620 cout<<"1:numPts="<<numPts<<endl;
1623 for (i=0; i<numPts; i++)
1625 if(DebugLevel>5) cout<<"Verts["<<i<<"].type="<<VertexType2Str(Verts[i].type)<<endl;
1626 if(Verts[i].edges != NULL && (npts = Verts[i].edges->GetNumberOfIds()) > 0)
1628 for (j=0; j<npts; j++)
1630 if(DebugLevel>5) cout<<"Verts["<<i<<"].edges->GetId("<<j<<")="<<Verts[i].edges->GetId(j)<<endl;
1631 }//for all connected points
1635 //Copy node type info from Verts
1636 EG_VTKDCN(vtkCharArray, node_type, grid, "node_type");
1637 if(DebugLevel>5) cout<<"nodes.size()="<<nodes.size()<<endl;
1638 foreach(vtkIdType node,nodes)
1640 if(DebugLevel>5) cout<<"Verts["<<node<<"].type="<<VertexType2Str(Verts[node].type)<<endl;
1641 node_type->SetValue(node,Verts[node].type);
1644 //free up connectivity storage
1645 for (int i=0; i<numPts; i++)
1647 if ( Verts[i].edges != NULL )
1649 Verts[i].edges->Delete();
1650 Verts[i].edges = NULL;
1653 delete [] Verts;
1655 cout<<"===UpdateNodeType END==="<<endl;
1656 return(0);
1658 //End of UpdateNodeType
1660 // DEFINITIONS:
1661 // Normal cell: nothing has changed
1662 // Dead cell: the cell does not exist anymore
1663 // Mutated cell: the cell's form has changed
1664 // Mutilated cell: the cell has less points than before
1666 vtkIdType Operation::FindSnapPoint(vtkUnstructuredGrid *src, vtkIdType DeadNode,QSet <vtkIdType> & DeadCells,QSet <vtkIdType> & MutatedCells,QSet <vtkIdType> & MutilatedCells, int& N_newpoints, int& N_newcells)
1668 getAllSurfaceCells(cells,src);
1669 getNodesFromCells(cells, nodes, src);
1670 setGrid(src);
1671 setCells(cells);
1673 UpdateNodeType_all();
1675 EG_VTKDCN(vtkCharArray, node_type, src, "node_type");
1676 if(node_type->GetValue(DeadNode)==VTK_FIXED_VERTEX)
1678 cout<<"Sorry, unable to remove fixed vertex."<<endl;
1679 return(-1);
1682 //src grid info
1683 int N_points=src->GetNumberOfPoints();
1684 int N_cells=src->GetNumberOfCells();
1685 N_newpoints=-1;
1686 N_newcells=0;
1688 vtkIdType SnapPoint=-1;
1690 foreach(vtkIdType PSP, n2n[DeadNode])
1692 bool IsValidSnapPoint=true;
1694 if(DebugLevel>10) cout<<"====>PSP="<<PSP<<endl;
1695 bool IsTetra=true;
1696 if(NumberOfCommonPoints(DeadNode,PSP,IsTetra)>2)//common point check
1698 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1699 IsValidSnapPoint=false;
1701 if(IsTetra)//tetra check
1703 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1704 IsValidSnapPoint=false;
1707 //count number of points and cells to remove + analyse cell transformations
1708 N_newpoints=-1;
1709 N_newcells=0;
1710 DeadCells.clear();
1711 MutatedCells.clear();
1712 MutilatedCells.clear();
1713 foreach(vtkIdType C, n2c[DeadNode])//loop through potentially dead cells
1715 //get points around cell
1716 vtkIdType N_pts, *pts;
1717 src->GetCellPoints(C, N_pts, pts);
1719 bool ContainsSnapPoint=false;
1720 bool invincible=false;
1721 for(int i=0;i<N_pts;i++)
1723 if(DebugLevel>10) cout<<"pts["<<i<<"]="<<pts[i]<<" and PSP="<<PSP<<endl;
1724 if(pts[i]==PSP) {ContainsSnapPoint=true;}
1725 if(pts[i]!=DeadNode && pts[i]!=PSP && n2c[pts[i]].size()<=1) invincible=true;
1727 if(ContainsSnapPoint)
1729 if(N_pts==3)//dead cell
1731 if(invincible)//Check that empty lines aren't left behind when a cell is killed
1733 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1734 IsValidSnapPoint=false;
1736 else
1738 DeadCells.insert(C);
1739 N_newcells-=1;
1740 if(DebugLevel>10) cout<<"cell "<<C<<" has been pwned!"<<endl;
1743 else
1745 cout<<"RED ALERT: Xenomorph detected!"<<endl;
1746 EG_BUG;
1749 else
1751 vtkIdType src_N_pts, *src_pts;
1752 src->GetCellPoints(C, src_N_pts, src_pts);
1754 if(src_N_pts!=3)
1756 cout<<"RED ALERT: Xenomorph detected!"<<endl;
1757 EG_BUG;
1760 vtkIdType OldTriangle[3];
1761 vtkIdType NewTriangle[3];
1763 for(int i=0;i<src_N_pts;i++)
1765 OldTriangle[i]=src_pts[i];
1766 NewTriangle[i]=( (src_pts[i]==DeadNode) ? PSP : src_pts[i] );
1768 vec3_t Old_N= triNormal(src, OldTriangle[0], OldTriangle[1], OldTriangle[2]);
1769 vec3_t New_N= triNormal(src, NewTriangle[0], NewTriangle[1], NewTriangle[2]);
1770 double OldArea=Old_N.abs();
1771 double NewArea=New_N.abs();
1772 double scal=Old_N*New_N;
1773 double cross=(Old_N.cross(New_N)).abs();//double-cross on Nar Shadaa B-)
1775 if(DebugLevel>10) {
1776 cout<<"OldArea="<<OldArea<<endl;
1777 cout<<"NewArea="<<NewArea<<endl;
1778 cout<<"scal="<<scal<<endl;
1779 cout<<"cross="<<cross<<endl;
1782 if(Old_N*New_N<Old_N*Old_N*1./100.)//area + inversion check
1784 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1785 IsValidSnapPoint=false;
1788 //mutated cell
1789 MutatedCells.insert(C);
1790 if(DebugLevel>10) cout<<"cell "<<C<<" has been infected!"<<endl;
1794 if(N_cells+N_newcells<=0)//survivor check
1796 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1797 IsValidSnapPoint=false;
1800 if(node_type->GetValue(DeadNode)==VTK_BOUNDARY_EDGE_VERTEX && node_type->GetValue(PSP)==VTK_SIMPLE_VERTEX)
1802 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1803 IsValidSnapPoint=false;
1806 if(node_type->GetValue(DeadNode)==VTK_BOUNDARY_EDGE_VERTEX)
1808 int BC=0;
1809 QVector <vtkIdType> Peons;
1810 getNeighbours(DeadNode, Peons, BC);
1811 if(!Peons.contains(PSP))
1813 if(DebugLevel>0) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1814 IsValidSnapPoint=false;
1818 if(node_type->GetValue(DeadNode)==VTK_FEATURE_EDGE_VERTEX && node_type->GetValue(PSP)==VTK_SIMPLE_VERTEX)
1820 if(DebugLevel>10) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1821 IsValidSnapPoint=false;
1824 if(node_type->GetValue(DeadNode)==VTK_FEATURE_EDGE_VERTEX)
1826 int BC=0;
1827 QVector <vtkIdType> Peons;
1828 getNeighbours(DeadNode, Peons, BC);
1829 if(!Peons.contains(PSP))
1831 if(DebugLevel>0) cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
1832 IsValidSnapPoint=false;
1836 if(IsValidSnapPoint) {SnapPoint=PSP; break;}
1837 }//end of loop through potential SnapPoints
1839 if(DebugLevel>10)
1841 cout<<"AT FINDSNAPPOINT EXIT"<<endl;
1842 cout<<"N_points="<<N_points<<endl;
1843 cout<<"N_cells="<<N_cells<<endl;
1844 cout<<"N_newpoints="<<N_newpoints<<endl;
1845 cout<<"N_newcells="<<N_newcells<<endl;
1847 return(SnapPoint);
1849 //End of FindSnapPoint
1851 bool Operation::DeletePoint_2(vtkUnstructuredGrid *src, vtkIdType DeadNode, int& N_newpoints, int& N_newcells)
1853 getAllSurfaceCells(cells,src);
1854 // getNodesFromCells(cells, nodes, src);
1855 setGrid(src);
1856 setCells(cells);
1857 UpdateNodeType_all();
1859 //src grid info
1860 int N_points=src->GetNumberOfPoints();
1861 int N_cells=src->GetNumberOfCells();
1862 N_newpoints=-1;
1863 N_newcells=0;
1865 if(DeadNode<0 || DeadNode>=N_points)
1867 cout<<"Warning: Point out of range: DeadNode="<<DeadNode<<" N_points="<<N_points<<endl;
1868 return(false);
1871 QSet <vtkIdType> DeadCells;
1872 QSet <vtkIdType> MutatedCells;
1873 QSet <vtkIdType> MutilatedCells;
1875 if(DebugLevel>10) {
1876 cout<<"BEFORE FINDSNAPPOINT"<<endl;
1877 cout<<"N_points="<<N_points<<endl;
1878 cout<<"N_cells="<<N_cells<<endl;
1879 cout<<"N_newpoints="<<N_newpoints<<endl;
1880 cout<<"N_newcells="<<N_newcells<<endl;
1882 vtkIdType SnapPoint=FindSnapPoint(src,DeadNode,DeadCells,MutatedCells,MutilatedCells, N_newpoints, N_newcells);
1884 if(DebugLevel>0) cout<<"===>DeadNode="<<DeadNode<<" moving to SNAPPOINT="<<SnapPoint<<" DebugLevel="<<DebugLevel<<endl;
1885 if(SnapPoint<0) {cout<<"Sorry no possible SnapPoint found."<<endl; return(false);}
1887 //allocate
1888 if(DebugLevel>10) {
1889 cout<<"BEFORE ALLOCATION"<<endl;
1890 cout<<"N_points="<<N_points<<endl;
1891 cout<<"N_cells="<<N_cells<<endl;
1892 cout<<"N_newpoints="<<N_newpoints<<endl;
1893 cout<<"N_newcells="<<N_newcells<<endl;
1895 N_points=src->GetNumberOfPoints();
1896 N_cells=src->GetNumberOfCells();
1898 if(DebugLevel>47) {
1899 cout<<"N_points="<<N_points<<endl;
1900 cout<<"N_cells="<<N_cells<<endl;
1901 cout<<"N_newpoints="<<N_newpoints<<endl;
1902 cout<<"N_newcells="<<N_newcells<<endl;
1904 EG_VTKSP(vtkUnstructuredGrid,dst);
1905 allocateGrid(dst,N_cells+N_newcells,N_points+N_newpoints);
1907 //vector used to redefine the new point IDs
1908 QVector <vtkIdType> OffSet(N_points);
1910 //copy undead points
1911 vtkIdType dst_id_node=0;
1912 for (vtkIdType src_id_node = 0; src_id_node < N_points; src_id_node++) {//loop through src points
1913 if(src_id_node!=DeadNode)//if the node isn't dead, copy it
1915 vec3_t x;
1916 src->GetPoints()->GetPoint(src_id_node, x.data());
1917 dst->GetPoints()->SetPoint(dst_id_node, x.data());
1918 copyNodeData(src, src_id_node, dst, dst_id_node);
1919 OffSet[src_id_node]=src_id_node-dst_id_node;
1920 dst_id_node++;
1922 else
1924 if(DebugLevel>0) cout<<"src_id_node="<<src_id_node<<" dst_id_node="<<dst_id_node<<endl;
1927 if(DebugLevel>10) {
1928 cout<<"DeadCells="<<DeadCells<<endl;
1929 cout<<"MutatedCells="<<MutatedCells<<endl;
1930 cout<<"MutilatedCells="<<MutilatedCells<<endl;
1932 //Copy undead cells
1933 for (vtkIdType id_cell = 0; id_cell < src->GetNumberOfCells(); ++id_cell) {//loop through src cells
1934 if(!DeadCells.contains(id_cell))//if the cell isn't dead
1936 vtkIdType src_N_pts, *src_pts;
1937 vtkIdType dst_N_pts, *dst_pts;
1938 src->GetCellPoints(id_cell, src_N_pts, src_pts);
1940 vtkIdType type_cell = src->GetCellType(id_cell);
1941 if(DebugLevel>10) cout<<"-->id_cell="<<id_cell<<endl;
1942 if(DebugLevel>10) for(int i=0;i<src_N_pts;i++) cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
1943 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
1944 dst_N_pts=src_N_pts;
1945 dst_pts=new vtkIdType[dst_N_pts];
1946 if(MutatedCells.contains(id_cell))//mutated cell
1948 if(DebugLevel>10) cout<<"processing mutated cell "<<id_cell<<endl;
1949 for(int i=0;i<src_N_pts;i++)
1951 if(src_pts[i]==DeadNode) {
1952 if(DebugLevel>10) {
1953 cout<<"SnapPoint="<<SnapPoint<<endl;
1954 cout<<"OffSet[SnapPoint]="<<OffSet[SnapPoint]<<endl;
1955 cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
1957 dst_pts[i]=SnapPoint-OffSet[SnapPoint];
1959 else dst_pts[i]=src_pts[i]-OffSet[src_pts[i]];
1961 if(DebugLevel>10) cout<<"--->dst_pts:"<<endl;
1962 if(DebugLevel>10) for(int i=0;i<dst_N_pts;i++) cout<<"dst_pts["<<i<<"]="<<dst_pts[i]<<endl;
1965 else if(MutilatedCells.contains(id_cell))//mutilated cell
1967 if(DebugLevel>10) cout<<"processing mutilated cell "<<id_cell<<endl;
1969 if(type_cell==VTK_QUAD) {
1970 type_cell=VTK_TRIANGLE;
1971 dst_N_pts-=1;
1973 else {cout<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl;EG_BUG;}
1974 //merge points
1975 int j=0;
1976 for(int i=0;i<src_N_pts;i++)
1978 if(src_pts[i]==SnapPoint) { dst_pts[j]=SnapPoint-OffSet[SnapPoint];j++; }//SnapPoint
1979 else if(src_pts[i]!=DeadNode) { dst_pts[j]=src_pts[i]-OffSet[src_pts[i]];j++; }//pre-snap/dead + post-snap/dead
1980 //do nothing in case of DeadNode
1983 else//normal cell
1985 if(DebugLevel>10) cout<<"processing normal cell "<<id_cell<<endl;
1986 for(int i=0;i<src_N_pts;i++)
1988 dst_pts[i]=src_pts[i]-OffSet[src_pts[i]];
1991 //copy the cell
1992 vtkIdType id_new_cell = dst->InsertNextCell(type_cell, dst_N_pts, dst_pts);
1993 copyCellData(src, id_cell, dst, id_new_cell);
1994 if(DebugLevel>10) {
1995 cout<<"===Copying cell "<<id_cell<<" to "<<id_new_cell<<"==="<<endl;
1996 cout<<"src_pts:"<<endl;
1997 for(int i=0;i<src_N_pts;i++) cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
1998 cout<<"dst_pts:"<<endl;
1999 for(int i=0;i<dst_N_pts;i++) cout<<"dst_pts["<<i<<"]="<<dst_pts[i]<<endl;
2000 cout<<"OffSet="<<OffSet<<endl;
2001 cout<<"===Copying cell end==="<<endl;
2003 delete dst_pts;
2006 // cout_grid(cout,dst,true,true,true,true);
2007 makeCopy(dst, src);
2008 return(true);
2010 //End of DeletePoint_2
2012 bool Operation::DeleteSetOfPoints(vtkUnstructuredGrid *src, QSet <vtkIdType> DeadNodes, int& N_newpoints, int& N_newcells)
2014 QVector <vtkIdType> DeadNode_vector=Set2Vector(DeadNodes,false);
2016 getAllSurfaceCells(cells,src);
2017 // getNodesFromCells(cells, nodes, src);
2018 setGrid(src);
2019 setCells(cells);
2020 UpdateNodeType_all();
2022 //src grid info
2023 int N_points=src->GetNumberOfPoints();
2024 int N_cells=src->GetNumberOfCells();
2026 QSet <vtkIdType> DeadCells;
2027 QSet <vtkIdType> MutatedCells;
2028 QSet <vtkIdType> MutilatedCells;
2029 QVector <vtkIdType> SnapPoint(DeadNode_vector.size());
2031 //counter init
2032 N_newpoints=0;
2033 N_newcells=0;
2035 for(int i=0;i<DeadNode_vector.size();i++)
2037 if(DeadNode_vector[i]<0 || DeadNode_vector[i]>=N_points)
2039 cout<<"Warning: Point out of range: DeadNode_vector[i]="<<DeadNode_vector[i]<<" N_points="<<N_points<<endl;
2040 return(false);
2043 if(DebugLevel>10) {
2044 cout<<"BEFORE FINDSNAPPOINT"<<endl;
2045 cout<<"N_points="<<N_points<<endl;
2046 cout<<"N_cells="<<N_cells<<endl;
2047 cout<<"N_newpoints="<<N_newpoints<<endl;
2048 cout<<"N_newcells="<<N_newcells<<endl;
2051 //local values
2052 int l_N_newpoints;
2053 int l_N_newcells;
2054 QSet <vtkIdType> l_DeadCells;
2055 QSet <vtkIdType> l_MutatedCells;
2056 QSet <vtkIdType> l_MutilatedCells;
2058 SnapPoint[i]=FindSnapPoint(src,DeadNode_vector[i], l_DeadCells, l_MutatedCells, l_MutilatedCells, l_N_newpoints, l_N_newcells);
2059 //global values
2060 N_newpoints+=l_N_newpoints;
2061 N_newcells+=l_N_newcells;
2062 DeadCells.unite(l_DeadCells);//DeadCells unite! Kill the living! :D
2063 MutatedCells.unite(l_MutatedCells);
2064 MutilatedCells.unite(l_MutilatedCells);
2066 if(DebugLevel>0) cout<<"===>DeadNode_vector[i]="<<DeadNode_vector[i]<<" moving to SNAPPOINT="<<SnapPoint[i]<<" DebugLevel="<<DebugLevel<<endl;
2067 if(SnapPoint[i]<0) {cout<<"Sorry no possible SnapPoint found."<<endl; return(false);}
2070 //allocate
2071 if(DebugLevel>10) {
2072 cout<<"BEFORE ALLOCATION"<<endl;
2073 cout<<"N_points="<<N_points<<endl;
2074 cout<<"N_cells="<<N_cells<<endl;
2075 cout<<"N_newpoints="<<N_newpoints<<endl;
2076 cout<<"N_newcells="<<N_newcells<<endl;
2078 // N_points=src->GetNumberOfPoints();
2079 // N_cells=src->GetNumberOfCells();
2081 if(DebugLevel>47) {
2082 cout<<"N_points="<<N_points<<endl;
2083 cout<<"N_cells="<<N_cells<<endl;
2084 cout<<"N_newpoints="<<N_newpoints<<endl;
2085 cout<<"N_newcells="<<N_newcells<<endl;
2087 EG_VTKSP(vtkUnstructuredGrid,dst);
2088 allocateGrid(dst,N_cells+N_newcells,N_points+N_newpoints);
2090 //vector used to redefine the new point IDs
2091 QVector <vtkIdType> OffSet(N_points);
2093 //copy undead points
2094 vtkIdType dst_id_node=0;
2095 for (vtkIdType src_id_node = 0; src_id_node < N_points; src_id_node++) {//loop through src points
2096 if(!DeadNode_vector.contains(src_id_node))//if the node isn't dead, copy it
2098 vec3_t x;
2099 src->GetPoints()->GetPoint(src_id_node, x.data());
2100 dst->GetPoints()->SetPoint(dst_id_node, x.data());
2101 copyNodeData(src, src_id_node, dst, dst_id_node);
2102 OffSet[src_id_node]=src_id_node-dst_id_node;
2103 dst_id_node++;
2105 else
2107 if(DebugLevel>0) cout<<"src_id_node="<<src_id_node<<" dst_id_node="<<dst_id_node<<endl;
2110 if(DebugLevel>10) {
2111 cout<<"DeadCells="<<DeadCells<<endl;
2112 cout<<"MutatedCells="<<MutatedCells<<endl;
2113 cout<<"MutilatedCells="<<MutilatedCells<<endl;
2115 //Copy undead cells
2116 for (vtkIdType id_cell = 0; id_cell < src->GetNumberOfCells(); ++id_cell) {//loop through src cells
2117 if(!DeadCells.contains(id_cell))//if the cell isn't dead
2119 vtkIdType src_N_pts, *src_pts;
2120 vtkIdType dst_N_pts, *dst_pts;
2121 src->GetCellPoints(id_cell, src_N_pts, src_pts);
2123 vtkIdType type_cell = src->GetCellType(id_cell);
2124 if(DebugLevel>10) cout<<"-->id_cell="<<id_cell<<endl;
2125 if(DebugLevel>10) for(int i=0;i<src_N_pts;i++) cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
2126 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
2127 dst_N_pts=src_N_pts;
2128 dst_pts=new vtkIdType[dst_N_pts];
2129 if(MutatedCells.contains(id_cell))//mutated cell
2131 if(DebugLevel>10) cout<<"processing mutated cell "<<id_cell<<endl;
2132 for(int i=0;i<src_N_pts;i++)
2134 int DeadIndex = DeadNode_vector.indexOf(src_pts[i]);
2135 if(DeadIndex!=-1) {
2136 if(DebugLevel>10) {
2137 cout<<"SnapPoint="<<SnapPoint[DeadIndex]<<endl;
2138 cout<<"OffSet[SnapPoint]="<<OffSet[SnapPoint[DeadIndex]]<<endl;
2139 cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
2141 dst_pts[i]=SnapPoint[DeadIndex]-OffSet[SnapPoint[DeadIndex]];
2143 else dst_pts[i]=src_pts[i]-OffSet[src_pts[i]];
2145 if(DebugLevel>10) cout<<"--->dst_pts:"<<endl;
2146 if(DebugLevel>10) for(int i=0;i<dst_N_pts;i++) cout<<"dst_pts["<<i<<"]="<<dst_pts[i]<<endl;
2149 else if(MutilatedCells.contains(id_cell))//mutilated cell (ex: square becoming triangle)
2151 cout<<"FATAL ERROR: Quads not supported yet."<<endl;EG_BUG;
2153 if(DebugLevel>10) cout<<"processing mutilated cell "<<id_cell<<endl;
2155 if(type_cell==VTK_QUAD) {
2156 type_cell=VTK_TRIANGLE;
2157 dst_N_pts-=1;
2159 else {cout<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl;EG_BUG;}
2160 //merge points
2161 int j=0;
2162 for(int i=0;i<src_N_pts;i++)
2164 /* if(src_pts[i]==SnapPoint) { dst_pts[j]=SnapPoint-OffSet[SnapPoint];j++; }//SnapPoint
2165 else if(src_pts[i]!=DeadNode_vector[i]) { dst_pts[j]=src_pts[i]-OffSet[src_pts[i]];j++; }//pre-snap/dead + post-snap/dead*/
2166 //do nothing in case of DeadNode_vector[i]
2169 else//normal cell
2171 if(DebugLevel>10) cout<<"processing normal cell "<<id_cell<<endl;
2172 for(int i=0;i<src_N_pts;i++)
2174 dst_pts[i]=src_pts[i]-OffSet[src_pts[i]];
2177 //copy the cell
2178 vtkIdType id_new_cell = dst->InsertNextCell(type_cell, dst_N_pts, dst_pts);
2179 copyCellData(src, id_cell, dst, id_new_cell);
2180 if(DebugLevel>10) {
2181 cout<<"===Copying cell "<<id_cell<<" to "<<id_new_cell<<"==="<<endl;
2182 cout<<"src_pts:"<<endl;
2183 for(int i=0;i<src_N_pts;i++) cout<<"src_pts["<<i<<"]="<<src_pts[i]<<endl;
2184 cout<<"dst_pts:"<<endl;
2185 for(int i=0;i<dst_N_pts;i++) cout<<"dst_pts["<<i<<"]="<<dst_pts[i]<<endl;
2186 cout<<"OffSet="<<OffSet<<endl;
2187 cout<<"===Copying cell end==="<<endl;
2189 delete dst_pts;
2193 // cout_grid(cout,dst,true,true,true,true);
2194 makeCopy(dst, src);
2195 return(true);
2197 //End of DeleteSetOfPoints
2199 void Operation::TxtSave(QString a_filename)
2201 cout << a_filename.toAscii().data() << endl;
2202 ofstream file;
2203 file.open(a_filename.toAscii().data());
2204 cout_grid(file,grid,true,true,true,true);
2205 file.close();
2208 void Operation::DualSave(QString a_filename)
2210 TxtSave(a_filename+".txt");
2211 GuiMainWindow::pointer()->QuickSave(a_filename+".vtu");