source: src/Tesselation/unittests/Tesselation_BoundaryTriangleUnitTest.cpp@ 6a7fcbb

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 6a7fcbb was 6a7fcbb, checked in by Frederik Heber <heber@…>, 13 years ago

FIX: Rewrote BoundaryTriangleSet::GetClosestPointInsideTriangle().

  • was broken before, see failing unit test, as it returned points not inside the triangle (however on the plane). Now, we rely on getClosestPoint of Space and derived classes.
  • TESTFIX: Removed Tesselation_BoundaryTriangleUnitTest from XFAIL.
  • Property mode set to 100644
File size: 15.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * Tesselation_BoundaryTriangleUnitTest.cpp
10 *
11 * Created on: Jan 13, 2010
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20using namespace std;
21
22#include <cppunit/CompilerOutputter.h>
23#include <cppunit/extensions/TestFactoryRegistry.h>
24#include <cppunit/ui/text/TestRunner.h>
25
26#include <cstring>
27#include <iostream>
28
29#include "CodePatterns/Log.hpp"
30#include "Helpers/defs.hpp"
31#include "Atom/TesselPoint.hpp"
32#include "LinearAlgebra/Plane.hpp"
33#include "LinearAlgebra/RealSpaceMatrix.hpp"
34#include "LinearAlgebra/VectorSet.hpp"
35#include "Tesselation/BoundaryPointSet.hpp"
36#include "Tesselation/BoundaryLineSet.hpp"
37#include "Tesselation/BoundaryTriangleSet.hpp"
38#include "Tesselation/CandidateForTesselation.hpp"
39
40#include "Tesselation_BoundaryTriangleUnitTest.hpp"
41
42#ifdef HAVE_TESTRUNNER
43#include "UnitTestMain.hpp"
44#endif /*HAVE_TESTRUNNER*/
45
46const double TesselationBoundaryTriangleTest::SPHERERADIUS=2.;
47
48/********************************************** Test classes **************************************/
49
50// Registers the fixture into the 'registry'
51CPPUNIT_TEST_SUITE_REGISTRATION( TesselationBoundaryTriangleTest );
52
53
54void TesselationBoundaryTriangleTest::createTriangle(const std::vector<Vector> &Vectors)
55{
56 CPPUNIT_ASSERT_EQUAL( (size_t)3, Vectors.size() );
57
58 // create nodes
59 for (size_t count = 0; count < NDIM; ++count) {
60 tesselpoints[count] = new TesselPoint;
61 tesselpoints[count]->setPosition( Vectors[count] );
62 tesselpoints[count]->setName(toString(count));
63 tesselpoints[count]->setNr(count);
64 points[count] = new BoundaryPointSet(tesselpoints[count]);
65 }
66
67 // create line
68 lines[0] = new BoundaryLineSet(points[0], points[1], 0);
69 lines[1] = new BoundaryLineSet(points[1], points[2], 1);
70 lines[2] = new BoundaryLineSet(points[0], points[2], 2);
71
72 // create triangle
73 triangle = new BoundaryTriangleSet(lines, 0);
74 Plane p(Vectors[0], Vectors[1], Vectors[2]);
75 triangle->GetNormalVector(p.getNormal());
76}
77
78void TesselationBoundaryTriangleTest::setUp()
79{
80 setVerbosity(5);
81
82 // create nodes
83 std::vector<Vector> Vectors;
84 Vectors.push_back( Vector(0., 0., 0.) );
85 Vectors.push_back( Vector(0., 1., 0.) );
86 Vectors.push_back( Vector(1., 0., 0.) );
87
88 // create triangle
89 createTriangle(Vectors);
90}
91
92void TesselationBoundaryTriangleTest::tearDown()
93{
94 delete(triangle);
95 for (int i=0;i<3;++i) {
96 // TesselPoint does not delete its vector as it only got a reference
97 delete tesselpoints[i];
98 }
99 logger::purgeInstance();
100 errorLogger::purgeInstance();
101}
102
103/** UnitTest for Tesselation::IsInsideTriangle()
104 */
105void TesselationBoundaryTriangleTest::IsInsideTriangleTest()
106{
107 // inside points
108 {
109 // check each endnode
110 for (size_t i=0; i< NDIM; ++i) {
111 const Vector testPoint(triangle->endpoints[i]->node->getPosition());
112 LOG(1, "INFO: Testing whether " << testPoint << " is an inner point.");
113 CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint ) );
114 }
115 }
116
117 {
118 // check points along each BoundaryLine
119 for (size_t i=0; i< NDIM; ++i) {
120 Vector offset = triangle->endpoints[i%3]->node->getPosition();
121 Vector direction = triangle->endpoints[(i+1)%3]->node->getPosition() - offset;
122 for (double s = 0.1; s < 1.; s+= 0.1) {
123 Vector testPoint = offset + s*direction;
124 LOG(1, "INFO: Testing whether " << testPoint << " is an inner point.");
125 CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint ) );
126 }
127 }
128 }
129
130 {
131 // check central point
132 Vector center;
133 triangle->GetCenter(center);
134 LOG(1, "INFO: Testing whether " << center << " is an inner point.");
135 CPPUNIT_ASSERT( triangle->IsInsideTriangle( center ) );
136 }
137
138 // outside points
139 {
140 // check points outside (i.e. those not in xy-plane through origin)
141 double n[3];
142 const double boundary = 4.;
143 const double step = 1.;
144 // go through the cube and check each point
145 for (n[0] = -boundary; n[0] <= boundary; n[0]+=step)
146 for (n[1] = -boundary; n[1] <= boundary; n[1]+=step)
147 for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) {
148 const Vector testPoint(n[0], n[1], n[2]);
149 if (n[2] != 0) {
150 LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point.");
151 CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint ) );
152 }
153 }
154 }
155
156 {
157 // check points within the plane but outside of triangle
158 double n[3];
159 const double boundary = 4.;
160 const double step = 1.;
161 n[2] = 0;
162 for (n[0] = -boundary; n[0] <= boundary; n[0]+=step)
163 for (n[1] = -boundary; n[1] <= boundary; n[1]+=step) {
164 const Vector testPoint(n[0], n[1], n[2]);
165 if ((n[0] >=0) && (n[1] >=0) && (n[0]<=1) && (n[1]<=1)) {
166 if (n[0]+n[1] <= 1) {
167 LOG(1, "INFO: Testing whether " << testPoint << " is an inner point.");
168 CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint) );
169 } else {
170 LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point.");
171 CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint) );
172 }
173 } else {
174 LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point.");
175 CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint) );
176 }
177 }
178 }
179}
180
181/** UnitTest for Tesselation::IsInsideTriangle()
182 *
183 * We test for some specific points that occured in larger examples of the code.
184 *
185 */
186void TesselationBoundaryTriangleTest::IsInsideTriangle_specificTest()
187{
188 {
189 delete triangle;
190 // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data
191 // failure is: Intersection (23.1644,24.1867,65.1272) is not inside triangle [659|Na2451,O3652,Na3762].
192 const Vector testPoint(1.57318,1.57612,10.9874);
193 const Vector testIntersection(23.1644,24.1867,65.1272);
194 std::vector<Vector> vectors;
195 vectors.push_back( Vector(23.0563,30.4673,73.7555) );
196 vectors.push_back( Vector(25.473,25.1512,68.5467) );
197 vectors.push_back( Vector(23.1644,24.1867,65.1272) );
198 createTriangle(vectors);
199 CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) );
200 }
201 {
202 delete triangle;
203 // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data
204 // failure is: Intersection (20.6787,70.655,71.5657) is not inside triangle [622|Na1197,Na2166,O3366].
205 // fix is lower LINALG_MYEPSILON (not std::numeric_limits<doubble>*100 but *1e-4)
206 const Vector testPoint(1.57318,14.185,61.2155);
207 const Vector testIntersection(20.67867516517798,70.65496977054023,71.56572984946152);
208 std::vector<Vector> vectors;
209 vectors.push_back( Vector(22.9592,68.7791,77.5907) );
210 vectors.push_back( Vector(18.4729,72.0386,68.08839999999999) );
211 vectors.push_back( Vector(20.3834,71.0154,70.1443) );
212 createTriangle(vectors);
213 CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) );
214 }
215 {
216 delete triangle;
217 // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data
218 // failure is:Intersection (27.56537519896,13.40256646925,6.672946688134) is not inside triangle [702|Na5016,O6388,Na6498].
219 // note that the Intersection cannot possibly lie be within the triangle!
220 // we test now against correct intersection
221 const Vector testIntersection(14.6872,36.204,39.8043);
222 std::vector<Vector> vectors;
223 vectors.push_back( Vector(10.7513,43.4247,48.4127) );
224 vectors.push_back( Vector(13.7119,37.0827,47.4203) );
225 vectors.push_back( Vector(14.6872,36.204,39.8043) );
226 createTriangle(vectors);
227 CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) );
228 }
229}
230
231/** UnitTest for Tesselation::GetClosestPointInsideTriangle()
232 *
233 * We check whether this function always returns a intersection inside the
234 * triangle.
235 *
236 */
237void TesselationBoundaryTriangleTest::GetClosestPointInsideTriangleTest()
238{
239 Vector TestIntersection;
240
241 {
242 // march through a cube mesh on triangle in xy plane
243 double n[3];
244 const double boundary = 4.;
245 const double step = 1.;
246 // go through the cube and check each point
247 for (n[0] = -boundary; n[0] <= boundary; n[0]+=step)
248 for (n[1] = -boundary; n[1] <= boundary; n[1]+=step)
249 for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) {
250 const Vector testPoint(n[0], n[1], n[2]);
251 triangle->GetClosestPointInsideTriangle(testPoint, TestIntersection);
252 CPPUNIT_ASSERT( triangle->IsInsideTriangle( TestIntersection ));
253 }
254 }
255
256 delete triangle;
257 // create better triangle;
258 VECTORSET(std::vector) Vectors;
259 Vectors.push_back( Vector(0., 0., 0.) );
260 Vectors.push_back( Vector(0., 1., 0.) );
261 Vectors.push_back( Vector(1., 0., 0.) );
262 RealSpaceMatrix M;
263 M.setRotation(M_PI/3., M_PI/4., 2.*M_PI/3.);
264 Vectors.transform(M);
265 createTriangle(Vectors);
266
267 {
268 // march through a cube mesh on rotated triangle
269 double n[3];
270 const double boundary = 4.;
271 const double step = 1.;
272 // go through the cube and check each point
273 for (n[0] = -boundary; n[0] <= boundary; n[0]+=step)
274 for (n[1] = -boundary; n[1] <= boundary; n[1]+=step)
275 for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) {
276 const Vector testPoint(n[0], n[1], n[2]);
277 triangle->GetClosestPointInsideTriangle(testPoint, TestIntersection);
278 CPPUNIT_ASSERT( triangle->IsInsideTriangle( TestIntersection ));
279 }
280 }
281}
282
283/** UnitTest for Tesselation::GetClosestPointInsideTriangle()
284 *
285 * We test for some specific points that occured in larger examples of the code.
286 *
287 */
288void TesselationBoundaryTriangleTest::GetClosestPointInsideTriangle_specificTest()
289{
290 {
291 delete triangle;
292 // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data
293 // failure is:Intersection (27.56537519896,13.40256646925,6.672946688134) is not inside triangle [702|Na5016,O6388,Na6498].
294 // note that the Intersection cannot possibly lie be within the triangle
295 // however, it is on its plane (off only by 2.7e-12)
296 // testPoint2 is corrected version
297 const Vector testPoint(27.56537519896,13.40256646925,6.672946688134);
298 const Vector testPoint2(14.6872,36.204,39.8043);
299 Vector testIntersection;
300 std::vector<Vector> vectors;
301 vectors.push_back( Vector(10.7513,43.4247,48.4127) );
302 vectors.push_back( Vector(13.7119,37.0827,47.4203) );
303 vectors.push_back( Vector(14.6872,36.204,39.8043) );
304 createTriangle(vectors);
305 triangle->GetClosestPointInsideTriangle(testPoint, testIntersection);
306 CPPUNIT_ASSERT ( testPoint != testIntersection );
307 CPPUNIT_ASSERT ( testPoint2 == testIntersection );
308 }
309}
310
311/** UnitTest for Tesselation::IsInnerPoint()
312 */
313void TesselationBoundaryTriangleTest::GetClosestPointOnPlaneTest()
314{
315 Vector TestIntersection;
316 Vector Point;
317
318 // simple test on y line
319 Point = Vector(-1.,0.5,0.);
320 CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
321 Point = Vector(0.,0.5,0.);
322 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
323 Point = Vector(-4.,0.5,0.);
324 CPPUNIT_ASSERT_EQUAL( 16., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
325 Point = Vector(0.,0.5,0.);
326 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
327
328 // simple test on x line
329 Point = Vector(0.5,-1.,0.);
330 CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
331 Point = Vector(0.5,0.,0.);
332 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
333 Point = Vector(0.5,-6.,0.);
334 CPPUNIT_ASSERT_EQUAL( 36., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
335 Point = Vector(0.5,0.,0.);
336 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
337
338 // simple test on slanted line
339 Point = Vector(1.,1.,0.);
340 CPPUNIT_ASSERT_EQUAL( 0.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
341 Point = Vector(0.5,0.5,0.);
342 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
343 Point = Vector(5.,5.,0.);
344 CPPUNIT_ASSERT_EQUAL( 40.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
345 Point = Vector(0.5,0.5,0.);
346 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
347
348 // simple test on first node
349 Point = Vector(-1.,-1.,0.);
350 CPPUNIT_ASSERT_EQUAL( 2., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
351 Point = Vector(0.,0.,0.);
352 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
353
354 // simple test on second node
355 Point = Vector(0.,2.,0.);
356 CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
357 Point = Vector(0.,1.,0.);
358 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
359
360 // simple test on third node
361 Point = Vector(2.,0.,0.);
362 CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
363 Point = Vector(1.,0.,0.);
364 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
365};
366
367/** UnitTest for Tesselation::IsInnerPoint()
368 */
369void TesselationBoundaryTriangleTest::GetClosestPointOffPlaneTest()
370{
371 Vector TestIntersection;
372 Vector Point;
373
374 // straight down/up
375 Point = Vector(1./3.,1./3.,+5.);
376 CPPUNIT_ASSERT_EQUAL( 25. , triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
377 Point = Vector(1./3.,1./3.,0.);
378 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
379 Point = Vector(1./3.,1./3.,-5.);
380 CPPUNIT_ASSERT_EQUAL( 25. , triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
381 Point = Vector(1./3.,1./3.,0.);
382 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
383
384 // simple test on y line
385 Point = Vector(-1.,0.5,+2.);
386 CPPUNIT_ASSERT_EQUAL( 5., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
387 Point = Vector(0.,0.5,0.);
388 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
389 Point = Vector(-1.,0.5,-3.);
390 CPPUNIT_ASSERT_EQUAL( 10., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
391 Point = Vector(0.,0.5,0.);
392 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
393
394 // simple test on x line
395 Point = Vector(0.5,-1.,+1.);
396 CPPUNIT_ASSERT_EQUAL( 2., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
397 Point = Vector(0.5,0.,0.);
398 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
399 Point = Vector(0.5,-1.,-2.);
400 CPPUNIT_ASSERT_EQUAL( 5., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
401 Point = Vector(0.5,0.,0.);
402 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
403
404 // simple test on slanted line
405 Point = Vector(1.,1.,+3.);
406 CPPUNIT_ASSERT_EQUAL( 9.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
407 Point = Vector(0.5,0.5,0.);
408 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
409 Point = Vector(1.,1.,-4.);
410 CPPUNIT_ASSERT_EQUAL( 16.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
411 Point = Vector(0.5,0.5,0.);
412 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
413
414 // simple test on first node
415 Point = Vector(-1.,-1.,5.);
416 CPPUNIT_ASSERT_EQUAL( 27., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
417 Point = Vector(0.,0.,0.);
418 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
419
420 // simple test on second node
421 Point = Vector(0.,2.,5.);
422 CPPUNIT_ASSERT_EQUAL( 26., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
423 Point = Vector(0.,1.,0.);
424 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
425
426 // simple test on third node
427 Point = Vector(2.,0.,5.);
428 CPPUNIT_ASSERT_EQUAL( 26., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) );
429 Point = Vector(1.,0.,0.);
430 CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection );
431};
Note: See TracBrowser for help on using the repository browser.