1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : UnitTetraIntersectionBaryTest.cxx
21 // Created : Thu Dec 11 15:54:41 2008
22 // Author : Edward AGAPOV (eap)
24 #include "UnitTetraIntersectionBaryTest.hxx"
26 #include "UnitTetraIntersectionBary.hxx"
27 #include "TetraAffineTransform.hxx"
28 #include "InterpolationUtils.hxx"
29 #include "SplitterTetra.txx"
33 using namespace INTERP_KERNEL;
37 void fill_UnitTetraIntersectionBary(UnitTetraIntersectionBary& bary, double nodes[][3])
39 int faceConn[4][3] = { { 0, 1, 2 },// inverse order
43 // int faceConn[4][3] = { { 0, 2, 1 },
48 for ( int i = 0; i < 4; ++i ) {
49 int* faceNodes = faceConn[ i ];
50 TransformedTriangle tri(nodes[faceNodes[0]], nodes[faceNodes[1]], nodes[faceNodes[2]]);
51 tri.calculateIntersectionVolume();
55 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_1()
57 // cutting tetra coincides with the unit one
58 double nodes[4][3] = { { 0.0, 0.0, 0.0 },
62 UnitTetraIntersectionBary bary;
63 fill_UnitTetraIntersectionBary(bary,nodes);
65 bool ok = bary.getBary( baryCenter );
66 double vol = bary.getVolume();
68 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.166667, vol, 1e-5);
69 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[0], 1e-5);
70 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[1], 1e-5);
71 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[2], 1e-5);
73 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_2()
75 // cutting tetra fully include the unit one
76 double nodes[4][3] = { {-0.1,-0.1,-0.1 },
80 UnitTetraIntersectionBary bary;
81 fill_UnitTetraIntersectionBary(bary,nodes);
83 bool ok = bary.getBary( baryCenter );
84 double vol = bary.getVolume();
86 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.166667, vol, 1e-5);
87 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[0], 1e-5);
88 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[1], 1e-5);
89 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[2], 1e-5);
91 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_3()
93 // cutting tetra is same as the unit one but moved up by 0.5
94 double nodes[4][3] = { { 0.0, 0.0, 0.5 },
98 UnitTetraIntersectionBary bary;
99 fill_UnitTetraIntersectionBary(bary,nodes);
100 double baryCenter[3];
101 bool ok = bary.getBary( baryCenter );
102 double vol = bary.getVolume();
103 CPPUNIT_ASSERT( ok );
104 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.020833333333333332, vol, 1e-5);
105 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.125, baryCenter[0], 1e-5);
106 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.125, baryCenter[1], 1e-5);
107 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.625, baryCenter[2], 1e-5);
109 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_4()
111 // same as previous but no cutting sides lay on the sides of unit tetra
112 double nodes[4][3] = { {-0.2,-0.2, 0.5 },
116 UnitTetraIntersectionBary bary;
117 fill_UnitTetraIntersectionBary(bary,nodes);
118 double baryCenter[3];
119 bool ok = bary.getBary( baryCenter );
120 double vol = bary.getVolume();
121 CPPUNIT_ASSERT( ok );
122 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.020833333333333332, vol, 1e-5);
123 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.125, baryCenter[0], 1e-5);
124 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.125, baryCenter[1], 1e-5);
125 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.625, baryCenter[2], 1e-5);
127 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_5()
129 // cutting tetra is similar and parallel to the UT but moved (-0.1,-0.1,-0.1)
130 double nodes[4][3] = { {-0.1,-0.1,-0.1 },
134 UnitTetraIntersectionBary bary;
135 fill_UnitTetraIntersectionBary(bary,nodes);
136 double baryCenter[3];
137 bool ok = bary.getBary( baryCenter );
138 double vol = bary.getVolume();
139 CPPUNIT_ASSERT( ok );
140 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.1215, vol, 1e-5);
141 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.225, baryCenter[0], 1e-5);
142 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.225, baryCenter[1], 1e-5);
143 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.225, baryCenter[2], 1e-5);
145 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_6()
147 // cutting tetra is deeped into the UT with one corner
148 double nodes[4][3] = { { 0.2, 0.2, 0.2 },
152 UnitTetraIntersectionBary bary;
153 fill_UnitTetraIntersectionBary(bary,nodes);
154 double baryCenter[3];
155 bool ok = bary.getBary( baryCenter );
156 double vol = bary.getVolume();
157 CPPUNIT_ASSERT( ok );
158 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.000441855, vol, 1e-5);
159 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.353463 , baryCenter[0], 1e-5 );
160 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.33877 , baryCenter[1], 1e-5 );
161 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.207767 , baryCenter[2], 1e-5 );
163 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_7()
165 // cutting tetra passes through the UT with one corner
166 double nodes[4][3] = { {-0.2, 0.2, 0.2 },
170 UnitTetraIntersectionBary bary;
171 fill_UnitTetraIntersectionBary(bary,nodes);
172 double baryCenter[3];
173 bool ok = bary.getBary( baryCenter );
174 double vol = bary.getVolume();
175 CPPUNIT_ASSERT( ok );
176 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0103501, vol, 1e-5);
177 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.215578 , baryCenter[0], 1e-5 );
178 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.341363 , baryCenter[1], 1e-5 );
179 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.263903 , baryCenter[2], 1e-5 );
181 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_8()
183 // cutting tetra passes through the UT with one edge
184 double nodes[4][3] = { { 0.5, 0.2, -0.2 }, // O
185 {-0.5,-0.2, -0.2 }, // OX
186 { 1.0,-0.5, -0.2 }, // OY
187 { 0.5, 0.2, 1.5 } };//OZ
188 UnitTetraIntersectionBary bary;
189 fill_UnitTetraIntersectionBary(bary,nodes);
190 double baryCenter[3];
191 bool ok = bary.getBary( baryCenter );
192 double vol = bary.getVolume();
193 CPPUNIT_ASSERT( ok );
194 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0349217, vol, 1e-5);
195 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.332275 , baryCenter[0], 1e-2 );
196 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0565892 , baryCenter[1], 1e-3 );
197 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.308713 , baryCenter[2], 1e-2 );
199 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_9()
201 // cutting tetra touches the UT at an edge, intersection volume == 0
202 double nodes[4][3] = { { 1.0, 0.0, 0.0 }, // 0
203 {-1.0, 2.0, 2.0 }, // OX
204 {-1.0,-2.0, 2.0 }, // OY
205 { 1.0, 0.0, 2.0 } };//OZ
206 UnitTetraIntersectionBary bary;
207 fill_UnitTetraIntersectionBary(bary,nodes);
208 double baryCenter[3];
209 bool ok = bary.getBary( baryCenter );
210 double vol = bary.getVolume();
211 CPPUNIT_ASSERT( !ok );
212 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, vol, 1e-15);
213 CPPUNIT_ASSERT_DOUBLES_EQUAL( -1. , baryCenter[0], 1e-5 );
214 CPPUNIT_ASSERT_DOUBLES_EQUAL( -1. , baryCenter[1], 1e-5 );
215 CPPUNIT_ASSERT_DOUBLES_EQUAL( -1. , baryCenter[2], 1e-5 );
217 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_10()
219 // cutting tetra fully includes theUT and touches it at an edge
220 double nodes[4][3] = { { 1.0, 0.0, 0.0 }, // 0
221 {-1.0,-4.0, 2.0 }, // OX
222 {-1.0, 4.0, 2.0 }, // OY
223 { 1.0, 0.0,-2.0 } };//OZ
224 UnitTetraIntersectionBary bary;
225 fill_UnitTetraIntersectionBary(bary,nodes);
226 double baryCenter[3];
227 bool ok = bary.getBary( baryCenter );
228 double vol = bary.getVolume();
229 CPPUNIT_ASSERT( ok );
230 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.166667, vol, 1e-5);
231 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[0], 1e-5);
232 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[1], 1e-5);
233 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.25, baryCenter[2], 1e-5);
235 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_11()
237 // cutting tetra intersects the UT and touches it at an edge
238 double nodes[4][3] = { { 1.0, 0.0, 0.0 }, // 0
239 {-1.0,-4.0, 2.0 }, // OX
240 {-1.0, 4.0, 2.0 }, // OY
241 {-1.0, 0.0,-1.0 } };//OZ
242 UnitTetraIntersectionBary bary;
243 fill_UnitTetraIntersectionBary(bary,nodes);
244 double baryCenter[3];
245 bool ok = bary.getBary( baryCenter );
246 double vol = bary.getVolume();
247 CPPUNIT_ASSERT( ok );
248 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.15873 , vol, 1e-5);
249 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.250000, baryCenter[0], 1e-5);
250 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.230952, baryCenter[1], 1e-5);
251 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.260714, baryCenter[2], 1e-5);
253 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_12()
255 // cutting tetra has one corner inside the UT and one its side passes through an UT edge
256 double nodes[4][3] = { { 0.25, 0.25, 0.25 }, // 0
257 { 1.75,-0.25,-0.25 }, // OX
258 { 0.5 , 0.25, 0.25 }, // OY
259 { 0.5 , 0 , 0.5 } };//OZ
260 UnitTetraIntersectionBary bary;
261 fill_UnitTetraIntersectionBary(bary,nodes);
262 double baryCenter[3];
263 bool ok = bary.getBary( baryCenter );
264 double vol = bary.getVolume();
265 CPPUNIT_ASSERT( ok );
266 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.005208 , vol, 1e-5);
267 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.562500, baryCenter[0], 1e-5);
268 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.125000, baryCenter[1], 1e-5);
269 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.250000, baryCenter[2], 1e-5);
274 typedef int MyConnType;
277 void UnitTetraIntersectionBaryTest::test_UnitTetraIntersectionBary_13()
280 66.6666666666666714,133.333333333333343,66.6666666666666714,
286 100,166.666666666666657,66.6666666666666714,
291 int conn[4] = { 0,1,2,3 };
293 const double* tnodes[4]={ T, T+3, T+6, T+9 };
294 const double* snodes[4]={ S, S+3, S+6, S+9 };
296 __MESH_DUMMY dummyMesh;
297 SplitterTetra<__MESH_DUMMY> src( dummyMesh, snodes, conn );
298 double volume = src.intersectTetra( tnodes );
299 CPPUNIT_ASSERT_DOUBLES_EQUAL(6944.4444444444443,volume,1e-9);
302 void UnitTetraIntersectionBaryTest::test_TetraAffineTransform_reverseApply()
304 double nodes[12] = { -4.0, 9.0, 3.0,
308 // double pSrc[3] = { -4.0, 9.0, 3.0 };
309 double pSrc[3] = { 40., -20., 100. };
310 double pDest[] = {1,1,1};
311 TetraAffineTransform a(nodes);
312 a.apply( pDest, pSrc );
313 a.reverseApply( pDest, pDest );
314 CPPUNIT_ASSERT_DOUBLES_EQUAL( pSrc[0], pDest[0], 1e-12);
315 CPPUNIT_ASSERT_DOUBLES_EQUAL( pSrc[1], pDest[1], 1e-12);
316 CPPUNIT_ASSERT_DOUBLES_EQUAL( pSrc[2], pDest[2], 1e-12);
319 void UnitTetraIntersectionBaryTest::test_barycentric_coords()
321 // compute barycentric coordinates
322 double nodes[4][3] = { {11.0, 0.0, 2.0 },
326 std::vector<const double*> n (4);
331 double p [3] = { 2, 2, 5 }, bc[4];
332 barycentric_coords(n, p, bc);
334 double p2 [3] = { 0,0,0 };
335 for ( int i = 0; i < 4; ++i ) {
337 p2[0] += bc[i]*n[i][0];
338 p2[1] += bc[i]*n[i][1];
339 p2[2] += bc[i]*n[i][2];
341 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1., bcSum, 1e-12);
342 CPPUNIT_ASSERT_DOUBLES_EQUAL( p[0], p2[0], 1e-12);
343 CPPUNIT_ASSERT_DOUBLES_EQUAL( p[1], p2[1], 1e-12);
344 CPPUNIT_ASSERT_DOUBLES_EQUAL( p[2], p2[2], 1e-12);