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>
40 #include "geometrytools.h"
41 using namespace GeometryTools
;
43 #include <QApplication>
45 QSet
<Operation
*> Operation::garbage_operations
;
47 void Operation::collectGarbage()
49 QSet
<Operation
*> delete_operations
;
50 foreach (Operation
*op
, garbage_operations
) {
51 if (!op
->getThread().isRunning()) {
52 delete_operations
.insert(op
);
53 cout
<< "deleting Operation " << op
<< endl
;
57 foreach (Operation
*op
, delete_operations
) {
58 garbage_operations
.remove(op
);
62 Operation::Operation()
70 Operation::~Operation()
80 garbage_operations
.insert(this);
83 void OperationThread::run()
86 GuiMainWindow::lock();
87 GuiMainWindow::pointer()->setBusy();
90 op
->err
= new Error();
93 GuiMainWindow::unlock();
94 GuiMainWindow::pointer()->setIdle();
97 void Operation::operator()()
100 if (GuiMainWindow::tryLock()) {
102 thread
.setOperation(this);
103 GuiMainWindow::unlock();
104 thread
.start(QThread::LowPriority
);
106 QMessageBox::warning(NULL
, "not permitted", "Operation is not permitted while background process is running!");
118 void Operation::setAllCells()
120 QVector
<vtkIdType
> all_cells
;
121 getAllCells(all_cells
, grid
);
125 void Operation::setAllVolumeCells()
127 QVector
<vtkIdType
> cells
;
128 getAllVolumeCells(cells
, grid
);
132 void Operation::setAllSurfaceCells()
134 QVector
<vtkIdType
> cells
;
135 getAllSurfaceCells(cells
, grid
);
139 void Operation::initMapping()
141 nodes_map
.resize(nodes
.size());
142 for (int i_nodes
= 0; i_nodes
< nodes
.size(); ++i_nodes
) {
143 nodes_map
[i_nodes
] = nodes
[i_nodes
];
145 cells_map
.resize(cells
.size());
146 for (int i_cells
= 0; i_cells
< cells
.size(); ++i_cells
) {
147 cells_map
[i_cells
] = cells
[i_cells
];
151 void Operation::checkGrid()
154 grid
= GuiMainWindow::pointer()->getGrid();
156 if ((cells
.size() == 0) && autoset
) {
161 void Operation::updateActors()
163 mainWindow()->updateActors();
166 GuiMainWindow
* Operation::mainWindow()
168 return GuiMainWindow::pointer();
171 void Operation::populateBoundaryCodes(QListWidget
*lw
)
174 mainWindow()->getAllBoundaryCodes(bcs
);
175 foreach(int bc
, bcs
) {
176 QListWidgetItem
*lwi
= new QListWidgetItem(lw
);
177 lwi
->setCheckState(Qt::Unchecked
);
179 QTextStream
ts(&text
);
182 lwi
->setFlags(Qt::ItemIsUserCheckable
| Qt::ItemIsEnabled
);
186 stencil_t
Operation::getStencil(vtkIdType id_cell1
, int j1
)
190 S
.id_cell1
= id_cell1
;
191 if (c2c
[_cells
[id_cell1
]][j1
] != -1) {
192 S
.id_cell2
= cells
[c2c
[_cells
[id_cell1
]][j1
]];
193 if (grid
->GetCellType(S
.id_cell2
) != VTK_TRIANGLE
) {
196 vtkIdType N1
, N2
, *pts1
, *pts2
;
197 grid
->GetCellPoints(S
.id_cell1
, N1
, pts1
);
198 grid
->GetCellPoints(S
.id_cell2
, N2
, pts2
);
199 if (j1
== 0) { S
.p
[0] = pts1
[2]; S
.p
[1] = pts1
[0]; S
.p
[3] = pts1
[1]; }
200 else if (j1
== 1) { S
.p
[0] = pts1
[0]; S
.p
[1] = pts1
[1]; S
.p
[3] = pts1
[2]; }
201 else if (j1
== 2) { S
.p
[0] = pts1
[1]; S
.p
[1] = pts1
[2]; S
.p
[3] = pts1
[0]; };
203 if (c2c
[_cells
[S
.id_cell2
]][0] != -1) {
204 if (cells
[c2c
[_cells
[S
.id_cell2
]][0]] == S
.id_cell1
) {
209 if (c2c
[_cells
[S
.id_cell2
]][1] != -1) {
210 if (cells
[c2c
[_cells
[S
.id_cell2
]][1]] == S
.id_cell1
) {
215 if (c2c
[_cells
[S
.id_cell2
]][2] != -1) {
216 if (cells
[c2c
[_cells
[S
.id_cell2
]][2]] == S
.id_cell1
) {
228 grid
->GetCellPoints(S
.id_cell1
, N1
, pts1
);
229 if (j1
== 0) { S
.p
[0] = pts1
[2]; S
.p
[1] = pts1
[0]; S
.p
[3] = pts1
[1]; }
230 else if (j1
== 1) { S
.p
[0] = pts1
[0]; S
.p
[1] = pts1
[1]; S
.p
[3] = pts1
[2]; }
231 else if (j1
== 2) { S
.p
[0] = pts1
[1]; S
.p
[1] = pts1
[2]; S
.p
[3] = pts1
[0]; };
236 ostream
& operator<<(ostream
&out
, stencil_t S
)
238 out
<<"S.id_cell1="<<S
.id_cell1
<<" ";
239 out
<<"S.id_cell2="<<S
.id_cell2
<<" ";
240 out
<<"S.valid="<<S
.valid
<<" ";
242 for(int i
=0;i
<4;i
++){
250 //////////////////////////////////////////////
251 double CurrentVertexAvgDist(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
255 int N
=n2n
[a_vertex
].size();
257 a_grid
->GetPoint(a_vertex
, C
.data());
258 foreach(int i
,n2n
[a_vertex
])
261 a_grid
->GetPoint(i
, M
.data());
262 total_dist
+=(M
-C
).abs();
264 avg_dist
=total_dist
/(double)N
;
268 double CurrentMeshDensity(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
272 int N
=n2n
[a_vertex
].size();
274 a_grid
->GetPoint(a_vertex
, C
.data());
275 foreach(int i
,n2n
[a_vertex
])
278 a_grid
->GetPoint(i
, M
.data());
279 total_dist
+=(M
-C
).abs();
281 avg_dist
=total_dist
/(double)N
;
282 double avg_density
=1./avg_dist
;
286 double DesiredVertexAvgDist(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
290 EG_VTKDCN(vtkDoubleArray
, node_meshdensity
, a_grid
, "node_meshdensity");
291 int N
=n2n
[a_vertex
].size();
292 foreach(int i
,n2n
[a_vertex
])
294 total_dist
+=1./node_meshdensity
->GetValue(i
);
296 avg_dist
=total_dist
/(double)N
;
300 double DesiredMeshDensity(vtkIdType a_vertex
,QVector
< QSet
< int > > &n2n
,vtkUnstructuredGrid
*a_grid
)
302 double total_density
=0;
303 double avg_density
=0;
304 EG_VTKDCN(vtkDoubleArray
, node_meshdensity
, a_grid
, "node_meshdensity");
305 int N
=n2n
[a_vertex
].size();
306 foreach(int i
,n2n
[a_vertex
])
308 total_density
+=node_meshdensity
->GetValue(i
);
310 avg_density
=total_density
/(double)N
;
314 ///////////////////////////////////////////
315 vtkIdType
Operation::getClosestNode(vtkIdType a_id_node
,vtkUnstructuredGrid
* a_grid
)
318 a_grid
->GetPoint(a_id_node
,C
.data());
319 vtkIdType id_minlen
=-1;
321 foreach(vtkIdType neighbour
,n2n
[a_id_node
])
324 a_grid
->GetPoint(neighbour
,M
.data());
325 double len
=(M
-C
).abs();
326 if(minlen
<0 or len
<minlen
)
335 vtkIdType
Operation::getFarthestNode(vtkIdType a_id_node
,vtkUnstructuredGrid
* a_grid
)
338 a_grid
->GetPoint(a_id_node
,C
.data());
339 vtkIdType id_maxlen
=-1;
341 foreach(vtkIdType neighbour
,n2n
[a_id_node
])
344 a_grid
->GetPoint(neighbour
,M
.data());
345 double len
=(M
-C
).abs();
346 if(maxlen
<0 or len
>maxlen
)
355 bool Operation::SwapCells(vtkUnstructuredGrid
* a_grid
, stencil_t S
)
359 vec3_t x3
[4], x3_0(0,0,0);
361 for (int k
= 0; k
< 4; ++k
) {
362 a_grid
->GetPoints()->GetPoint(S
.p
[k
], x3
[k
].data());
365 vec3_t n1
= triNormal(x3
[0], x3
[1], x3
[3]);
366 vec3_t n2
= triNormal(x3
[1], x3
[2], x3
[3]);
369 if ( (n1
*n2
) > 0.8) {
372 vec3_t ex
= orthogonalVector(n
);
373 vec3_t ey
= ex
.cross(n
);
374 for (int k
= 0; k
< 4; ++k
) {
375 x
[k
] = vec2_t(x3
[k
]*ex
, x3
[k
]*ey
);
377 vec2_t r1
, r2
, r3
, u1
, u2
, u3
;
378 r1
= 0.5*(x
[0] + x
[1]); u1
= turnLeft(x
[1] - x
[0]);
379 r2
= 0.5*(x
[1] + x
[2]); u2
= turnLeft(x
[2] - x
[1]);
380 r3
= 0.5*(x
[1] + x
[3]); u3
= turnLeft(x
[3] - x
[1]);
384 if (intersection(k
, l
, r1
, u1
, r3
, u3
)) {
386 if (intersection(k
, l
, r2
, u2
, r3
, u3
)) {
396 if ((xm1
- x
[2]).abs() < (xm1
- x
[0]).abs()) {
399 if ((xm2
- x
[0]).abs() < (xm2
- x
[2]).abs()) {
406 vtkIdType new_pts1
[3], new_pts2
[3];
407 new_pts1
[0] = S
.p
[1];
408 new_pts1
[1] = S
.p
[2];
409 new_pts1
[2] = S
.p
[0];
410 new_pts2
[0] = S
.p
[2];
411 new_pts2
[1] = S
.p
[3];
412 new_pts2
[2] = S
.p
[0];
413 a_grid
->ReplaceCell(S
.id_cell1
, 3, new_pts1
);
414 a_grid
->ReplaceCell(S
.id_cell2
, 3, new_pts2
);
419 void Operation::quad2triangle(vtkUnstructuredGrid
* src
,vtkIdType quadcell
)
421 vtkIdType type_cell
= grid
->GetCellType(quadcell
);
422 cout
<<"It's a "<<type_cell
<<endl
;
423 if(type_cell
==VTK_QUAD
)
425 cout_grid(cout
,src
,true,true,true,true);
426 EG_VTKSP(vtkUnstructuredGrid
, dst
);
428 int N_points
=src
->GetNumberOfPoints();
429 int N_cells
=src
->GetNumberOfCells();
430 allocateGrid(dst
,N_cells
+1,N_points
);
432 for (vtkIdType id_node
= 0; id_node
< src
->GetNumberOfPoints(); ++id_node
) {
434 src
->GetPoints()->GetPoint(id_node
, x
.data());
435 dst
->GetPoints()->SetPoint(id_node
, x
.data());
436 copyNodeData(src
, id_node
, dst
, id_node
);
438 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {
439 vtkIdType N_pts
, *pts
;
440 vtkIdType type_cell
= src
->GetCellType(id_cell
);
441 src
->GetCellPoints(id_cell
, N_pts
, pts
);
442 vtkIdType id_new_cell
;
443 vtkIdType id_new_cell1
;
444 vtkIdType id_new_cell2
;
445 if(id_cell
!=quadcell
)
447 id_new_cell
= dst
->InsertNextCell(type_cell
, N_pts
, pts
);
448 copyCellData(src
, id_cell
, dst
, id_new_cell
);
452 vtkIdType triangle1
[3];
453 vtkIdType triangle2
[3];
460 id_new_cell1
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle1
);
461 copyCellData(src
, id_cell
, dst
, id_new_cell1
);
462 id_new_cell2
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle2
);
463 copyCellData(src
, id_cell
, dst
, id_new_cell2
);
465 S
.id_cell1
=id_new_cell1
;
466 S
.id_cell2
=id_new_cell2
;
475 cout_grid(cout
,dst
,true,true,true,true);
480 void Operation::quad2triangle(vtkUnstructuredGrid
* src
,vtkIdType quadcell
,vtkIdType MovingPoint
)
482 vtkIdType type_cell
= grid
->GetCellType(quadcell
);
483 cout
<<"It's a "<<type_cell
<<endl
;
484 if(type_cell
==VTK_QUAD
)
486 cout_grid(cout
,src
,true,true,true,true);
487 EG_VTKSP(vtkUnstructuredGrid
, dst
);
489 int N_points
=src
->GetNumberOfPoints();
490 int N_cells
=src
->GetNumberOfCells();
491 allocateGrid(dst
,N_cells
+1,N_points
);
493 for (vtkIdType id_node
= 0; id_node
< src
->GetNumberOfPoints(); ++id_node
) {
495 src
->GetPoints()->GetPoint(id_node
, x
.data());
496 dst
->GetPoints()->SetPoint(id_node
, x
.data());
497 copyNodeData(src
, id_node
, dst
, id_node
);
499 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {
500 vtkIdType N_pts
, *pts
;
501 src
->GetCellPoints(id_cell
, N_pts
, pts
);
502 vtkIdType type_cell
= src
->GetCellType(id_cell
);
503 vtkIdType id_new_cell
;
504 vtkIdType id_new_cell1
;
505 vtkIdType id_new_cell2
;
506 if(id_cell
!=quadcell
)
508 id_new_cell
= dst
->InsertNextCell(type_cell
, N_pts
, pts
);
509 copyCellData(src
, id_cell
, dst
, id_new_cell
);
513 vtkIdType triangle1
[3];
514 vtkIdType triangle2
[3];
515 if(MovingPoint
==pts
[0] || MovingPoint
==pts
[2])
533 id_new_cell1
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle1
);
534 copyCellData(src
, id_cell
, dst
, id_new_cell1
);
535 id_new_cell2
= dst
->InsertNextCell(VTK_TRIANGLE
, 3, triangle2
);
536 copyCellData(src
, id_cell
, dst
, id_new_cell2
);
539 cout_grid(cout
,dst
,true,true,true,true);
544 int Operation::NumberOfCommonPoints(vtkIdType node1
, vtkIdType node2
, bool& IsTetra
)
546 // QVector< QSet< int > > n2n
547 QSet
<int> node1_neighbours
=n2n
[node1
];
548 QSet
<int> node2_neighbours
=n2n
[node2
];
549 QSet
<int> intersection
=node1_neighbours
.intersect(node2_neighbours
);
550 int N
=intersection
.size();
554 QSet
<int>::const_iterator p1
=intersection
.begin();
555 QSet
<int>::const_iterator p2
=p1
+1;
556 vtkIdType intersection1
=_nodes
[*p1
];
557 vtkIdType intersection2
=_nodes
[*p2
];
558 if(n2n
[intersection1
].contains(intersection2
))//if there's an edge between intersection1 and intersection2
560 //check if (node1,intersection1,intersection2) and (node2,intersection1,intersection2) are defined as cells!
561 // QVector< QSet< int > > n2c
562 QSet
< int > S1
=n2c
[intersection1
];
563 QSet
< int > S2
=n2c
[intersection2
];
564 QSet
< int > Si
=S1
.intersect(S2
);
566 foreach(vtkIdType C
,Si
){
567 vtkIdType N_pts
, *pts
;
568 grid
->GetCellPoints(C
, N_pts
, pts
);
569 for(int i
=0;i
<N_pts
;i
++)
571 if(pts
[i
]==node1
|| pts
[i
]==node2
) counter
++;
574 if(counter
>=2) IsTetra
=true;
580 // vtkIdType Operation::FindSnapPoint(vtkUnstructuredGrid *src, vtkIdType DeadNode)
585 bool Operation::DeletePoint(vtkUnstructuredGrid
*src
, vtkIdType DeadNode
)
587 EG_VTKSP(vtkUnstructuredGrid
, dst
);
590 int N_points
=src
->GetNumberOfPoints();
591 int N_cells
=src
->GetNumberOfCells();
595 if(DeadNode
<0 || DeadNode
>=N_points
)
597 cout
<<"Warning: Point out of range: DeadNode="<<DeadNode
<<" N_points="<<N_points
<<endl
;
601 QSet
<vtkIdType
> DeadCells
;
602 QSet
<vtkIdType
> MutatedCells
;
603 QSet
<vtkIdType
> MutilatedCells
;
605 vtkIdType SnapPoint
=-1;
606 //Find closest point to DeadNode
607 // vtkIdType SnapPoint = getClosestNode(DeadNode,src);//DeadNode moves to SnapPoint
609 foreach(vtkIdType PSP
, n2n
[DeadNode
])
611 bool IsValidSnapPoint
=true;
613 cout
<<"====>PSP="<<PSP
<<endl
;
615 if(NumberOfCommonPoints(DeadNode
,PSP
,IsTetra
)>2)//common point check
617 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
618 IsValidSnapPoint
=false;
620 if(IsTetra
)//tetra check
622 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
623 IsValidSnapPoint
=false;
626 //count number of points and cells to remove + analyse cell transformations
630 MutatedCells
.clear();
631 MutilatedCells
.clear();
632 foreach(vtkIdType C
, n2c
[DeadNode
])//loop through potentially dead cells
635 //get points around cell
636 vtkIdType N_pts
, *pts
;
637 src
->GetCellPoints(C
, N_pts
, pts
);
639 bool ContainsSnapPoint
=false;
640 bool invincible
=false;
641 for(int i
=0;i
<N_pts
;i
++)
643 cout
<<"pts["<<i
<<"]="<<pts
[i
]<<" and PSP="<<PSP
<<endl
;
644 if(pts
[i
]==PSP
) {ContainsSnapPoint
=true;}
645 if(pts
[i
]!=DeadNode
&& pts
[i
]!=PSP
&& n2c
[pts
[i
]].size()<=1) invincible
=true;
647 if(ContainsSnapPoint
)
649 if(N_pts
==3)//dead cell
651 if(invincible
)//Check that empty lines aren't left behind when a cell is killed
653 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
654 IsValidSnapPoint
=false;
660 cout
<<"cell "<<C
<<" has been pwned!"<<endl
;
663 /* else if(N_pts==4)//mutilated cell
665 MutilatedCells.insert(C);
666 cout<<"cell "<<C<<" has lost a limb!"<<endl;
670 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
676 vtkIdType src_N_pts
, *src_pts
;
677 src
->GetCellPoints(C
, src_N_pts
, src_pts
);
681 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
685 vtkIdType OldTriangle
[3];
686 vtkIdType NewTriangle
[3];
688 for(int i
=0;i
<src_N_pts
;i
++)
690 OldTriangle
[i
]=src_pts
[i
];
691 NewTriangle
[i
]=( (src_pts
[i
]==DeadNode
) ? PSP
: src_pts
[i
] );
693 vec3_t Old_N
= triNormal(src
, OldTriangle
[0], OldTriangle
[1], OldTriangle
[2]);
694 vec3_t New_N
= triNormal(src
, NewTriangle
[0], NewTriangle
[1], NewTriangle
[2]);
695 double OldArea
=Old_N
.abs();
696 double NewArea
=New_N
.abs();
697 double scal
=Old_N
*New_N
;
698 double cross
=(Old_N
.cross(New_N
)).abs();//double-cross on Nar Shadaa B-)
700 cout
<<"OldArea="<<OldArea
<<endl
;
701 cout
<<"NewArea="<<NewArea
<<endl
;
702 cout
<<"scal="<<scal
<<endl
;
703 cout
<<"cross="<<cross
<<endl
;
705 if(Old_N
*New_N
<Old_N
*Old_N
*1./100.)//area + inversion check
707 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
708 IsValidSnapPoint
=false;
711 /* if(NewArea<OldArea*1./100.)
713 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
714 IsValidSnapPoint=false;
719 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
720 IsValidSnapPoint=false;
724 MutatedCells
.insert(C
);
725 cout
<<"cell "<<C
<<" has been infected!"<<endl
;
729 if(N_cells
+N_newcells
<=0)//survivor check
731 cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
732 IsValidSnapPoint
=false;
734 /* if(EmptyVolume(DeadNode,PSP))//simplified volume check
736 cout<<"Sorry, but you are not allowed to move point "<<DeadNode<<" to point "<<PSP<<"."<<endl;
737 IsValidSnapPoint=false;
739 if(IsValidSnapPoint
) {SnapPoint
=PSP
; break;}
740 }//end of loop through potential SnapPoints
742 cout
<<"===>SNAPPOINT="<<SnapPoint
<<endl
;
743 if(SnapPoint
<0) {cout
<<"Sorry no possible SnapPoint found."<<endl
; return(false);}
746 cout
<<"N_points="<<N_points
<<endl
;
747 cout
<<"N_cells="<<N_cells
<<endl
;
748 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
749 cout
<<"N_newcells="<<N_newcells
<<endl
;
750 allocateGrid(dst
,N_cells
+N_newcells
,N_points
+N_newpoints
);
752 //vector used to redefine the new point IDs
753 QVector
<vtkIdType
> OffSet(N_points
);
756 vtkIdType dst_id_node
=0;
757 for (vtkIdType src_id_node
= 0; src_id_node
< N_points
; src_id_node
++) {//loop through src points
758 if(src_id_node
!=DeadNode
)//if the node isn't dead, copy it
761 src
->GetPoints()->GetPoint(src_id_node
, x
.data());
762 dst
->GetPoints()->SetPoint(dst_id_node
, x
.data());
763 copyNodeData(src
, src_id_node
, dst
, dst_id_node
);
764 OffSet
[src_id_node
]=src_id_node
-dst_id_node
;
769 cout
<<"DeadCells="<<DeadCells
<<endl
;
770 cout
<<"MutatedCells="<<MutatedCells
<<endl
;
771 cout
<<"MutilatedCells="<<MutilatedCells
<<endl
;
774 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {//loop through src cells
775 if(!DeadCells
.contains(id_cell
))//if the cell isn't dead
777 vtkIdType src_N_pts
, *src_pts
;
778 vtkIdType dst_N_pts
, *dst_pts
;
779 src
->GetCellPoints(id_cell
, src_N_pts
, src_pts
);
781 vtkIdType type_cell
= src
->GetCellType(id_cell
);
782 cout
<<"-->id_cell="<<id_cell
<<endl
;
783 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
784 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
786 dst_pts
=new vtkIdType
[dst_N_pts
];
787 if(MutatedCells
.contains(id_cell
))//mutated cell
789 cout
<<"processing mutated cell "<<id_cell
<<endl
;
790 for(int i
=0;i
<src_N_pts
;i
++)
792 if(src_pts
[i
]==DeadNode
) {
793 cout
<<"SnapPoint="<<SnapPoint
<<endl
;
794 cout
<<"OffSet[SnapPoint]="<<OffSet
[SnapPoint
]<<endl
;
795 cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
796 dst_pts
[i
]=SnapPoint
-OffSet
[SnapPoint
];
798 else dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
800 cout
<<"--->dst_pts:"<<endl
;
801 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
804 else if(MutilatedCells
.contains(id_cell
))//mutilated cell
806 cout
<<"processing mutilated cell "<<id_cell
<<endl
;
808 if(type_cell
==VTK_QUAD
) {
809 type_cell
=VTK_TRIANGLE
;
812 else {cout
<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl
;EG_BUG
;}
815 for(int i
=0;i
<src_N_pts
;i
++)
817 if(src_pts
[i
]==SnapPoint
) { dst_pts
[j
]=SnapPoint
-OffSet
[SnapPoint
];j
++; }//SnapPoint
818 else if(src_pts
[i
]!=DeadNode
) { dst_pts
[j
]=src_pts
[i
]-OffSet
[src_pts
[i
]];j
++; }//pre-snap/dead + post-snap/dead
819 //do nothing in case of DeadNode
824 cout
<<"processing normal cell "<<id_cell
<<endl
;
825 for(int i
=0;i
<src_N_pts
;i
++)
827 dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
831 vtkIdType id_new_cell
= dst
->InsertNextCell(type_cell
, dst_N_pts
, dst_pts
);
832 copyCellData(src
, id_cell
, dst
, id_new_cell
);
833 cout
<<"===Copying cell "<<id_cell
<<" to "<<id_new_cell
<<"==="<<endl
;
834 cout
<<"src_pts:"<<endl
;
835 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
836 cout
<<"dst_pts:"<<endl
;
837 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
838 cout
<<"OffSet="<<OffSet
<<endl
;
839 cout
<<"===Copying cell end==="<<endl
;
843 // cout_grid(cout,dst,true,true,true,true);
848 bool Operation::EmptyVolume(vtkIdType DeadNode
, vtkIdType PSP
)
855 vec3_t
Operation::GetCenter(vtkIdType cellId
, double& R
)
857 vtkIdType
*pts
, Npts
;
858 grid
->GetCellPoints(cellId
, Npts
, pts
);
861 for (vtkIdType i
= 0; i
< Npts
; ++i
) {
863 grid
->GetPoints()->GetPoint(pts
[i
], xp
.data());
864 x
+= double(1)/Npts
* xp
;
868 for (vtkIdType i
= 0; i
< Npts
; ++i
) {
870 grid
->GetPoints()->GetPoint(pts
[i
], xp
.data());
871 R
= min(R
, 0.25*(xp
-x
).abs());
877 bool Operation::getNeighbours(vtkIdType Boss
, QVector
<vtkIdType
>& Peons
, int BC
)
879 // QVector <vtkIdType> Peons;
881 QSet
<int> S1
=n2c
[Boss
];
882 cout
<<"S1="<<S1
<<endl
;
883 foreach(vtkIdType PN
,n2n
[Boss
])
885 cout
<<"PN="<<PN
<<endl
;
886 QSet
<int> S2
=n2c
[PN
];
887 cout
<<"S2="<<S2
<<endl
;
888 QSet
<int> Si
=S2
.intersect(S1
);
889 cout
<<"PN="<<PN
<<" Si="<<Si
<<endl
;
890 if(Si
.size()<2)//only one common cell
897 foreach(vtkIdType C
,Si
)
899 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
900 int bc
=cell_code
->GetValue(C
);
901 cout
<<"C="<<C
<<" bc="<<bc
<<endl
;
904 if(bc_set
.size()>1)//2 different boundary codes
918 int N
=n2n
[Boss
].size();
919 QVector
<vtkIdType
> neighbours(N
);
920 qCopy(n2n
[Boss
].begin(), n2n
[Boss
].end(), neighbours
.begin());
922 double alphamin_value
;
923 vtkIdType alphamin_i
;
924 vtkIdType alphamin_j
;
929 for(int j
=i
+1;j
<N
;j
++)
931 double alpha
=deviation(grid
,neighbours
[i
],Boss
,neighbours
[j
]);
932 // cout<<"alpha("<<neighbours[i]<<","<<Boss<<","<<neighbours[j]<<")="<<alpha<<endl;
934 alphamin_value
=alpha
;
941 if(alpha
<alphamin_value
)
943 alphamin_value
=alpha
;
950 // cout<<"alphamin_value="<<alphamin_value<<endl;
953 Peons
[0]=neighbours
[alphamin_i
];
954 Peons
[1]=neighbours
[alphamin_j
];
956 /* cout<<"FATAL ERROR: number of neighbours != 2"<<endl;
962 int Operation::UpdateMeshDensity()
964 cout
<<"===UpdateMeshDensity START==="<<endl
;
966 getAllSurfaceCells(cells
,grid
);
967 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
968 EG_VTKDCN(vtkDoubleArray
, node_meshdensity
, grid
, "node_meshdensity");
969 getNodesFromCells(cells
, nodes
, grid
);
973 if(DebugLevel
>5) cout
<<"cells.size()="<<cells
.size()<<endl
;
975 EG_VTKDCN(vtkDoubleArray
, node_meshdensity_current
, grid
, "node_meshdensity_current");
976 foreach(vtkIdType node
,nodes
)
978 double L
=CurrentVertexAvgDist(node
,n2n
,grid
);
980 node_meshdensity_current
->SetValue(node
, D
);
982 cout
<<"===UpdateMeshDensity END==="<<endl
;
986 // Special structure for marking vertices
987 typedef struct _vtkMeshVertex
990 vtkIdList
*edges
; // connected edges (list of connected point ids)
991 } vtkMeshVertex
, *vtkMeshVertexPtr
;
993 int Operation::UpdateNodeType()
995 if(DebugLevel
>47) cout
<<"this->FeatureAngle="<<this->FeatureAngle
<<endl
;
996 if(DebugLevel
>47) cout
<<"this->EdgeAngle="<<this->EdgeAngle
<<endl
;
997 // cout<<"===UpdateNodeType START==="<<endl;
999 getAllSurfaceCells(cells
,grid
);
1000 if(DebugLevel
>5) cout
<<"cells.size()="<<cells
.size()<<endl
;
1002 EG_VTKSP(vtkPolyData
, pdata
);
1003 // addToPolyData(m_SelectedCells, pdata, grid);
1004 addToPolyData(cells
, pdata
, grid
);
1006 vtkPolyData
* input
=pdata
;
1008 vtkPolyData
*source
= 0;
1010 vtkIdType numPts
, numCells
, i
, numPolys
;
1015 double x
[3], y
[3], deltaX
[3], xNew
[3], conv
, maxDist
, dist
, factor
;
1016 double x1
[3], x2
[3], x3
[3], l1
[3], l2
[3];
1017 double CosFeatureAngle
; //Cosine of angle between adjacent polys
1018 double CosEdgeAngle
; // Cosine of angle between adjacent edges
1019 double closestPt
[3], dist2
, *w
= NULL
;
1020 int iterationNumber
, abortExecute
;
1021 vtkIdType numSimple
=0, numBEdges
=0, numFixed
=0, numFEdges
=0;
1022 vtkPolyData
*inMesh
, *Mesh
;
1024 vtkCellArray
*inVerts
, *inLines
, *inPolys
;
1026 vtkMeshVertexPtr Verts
;
1027 vtkCellLocator
*cellLocator
=NULL
;
1031 numPts
=input
->GetNumberOfPoints();
1032 numCells
=input
->GetNumberOfCells();
1033 if (numPts
< 1 || numCells
< 1)
1035 cout
<<"No data to smooth!"<<endl
;
1040 cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle
);
1041 CosEdgeAngle
= cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle
);
1044 cout
<<"Smoothing " << numPts
<< " vertices, " << numCells
1046 << "\tConvergence= " << this->Convergence
<< "\n"
1047 << "\tIterations= " << this->NumberOfIterations
<< "\n"
1048 << "\tRelaxation Factor= " << this->RelaxationFactor
<< "\n"
1049 << "\tEdge Angle= " << this->EdgeAngle
<< "\n"
1050 << "\tBoundary Smoothing " << (this->BoundarySmoothing
? "On\n" : "Off\n")
1051 << "\tFeature Edge Smoothing " << (this->FeatureEdgeSmoothing
? "On\n" : "Off\n")
1052 << "\tError Scalars " << (this->GenerateErrorScalars
? "On\n" : "Off\n")
1053 << "\tError Vectors " << (this->GenerateErrorVectors
? "On\n" : "Off\n")<<endl
;
1055 // Peform topological analysis. What we're gonna do is build a connectivity
1056 // array of connected vertices. The outcome will be one of three
1057 // classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or
1058 // VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected
1059 // vertices. FIXED vertices are never smoothed. Edge vertices are smoothed
1060 // using a subset of the attached vertices.
1062 if(DebugLevel
>5) cout
<<"===>Analyze topology==="<<endl
;
1063 if(DebugLevel
>5) cout
<<"Analyzing topology..."<<endl
;
1064 if(DebugLevel
>5) cout
<<"0:numPts="<<numPts
<<endl
;
1065 Verts
= new vtkMeshVertex
[numPts
];
1066 for (i
=0; i
<numPts
; i
++)
1068 if(DebugLevel
>5) cout
<<"0:VTK_SIMPLE_VERTEX"<<endl
;
1069 Verts
[i
].type
= VTK_SIMPLE_VERTEX
; //can smooth
1070 Verts
[i
].edges
= NULL
;
1073 inPts
= input
->GetPoints();
1074 conv
= this->Convergence
* input
->GetLength();
1076 if(DebugLevel
>5) cout
<<"==polygons and triangle strips=="<<endl
;
1077 // now polygons and triangle strips-------------------------------
1078 inPolys
=input
->GetPolys();
1079 numPolys
= inPolys
->GetNumberOfCells();
1081 if(DebugLevel
>5) cout
<<"numPolys="<<numPolys
<<endl
;
1084 { //build cell structure
1085 vtkCellArray
*polys
;
1087 int numNei
, nei
, edge
;
1088 vtkIdType numNeiPts
;
1090 double normal
[3], neiNormal
[3];
1091 vtkIdList
*neighbors
;
1093 neighbors
= vtkIdList::New();
1094 neighbors
->Allocate(VTK_CELL_SIZE
);
1096 inMesh
= vtkPolyData::New();
1097 inMesh
->SetPoints(inPts
);
1098 inMesh
->SetPolys(inPolys
);
1101 Mesh
->BuildLinks(); //to do neighborhood searching
1102 polys
= Mesh
->GetPolys();
1104 for (cellId
=0, polys
->InitTraversal(); polys
->GetNextCell(npts
,pts
);
1107 if(DebugLevel
>5) cout
<<"->cellId="<<cellId
<<endl
;
1108 for (i
=0; i
< npts
; i
++)
1110 if(DebugLevel
>5) cout
<<"-->i="<<i
<<endl
;
1112 p2
= pts
[(i
+1)%npts
];
1114 if ( Verts
[p1
].edges
== NULL
)
1116 Verts
[p1
].edges
= vtkIdList::New();
1117 Verts
[p1
].edges
->Allocate(16,6);
1119 if ( Verts
[p2
].edges
== NULL
)
1121 Verts
[p2
].edges
= vtkIdList::New();
1122 Verts
[p2
].edges
->Allocate(16,6);
1125 Mesh
->GetCellEdgeNeighbors(cellId
,p1
,p2
,neighbors
);
1126 numNei
= neighbors
->GetNumberOfIds();
1127 if(DebugLevel
>5) cout
<<"-->numNei="<<numNei
<<endl
;
1129 edge
= VTK_SIMPLE_VERTEX
;
1132 edge
= VTK_BOUNDARY_EDGE_VERTEX
;
1135 else if ( numNei
>= 2 )
1137 // check to make sure that this edge hasn't been marked already
1138 for (j
=0; j
< numNei
; j
++)
1140 if ( neighbors
->GetId(j
) < cellId
)
1147 edge
= VTK_FEATURE_EDGE_VERTEX
;
1151 else if ( numNei
== 1 && (nei
=neighbors
->GetId(0)) > cellId
)
1153 vtkPolygon::ComputeNormal(inPts
,npts
,pts
,normal
);
1154 Mesh
->GetCellPoints(nei
,numNeiPts
,neiPts
);
1155 vtkPolygon::ComputeNormal(inPts
,numNeiPts
,neiPts
,neiNormal
);
1157 if ( this->FeatureEdgeSmoothing
&&
1158 vtkMath::Dot(normal
,neiNormal
) <= CosFeatureAngle
)
1160 edge
= VTK_FEATURE_EDGE_VERTEX
;
1163 else // a visited edge; skip rest of analysis
1168 if ( edge
&& Verts
[p1
].type
== VTK_SIMPLE_VERTEX
)
1170 Verts
[p1
].edges
->Reset();
1171 Verts
[p1
].edges
->InsertNextId(p2
);
1172 Verts
[p1
].type
= edge
;
1174 else if ( (edge
&& Verts
[p1
].type
== VTK_BOUNDARY_EDGE_VERTEX
) ||
1175 (edge
&& Verts
[p1
].type
== VTK_FEATURE_EDGE_VERTEX
) ||
1176 (!edge
&& Verts
[p1
].type
== VTK_SIMPLE_VERTEX
) )
1178 Verts
[p1
].edges
->InsertNextId(p2
);
1179 if ( Verts
[p1
].type
&& edge
== VTK_BOUNDARY_EDGE_VERTEX
)
1181 Verts
[p1
].type
= VTK_BOUNDARY_EDGE_VERTEX
;
1185 if ( edge
&& Verts
[p2
].type
== VTK_SIMPLE_VERTEX
)
1187 Verts
[p2
].edges
->Reset();
1188 Verts
[p2
].edges
->InsertNextId(p1
);
1189 Verts
[p2
].type
= edge
;
1191 else if ( (edge
&& Verts
[p2
].type
== VTK_BOUNDARY_EDGE_VERTEX
) ||
1192 (edge
&& Verts
[p2
].type
== VTK_FEATURE_EDGE_VERTEX
) ||
1193 (!edge
&& Verts
[p2
].type
== VTK_SIMPLE_VERTEX
) )
1195 Verts
[p2
].edges
->InsertNextId(p1
);
1196 if ( Verts
[p2
].type
&& edge
== VTK_BOUNDARY_EDGE_VERTEX
)
1198 Verts
[p2
].type
= VTK_BOUNDARY_EDGE_VERTEX
;
1206 neighbors
->Delete();
1207 }//if strips or polys
1209 //post-process edge vertices to make sure we can smooth them
1210 for (i
=0; i
<numPts
; i
++)
1212 if ( Verts
[i
].type
== VTK_SIMPLE_VERTEX
)
1217 else if ( Verts
[i
].type
== VTK_FIXED_VERTEX
)
1222 else if ( Verts
[i
].type
== VTK_FEATURE_EDGE_VERTEX
||
1223 Verts
[i
].type
== VTK_BOUNDARY_EDGE_VERTEX
)
1224 { //see how many edges; if two, what the angle is
1226 if ( !this->BoundarySmoothing
&&
1227 Verts
[i
].type
== VTK_BOUNDARY_EDGE_VERTEX
)
1229 if(DebugLevel
>5) cout
<<"Verts[i].type = VTK_FIXED_VERTEX; 4"<<endl
;
1230 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1234 else if ( (npts
= Verts
[i
].edges
->GetNumberOfIds()) != 2 )
1236 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type = VTK_FIXED_VERTEX; 5"<<endl
;
1237 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1241 else //check angle between edges
1243 inPts
->GetPoint(Verts
[i
].edges
->GetId(0),x1
);
1244 inPts
->GetPoint(i
,x2
);
1245 inPts
->GetPoint(Verts
[i
].edges
->GetId(1),x3
);
1249 l1
[k
] = x2
[k
] - x1
[k
];
1250 l2
[k
] = x3
[k
] - x2
[k
];
1252 if ( vtkMath::Normalize(l1
) >= 0.0 &&
1253 vtkMath::Normalize(l2
) >= 0.0 &&
1254 vtkMath::Dot(l1
,l2
) < CosEdgeAngle
)
1256 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type = VTK_FIXED_VERTEX; 6"<<endl
;
1257 Verts
[i
].type
= VTK_FIXED_VERTEX
;
1262 if ( Verts
[i
].type
== VTK_FEATURE_EDGE_VERTEX
)
1276 cout
<<"Found\n\t" << numSimple
<< " simple vertices\n\t"
1277 << numFEdges
<< " feature edge vertices\n\t"
1278 << numBEdges
<< " boundary edge vertices\n\t"
1279 << numFixed
<< " fixed vertices\n\t"<<endl
;
1280 cout
<<"1:numPts="<<numPts
<<endl
;
1283 for (i
=0; i
<numPts
; i
++)
1285 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].type="<<VertexType2Str(Verts
[i
].type
)<<endl
;
1286 if(Verts
[i
].edges
!= NULL
&& (npts
= Verts
[i
].edges
->GetNumberOfIds()) > 0)
1288 for (j
=0; j
<npts
; j
++)
1290 if(DebugLevel
>5) cout
<<"Verts["<<i
<<"].edges->GetId("<<j
<<")="<<Verts
[i
].edges
->GetId(j
)<<endl
;
1291 }//for all connected points
1295 //Copy node type info from Verts
1296 EG_VTKDCN(vtkCharArray
, node_type
, grid
, "node_type");
1297 if(DebugLevel
>5) cout
<<"nodes.size()="<<nodes
.size()<<endl
;
1298 foreach(vtkIdType node
,nodes
)
1300 if(DebugLevel
>5) cout
<<"Verts["<<node
<<"].type="<<VertexType2Str(Verts
[node
].type
)<<endl
;
1301 node_type
->SetValue(node
,Verts
[node
].type
);
1304 //free up connectivity storage
1305 for (int i
=0; i
<numPts
; i
++)
1307 if ( Verts
[i
].edges
!= NULL
)
1309 Verts
[i
].edges
->Delete();
1310 Verts
[i
].edges
= NULL
;
1317 //End of UpdateNodeType
1320 // Normal cell: nothing has changed
1321 // Dead cell: the cell does not exist anymore
1322 // Mutated cell: the cell's form has changed
1323 // Mutilated cell: the cell has less points than before
1325 vtkIdType
Operation::FindSnapPoint(vtkUnstructuredGrid
*src
, vtkIdType DeadNode
,QSet
<vtkIdType
> & DeadCells
,QSet
<vtkIdType
> & MutatedCells
,QSet
<vtkIdType
> & MutilatedCells
, int& N_newpoints
, int& N_newcells
)
1327 getAllSurfaceCells(cells
,src
);
1328 getNodesFromCells(cells
, nodes
, src
);
1334 EG_VTKDCN(vtkCharArray
, node_type
, src
, "node_type");
1335 if(node_type
->GetValue(DeadNode
)==VTK_FIXED_VERTEX
)
1337 cout
<<"Sorry, unable to remove fixed vertex."<<endl
;
1342 int N_points
=src
->GetNumberOfPoints();
1343 int N_cells
=src
->GetNumberOfCells();
1347 vtkIdType SnapPoint
=-1;
1349 foreach(vtkIdType PSP
, n2n
[DeadNode
])
1351 bool IsValidSnapPoint
=true;
1353 if(DebugLevel
>10) cout
<<"====>PSP="<<PSP
<<endl
;
1355 if(NumberOfCommonPoints(DeadNode
,PSP
,IsTetra
)>2)//common point check
1357 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1358 IsValidSnapPoint
=false;
1360 if(IsTetra
)//tetra check
1362 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1363 IsValidSnapPoint
=false;
1366 //count number of points and cells to remove + analyse cell transformations
1370 MutatedCells
.clear();
1371 MutilatedCells
.clear();
1372 foreach(vtkIdType C
, n2c
[DeadNode
])//loop through potentially dead cells
1374 //get points around cell
1375 vtkIdType N_pts
, *pts
;
1376 src
->GetCellPoints(C
, N_pts
, pts
);
1378 bool ContainsSnapPoint
=false;
1379 bool invincible
=false;
1380 for(int i
=0;i
<N_pts
;i
++)
1382 if(DebugLevel
>10) cout
<<"pts["<<i
<<"]="<<pts
[i
]<<" and PSP="<<PSP
<<endl
;
1383 if(pts
[i
]==PSP
) {ContainsSnapPoint
=true;}
1384 if(pts
[i
]!=DeadNode
&& pts
[i
]!=PSP
&& n2c
[pts
[i
]].size()<=1) invincible
=true;
1386 if(ContainsSnapPoint
)
1388 if(N_pts
==3)//dead cell
1390 if(invincible
)//Check that empty lines aren't left behind when a cell is killed
1392 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1393 IsValidSnapPoint
=false;
1397 DeadCells
.insert(C
);
1399 if(DebugLevel
>10) cout
<<"cell "<<C
<<" has been pwned!"<<endl
;
1404 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
1410 vtkIdType src_N_pts
, *src_pts
;
1411 src
->GetCellPoints(C
, src_N_pts
, src_pts
);
1415 cout
<<"RED ALERT: Xenomorph detected!"<<endl
;
1419 vtkIdType OldTriangle
[3];
1420 vtkIdType NewTriangle
[3];
1422 for(int i
=0;i
<src_N_pts
;i
++)
1424 OldTriangle
[i
]=src_pts
[i
];
1425 NewTriangle
[i
]=( (src_pts
[i
]==DeadNode
) ? PSP
: src_pts
[i
] );
1427 vec3_t Old_N
= triNormal(src
, OldTriangle
[0], OldTriangle
[1], OldTriangle
[2]);
1428 vec3_t New_N
= triNormal(src
, NewTriangle
[0], NewTriangle
[1], NewTriangle
[2]);
1429 double OldArea
=Old_N
.abs();
1430 double NewArea
=New_N
.abs();
1431 double scal
=Old_N
*New_N
;
1432 double cross
=(Old_N
.cross(New_N
)).abs();//double-cross on Nar Shadaa B-)
1435 cout
<<"OldArea="<<OldArea
<<endl
;
1436 cout
<<"NewArea="<<NewArea
<<endl
;
1437 cout
<<"scal="<<scal
<<endl
;
1438 cout
<<"cross="<<cross
<<endl
;
1441 if(Old_N
*New_N
<Old_N
*Old_N
*1./100.)//area + inversion check
1443 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1444 IsValidSnapPoint
=false;
1448 MutatedCells
.insert(C
);
1449 if(DebugLevel
>10) cout
<<"cell "<<C
<<" has been infected!"<<endl
;
1453 if(N_cells
+N_newcells
<=0)//survivor check
1455 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1456 IsValidSnapPoint
=false;
1459 if(node_type
->GetValue(DeadNode
)==VTK_BOUNDARY_EDGE_VERTEX
&& node_type
->GetValue(PSP
)==VTK_SIMPLE_VERTEX
)
1461 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1462 IsValidSnapPoint
=false;
1465 if(node_type
->GetValue(DeadNode
)==VTK_BOUNDARY_EDGE_VERTEX
)
1468 QVector
<vtkIdType
> Peons
;
1469 getNeighbours(DeadNode
, Peons
, BC
);
1470 if(!Peons
.contains(PSP
))
1472 if(DebugLevel
>0) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1473 IsValidSnapPoint
=false;
1477 if(node_type
->GetValue(DeadNode
)==VTK_FEATURE_EDGE_VERTEX
&& node_type
->GetValue(PSP
)==VTK_SIMPLE_VERTEX
)
1479 if(DebugLevel
>10) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1480 IsValidSnapPoint
=false;
1483 if(node_type
->GetValue(DeadNode
)==VTK_FEATURE_EDGE_VERTEX
)
1486 QVector
<vtkIdType
> Peons
;
1487 getNeighbours(DeadNode
, Peons
, BC
);
1488 if(!Peons
.contains(PSP
))
1490 if(DebugLevel
>0) cout
<<"Sorry, but you are not allowed to move point "<<DeadNode
<<" to point "<<PSP
<<"."<<endl
;
1491 IsValidSnapPoint
=false;
1495 if(IsValidSnapPoint
) {SnapPoint
=PSP
; break;}
1496 }//end of loop through potential SnapPoints
1500 cout
<<"AT FINDSNAPPOINT EXIT"<<endl
;
1501 cout
<<"N_points="<<N_points
<<endl
;
1502 cout
<<"N_cells="<<N_cells
<<endl
;
1503 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1504 cout
<<"N_newcells="<<N_newcells
<<endl
;
1508 //End of FindSnapPoint
1510 bool Operation::DeletePoint_2(vtkUnstructuredGrid
*src
, vtkIdType DeadNode
, int& N_newpoints
, int& N_newcells
)
1512 getAllSurfaceCells(cells
,src
);
1513 // getNodesFromCells(cells, nodes, src);
1519 int N_points
=src
->GetNumberOfPoints();
1520 int N_cells
=src
->GetNumberOfCells();
1524 if(DeadNode
<0 || DeadNode
>=N_points
)
1526 cout
<<"Warning: Point out of range: DeadNode="<<DeadNode
<<" N_points="<<N_points
<<endl
;
1530 QSet
<vtkIdType
> DeadCells
;
1531 QSet
<vtkIdType
> MutatedCells
;
1532 QSet
<vtkIdType
> MutilatedCells
;
1535 cout
<<"BEFORE FINDSNAPPOINT"<<endl
;
1536 cout
<<"N_points="<<N_points
<<endl
;
1537 cout
<<"N_cells="<<N_cells
<<endl
;
1538 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1539 cout
<<"N_newcells="<<N_newcells
<<endl
;
1541 vtkIdType SnapPoint
=FindSnapPoint(src
,DeadNode
,DeadCells
,MutatedCells
,MutilatedCells
, N_newpoints
, N_newcells
);
1543 if(DebugLevel
>0) cout
<<"===>DeadNode="<<DeadNode
<<" moving to SNAPPOINT="<<SnapPoint
<<" DebugLevel="<<DebugLevel
<<endl
;
1544 if(SnapPoint
<0) {cout
<<"Sorry no possible SnapPoint found."<<endl
; return(false);}
1548 cout
<<"BEFORE ALLOCATION"<<endl
;
1549 cout
<<"N_points="<<N_points
<<endl
;
1550 cout
<<"N_cells="<<N_cells
<<endl
;
1551 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1552 cout
<<"N_newcells="<<N_newcells
<<endl
;
1554 N_points
=src
->GetNumberOfPoints();
1555 N_cells
=src
->GetNumberOfCells();
1558 cout
<<"N_points="<<N_points
<<endl
;
1559 cout
<<"N_cells="<<N_cells
<<endl
;
1560 cout
<<"N_newpoints="<<N_newpoints
<<endl
;
1561 cout
<<"N_newcells="<<N_newcells
<<endl
;
1563 EG_VTKSP(vtkUnstructuredGrid
,dst
);
1564 allocateGrid(dst
,N_cells
+N_newcells
,N_points
+N_newpoints
);
1566 //vector used to redefine the new point IDs
1567 QVector
<vtkIdType
> OffSet(N_points
);
1569 //copy undead points
1570 vtkIdType dst_id_node
=0;
1571 for (vtkIdType src_id_node
= 0; src_id_node
< N_points
; src_id_node
++) {//loop through src points
1572 if(src_id_node
!=DeadNode
)//if the node isn't dead, copy it
1575 src
->GetPoints()->GetPoint(src_id_node
, x
.data());
1576 dst
->GetPoints()->SetPoint(dst_id_node
, x
.data());
1577 copyNodeData(src
, src_id_node
, dst
, dst_id_node
);
1578 OffSet
[src_id_node
]=src_id_node
-dst_id_node
;
1583 if(DebugLevel
>0) cout
<<"src_id_node="<<src_id_node
<<" dst_id_node="<<dst_id_node
<<endl
;
1587 cout
<<"DeadCells="<<DeadCells
<<endl
;
1588 cout
<<"MutatedCells="<<MutatedCells
<<endl
;
1589 cout
<<"MutilatedCells="<<MutilatedCells
<<endl
;
1592 for (vtkIdType id_cell
= 0; id_cell
< src
->GetNumberOfCells(); ++id_cell
) {//loop through src cells
1593 if(!DeadCells
.contains(id_cell
))//if the cell isn't dead
1595 vtkIdType src_N_pts
, *src_pts
;
1596 vtkIdType dst_N_pts
, *dst_pts
;
1597 src
->GetCellPoints(id_cell
, src_N_pts
, src_pts
);
1599 vtkIdType type_cell
= src
->GetCellType(id_cell
);
1600 if(DebugLevel
>10) cout
<<"-->id_cell="<<id_cell
<<endl
;
1601 if(DebugLevel
>10) for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
1602 // src->GetCellPoints(id_cell, dst_N_pts, dst_pts);
1603 dst_N_pts
=src_N_pts
;
1604 dst_pts
=new vtkIdType
[dst_N_pts
];
1605 if(MutatedCells
.contains(id_cell
))//mutated cell
1607 if(DebugLevel
>10) cout
<<"processing mutated cell "<<id_cell
<<endl
;
1608 for(int i
=0;i
<src_N_pts
;i
++)
1610 if(src_pts
[i
]==DeadNode
) {
1612 cout
<<"SnapPoint="<<SnapPoint
<<endl
;
1613 cout
<<"OffSet[SnapPoint]="<<OffSet
[SnapPoint
]<<endl
;
1614 cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
1616 dst_pts
[i
]=SnapPoint
-OffSet
[SnapPoint
];
1618 else dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
1620 if(DebugLevel
>10) cout
<<"--->dst_pts:"<<endl
;
1621 if(DebugLevel
>10) for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
1624 else if(MutilatedCells
.contains(id_cell
))//mutilated cell
1626 if(DebugLevel
>10) cout
<<"processing mutilated cell "<<id_cell
<<endl
;
1628 if(type_cell
==VTK_QUAD
) {
1629 type_cell
=VTK_TRIANGLE
;
1632 else {cout
<<"FATAL ERROR: Unknown mutilated cell detected! It is not a quad! Potential xenomorph infestation!"<<endl
;EG_BUG
;}
1635 for(int i
=0;i
<src_N_pts
;i
++)
1637 if(src_pts
[i
]==SnapPoint
) { dst_pts
[j
]=SnapPoint
-OffSet
[SnapPoint
];j
++; }//SnapPoint
1638 else if(src_pts
[i
]!=DeadNode
) { dst_pts
[j
]=src_pts
[i
]-OffSet
[src_pts
[i
]];j
++; }//pre-snap/dead + post-snap/dead
1639 //do nothing in case of DeadNode
1644 if(DebugLevel
>10) cout
<<"processing normal cell "<<id_cell
<<endl
;
1645 for(int i
=0;i
<src_N_pts
;i
++)
1647 dst_pts
[i
]=src_pts
[i
]-OffSet
[src_pts
[i
]];
1651 vtkIdType id_new_cell
= dst
->InsertNextCell(type_cell
, dst_N_pts
, dst_pts
);
1652 copyCellData(src
, id_cell
, dst
, id_new_cell
);
1654 cout
<<"===Copying cell "<<id_cell
<<" to "<<id_new_cell
<<"==="<<endl
;
1655 cout
<<"src_pts:"<<endl
;
1656 for(int i
=0;i
<src_N_pts
;i
++) cout
<<"src_pts["<<i
<<"]="<<src_pts
[i
]<<endl
;
1657 cout
<<"dst_pts:"<<endl
;
1658 for(int i
=0;i
<dst_N_pts
;i
++) cout
<<"dst_pts["<<i
<<"]="<<dst_pts
[i
]<<endl
;
1659 cout
<<"OffSet="<<OffSet
<<endl
;
1660 cout
<<"===Copying cell end==="<<endl
;
1665 // cout_grid(cout,dst,true,true,true,true);
1669 //End of DeletePoint_2
1671 void Operation::TxtSave(QString a_filename
)
1673 cout
<< a_filename
.toAscii().data() << endl
;
1675 file
.open(a_filename
.toAscii().data());
1676 cout_grid(file
,grid
,true,true,true,true);
1680 void Operation::DualSave(QString a_filename
)
1682 TxtSave(a_filename
+".txt");
1683 GuiMainWindow::pointer()->QuickSave(a_filename
+".vtu");