/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * Tesselation_BoundaryTriangleUnitTest.cpp * * Created on: Jan 13, 2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif using namespace std; #include #include #include #include #include #include "CodePatterns/Log.hpp" #include "Helpers/defs.hpp" #include "Atom/TesselPoint.hpp" #include "LinearAlgebra/Plane.hpp" #include "LinearAlgebra/RealSpaceMatrix.hpp" #include "LinearAlgebra/VectorSet.hpp" #include "Tesselation/BoundaryPointSet.hpp" #include "Tesselation/BoundaryLineSet.hpp" #include "Tesselation/BoundaryTriangleSet.hpp" #include "Tesselation/CandidateForTesselation.hpp" #include "Tesselation_BoundaryTriangleUnitTest.hpp" #ifdef HAVE_TESTRUNNER #include "UnitTestMain.hpp" #endif /*HAVE_TESTRUNNER*/ const double TesselationBoundaryTriangleTest::SPHERERADIUS=2.; /********************************************** Test classes **************************************/ // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( TesselationBoundaryTriangleTest ); void TesselationBoundaryTriangleTest::createTriangle(const std::vector &Vectors) { CPPUNIT_ASSERT_EQUAL( (size_t)3, Vectors.size() ); // create nodes for (size_t count = 0; count < NDIM; ++count) { tesselpoints[count] = new TesselPoint; tesselpoints[count]->setPosition( Vectors[count] ); tesselpoints[count]->setName(toString(count)); tesselpoints[count]->setNr(count); points[count] = new BoundaryPointSet(tesselpoints[count]); } // create line lines[0] = new BoundaryLineSet(points[0], points[1], 0); lines[1] = new BoundaryLineSet(points[1], points[2], 1); lines[2] = new BoundaryLineSet(points[0], points[2], 2); // create triangle triangle = new BoundaryTriangleSet(lines, 0); Plane p(Vectors[0], Vectors[1], Vectors[2]); triangle->GetNormalVector(p.getNormal()); } void TesselationBoundaryTriangleTest::setUp() { setVerbosity(5); // create nodes std::vector Vectors; Vectors.push_back( Vector(0., 0., 0.) ); Vectors.push_back( Vector(0., 1., 0.) ); Vectors.push_back( Vector(1., 0., 0.) ); // create triangle createTriangle(Vectors); } void TesselationBoundaryTriangleTest::tearDown() { delete(triangle); for (int i=0;i<3;++i) { // TesselPoint does not delete its vector as it only got a reference delete tesselpoints[i]; } logger::purgeInstance(); errorLogger::purgeInstance(); } /** UnitTest for Tesselation::IsInsideTriangle() */ void TesselationBoundaryTriangleTest::IsInsideTriangleTest() { // inside points { // check each endnode for (size_t i=0; i< NDIM; ++i) { const Vector testPoint(triangle->endpoints[i]->node->getPosition()); LOG(1, "INFO: Testing whether " << testPoint << " is an inner point."); CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint ) ); } } { // check points along each BoundaryLine for (size_t i=0; i< NDIM; ++i) { Vector offset = triangle->endpoints[i%3]->node->getPosition(); Vector direction = triangle->endpoints[(i+1)%3]->node->getPosition() - offset; for (double s = 0.1; s < 1.; s+= 0.1) { Vector testPoint = offset + s*direction; LOG(1, "INFO: Testing whether " << testPoint << " is an inner point."); CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint ) ); } } } { // check central point Vector center; triangle->GetCenter(center); LOG(1, "INFO: Testing whether " << center << " is an inner point."); CPPUNIT_ASSERT( triangle->IsInsideTriangle( center ) ); } // outside points { // check points outside (i.e. those not in xy-plane through origin) double n[3]; const double boundary = 4.; const double step = 1.; // go through the cube and check each point for (n[0] = -boundary; n[0] <= boundary; n[0]+=step) for (n[1] = -boundary; n[1] <= boundary; n[1]+=step) for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) { const Vector testPoint(n[0], n[1], n[2]); if (n[2] != 0) { LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point."); CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint ) ); } } } { // check points within the plane but outside of triangle double n[3]; const double boundary = 4.; const double step = 1.; n[2] = 0; for (n[0] = -boundary; n[0] <= boundary; n[0]+=step) for (n[1] = -boundary; n[1] <= boundary; n[1]+=step) { const Vector testPoint(n[0], n[1], n[2]); if ((n[0] >=0) && (n[1] >=0) && (n[0]<=1) && (n[1]<=1)) { if (n[0]+n[1] <= 1) { LOG(1, "INFO: Testing whether " << testPoint << " is an inner point."); CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint) ); } else { LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point."); CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint) ); } } else { LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point."); CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint) ); } } } } /** UnitTest for Tesselation::IsInsideTriangle() * * We test for some specific points that occured in larger examples of the code. * */ void TesselationBoundaryTriangleTest::IsInsideTriangle_specificTest() { { delete triangle; // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data // failure is: Intersection (23.1644,24.1867,65.1272) is not inside triangle [659|Na2451,O3652,Na3762]. const Vector testPoint(1.57318,1.57612,10.9874); const Vector testIntersection(23.1644,24.1867,65.1272); std::vector vectors; vectors.push_back( Vector(23.0563,30.4673,73.7555) ); vectors.push_back( Vector(25.473,25.1512,68.5467) ); vectors.push_back( Vector(23.1644,24.1867,65.1272) ); createTriangle(vectors); CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) ); } { delete triangle; // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data // failure is: Intersection (20.6787,70.655,71.5657) is not inside triangle [622|Na1197,Na2166,O3366]. // fix is lower LINALG_MYEPSILON (not std::numeric_limits*100 but *1e-4) const Vector testPoint(1.57318,14.185,61.2155); const Vector testIntersection(20.67867516517798,70.65496977054023,71.56572984946152); std::vector vectors; vectors.push_back( Vector(22.9592,68.7791,77.5907) ); vectors.push_back( Vector(18.4729,72.0386,68.08839999999999) ); vectors.push_back( Vector(20.3834,71.0154,70.1443) ); createTriangle(vectors); CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) ); } { delete triangle; // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data // failure is:Intersection (27.56537519896,13.40256646925,6.672946688134) is not inside triangle [702|Na5016,O6388,Na6498]. // note that the Intersection cannot possibly lie be within the triangle! // we test now against correct intersection const Vector testIntersection(14.6872,36.204,39.8043); std::vector vectors; vectors.push_back( Vector(10.7513,43.4247,48.4127) ); vectors.push_back( Vector(13.7119,37.0827,47.4203) ); vectors.push_back( Vector(14.6872,36.204,39.8043) ); createTriangle(vectors); CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) ); } } /** UnitTest for Tesselation::GetClosestPointInsideTriangle() * * We check whether this function always returns a intersection inside the * triangle. * */ void TesselationBoundaryTriangleTest::GetClosestPointInsideTriangleTest() { Vector TestIntersection; { // march through a cube mesh on triangle in xy plane double n[3]; const double boundary = 4.; const double step = 1.; // go through the cube and check each point for (n[0] = -boundary; n[0] <= boundary; n[0]+=step) for (n[1] = -boundary; n[1] <= boundary; n[1]+=step) for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) { const Vector testPoint(n[0], n[1], n[2]); triangle->GetClosestPointInsideTriangle(testPoint, TestIntersection); CPPUNIT_ASSERT( triangle->IsInsideTriangle( TestIntersection )); } } delete triangle; // create better triangle; VECTORSET(std::vector) Vectors; Vectors.push_back( Vector(0., 0., 0.) ); Vectors.push_back( Vector(0., 1., 0.) ); Vectors.push_back( Vector(1., 0., 0.) ); RealSpaceMatrix M; M.setRotation(M_PI/3., M_PI/4., 2.*M_PI/3.); Vectors.transform(M); createTriangle(Vectors); { // march through a cube mesh on rotated triangle double n[3]; const double boundary = 4.; const double step = 1.; // go through the cube and check each point for (n[0] = -boundary; n[0] <= boundary; n[0]+=step) for (n[1] = -boundary; n[1] <= boundary; n[1]+=step) for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) { const Vector testPoint(n[0], n[1], n[2]); triangle->GetClosestPointInsideTriangle(testPoint, TestIntersection); CPPUNIT_ASSERT( triangle->IsInsideTriangle( TestIntersection )); } } } /** UnitTest for Tesselation::GetClosestPointInsideTriangle() * * We test for some specific points that occured in larger examples of the code. * */ void TesselationBoundaryTriangleTest::GetClosestPointInsideTriangle_specificTest() { { delete triangle; // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data // failure is:Intersection (27.56537519896,13.40256646925,6.672946688134) is not inside triangle [702|Na5016,O6388,Na6498]. // note that the Intersection cannot possibly lie be within the triangle // however, it is on its plane (off only by 2.7e-12) // testPoint2 is corrected version const Vector testPoint(27.56537519896,13.40256646925,6.672946688134); const Vector testPoint2(14.6872,36.204,39.8043); Vector testIntersection; std::vector vectors; vectors.push_back( Vector(10.7513,43.4247,48.4127) ); vectors.push_back( Vector(13.7119,37.0827,47.4203) ); vectors.push_back( Vector(14.6872,36.204,39.8043) ); createTriangle(vectors); triangle->GetClosestPointInsideTriangle(testPoint, testIntersection); CPPUNIT_ASSERT ( testPoint != testIntersection ); CPPUNIT_ASSERT ( testPoint2 == testIntersection ); } } /** UnitTest for Tesselation::IsInnerPoint() */ void TesselationBoundaryTriangleTest::GetClosestPointOnPlaneTest() { Vector TestIntersection; Vector Point; // simple test on y line Point = Vector(-1.,0.5,0.); CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(-4.,0.5,0.); CPPUNIT_ASSERT_EQUAL( 16., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on x line Point = Vector(0.5,-1.,0.); CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(0.5,-6.,0.); CPPUNIT_ASSERT_EQUAL( 36., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on slanted line Point = Vector(1.,1.,0.); CPPUNIT_ASSERT_EQUAL( 0.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(5.,5.,0.); CPPUNIT_ASSERT_EQUAL( 40.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on first node Point = Vector(-1.,-1.,0.); CPPUNIT_ASSERT_EQUAL( 2., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on second node Point = Vector(0.,2.,0.); CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,1.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on third node Point = Vector(2.,0.,0.); CPPUNIT_ASSERT_EQUAL( 1., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(1.,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); }; /** UnitTest for Tesselation::IsInnerPoint() */ void TesselationBoundaryTriangleTest::GetClosestPointOffPlaneTest() { Vector TestIntersection; Vector Point; // straight down/up Point = Vector(1./3.,1./3.,+5.); CPPUNIT_ASSERT_EQUAL( 25. , triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(1./3.,1./3.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(1./3.,1./3.,-5.); CPPUNIT_ASSERT_EQUAL( 25. , triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(1./3.,1./3.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on y line Point = Vector(-1.,0.5,+2.); CPPUNIT_ASSERT_EQUAL( 5., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(-1.,0.5,-3.); CPPUNIT_ASSERT_EQUAL( 10., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on x line Point = Vector(0.5,-1.,+1.); CPPUNIT_ASSERT_EQUAL( 2., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(0.5,-1.,-2.); CPPUNIT_ASSERT_EQUAL( 5., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on slanted line Point = Vector(1.,1.,+3.); CPPUNIT_ASSERT_EQUAL( 9.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); Point = Vector(1.,1.,-4.); CPPUNIT_ASSERT_EQUAL( 16.5, triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.5,0.5,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on first node Point = Vector(-1.,-1.,5.); CPPUNIT_ASSERT_EQUAL( 27., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on second node Point = Vector(0.,2.,5.); CPPUNIT_ASSERT_EQUAL( 26., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(0.,1.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); // simple test on third node Point = Vector(2.,0.,5.); CPPUNIT_ASSERT_EQUAL( 26., triangle->GetClosestPointInsideTriangle(Point, TestIntersection) ); Point = Vector(1.,0.,0.); CPPUNIT_ASSERT_EQUAL( true , Point == TestIntersection ); };