/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2014 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * SphericalPointDistributionUnitTest.cpp * * Created on: May 29, 2014 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif using namespace std; #include #include #include // include headers that implement a archive in simple text format #include #include #include "SphericalPointDistributionUnitTest.hpp" #include #include #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "LinearAlgebra/Line.hpp" #include "Fragmentation/Exporters/SphericalPointDistribution.hpp" #ifdef HAVE_TESTRUNNER #include "UnitTestMain.hpp" #endif /*HAVE_TESTRUNNER*/ using namespace boost::assign; /********************************************** Test classes **************************************/ // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( SphericalPointDistributionTest ); void SphericalPointDistributionTest::setUp() { // failing asserts should be thrown ASSERT_DO(Assert::Throw); setVerbosity(5); } void SphericalPointDistributionTest::tearDown() { } void SphericalPointDistributionTest::QuaternionTest() { Vector oldCenter(0.,1.,0.); Vector newCenter(1.,0.,0.); { // setup quaternion Vector RotationAxis = newCenter; RotationAxis.VectorProduct(oldCenter); RotationAxis.Normalize(); const double RotationAngle = oldCenter.Angle(newCenter)/(M_PI/2.); // RotationAxis.Angle(oldCenter) - RotationAxis.Angle(newCenter); boost::math::quaternion q (RotationAngle, RotationAxis[0], RotationAxis[1], RotationAxis[2]); LOG(5, "DEBUG: RotationAxis is " << RotationAxis << ", RotationAngle is " << RotationAngle); LOG(5, "DEBUG: Quaternion describing rotation is " << q); boost::math::quaternion q_inverse = boost::math::conj(q)/(boost::math::norm(q)); LOG(5, "DEBUG: Quaternion inverse is " << q_inverse); boost::math::quaternion identity(1,0,0,0); const boost::math::quaternion unity = q*q_inverse; LOG(5, "DEBUG: q * q^-1 is " << unity); CPPUNIT_ASSERT( boost::math::norm(unity - identity) < std::numeric_limits::epsilon()*1e4); // check that rotation works boost::math::quaternion p(0., newCenter[0], newCenter[1], newCenter[2]); LOG(5, "DEBUG: Original newCenter is " << p); p = p * q_inverse; p = q * p; LOG(5, "DEBUG: Rotated newCenter is " << p); boost::math::quaternion comparison(0., -oldCenter[0], oldCenter[1], oldCenter[2]); LOG(5, "DEBUG: Difference norm is " << boost::math::norm(p - comparison)); CPPUNIT_ASSERT( boost::math::norm(p - comparison) < std::numeric_limits::epsilon()*1e4); } // rotating with angle = 0 flips the vector unwantedly { // setup quaternion Vector RotationAxis = newCenter; RotationAxis.VectorProduct(oldCenter); RotationAxis.Normalize(); const double RotationAngle = 0.; // RotationAxis.Angle(oldCenter) - RotationAxis.Angle(newCenter); boost::math::quaternion q (RotationAngle, RotationAxis[0], RotationAxis[1], RotationAxis[2]); LOG(5, "DEBUG: RotationAxis is " << RotationAxis << ", RotationAngle is " << RotationAngle); LOG(5, "DEBUG: Quaternion describing rotation is " << q); boost::math::quaternion q_inverse = boost::math::conj(q)/(boost::math::norm(q)); LOG(5, "DEBUG: Quaternion inverse is " << q_inverse); boost::math::quaternion identity(1,0,0,0); const boost::math::quaternion unity = q*q_inverse; LOG(5, "DEBUG: q * q^-1 is " << unity); CPPUNIT_ASSERT( boost::math::norm(unity - identity) < std::numeric_limits::epsilon()*1e4); // check that rotation works boost::math::quaternion p(0., newCenter[0], newCenter[1], newCenter[2]); boost::math::quaternion comparison(0., -newCenter[0], newCenter[1], newCenter[2]); LOG(5, "DEBUG: Original newCenter is " << p); p = p * q_inverse; p = q * p; LOG(5, "DEBUG: Rotated newCenter is " << p); LOG(5, "DEBUG: Difference norm is " << boost::math::norm(p - comparison)); CPPUNIT_ASSERT( boost::math::norm(p - comparison) < std::numeric_limits::epsilon()*1e4); } } /** UnitTest for matchSphericalPointDistributions() with two points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_2() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<2>(); SphericalPointDistribution::Polygon_t expected; expected += Vector(-1.,0.,0.); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<2>(); SphericalPointDistribution::Polygon_t expected; expected += Vector(0.,-1.,0.); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip to another axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,0.,-1.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<2>(); SphericalPointDistribution::Polygon_t expected; expected += Vector(0.,0.,1.); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, full rotation { Line RotationAxis(zeroVec, Vector(0.2, 0.43, 0.6893248)); SphericalPointDistribution::Polygon_t polygon; polygon += RotationAxis.rotateVector(Vector(1.,0.,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<2>(); SphericalPointDistribution::Polygon_t expected; expected += RotationAxis.rotateVector(Vector(-1.,0.,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } } /** UnitTest for matchSphericalPointDistributions() with three points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_3() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<3>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of x and y axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<3>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) { std::swap((*iter)[0], (*iter)[1]); (*iter)[0] *= -1.; } SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } } /** UnitTest for matchSphericalPointDistributions() with four points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_4() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) { std::swap((*iter)[0], (*iter)[1]); (*iter)[0] *= -1.; } SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } } /** UnitTest for matchSphericalPointDistributions() with five points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_5() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<5>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<5>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) { std::swap((*iter)[0], (*iter)[1]); (*iter)[0] *= -1.; } SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } } /** UnitTest for matchSphericalPointDistributions() with six points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_6() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<6>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<6>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) { std::swap((*iter)[0], (*iter)[1]); (*iter)[0] *= -1.; } SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } } /** UnitTest for matchSphericalPointDistributions() with seven points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_7() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<7>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<7>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) { std::swap((*iter)[0], (*iter)[1]); (*iter)[0] *= -1.; } SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } } /** UnitTest for matchSphericalPointDistributions() with eight points */ void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_8() { SphericalPointDistribution SPD(1.); // test with one point, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<8>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } // test with one point, just a flip of axis { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<8>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) { std::swap((*iter)[0], (*iter)[1]); (*iter)[0] *= -1.; } SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); } }