2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008,2009 Oliver Gloth +
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. +
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. +
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/>. +
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"
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
;
58 foreach (Operation
*op
, delete_operations
) {
59 garbage_operations
.remove(op
);
63 Operation::Operation()
68 m_resetoperationcounter
= false;
72 //default values for determining node types and for smoothing operations
74 NumberOfIterations
=20;
75 RelaxationFactor
=0.01;
76 FeatureEdgeSmoothing
=1;//0 by default in VTK, but we need 1 to avoid the "potatoe effect" ^^
80 GenerateErrorScalars
=0;
81 GenerateErrorVectors
=0;
84 Operation::~Operation()
94 garbage_operations
.insert(this);
97 void OperationThread::run()
100 GuiMainWindow::lock();
101 GuiMainWindow::pointer()->setBusy();
103 } catch (Error err
) {
104 op
->err
= new Error();
107 GuiMainWindow::unlock();
108 GuiMainWindow::pointer()->setIdle();
111 void Operation::operator()()
114 if (GuiMainWindow::tryLock()) {
116 thread
.setOperation(this);
117 GuiMainWindow::unlock();
118 thread
.start(QThread::LowPriority
);
120 QMessageBox::warning(NULL
, "not permitted", "Operation is not permitted while background process is running!");
125 if(m_resetoperationcounter
) GuiMainWindow::pointer()->ResetOperationCounter();
126 if(m_quicksave
) GuiMainWindow::pointer()->QuickSave();
130 void Operation::setAllCells()
132 QVector
<vtkIdType
> all_cells
;
133 getAllCells(all_cells
, grid
);
137 void Operation::setAllVolumeCells()
139 QVector
<vtkIdType
> cells
;
140 getAllVolumeCells(cells
, grid
);
144 void Operation::setAllSurfaceCells()
146 QVector
<vtkIdType
> cells
;
147 getAllSurfaceCells(cells
, grid
);
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()
166 grid
= GuiMainWindow::pointer()->getGrid();
168 if ((cells
.size() == 0) && autoset
) {
173 void Operation::updateActors()
175 mainWindow()->updateActors();
178 GuiMainWindow
* Operation::mainWindow()
180 return GuiMainWindow::pointer();
183 void Operation::populateBoundaryCodes(QListWidget
*lw
)
186 mainWindow()->getAllBoundaryCodes(bcs
);
187 foreach(int bc
, bcs
) {
188 QListWidgetItem
*lwi
= new QListWidgetItem(lw
);
189 lwi
->setCheckState(Qt::Unchecked
);
191 QTextStream
ts(&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
)
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
) {
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]; };
216 if (c2c
[_cells
[S
.id_cell2
]][0] != -1) {
217 if (cells
[c2c
[_cells
[S
.id_cell2
]][0]] == S
.id_cell1
) {
222 if (c2c
[_cells
[S
.id_cell2
]][1] != -1) {
223 if (cells
[c2c
[_cells
[S
.id_cell2
]][1]] == S
.id_cell1
) {
228 if (c2c
[_cells
[S
.id_cell2
]][2] != -1) {
229 if (cells
[c2c
[_cells
[S
.id_cell2
]][2]] == S
.id_cell1
) {
235 cout
<<"S.id_cell1="<<S
.id_cell1
<<endl
;
236 cout
<<"S.id_cell2="<<S
.id_cell2
<<endl
;
243 grid
->GetCellPoints(S
.id_cell1
, N1
, pts1
);
244 if (j1
== 0) { S
.p
[0] = pts1
[2]; S
.p
[1] = pts1
[0]; S
.p
[3] = pts1
[1]; }
245 else if (j1
== 1) { S
.p
[0] = pts1
[0]; S
.p
[1] = pts1
[1]; S
.p
[3] = pts1
[2]; }
246 else if (j1
== 2) { S
.p
[0] = pts1
[1]; S
.p
[1] = pts1
[2]; S
.p
[3] = pts1
[0]; };
251 ostream
& operator<<(ostream
&out
, stencil_t S
)
253 out
<<"S.id_cell1="<<S
.id_cell1
<<" ";
254 out
<<"S.id_cell2="<<S
.id_cell2
<<" ";
255 out
<<"S.valid="<<S
.valid
<<" ";
257 for(int i
=0;i
<4;i
++){
265 //////////////////////////////////////////////
266 double CurrentVertexAvgDist(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
270 int N
=n2n
[a_vertex
].size();
272 a_grid
->GetPoint(a_vertex
, C
.data());
273 foreach(int i
,n2n
[a_vertex
])
276 a_grid
->GetPoint(i
, M
.data());
277 total_dist
+=(M
-C
).abs();
279 avg_dist
=total_dist
/(double)N
;
283 double CurrentMeshDensity(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
287 int N
=n2n
[a_vertex
].size();
289 a_grid
->GetPoint(a_vertex
, C
.data());
290 foreach(int i
,n2n
[a_vertex
])
293 a_grid
->GetPoint(i
, M
.data());
294 total_dist
+=(M
-C
).abs();
296 avg_dist
=total_dist
/(double)N
;
297 double avg_density
=1./avg_dist
;
301 double DesiredVertexAvgDist(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
305 EG_VTKDCN(vtkDoubleArray
, node_meshdensity
, a_grid
, "node_meshdensity");
306 int N
=n2n
[a_vertex
].size();
307 foreach(int i
,n2n
[a_vertex
])
309 total_dist
+=1./node_meshdensity
->GetValue(i
);
311 avg_dist
=total_dist
/(double)N
;
315 double DesiredMeshDensity(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
317 double total_density
=0;
318 double avg_density
=0;
319 EG_VTKDCN(vtkDoubleArray
, node_meshdensity
, a_grid
, "node_meshdensity");
320 int N
=n2n
[a_vertex
].size();
321 foreach(int i
,n2n
[a_vertex
])
323 total_density
+=node_meshdensity
->GetValue(i
);
325 avg_density
=total_density
/(double)N
;
329 ///////////////////////////////////////////
330 vtkIdType
Operation::getClosestNode(vtkIdType a_id_node
,vtkUnstructuredGrid
* a_grid
)
333 a_grid
->GetPoint(a_id_node
,C
.data());
334 vtkIdType id_minlen
=-1;
336 foreach(vtkIdType neighbour
,n2n
[a_id_node
])
339 a_grid
->GetPoint(neighbour
,M
.data());
340 double len
=(M
-C
).abs();
341 if(minlen
<0 or len
<minlen
)
350 vtkIdType
Operation::getFarthestNode(vtkIdType a_id_node
,vtkUnstructuredGrid
* a_grid
)
353 a_grid
->GetPoint(a_id_node
,C
.data());
354 vtkIdType id_maxlen
=-1;
356 foreach(vtkIdType neighbour
,n2n
[a_id_node
])
359 a_grid
->GetPoint(neighbour
,M
.data());
360 double len
=(M
-C
).abs();
361 if(maxlen
<0 or len
>maxlen
)
370 bool Operation::SwapCells(vtkUnstructuredGrid
* a_grid
, stencil_t S
)
374 vec3_t x3
[4], x3_0(0,0,0);
376 for (int k
= 0; k
< 4; ++k
) {
377 a_grid
->GetPoints()->GetPoint(S
.p
[k
], x3
[k
].data());
380 vec3_t n1
= triNormal(x3
[0], x3
[1], x3
[3]);
381 vec3_t n2
= triNormal(x3
[1], x3
[2], x3
[3]);
384 if ( (n1
*n2
) > 0.8) {
387 vec3_t ex
= orthogonalVector(n
);
388 vec3_t ey
= ex
.cross(n
);
389 for (int k
= 0; k
< 4; ++k
) {
390 x
[k
] = vec2_t(x3
[k
]*ex
, x3
[k
]*ey
);
392 vec2_t r1
, r2
, r3
, u1
, u2
, u3
;
393 r1
= 0.5*(x
[0] + x
[1]); u1
= turnLeft(x
[1] - x
[0]);
394 r2
= 0.5*(x
[1] + x
[2]); u2
= turnLeft(x
[2] - x
[1]);
395 r3
= 0.5*(x
[1] + x
[3]); u3
= turnLeft(x
[3] - x
[1]);
399 if (intersection(k
, l
, r1
, u1
, r3
, u3
)) {
401 if (intersection(k
, l
, r2
, u2
, r3
, u3
)) {
411 if ((xm1
- x
[2]).abs() < (xm1
- x
[0]).abs()) {
414 if ((xm2
- x
[0]).abs() < (xm2
- x
[2]).abs()) {
421 vtkIdType new_pts1
[3], new_pts2
[3];
422 new_pts1
[0] = S
.p
[1];
423 new_pts1
[1] = S
.p
[2];
424 new_pts1
[2] = S
.p
[0];
425 new_pts2
[0] = S
.p
[2];
426 new_pts2
[1] = S
.p
[3];
427 new_pts2
[2] = S
.p
[0];
428 a_grid
->ReplaceCell(S
.id_cell1
, 3, new_pts1
);
429 a_grid
->ReplaceCell(S
.id_cell2
, 3, new_pts2
);
434 void Operation::quad2triangle(vtkUnstructuredGrid
* src
,vtkIdType quadcell
)
436 vtkIdType type_cell
= grid
->GetCellType(quadcell
);
437 cout
<<"It's a "<<type_cell
<<endl
;
438 if(type_cell
==VTK_QUAD
)
440 cout_grid(cout
,src
,true,true,true,true);
441 EG_VTKSP(vtkUnstructuredGrid
, dst
);
443 int N_points
=src
->GetNumberOfPoints();
444 int N_cells
=src
->GetNumberOfCells();
445 allocateGrid(dst
,N_cells
+1,N_points
);
447 for (vtkIdType id_node
= 0; id_node
< src
->GetNumberOfPoints(); ++id_node
) {
449 src
->GetPoints()->GetPoint(id_node
, x
.data());
450 dst
->GetPoints()->SetPoint(id_node
, x
.data());
451 copyNodeData(src
, id_node
, dst
, id_node
);
453 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {
454 vtkIdType N_pts
, *pts
;
455 vtkIdType type_cell
= src
->GetCellType(id_cell
);
456 src
->GetCellPoints(id_cell
, N_pts
, pts
);
457 vtkIdType id_new_cell
;
458 vtkIdType id_new_cell1
;
459 vtkIdType id_new_cell2
;
460 if(id_cell
!=quadcell
)
462 id_new_cell
= dst
->InsertNextCell(type_cell
, N_pts
, pts
);
463 copyCellData(src
, id_cell
, dst
, id_new_cell
);
467 vtkIdType triangle1
[3];
468 vtkIdType triangle2
[3];
475 id_new_cell1
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle1
);
476 copyCellData(src
, id_cell
, dst
, id_new_cell1
);
477 id_new_cell2
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle2
);
478 copyCellData(src
, id_cell
, dst
, id_new_cell2
);
480 S
.id_cell1
=id_new_cell1
;
481 S
.id_cell2
=id_new_cell2
;
490 cout_grid(cout
,dst
,true,true,true,true);
495 void Operation::quad2triangle(vtkUnstructuredGrid
* src
,vtkIdType quadcell
,vtkIdType MovingPoint
)
497 vtkIdType type_cell
= grid
->GetCellType(quadcell
);
498 cout
<<"It's a "<<type_cell
<<endl
;
499 if(type_cell
==VTK_QUAD
)
501 cout_grid(cout
,src
,true,true,true,true);
502 EG_VTKSP(vtkUnstructuredGrid
, dst
);
504 int N_points
=src
->GetNumberOfPoints();
505 int N_cells
=src
->GetNumberOfCells();
506 allocateGrid(dst
,N_cells
+1,N_points
);
508 for (vtkIdType id_node
= 0; id_node
< src
->GetNumberOfPoints(); ++id_node
) {
510 src
->GetPoints()->GetPoint(id_node
, x
.data());
511 dst
->GetPoints()->SetPoint(id_node
, x
.data());
512 copyNodeData(src
, id_node
, dst
, id_node
);
514 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {
515 vtkIdType N_pts
, *pts
;
516 src
->GetCellPoints(id_cell
, N_pts
, pts
);
517 vtkIdType type_cell
= src
->GetCellType(id_cell
);
518 vtkIdType id_new_cell
;
519 vtkIdType id_new_cell1
;
520 vtkIdType id_new_cell2
;
521 if(id_cell
!=quadcell
)
523 id_new_cell
= dst
->InsertNextCell(type_cell
, N_pts
, pts
);
524 copyCellData(src
, id_cell
, dst
, id_new_cell
);
528 vtkIdType triangle1
[3];
529 vtkIdType triangle2
[3];
530 if(MovingPoint
==pts
[0] || MovingPoint
==pts
[2])
548 id_new_cell1
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle1
);
549 copyCellData(src
, id_cell
, dst
, id_new_cell1
);
550 id_new_cell2
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle2
);
551 copyCellData(src
, id_cell
, dst
, id_new_cell2
);
554 cout_grid(cout
,dst
,true,true,true,true);
559 int Operation::NumberOfCommonPoints(vtkIdType node1
, vtkIdType node2
, bool& IsTetra
)
561 // QVector< QSet< int > > n2n
562 QSet
<int> node1_neighbours
=n2n
[node1
];
563 QSet
<int> node2_neighbours
=n2n
[node2
];
564 QSet
<int> intersection
=node1_neighbours
.intersect(node2_neighbours
);
565 int N
=intersection
.size();
569 QSet
<int>::const_iterator p1
=intersection
.begin();
570 QSet
<int>::const_iterator p2
=p1
+1;
571 vtkIdType intersection1
=_nodes
[*p1
];
572 vtkIdType intersection2
=_nodes
[*p2
];
573 if(n2n
[intersection1
].contains(intersection2
))//if there's an edge between intersection1 and intersection2
575 //check if (node1,intersection1,intersection2) and (node2,intersection1,intersection2) are defined as cells!
576 // QVector< QSet< int > > n2c
577 QSet
< int > S1
=n2c
[intersection1
];
578 QSet
< int > S2
=n2c
[intersection2
];
579 QSet
< int > Si
=S1
.intersect(S2
);
581 foreach(vtkIdType C
,Si
){
582 vtkIdType N_pts
, *pts
;
583 grid
->GetCellPoints(C
, N_pts
, pts
);
584 for(int i
=0;i
<N_pts
;i
++)
586 if(pts
[i
]==node1
|| pts
[i
]==node2
) counter
++;
589 if(counter
>=2) IsTetra
=true;
595 // vtkIdType Operation::FindSnapPoint(vtkUnstructuredGrid *src, vtkIdType DeadNode)
600 bool Operation::DeletePoint(vtkUnstructuredGrid
*src
, vtkIdType DeadNode
)
602 EG_VTKSP(vtkUnstructuredGrid
, dst
);
605 int N_points
=src
->GetNumberOfPoints();
606 int N_cells
=src
->GetNumberOfCells();
610 if(DeadNode
<0 || DeadNode
>=N_points
)
612 cout
<<"Warning: Point out of range: DeadNode="<<DeadNode
<<" N_points="<<N_points
<<endl
;
616 QSet
<vtkIdType
> DeadCells
;
617 QSet
<vtkIdType
> MutatedCells
;
618 QSet
<vtkIdType
> MutilatedCells
;
620 vtkIdType SnapPoint
=-1;
621 //Find closest point to DeadNode
622 // vtkIdType SnapPoint = getClosestNode(DeadNode,src);//DeadNode moves to SnapPoint
624 foreach(vtkIdType PSP
, n2n
[DeadNode
])
626 bool IsValidSnapPoint
=true;
628 cout
<<"====>PSP="<<PSP
<<endl
;
630 if(NumberOfCommonPoints(DeadNode
,PSP
,IsTetra
)>2)//common point check
632 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
633 IsValidSnapPoint
=false;
635 if(IsTetra
)//tetra check
637 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
638 IsValidSnapPoint
=false;
641 //count number of points and cells to remove + analyse cell transformations
645 MutatedCells
.clear();
646 MutilatedCells
.clear();
647 foreach(vtkIdType C
, n2c
[DeadNode
])//loop through potentially dead cells
650 //get points around cell
651 vtkIdType N_pts
, *pts
;
652 src
->GetCellPoints(C
, N_pts
, pts
);
654 bool ContainsSnapPoint
=false;
655 bool invincible
=false;
656 for(int i
=0;i
<N_pts
;i
++)
658 cout
<<"pts["<<i
<<"]="<<pts
[i
]<<" and PSP="<<PSP
<<endl
;
659 if(pts
[i
]==PSP
) {ContainsSnapPoint
=true;}
660 if(pts
[i
]!=DeadNode
&& pts
[i
]!=PSP
&& n2c
[pts
[i
]].size()<=1) invincible
=true;
662 if(ContainsSnapPoint
)
664 if(N_pts
==3)//dead cell
666 if(invincible
)//Check that empty lines aren't left behind when a cell is killed
668 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
669 IsValidSnapPoint
=false;
675 cout
<<"cell "<<C
<<" has been pwned!"<<endl
;
678 /* else if(N_pts==4)//mutilated cell
680 MutilatedCells.insert(C);
681 cout<<"cell "<<C<<" has lost a limb!"<<endl;
685 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
691 vtkIdType src_N_pts
, *src_pts
;
692 src
->GetCellPoints(C
, src_N_pts
, src_pts
);
696 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
700 vtkIdType OldTriangle
[3];
701 vtkIdType NewTriangle
[3];
703 for(int i
=0;i
<src_N_pts
;i
++)
705 OldTriangle
[i
]=src_pts
[i
];
706 NewTriangle
[i
]=( (src_pts
[i
]==DeadNode
) ? PSP
: src_pts
[i
] );
708 vec3_t Old_N
= triNormal(src
, OldTriangle
[0], OldTriangle
[1], OldTriangle
[2]);
709 vec3_t New_N
= triNormal(src
, NewTriangle
[0], NewTriangle
[1], NewTriangle
[2]);
710 double OldArea
=Old_N
.abs();
711 double NewArea
=New_N
.abs();
712 double scal
=Old_N
*New_N
;
713 double cross
=(Old_N
.cross(New_N
)).abs();//double-cross on Nar Shadaa B-)
715 cout
<<"OldArea="<<OldArea
<<endl
;
716 cout
<<"NewArea="<<NewArea
<<endl
;
717 cout
<<"scal="<<scal
<<endl
;
718 cout
<<"cross="<<cross
<<endl
;
720 if(Old_N
*New_N
<Old_N
*Old_N
*1./100.)//area + inversion check
722 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
723 IsValidSnapPoint
=false;
726 /* if(NewArea<OldArea*1./100.)
728 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
729 IsValidSnapPoint=false;
734 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
735 IsValidSnapPoint=false;
739 MutatedCells
.insert(C
);
740 cout
<<"cell "<<C
<<" has been infected!"<<endl
;
744 if(N_cells
+N_newcells
<=0)//survivor check
746 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
747 IsValidSnapPoint
=false;
749 /* if(EmptyVolume(DeadNode,PSP))//simplified volume check
751 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
752 IsValidSnapPoint=false;
754 if(IsValidSnapPoint
) {SnapPoint
=PSP
; break;}
755 }//end of loop through potential SnapPoints
757 cout
<<"===>SNAPPOINT="<<SnapPoint
<<endl
;
758 if(SnapPoint
<0) {cout
<<"Sorry no possible SnapPoint found."<<endl
; return(false);}
761 cout
<<"N_points="<<N_points
<<endl
;
762 cout
<<"N_cells="<<N_cells
<<endl
;
763 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
764 cout
<<"N_newcells="<<N_newcells
<<endl
;
765 allocateGrid(dst
,N_cells
+N_newcells
,N_points
+N_newpoints
);
767 //vector used to redefine the new point IDs
768 QVector
<vtkIdType
> OffSet(N_points
);
771 vtkIdType dst_id_node
=0;
772 for (vtkIdType src_id_node
= 0; src_id_node
< N_points
; src_id_node
++) {//loop through src points
773 if(src_id_node
!=DeadNode
)//if the node isn't dead, copy it
776 src
->GetPoints()->GetPoint(src_id_node
, x
.data());
777 dst
->GetPoints()->SetPoint(dst_id_node
, x
.data());
778 copyNodeData(src
, src_id_node
, dst
, dst_id_node
);
779 OffSet
[src_id_node
]=src_id_node
-dst_id_node
;
784 cout
<<"DeadCells="<<DeadCells
<<endl
;
785 cout
<<"MutatedCells="<<MutatedCells
<<endl
;
786 cout
<<"MutilatedCells="<<MutilatedCells
<<endl
;
789 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {//loop through src cells
790 if(!DeadCells
.contains(id_cell
))//if the cell isn't dead
792 vtkIdType src_N_pts
, *src_pts
;
793 vtkIdType dst_N_pts
, *dst_pts
;
794 src
->GetCellPoints(id_cell
, src_N_pts
, src_pts
);
796 vtkIdType type_cell
= src
->GetCellType(id_cell
);
797 cout
<<"-->id_cell="<<id_cell
<<endl
;
798 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
799 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
801 dst_pts
=new vtkIdType
[dst_N_pts
];
802 if(MutatedCells
.contains(id_cell
))//mutated cell
804 cout
<<"processing mutated cell "<<id_cell
<<endl
;
805 for(int i
=0;i
<src_N_pts
;i
++)
807 if(src_pts
[i
]==DeadNode
) {
808 cout
<<"SnapPoint="<<SnapPoint
<<endl
;
809 cout
<<"OffSet[SnapPoint]="<<OffSet
[SnapPoint
]<<endl
;
810 cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
811 dst_pts
[i
]=SnapPoint
-OffSet
[SnapPoint
];
813 else dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
815 cout
<<"--->dst_pts:"<<endl
;
816 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
819 else if(MutilatedCells
.contains(id_cell
))//mutilated cell
821 cout
<<"processing mutilated cell "<<id_cell
<<endl
;
823 if(type_cell
==VTK_QUAD
) {
824 type_cell
=VTK_TRIANGLE
;
827 else {cout
<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl
;EG_BUG
;}
830 for(int i
=0;i
<src_N_pts
;i
++)
832 if(src_pts
[i
]==SnapPoint
) { dst_pts
[j
]=SnapPoint
-OffSet
[SnapPoint
];j
++; }//SnapPoint
833 else if(src_pts
[i
]!=DeadNode
) { dst_pts
[j
]=src_pts
[i
]-OffSet
[src_pts
[i
]];j
++; }//pre-snap/dead + post-snap/dead
834 //do nothing in case of DeadNode
839 cout
<<"processing normal cell "<<id_cell
<<endl
;
840 for(int i
=0;i
<src_N_pts
;i
++)
842 dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
846 vtkIdType id_new_cell
= dst
->InsertNextCell(type_cell
, dst_N_pts
, dst_pts
);
847 copyCellData(src
, id_cell
, dst
, id_new_cell
);
848 cout
<<"===Copying cell "<<id_cell
<<" to "<<id_new_cell
<<"==="<<endl
;
849 cout
<<"src_pts:"<<endl
;
850 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
851 cout
<<"dst_pts:"<<endl
;
852 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
853 cout
<<"OffSet="<<OffSet
<<endl
;
854 cout
<<"===Copying cell end==="<<endl
;
858 // cout_grid(cout,dst,true,true,true,true);
863 bool Operation::EmptyVolume(vtkIdType DeadNode
, vtkIdType PSP
)
870 vec3_t
Operation::GetCenter(vtkIdType cellId
, double& R
)
872 vtkIdType
*pts
, Npts
;
873 grid
->GetCellPoints(cellId
, Npts
, pts
);
876 for (vtkIdType i
= 0; i
< Npts
; ++i
) {
878 grid
->GetPoints()->GetPoint(pts
[i
], xp
.data());
879 x
+= double(1)/Npts
* xp
;
883 for (vtkIdType i
= 0; i
< Npts
; ++i
) {
885 grid
->GetPoints()->GetPoint(pts
[i
], xp
.data());
886 R
= min(R
, 0.25*(xp
-x
).abs());
892 bool Operation::getNeighbours(vtkIdType Boss
, QVector
<vtkIdType
>& Peons
, int BC
)
894 // QVector <vtkIdType> Peons;
896 QSet
<int> S1
=n2c
[Boss
];
897 cout
<<"S1="<<S1
<<endl
;
898 foreach(vtkIdType PN
,n2n
[Boss
])
900 cout
<<"PN="<<PN
<<endl
;
901 QSet
<int> S2
=n2c
[PN
];
902 cout
<<"S2="<<S2
<<endl
;
903 QSet
<int> Si
=S2
.intersect(S1
);
904 cout
<<"PN="<<PN
<<" Si="<<Si
<<endl
;
905 if(Si
.size()<2)//only one common cell
912 foreach(vtkIdType C
,Si
)
914 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
915 int bc
=cell_code
->GetValue(C
);
916 cout
<<"C="<<C
<<" bc="<<bc
<<endl
;
919 if(bc_set
.size()>1)//2 different boundary codes
933 int N
=n2n
[Boss
].size();
934 QVector
<vtkIdType
> neighbours(N
);
935 qCopy(n2n
[Boss
].begin(), n2n
[Boss
].end(), neighbours
.begin());
937 double alphamin_value
;
938 vtkIdType alphamin_i
;
939 vtkIdType alphamin_j
;
944 for(int j
=i
+1;j
<N
;j
++)
946 double alpha
=deviation(grid
,neighbours
[i
],Boss
,neighbours
[j
]);
947 // cout<<"alpha("<<neighbours[i]<<","<<Boss<<","<<neighbours[j]<<")="<<alpha<<endl;
949 alphamin_value
=alpha
;
956 if(alpha
<alphamin_value
)
958 alphamin_value
=alpha
;
965 // cout<<"alphamin_value="<<alphamin_value<<endl;
968 Peons
[0]=neighbours
[alphamin_i
];
969 Peons
[1]=neighbours
[alphamin_j
];
971 /* cout<<"FATAL ERROR: number of neighbours != 2"<<endl;
977 int Operation::UpdateMeshDensity()
979 if(DebugLevel
>0) cout
<<"===UpdateMeshDensity START==="<<endl
;
981 getAllSurfaceCells(cells
,grid
);
982 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
983 EG_VTKDCN(vtkDoubleArray
, node_meshdensity
, grid
, "node_meshdensity");
984 getNodesFromCells(cells
, nodes
, grid
);
988 if(DebugLevel
>5) cout
<<"cells.size()="<<cells
.size()<<endl
;
990 EG_VTKDCN(vtkDoubleArray
, node_meshdensity_current
, grid
, "node_meshdensity_current");
991 foreach(vtkIdType node
,nodes
)
993 double L
=CurrentVertexAvgDist(node
,n2n
,grid
);
995 node_meshdensity_current
->SetValue(node
, D
);
997 if(DebugLevel
>0) cout
<<"===UpdateMeshDensity END==="<<endl
;
1001 // Special structure for marking vertices
1002 typedef struct _vtkMeshVertex
1005 vtkIdList
*edges
; // connected edges (list of connected point ids)
1006 } vtkMeshVertex
, *vtkMeshVertexPtr
;
1008 int Operation::UpdateNodeType_all()
1010 cout
<<"===UpdateNodeType_all START==="<<endl
;
1011 if(DebugLevel
>47) cout
<<"this->FeatureAngle="<<this->FeatureAngle
<<endl
;
1012 if(DebugLevel
>47) cout
<<"this->EdgeAngle="<<this->EdgeAngle
<<endl
;
1014 getAllSurfaceCells(cells
,grid
);
1015 if(DebugLevel
>5) cout
<<"cells.size()="<<cells
.size()<<endl
;
1017 EG_VTKSP(vtkPolyData
, pdata
);
1018 // addToPolyData(m_SelectedCells, pdata, grid);
1019 addToPolyData(cells
, pdata
, grid
);
1021 vtkPolyData
* input
=pdata
;
1023 vtkPolyData
*source
= 0;
1025 vtkIdType numPts
, numCells
, i
, numPolys
;
1030 double x
[3], y
[3], deltaX
[3], xNew
[3], conv
, maxDist
, dist
, factor
;
1031 double x1
[3], x2
[3], x3
[3], l1
[3], l2
[3];
1032 double CosFeatureAngle
; //Cosine of angle between adjacent polys
1033 double CosEdgeAngle
; // Cosine of angle between adjacent edges
1034 double closestPt
[3], dist2
, *w
= NULL
;
1035 int iterationNumber
, abortExecute
;
1036 vtkIdType numSimple
=0, numBEdges
=0, numFixed
=0, numFEdges
=0;
1037 vtkPolyData
*inMesh
, *Mesh
;
1039 vtkCellArray
*inVerts
, *inLines
, *inPolys
;
1041 vtkMeshVertexPtr Verts
;
1042 vtkCellLocator
*cellLocator
=NULL
;
1046 numPts
=input
->GetNumberOfPoints();
1047 numCells
=input
->GetNumberOfCells();
1048 if (numPts
< 1 || numCells
< 1)
1050 cout
<<"No data to smooth!"<<endl
;
1055 cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle
);
1056 CosEdgeAngle
= cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle
);
1059 cout
<<"Smoothing " << numPts
<< " vertices, " << numCells
1061 << "\tConvergence= " << this->Convergence
<< "\n"
1062 << "\tIterations= " << this->NumberOfIterations
<< "\n"
1063 << "\tRelaxation Factor= " << this->RelaxationFactor
<< "\n"
1064 << "\tEdge Angle= " << this->EdgeAngle
<< "\n"
1065 << "\tBoundary Smoothing " << (this->BoundarySmoothing
? "On\n" : "Off\n")
1066 << "\tFeature Edge Smoothing " << (this->FeatureEdgeSmoothing
? "On\n" : "Off\n")
1067 << "\tError Scalars " << (this->GenerateErrorScalars
? "On\n" : "Off\n")
1068 << "\tError Vectors " << (this->GenerateErrorVectors
? "On\n" : "Off\n")<<endl
;
1070 // Peform topological analysis. What we're gonna do is build a connectivity
1071 // array of connected vertices. The outcome will be one of three
1072 // classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or
1073 // VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected
1074 // vertices. FIXED vertices are never smoothed. Edge vertices are smoothed
1075 // using a subset of the attached vertices.
1077 if(DebugLevel
>5) cout
<<"===>Analyze topology==="<<endl
;
1078 if(DebugLevel
>5) cout
<<"Analyzing topology..."<<endl
;
1079 if(DebugLevel
>5) cout
<<"0:numPts="<<numPts
<<endl
;
1080 Verts
= new vtkMeshVertex
[numPts
];
1081 for (i
=0; i
<numPts
; i
++)
1083 if(DebugLevel
>5) cout
<<"0:VTK_SIMPLE_VERTEX"<<endl
;
1084 Verts
[i
].type
= VTK_SIMPLE_VERTEX
; //can smooth
1085 Verts
[i
].edges
= NULL
;
1088 inPts
= input
->GetPoints();
1089 conv
= this->Convergence
* input
->GetLength();
1091 if(DebugLevel
>5) cout
<<"==polygons and triangle strips=="<<endl
;
1092 // now polygons and triangle strips-------------------------------
1093 inPolys
=input
->GetPolys();
1094 numPolys
= inPolys
->GetNumberOfCells();
1096 if(DebugLevel
>5) cout
<<"numPolys="<<numPolys
<<endl
;
1099 { //build cell structure
1100 vtkCellArray
*polys
;
1102 int numNei
, nei
, edge
;
1103 vtkIdType numNeiPts
;
1105 double normal
[3], neiNormal
[3];
1106 vtkIdList
*neighbors
;
1108 neighbors
= vtkIdList::New();
1109 neighbors
->Allocate(VTK_CELL_SIZE
);
1111 inMesh
= vtkPolyData::New();
1112 inMesh
->SetPoints(inPts
);
1113 inMesh
->SetPolys(inPolys
);
1116 Mesh
->BuildLinks(); //to do neighborhood searching
1117 polys
= Mesh
->GetPolys();
1119 for (cellId
=0, polys
->InitTraversal(); polys
->GetNextCell(npts
,pts
);
1122 if(DebugLevel
>5) cout
<<"->cellId="<<cellId
<<endl
;
1123 for (i
=0; i
< npts
; i
++)
1125 if(DebugLevel
>5) cout
<<"-->i="<<i
<<endl
;
1127 p2
= pts
[(i
+1)%npts
];
1129 if ( Verts
[p1
].edges
== NULL
)
1131 Verts
[p1
].edges
= vtkIdList::New();
1132 Verts
[p1
].edges
->Allocate(16,6);
1134 if ( Verts
[p2
].edges
== NULL
)
1136 Verts
[p2
].edges
= vtkIdList::New();
1137 Verts
[p2
].edges
->Allocate(16,6);
1140 Mesh
->GetCellEdgeNeighbors(cellId
,p1
,p2
,neighbors
);
1141 numNei
= neighbors
->GetNumberOfIds();
1142 if(DebugLevel
>5) cout
<<"-->numNei="<<numNei
<<endl
;
1144 edge
= VTK_SIMPLE_VERTEX
;
1147 edge
= VTK_BOUNDARY_EDGE_VERTEX
;
1150 else if ( numNei
>= 2 )
1152 // check to make sure that this edge hasn't been marked already
1153 for (j
=0; j
< numNei
; j
++)
1155 if ( neighbors
->GetId(j
) < cellId
)
1162 edge
= VTK_FEATURE_EDGE_VERTEX
;
1166 else if ( numNei
== 1 && (nei
=neighbors
->GetId(0)) > cellId
)
1168 vtkPolygon::ComputeNormal(inPts
,npts
,pts
,normal
);
1169 Mesh
->GetCellPoints(nei
,numNeiPts
,neiPts
);
1170 vtkPolygon::ComputeNormal(inPts
,numNeiPts
,neiPts
,neiNormal
);
1172 if ( this->FeatureEdgeSmoothing
&&
1173 vtkMath::Dot(normal
,neiNormal
) <= CosFeatureAngle
)
1175 edge
= VTK_FEATURE_EDGE_VERTEX
;
1178 else // a visited edge; skip rest of analysis
1183 if ( edge
&& Verts
[p1
].type
== VTK_SIMPLE_VERTEX
)
1185 Verts
[p1
].edges
->Reset();
1186 Verts
[p1
].edges
->InsertNextId(p2
);
1187 Verts
[p1
].type
= edge
;
1189 else if ( (edge
&& Verts
[p1
].type
== VTK_BOUNDARY_EDGE_VERTEX
) ||
1190 (edge
&& Verts
[p1
].type
== VTK_FEATURE_EDGE_VERTEX
) ||
1191 (!edge
&& Verts
[p1
].type
== VTK_SIMPLE_VERTEX
) )
1193 Verts
[p1
].edges
->InsertNextId(p2
);
1194 if ( Verts
[p1
].type
&& edge
== VTK_BOUNDARY_EDGE_VERTEX
)
1196 Verts
[p1
].type
= VTK_BOUNDARY_EDGE_VERTEX
;
1200 if ( edge
&& Verts
[p2
].type
== VTK_SIMPLE_VERTEX
)
1202 Verts
[p2
].edges
->Reset();
1203 Verts
[p2
].edges
->InsertNextId(p1
);
1204 Verts
[p2
].type
= edge
;
1206 else if ( (edge
&& Verts
[p2
].type
== VTK_BOUNDARY_EDGE_VERTEX
) ||
1207 (edge
&& Verts
[p2
].type
== VTK_FEATURE_EDGE_VERTEX
) ||
1208 (!edge
&& Verts
[p2
].type
== VTK_SIMPLE_VERTEX
) )
1210 Verts
[p2
].edges
->InsertNextId(p1
);
1211 if ( Verts
[p2
].type
&& edge
== VTK_BOUNDARY_EDGE_VERTEX
)
1213 Verts
[p2
].type
= VTK_BOUNDARY_EDGE_VERTEX
;
1221 neighbors
->Delete();
1222 }//if strips or polys
1224 //post-process edge vertices to make sure we can smooth them
1225 for (i
=0; i
<numPts
; i
++)
1227 if ( Verts
[i
].type
== VTK_SIMPLE_VERTEX
)
1232 else if ( Verts
[i
].type
== VTK_FIXED_VERTEX
)
1237 else if ( Verts
[i
].type
== VTK_FEATURE_EDGE_VERTEX
||
1238 Verts
[i
].type
== VTK_BOUNDARY_EDGE_VERTEX
)
1239 { //see how many edges; if two, what the angle is
1241 if ( !this->BoundarySmoothing
&&
1242 Verts
[i
].type
== VTK_BOUNDARY_EDGE_VERTEX
)
1244 if(DebugLevel
>5) cout
<<"Verts[i].type = VTK_FIXED_VERTEX; 4"<<endl
;
1245 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1249 else if ( (npts
= Verts
[i
].edges
->GetNumberOfIds()) != 2 )
1251 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type = VTK_FIXED_VERTEX; 5"<<endl
;
1252 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1256 else //check angle between edges
1258 inPts
->GetPoint(Verts
[i
].edges
->GetId(0),x1
);
1259 inPts
->GetPoint(i
,x2
);
1260 inPts
->GetPoint(Verts
[i
].edges
->GetId(1),x3
);
1264 l1
[k
] = x2
[k
] - x1
[k
];
1265 l2
[k
] = x3
[k
] - x2
[k
];
1267 if ( vtkMath::Normalize(l1
) >= 0.0 &&
1268 vtkMath::Normalize(l2
) >= 0.0 &&
1269 vtkMath::Dot(l1
,l2
) < CosEdgeAngle
)
1271 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type = VTK_FIXED_VERTEX; 6"<<endl
;
1272 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1277 if ( Verts
[i
].type
== VTK_FEATURE_EDGE_VERTEX
)
1291 cout
<<"Found\n\t" << numSimple
<< " simple vertices\n\t"
1292 << numFEdges
<< " feature edge vertices\n\t"
1293 << numBEdges
<< " boundary edge vertices\n\t"
1294 << numFixed
<< " fixed vertices\n\t"<<endl
;
1295 cout
<<"1:numPts="<<numPts
<<endl
;
1298 for (i
=0; i
<numPts
; i
++)
1300 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type="<<VertexType2Str(Verts
[i
].type
)<<endl
;
1301 if(Verts
[i
].edges
!= NULL
&& (npts
= Verts
[i
].edges
->GetNumberOfIds()) > 0)
1303 for (j
=0; j
<npts
; j
++)
1305 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].edges->GetId("<<j
<<")="<<Verts
[i
].edges
->GetId(j
)<<endl
;
1306 }//for all connected points
1310 //Copy node type info from Verts
1311 EG_VTKDCN(vtkCharArray
, node_type
, grid
, "node_type");
1312 if(DebugLevel
>5) cout
<<"nodes.size()="<<nodes
.size()<<endl
;
1313 foreach(vtkIdType node
,nodes
)
1315 if(DebugLevel
>5) cout
<<"Verts["<<node
<<"].type="<<VertexType2Str(Verts
[node
].type
)<<endl
;
1316 node_type
->SetValue(node
,Verts
[node
].type
);
1319 //free up connectivity storage
1320 for (int i
=0; i
<numPts
; i
++)
1322 if ( Verts
[i
].edges
!= NULL
)
1324 Verts
[i
].edges
->Delete();
1325 Verts
[i
].edges
= NULL
;
1330 cout
<<"===UpdateNodeType_all END==="<<endl
;
1333 //End of UpdateNodeType_all
1335 int Operation::UpdateNodeType()
1337 if(DebugLevel
>47) cout
<<"this->FeatureAngle="<<this->FeatureAngle
<<endl
;
1338 if(DebugLevel
>47) cout
<<"this->EdgeAngle="<<this->EdgeAngle
<<endl
;
1339 cout
<<"===UpdateNodeType START==="<<endl
;
1341 getAllSurfaceCells(cells
,grid
);
1342 if(DebugLevel
>5) cout
<<"cells.size()="<<cells
.size()<<endl
;
1344 EG_VTKSP(vtkPolyData
, pdata
);
1345 // addToPolyData(m_SelectedCells, pdata, grid);
1346 addToPolyData(cells
, pdata
, grid
);
1348 vtkPolyData
* input
=pdata
;
1350 vtkPolyData
*source
= 0;
1352 vtkIdType numPts
, numCells
, i
, numPolys
;
1357 double x
[3], y
[3], deltaX
[3], xNew
[3], conv
, maxDist
, dist
, factor
;
1358 double x1
[3], x2
[3], x3
[3], l1
[3], l2
[3];
1359 double CosFeatureAngle
; //Cosine of angle between adjacent polys
1360 double CosEdgeAngle
; // Cosine of angle between adjacent edges
1361 double closestPt
[3], dist2
, *w
= NULL
;
1362 int iterationNumber
, abortExecute
;
1363 vtkIdType numSimple
=0, numBEdges
=0, numFixed
=0, numFEdges
=0;
1364 vtkPolyData
*inMesh
, *Mesh
;
1366 vtkCellArray
*inVerts
, *inLines
, *inPolys
;
1368 vtkMeshVertexPtr Verts
;
1369 vtkCellLocator
*cellLocator
=NULL
;
1373 numPts
=input
->GetNumberOfPoints();
1374 numCells
=input
->GetNumberOfCells();
1375 if (numPts
< 1 || numCells
< 1)
1377 cout
<<"No data to smooth!"<<endl
;
1382 cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle
);
1383 CosEdgeAngle
= cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle
);
1386 cout
<<"Smoothing " << numPts
<< " vertices, " << numCells
1388 << "\tConvergence= " << this->Convergence
<< "\n"
1389 << "\tIterations= " << this->NumberOfIterations
<< "\n"
1390 << "\tRelaxation Factor= " << this->RelaxationFactor
<< "\n"
1391 << "\tEdge Angle= " << this->EdgeAngle
<< "\n"
1392 << "\tBoundary Smoothing " << (this->BoundarySmoothing
? "On\n" : "Off\n")
1393 << "\tFeature Edge Smoothing " << (this->FeatureEdgeSmoothing
? "On\n" : "Off\n")
1394 << "\tError Scalars " << (this->GenerateErrorScalars
? "On\n" : "Off\n")
1395 << "\tError Vectors " << (this->GenerateErrorVectors
? "On\n" : "Off\n")<<endl
;
1397 // Peform topological analysis. What we're gonna do is build a connectivity
1398 // array of connected vertices. The outcome will be one of three
1399 // classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or
1400 // VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected
1401 // vertices. FIXED vertices are never smoothed. Edge vertices are smoothed
1402 // using a subset of the attached vertices.
1404 if(DebugLevel
>5) cout
<<"===>Analyze topology==="<<endl
;
1405 if(DebugLevel
>5) cout
<<"Analyzing topology..."<<endl
;
1406 if(DebugLevel
>5) cout
<<"0:numPts="<<numPts
<<endl
;
1407 Verts
= new vtkMeshVertex
[numPts
];
1408 for (i
=0; i
<numPts
; i
++)
1410 if(DebugLevel
>5) cout
<<"0:VTK_SIMPLE_VERTEX"<<endl
;
1411 Verts
[i
].type
= VTK_SIMPLE_VERTEX
; //can smooth
1412 Verts
[i
].edges
= NULL
;
1415 inPts
= input
->GetPoints();
1416 conv
= this->Convergence
* input
->GetLength();
1418 if(DebugLevel
>5) cout
<<"==polygons and triangle strips=="<<endl
;
1419 // now polygons and triangle strips-------------------------------
1420 inPolys
=input
->GetPolys();
1421 numPolys
= inPolys
->GetNumberOfCells();
1423 if(DebugLevel
>5) cout
<<"numPolys="<<numPolys
<<endl
;
1426 { //build cell structure
1427 vtkCellArray
*polys
;
1429 int numNei
, nei
, edge
;
1430 vtkIdType numNeiPts
;
1432 double normal
[3], neiNormal
[3];
1433 vtkIdList
*neighbors
;
1435 neighbors
= vtkIdList::New();
1436 neighbors
->Allocate(VTK_CELL_SIZE
);
1438 inMesh
= vtkPolyData::New();
1439 inMesh
->SetPoints(inPts
);
1440 inMesh
->SetPolys(inPolys
);
1443 Mesh
->BuildLinks(); //to do neighborhood searching
1444 polys
= Mesh
->GetPolys();
1446 for (cellId
=0, polys
->InitTraversal(); polys
->GetNextCell(npts
,pts
);
1449 if(DebugLevel
>5) cout
<<"->cellId="<<cellId
<<endl
;
1450 for (i
=0; i
< npts
; i
++)
1452 if(DebugLevel
>5) cout
<<"-->i="<<i
<<endl
;
1454 p2
= pts
[(i
+1)%npts
];
1456 if ( Verts
[p1
].edges
== NULL
)
1458 Verts
[p1
].edges
= vtkIdList::New();
1459 Verts
[p1
].edges
->Allocate(16,6);
1461 if ( Verts
[p2
].edges
== NULL
)
1463 Verts
[p2
].edges
= vtkIdList::New();
1464 Verts
[p2
].edges
->Allocate(16,6);
1467 Mesh
->GetCellEdgeNeighbors(cellId
,p1
,p2
,neighbors
);
1468 numNei
= neighbors
->GetNumberOfIds();
1469 if(DebugLevel
>5) cout
<<"-->numNei="<<numNei
<<endl
;
1471 edge
= VTK_SIMPLE_VERTEX
;
1474 edge
= VTK_BOUNDARY_EDGE_VERTEX
;
1477 else if ( numNei
>= 2 )
1479 // check to make sure that this edge hasn't been marked already
1480 for (j
=0; j
< numNei
; j
++)
1482 if ( neighbors
->GetId(j
) < cellId
)
1489 edge
= VTK_FEATURE_EDGE_VERTEX
;
1493 else if ( numNei
== 1 && (nei
=neighbors
->GetId(0)) > cellId
)
1495 vtkPolygon::ComputeNormal(inPts
,npts
,pts
,normal
);
1496 Mesh
->GetCellPoints(nei
,numNeiPts
,neiPts
);
1497 vtkPolygon::ComputeNormal(inPts
,numNeiPts
,neiPts
,neiNormal
);
1499 if ( this->FeatureEdgeSmoothing
&&
1500 vtkMath::Dot(normal
,neiNormal
) <= CosFeatureAngle
)
1502 edge
= VTK_FEATURE_EDGE_VERTEX
;
1505 else // a visited edge; skip rest of analysis
1510 if ( edge
&& Verts
[p1
].type
== VTK_SIMPLE_VERTEX
)
1512 Verts
[p1
].edges
->Reset();
1513 Verts
[p1
].edges
->InsertNextId(p2
);
1514 Verts
[p1
].type
= edge
;
1516 else if ( (edge
&& Verts
[p1
].type
== VTK_BOUNDARY_EDGE_VERTEX
) ||
1517 (edge
&& Verts
[p1
].type
== VTK_FEATURE_EDGE_VERTEX
) ||
1518 (!edge
&& Verts
[p1
].type
== VTK_SIMPLE_VERTEX
) )
1520 Verts
[p1
].edges
->InsertNextId(p2
);
1521 if ( Verts
[p1
].type
&& edge
== VTK_BOUNDARY_EDGE_VERTEX
)
1523 Verts
[p1
].type
= VTK_BOUNDARY_EDGE_VERTEX
;
1527 if ( edge
&& Verts
[p2
].type
== VTK_SIMPLE_VERTEX
)
1529 Verts
[p2
].edges
->Reset();
1530 Verts
[p2
].edges
->InsertNextId(p1
);
1531 Verts
[p2
].type
= edge
;
1533 else if ( (edge
&& Verts
[p2
].type
== VTK_BOUNDARY_EDGE_VERTEX
) ||
1534 (edge
&& Verts
[p2
].type
== VTK_FEATURE_EDGE_VERTEX
) ||
1535 (!edge
&& Verts
[p2
].type
== VTK_SIMPLE_VERTEX
) )
1537 Verts
[p2
].edges
->InsertNextId(p1
);
1538 if ( Verts
[p2
].type
&& edge
== VTK_BOUNDARY_EDGE_VERTEX
)
1540 Verts
[p2
].type
= VTK_BOUNDARY_EDGE_VERTEX
;
1548 neighbors
->Delete();
1549 }//if strips or polys
1551 //post-process edge vertices to make sure we can smooth them
1552 for (i
=0; i
<numPts
; i
++)
1554 if ( Verts
[i
].type
== VTK_SIMPLE_VERTEX
)
1559 else if ( Verts
[i
].type
== VTK_FIXED_VERTEX
)
1564 else if ( Verts
[i
].type
== VTK_FEATURE_EDGE_VERTEX
||
1565 Verts
[i
].type
== VTK_BOUNDARY_EDGE_VERTEX
)
1566 { //see how many edges; if two, what the angle is
1568 if ( !this->BoundarySmoothing
&&
1569 Verts
[i
].type
== VTK_BOUNDARY_EDGE_VERTEX
)
1571 if(DebugLevel
>5) cout
<<"Verts[i].type = VTK_FIXED_VERTEX; 4"<<endl
;
1572 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1576 else if ( (npts
= Verts
[i
].edges
->GetNumberOfIds()) != 2 )
1578 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type = VTK_FIXED_VERTEX; 5"<<endl
;
1579 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1583 else //check angle between edges
1585 inPts
->GetPoint(Verts
[i
].edges
->GetId(0),x1
);
1586 inPts
->GetPoint(i
,x2
);
1587 inPts
->GetPoint(Verts
[i
].edges
->GetId(1),x3
);
1591 l1
[k
] = x2
[k
] - x1
[k
];
1592 l2
[k
] = x3
[k
] - x2
[k
];
1594 if ( vtkMath::Normalize(l1
) >= 0.0 &&
1595 vtkMath::Normalize(l2
) >= 0.0 &&
1596 vtkMath::Dot(l1
,l2
) < CosEdgeAngle
)
1598 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type = VTK_FIXED_VERTEX; 6"<<endl
;
1599 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1604 if ( Verts
[i
].type
== VTK_FEATURE_EDGE_VERTEX
)
1618 cout
<<"Found\n\t" << numSimple
<< " simple vertices\n\t"
1619 << numFEdges
<< " feature edge vertices\n\t"
1620 << numBEdges
<< " boundary edge vertices\n\t"
1621 << numFixed
<< " fixed vertices\n\t"<<endl
;
1622 cout
<<"1:numPts="<<numPts
<<endl
;
1625 for (i
=0; i
<numPts
; i
++)
1627 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type="<<VertexType2Str(Verts
[i
].type
)<<endl
;
1628 if(Verts
[i
].edges
!= NULL
&& (npts
= Verts
[i
].edges
->GetNumberOfIds()) > 0)
1630 for (j
=0; j
<npts
; j
++)
1632 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].edges->GetId("<<j
<<")="<<Verts
[i
].edges
->GetId(j
)<<endl
;
1633 }//for all connected points
1637 //Copy node type info from Verts
1638 EG_VTKDCN(vtkCharArray
, node_type
, grid
, "node_type");
1639 if(DebugLevel
>5) cout
<<"nodes.size()="<<nodes
.size()<<endl
;
1640 foreach(vtkIdType node
,nodes
)
1642 if(DebugLevel
>5) cout
<<"Verts["<<node
<<"].type="<<VertexType2Str(Verts
[node
].type
)<<endl
;
1643 node_type
->SetValue(node
,Verts
[node
].type
);
1646 //free up connectivity storage
1647 for (int i
=0; i
<numPts
; i
++)
1649 if ( Verts
[i
].edges
!= NULL
)
1651 Verts
[i
].edges
->Delete();
1652 Verts
[i
].edges
= NULL
;
1657 cout
<<"===UpdateNodeType END==="<<endl
;
1660 //End of UpdateNodeType
1663 // Normal cell: nothing has changed
1664 // Dead cell: the cell does not exist anymore
1665 // Mutated cell: the cell's form has changed
1666 // Mutilated cell: the cell has less points than before
1668 vtkIdType
Operation::FindSnapPoint(vtkUnstructuredGrid
*src
, vtkIdType DeadNode
,QSet
<vtkIdType
> & DeadCells
,QSet
<vtkIdType
> & MutatedCells
,QSet
<vtkIdType
> & MutilatedCells
, int& N_newpoints
, int& N_newcells
)
1670 getAllSurfaceCells(cells
,src
);
1671 getNodesFromCells(cells
, nodes
, src
);
1675 UpdateNodeType_all();
1677 EG_VTKDCN(vtkCharArray
, node_type
, src
, "node_type");
1678 if(node_type
->GetValue(DeadNode
)==VTK_FIXED_VERTEX
)
1680 cout
<<"Sorry, unable to remove fixed vertex."<<endl
;
1685 int N_points
=src
->GetNumberOfPoints();
1686 int N_cells
=src
->GetNumberOfCells();
1690 vtkIdType SnapPoint
=-1;
1692 foreach(vtkIdType PSP
, n2n
[DeadNode
])
1694 bool IsValidSnapPoint
=true;
1696 if(DebugLevel
>10) cout
<<"====>PSP="<<PSP
<<endl
;
1698 if(NumberOfCommonPoints(DeadNode
,PSP
,IsTetra
)>2)//common point check
1700 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1701 IsValidSnapPoint
=false;
1703 if(IsTetra
)//tetra check
1705 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1706 IsValidSnapPoint
=false;
1709 //count number of points and cells to remove + analyse cell transformations
1713 MutatedCells
.clear();
1714 MutilatedCells
.clear();
1715 foreach(vtkIdType C
, n2c
[DeadNode
])//loop through potentially dead cells
1717 //get points around cell
1718 vtkIdType N_pts
, *pts
;
1719 src
->GetCellPoints(C
, N_pts
, pts
);
1721 bool ContainsSnapPoint
=false;
1722 bool invincible
=false;
1723 for(int i
=0;i
<N_pts
;i
++)
1725 if(DebugLevel
>10) cout
<<"pts["<<i
<<"]="<<pts
[i
]<<" and PSP="<<PSP
<<endl
;
1726 if(pts
[i
]==PSP
) {ContainsSnapPoint
=true;}
1727 if(pts
[i
]!=DeadNode
&& pts
[i
]!=PSP
&& n2c
[pts
[i
]].size()<=1) invincible
=true;
1729 if(ContainsSnapPoint
)
1731 if(N_pts
==3)//dead cell
1733 if(invincible
)//Check that empty lines aren't left behind when a cell is killed
1735 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1736 IsValidSnapPoint
=false;
1740 DeadCells
.insert(C
);
1742 if(DebugLevel
>10) cout
<<"cell "<<C
<<" has been pwned!"<<endl
;
1747 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
1753 vtkIdType src_N_pts
, *src_pts
;
1754 src
->GetCellPoints(C
, src_N_pts
, src_pts
);
1758 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
1762 vtkIdType OldTriangle
[3];
1763 vtkIdType NewTriangle
[3];
1765 for(int i
=0;i
<src_N_pts
;i
++)
1767 OldTriangle
[i
]=src_pts
[i
];
1768 NewTriangle
[i
]=( (src_pts
[i
]==DeadNode
) ? PSP
: src_pts
[i
] );
1770 vec3_t Old_N
= triNormal(src
, OldTriangle
[0], OldTriangle
[1], OldTriangle
[2]);
1771 vec3_t New_N
= triNormal(src
, NewTriangle
[0], NewTriangle
[1], NewTriangle
[2]);
1772 double OldArea
=Old_N
.abs();
1773 double NewArea
=New_N
.abs();
1774 double scal
=Old_N
*New_N
;
1775 double cross
=(Old_N
.cross(New_N
)).abs();//double-cross on Nar Shadaa B-)
1778 cout
<<"OldArea="<<OldArea
<<endl
;
1779 cout
<<"NewArea="<<NewArea
<<endl
;
1780 cout
<<"scal="<<scal
<<endl
;
1781 cout
<<"cross="<<cross
<<endl
;
1784 if(Old_N
*New_N
<Old_N
*Old_N
*1./100.)//area + inversion check
1786 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1787 IsValidSnapPoint
=false;
1791 MutatedCells
.insert(C
);
1792 if(DebugLevel
>10) cout
<<"cell "<<C
<<" has been infected!"<<endl
;
1796 if(N_cells
+N_newcells
<=0)//survivor check
1798 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1799 IsValidSnapPoint
=false;
1802 if(node_type
->GetValue(DeadNode
)==VTK_BOUNDARY_EDGE_VERTEX
&& node_type
->GetValue(PSP
)==VTK_SIMPLE_VERTEX
)
1804 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1805 IsValidSnapPoint
=false;
1808 if(node_type
->GetValue(DeadNode
)==VTK_BOUNDARY_EDGE_VERTEX
)
1811 QVector
<vtkIdType
> Peons
;
1812 getNeighbours(DeadNode
, Peons
, BC
);
1813 if(!Peons
.contains(PSP
))
1815 if(DebugLevel
>0) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1816 IsValidSnapPoint
=false;
1820 if(node_type
->GetValue(DeadNode
)==VTK_FEATURE_EDGE_VERTEX
&& node_type
->GetValue(PSP
)==VTK_SIMPLE_VERTEX
)
1822 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1823 IsValidSnapPoint
=false;
1826 if(node_type
->GetValue(DeadNode
)==VTK_FEATURE_EDGE_VERTEX
)
1829 QVector
<vtkIdType
> Peons
;
1830 getNeighbours(DeadNode
, Peons
, BC
);
1831 if(!Peons
.contains(PSP
))
1833 if(DebugLevel
>0) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1834 IsValidSnapPoint
=false;
1838 if(IsValidSnapPoint
) {SnapPoint
=PSP
; break;}
1839 }//end of loop through potential SnapPoints
1843 cout
<<"AT FINDSNAPPOINT EXIT"<<endl
;
1844 cout
<<"N_points="<<N_points
<<endl
;
1845 cout
<<"N_cells="<<N_cells
<<endl
;
1846 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1847 cout
<<"N_newcells="<<N_newcells
<<endl
;
1851 //End of FindSnapPoint
1853 bool Operation::DeletePoint_2(vtkUnstructuredGrid
*src
, vtkIdType DeadNode
, int& N_newpoints
, int& N_newcells
)
1855 getAllSurfaceCells(cells
,src
);
1856 // getNodesFromCells(cells, nodes, src);
1859 UpdateNodeType_all();
1862 int N_points
=src
->GetNumberOfPoints();
1863 int N_cells
=src
->GetNumberOfCells();
1867 if(DeadNode
<0 || DeadNode
>=N_points
)
1869 cout
<<"Warning: Point out of range: DeadNode="<<DeadNode
<<" N_points="<<N_points
<<endl
;
1873 QSet
<vtkIdType
> DeadCells
;
1874 QSet
<vtkIdType
> MutatedCells
;
1875 QSet
<vtkIdType
> MutilatedCells
;
1878 cout
<<"BEFORE FINDSNAPPOINT"<<endl
;
1879 cout
<<"N_points="<<N_points
<<endl
;
1880 cout
<<"N_cells="<<N_cells
<<endl
;
1881 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1882 cout
<<"N_newcells="<<N_newcells
<<endl
;
1884 vtkIdType SnapPoint
=FindSnapPoint(src
,DeadNode
,DeadCells
,MutatedCells
,MutilatedCells
, N_newpoints
, N_newcells
);
1886 if(DebugLevel
>0) cout
<<"===>DeadNode="<<DeadNode
<<" moving to SNAPPOINT="<<SnapPoint
<<" DebugLevel="<<DebugLevel
<<endl
;
1887 if(SnapPoint
<0) {cout
<<"Sorry no possible SnapPoint found."<<endl
; return(false);}
1891 cout
<<"BEFORE ALLOCATION"<<endl
;
1892 cout
<<"N_points="<<N_points
<<endl
;
1893 cout
<<"N_cells="<<N_cells
<<endl
;
1894 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1895 cout
<<"N_newcells="<<N_newcells
<<endl
;
1897 N_points
=src
->GetNumberOfPoints();
1898 N_cells
=src
->GetNumberOfCells();
1901 cout
<<"N_points="<<N_points
<<endl
;
1902 cout
<<"N_cells="<<N_cells
<<endl
;
1903 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1904 cout
<<"N_newcells="<<N_newcells
<<endl
;
1906 EG_VTKSP(vtkUnstructuredGrid
,dst
);
1907 allocateGrid(dst
,N_cells
+N_newcells
,N_points
+N_newpoints
);
1909 //vector used to redefine the new point IDs
1910 QVector
<vtkIdType
> OffSet(N_points
);
1912 //copy undead points
1913 vtkIdType dst_id_node
=0;
1914 for (vtkIdType src_id_node
= 0; src_id_node
< N_points
; src_id_node
++) {//loop through src points
1915 if(src_id_node
!=DeadNode
)//if the node isn't dead, copy it
1918 src
->GetPoints()->GetPoint(src_id_node
, x
.data());
1919 dst
->GetPoints()->SetPoint(dst_id_node
, x
.data());
1920 copyNodeData(src
, src_id_node
, dst
, dst_id_node
);
1921 OffSet
[src_id_node
]=src_id_node
-dst_id_node
;
1926 if(DebugLevel
>0) cout
<<"src_id_node="<<src_id_node
<<" dst_id_node="<<dst_id_node
<<endl
;
1930 cout
<<"DeadCells="<<DeadCells
<<endl
;
1931 cout
<<"MutatedCells="<<MutatedCells
<<endl
;
1932 cout
<<"MutilatedCells="<<MutilatedCells
<<endl
;
1935 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {//loop through src cells
1936 if(!DeadCells
.contains(id_cell
))//if the cell isn't dead
1938 vtkIdType src_N_pts
, *src_pts
;
1939 vtkIdType dst_N_pts
, *dst_pts
;
1940 src
->GetCellPoints(id_cell
, src_N_pts
, src_pts
);
1942 vtkIdType type_cell
= src
->GetCellType(id_cell
);
1943 if(DebugLevel
>10) cout
<<"-->id_cell="<<id_cell
<<endl
;
1944 if(DebugLevel
>10) for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
1945 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
1946 dst_N_pts
=src_N_pts
;
1947 dst_pts
=new vtkIdType
[dst_N_pts
];
1948 if(MutatedCells
.contains(id_cell
))//mutated cell
1950 if(DebugLevel
>10) cout
<<"processing mutated cell "<<id_cell
<<endl
;
1951 for(int i
=0;i
<src_N_pts
;i
++)
1953 if(src_pts
[i
]==DeadNode
) {
1955 cout
<<"SnapPoint="<<SnapPoint
<<endl
;
1956 cout
<<"OffSet[SnapPoint]="<<OffSet
[SnapPoint
]<<endl
;
1957 cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
1959 dst_pts
[i
]=SnapPoint
-OffSet
[SnapPoint
];
1961 else dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
1963 if(DebugLevel
>10) cout
<<"--->dst_pts:"<<endl
;
1964 if(DebugLevel
>10) for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
1967 else if(MutilatedCells
.contains(id_cell
))//mutilated cell
1969 if(DebugLevel
>10) cout
<<"processing mutilated cell "<<id_cell
<<endl
;
1971 if(type_cell
==VTK_QUAD
) {
1972 type_cell
=VTK_TRIANGLE
;
1975 else {cout
<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl
;EG_BUG
;}
1978 for(int i
=0;i
<src_N_pts
;i
++)
1980 if(src_pts
[i
]==SnapPoint
) { dst_pts
[j
]=SnapPoint
-OffSet
[SnapPoint
];j
++; }//SnapPoint
1981 else if(src_pts
[i
]!=DeadNode
) { dst_pts
[j
]=src_pts
[i
]-OffSet
[src_pts
[i
]];j
++; }//pre-snap/dead + post-snap/dead
1982 //do nothing in case of DeadNode
1987 if(DebugLevel
>10) cout
<<"processing normal cell "<<id_cell
<<endl
;
1988 for(int i
=0;i
<src_N_pts
;i
++)
1990 dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
1994 vtkIdType id_new_cell
= dst
->InsertNextCell(type_cell
, dst_N_pts
, dst_pts
);
1995 copyCellData(src
, id_cell
, dst
, id_new_cell
);
1997 cout
<<"===Copying cell "<<id_cell
<<" to "<<id_new_cell
<<"==="<<endl
;
1998 cout
<<"src_pts:"<<endl
;
1999 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
2000 cout
<<"dst_pts:"<<endl
;
2001 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
2002 cout
<<"OffSet="<<OffSet
<<endl
;
2003 cout
<<"===Copying cell end==="<<endl
;
2008 // cout_grid(cout,dst,true,true,true,true);
2012 //End of DeletePoint_2
2014 bool Operation::DeleteSetOfPoints(vtkUnstructuredGrid
*src
, QSet
<vtkIdType
> DeadNodes
, int& N_newpoints
, int& N_newcells
)
2016 QVector
<vtkIdType
> DeadNode_vector
=Set2Vector(DeadNodes
,false);
2018 getAllSurfaceCells(cells
,src
);
2019 // getNodesFromCells(cells, nodes, src);
2022 UpdateNodeType_all();
2025 int N_points
=src
->GetNumberOfPoints();
2026 int N_cells
=src
->GetNumberOfCells();
2028 QSet
<vtkIdType
> DeadCells
;
2029 QSet
<vtkIdType
> MutatedCells
;
2030 QSet
<vtkIdType
> MutilatedCells
;
2031 QVector
<vtkIdType
> SnapPoint(DeadNode_vector
.size());
2037 for(int i
=0;i
<DeadNode_vector
.size();i
++)
2039 if(DeadNode_vector
[i
]<0 || DeadNode_vector
[i
]>=N_points
)
2041 cout
<<"Warning: Point out of range: DeadNode_vector[i]="<<DeadNode_vector
[i
]<<" N_points="<<N_points
<<endl
;
2046 cout
<<"BEFORE FINDSNAPPOINT"<<endl
;
2047 cout
<<"N_points="<<N_points
<<endl
;
2048 cout
<<"N_cells="<<N_cells
<<endl
;
2049 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
2050 cout
<<"N_newcells="<<N_newcells
<<endl
;
2056 QSet
<vtkIdType
> l_DeadCells
;
2057 QSet
<vtkIdType
> l_MutatedCells
;
2058 QSet
<vtkIdType
> l_MutilatedCells
;
2060 SnapPoint
[i
]=FindSnapPoint(src
,DeadNode_vector
[i
], l_DeadCells
, l_MutatedCells
, l_MutilatedCells
, l_N_newpoints
, l_N_newcells
);
2062 N_newpoints
+=l_N_newpoints
;
2063 N_newcells
+=l_N_newcells
;
2064 DeadCells
.unite(l_DeadCells
);//DeadCells unite! Kill the living! :D
2065 MutatedCells
.unite(l_MutatedCells
);
2066 MutilatedCells
.unite(l_MutilatedCells
);
2068 if(DebugLevel
>0) cout
<<"===>DeadNode_vector[i]="<<DeadNode_vector
[i
]<<" moving to SNAPPOINT="<<SnapPoint
[i
]<<" DebugLevel="<<DebugLevel
<<endl
;
2069 if(SnapPoint
[i
]<0) {cout
<<"Sorry no possible SnapPoint found."<<endl
; return(false);}
2074 cout
<<"BEFORE ALLOCATION"<<endl
;
2075 cout
<<"N_points="<<N_points
<<endl
;
2076 cout
<<"N_cells="<<N_cells
<<endl
;
2077 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
2078 cout
<<"N_newcells="<<N_newcells
<<endl
;
2080 // N_points=src->GetNumberOfPoints();
2081 // N_cells=src->GetNumberOfCells();
2084 cout
<<"N_points="<<N_points
<<endl
;
2085 cout
<<"N_cells="<<N_cells
<<endl
;
2086 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
2087 cout
<<"N_newcells="<<N_newcells
<<endl
;
2089 EG_VTKSP(vtkUnstructuredGrid
,dst
);
2090 allocateGrid(dst
,N_cells
+N_newcells
,N_points
+N_newpoints
);
2092 //vector used to redefine the new point IDs
2093 QVector
<vtkIdType
> OffSet(N_points
);
2095 //copy undead points
2096 vtkIdType dst_id_node
=0;
2097 for (vtkIdType src_id_node
= 0; src_id_node
< N_points
; src_id_node
++) {//loop through src points
2098 if(!DeadNode_vector
.contains(src_id_node
))//if the node isn't dead, copy it
2101 src
->GetPoints()->GetPoint(src_id_node
, x
.data());
2102 dst
->GetPoints()->SetPoint(dst_id_node
, x
.data());
2103 copyNodeData(src
, src_id_node
, dst
, dst_id_node
);
2104 OffSet
[src_id_node
]=src_id_node
-dst_id_node
;
2109 if(DebugLevel
>0) cout
<<"src_id_node="<<src_id_node
<<" dst_id_node="<<dst_id_node
<<endl
;
2113 cout
<<"DeadCells="<<DeadCells
<<endl
;
2114 cout
<<"MutatedCells="<<MutatedCells
<<endl
;
2115 cout
<<"MutilatedCells="<<MutilatedCells
<<endl
;
2118 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {//loop through src cells
2119 if(!DeadCells
.contains(id_cell
))//if the cell isn't dead
2121 vtkIdType src_N_pts
, *src_pts
;
2122 vtkIdType dst_N_pts
, *dst_pts
;
2123 src
->GetCellPoints(id_cell
, src_N_pts
, src_pts
);
2125 vtkIdType type_cell
= src
->GetCellType(id_cell
);
2126 if(DebugLevel
>10) cout
<<"-->id_cell="<<id_cell
<<endl
;
2127 if(DebugLevel
>10) for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
2128 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
2129 dst_N_pts
=src_N_pts
;
2130 dst_pts
=new vtkIdType
[dst_N_pts
];
2131 if(MutatedCells
.contains(id_cell
))//mutated cell
2133 if(DebugLevel
>10) cout
<<"processing mutated cell "<<id_cell
<<endl
;
2134 for(int i
=0;i
<src_N_pts
;i
++)
2136 int DeadIndex
= DeadNode_vector
.indexOf(src_pts
[i
]);
2139 cout
<<"SnapPoint="<<SnapPoint
[DeadIndex
]<<endl
;
2140 cout
<<"OffSet[SnapPoint]="<<OffSet
[SnapPoint
[DeadIndex
]]<<endl
;
2141 cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
2143 dst_pts
[i
]=SnapPoint
[DeadIndex
]-OffSet
[SnapPoint
[DeadIndex
]];
2145 else dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
2147 if(DebugLevel
>10) cout
<<"--->dst_pts:"<<endl
;
2148 if(DebugLevel
>10) for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
2151 else if(MutilatedCells
.contains(id_cell
))//mutilated cell (ex: square becoming triangle)
2153 cout
<<"FATAL ERROR: Quads not supported yet."<<endl
;EG_BUG
;
2155 if(DebugLevel
>10) cout
<<"processing mutilated cell "<<id_cell
<<endl
;
2157 if(type_cell
==VTK_QUAD
) {
2158 type_cell
=VTK_TRIANGLE
;
2161 else {cout
<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl
;EG_BUG
;}
2164 for(int i
=0;i
<src_N_pts
;i
++)
2166 /* if(src_pts[i]==SnapPoint) { dst_pts[j]=SnapPoint-OffSet[SnapPoint];j++; }//SnapPoint
2167 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*/
2168 //do nothing in case of DeadNode_vector[i]
2173 if(DebugLevel
>10) cout
<<"processing normal cell "<<id_cell
<<endl
;
2174 for(int i
=0;i
<src_N_pts
;i
++)
2176 dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
2180 vtkIdType id_new_cell
= dst
->InsertNextCell(type_cell
, dst_N_pts
, dst_pts
);
2181 copyCellData(src
, id_cell
, dst
, id_new_cell
);
2183 cout
<<"===Copying cell "<<id_cell
<<" to "<<id_new_cell
<<"==="<<endl
;
2184 cout
<<"src_pts:"<<endl
;
2185 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
2186 cout
<<"dst_pts:"<<endl
;
2187 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
2188 cout
<<"OffSet="<<OffSet
<<endl
;
2189 cout
<<"===Copying cell end==="<<endl
;
2195 // cout_grid(cout,dst,true,true,true,true);
2199 //End of DeleteSetOfPoints
2201 void Operation::TxtSave(QString a_filename
)
2203 cout
<< a_filename
.toAscii().data() << endl
;
2205 file
.open(a_filename
.toAscii().data());
2206 cout_grid(file
,grid
,true,true,true,true);
2210 void Operation::DualSave(QString a_filename
)
2212 TxtSave(a_filename
+".txt");
2213 GuiMainWindow::pointer()->QuickSave(a_filename
+".vtu");