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 "swaptriangles.h"
24 #include "guimainwindow.h"
26 #include <vtkCellArray.h>
28 #include "checksurfaceintegrity.h"
30 using namespace GeometryTools
;
32 SwapTriangles::SwapTriangles() : SurfaceOperation()
35 m_FeatureSwap
= false;
38 void SwapTriangles::operate()
40 //cout << "swapping edges of boundary triangles (Delaunay)" << endl;
42 static int nStatic_SwapTriangles
; // Value of nStatic_SwapTriangles is retained between each function call
43 nStatic_SwapTriangles
++;
44 //cout << "nStatic_SwapTriangles is " << nStatic_SwapTriangles << endl;
52 l2g_t cells
= getPartCells();
53 g2l_t _cells
= getPartLocalCells();
54 l2l_t n2c
= getPartN2C();
55 g2l_t _nodes
= getPartLocalNodes();
56 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
57 QVector
<bool> l_marked(cells
.size());
58 foreach (vtkIdType id_cell
, cells
) {
59 if (!boundary_codes
.contains(cell_code
->GetValue(id_cell
)) && grid
->GetCellType(id_cell
) == VTK_TRIANGLE
) { //if it is a selected triangle
60 if (!l_marked
[_cells
[id_cell
]]) {
61 for (int j
= 0; j
< 3; ++j
) {
63 stencil_t S
= getStencil(id_cell
, j
);
64 if(S
.twocells
&& S
.sameBC
&& (S
.neighbour_type
== VTK_TRIANGLE
)) {
65 if( ! isEdge(S
.p
[0],S
.p
[2]) ) {
66 if (!l_marked
[_cells
[S
.id_cell2
]]) {
67 vec3_t x3
[4], x3_0(0,0,0);
69 for (int k
= 0; k
< 4; ++k
) {
70 grid
->GetPoints()->GetPoint(S
.p
[k
], x3
[k
].data());
73 vec3_t n1
= triNormal(x3
[0], x3
[1], x3
[3]);
74 vec3_t n2
= triNormal(x3
[1], x3
[2], x3
[3]);
75 if ( m_FeatureSwap
|| (n1
*n2
) > 0.8*n1
.abs()*n2
.abs() ) {
79 vec3_t ex
= orthogonalVector(n
);
80 vec3_t ey
= ex
.cross(n
);
81 for (int k
= 0; k
< 4; ++k
) {
82 x
[k
] = vec2_t(x3
[k
]*ex
, x3
[k
]*ey
);
84 vec2_t r1
, r2
, r3
, u1
, u2
, u3
;
85 r1
= 0.5*(x
[0] + x
[1]); u1
= turnLeft(x
[1] - x
[0]);
86 r2
= 0.5*(x
[1] + x
[2]); u2
= turnLeft(x
[2] - x
[1]);
87 r3
= 0.5*(x
[1] + x
[3]); u3
= turnLeft(x
[3] - x
[1]);
91 if (intersection(k
, l
, r1
, u1
, r3
, u3
)) {
93 if (intersection(k
, l
, r2
, u2
, r3
, u3
)) {
103 if ((xm1
- x
[2]).abs() < (xm1
- x
[0]).abs()) {
106 if ((xm2
- x
[0]).abs() < (xm2
- x
[2]).abs()) {
111 } //end of if feature angle
112 } //end of if l_marked
113 } //end of if TestSwap
117 l_marked
[_cells
[S
.id_cell1
]] = true;
118 l_marked
[_cells
[S
.id_cell2
]] = true;
119 for(int i
= 0; i
< 4; i
++) {
120 foreach(int i_neighbour
, n2c
[_nodes
[S
.p
[i
]]]) {
121 l_marked
[i_neighbour
] = true;
124 vtkIdType new_pts1
[3], new_pts2
[3];
125 new_pts1
[0] = S
.p
[1];
126 new_pts1
[1] = S
.p
[2];
127 new_pts1
[2] = S
.p
[0];
128 new_pts2
[0] = S
.p
[2];
129 new_pts2
[1] = S
.p
[3];
130 new_pts2
[2] = S
.p
[0];
131 vtkIdType old_pts1
[3], old_pts2
[3];
132 old_pts1
[0] = S
.p
[0];
133 old_pts1
[1] = S
.p
[1];
134 old_pts1
[2] = S
.p
[3];
135 old_pts2
[0] = S
.p
[2];
136 old_pts2
[1] = S
.p
[3];
137 old_pts2
[2] = S
.p
[1];
138 grid
->ReplaceCell(S
.id_cell1
, 3, new_pts1
);
139 grid
->ReplaceCell(S
.id_cell2
, 3, new_pts2
);
144 } //end of loop through sides
146 } //end of if selected triangle
147 } //end of loop through cells
149 } while ((N_swaps
> 0) && (loop
<= 20));
150 //cout << N_total << " triangles have been swapped" << endl;
153 bool SwapTriangles::testSwap(stencil_t S
)
156 vec3_t n1_old
=triNormal(grid
,S
.p
[0],S
.p
[1],S
.p
[3]);
157 vec3_t n2_old
=triNormal(grid
,S
.p
[2],S
.p
[3],S
.p
[1]);
160 vec3_t n1_new
=triNormal(grid
,S
.p
[1],S
.p
[2],S
.p
[0]);
161 vec3_t n2_new
=triNormal(grid
,S
.p
[3],S
.p
[0],S
.p
[2]);
164 vec3_t Summit
=n1_old
+n2_old
;
166 for (int k
= 0; k
< 4; ++k
) {
167 grid
->GetPoints()->GetPoint(S
.p
[k
], M
[k
].data());
171 double V1_old
=tetraVol(M
[0], Summit
, M
[1], M
[3], true);
172 double V2_old
=tetraVol(M
[2], Summit
, M
[3], M
[1], true);
174 double V1_new
=tetraVol(M
[1], Summit
, M
[2], M
[0], true);
175 double V2_new
=tetraVol(M
[3], Summit
, M
[0], M
[2], true);
177 return(V1_old
>0 && V2_old
>0 && V1_new
>0 && V2_new
>0 );
180 bool SwapTriangles::isEdge(vtkIdType id_node1
, vtkIdType id_node2
)
182 l2g_t nodes
= getPartNodes();
183 g2l_t _nodes
= getPartLocalNodes();
184 l2l_t n2n
= getPartN2N();
187 foreach(int i_node
, n2n
[_nodes
[id_node1
]]) {
188 vtkIdType id_node
= nodes
[i_node
];
189 if( id_node
== id_node2
) ret
= true;