/* * 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" #include "LinearAlgebra/Line.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(6); } void SphericalPointDistributionTest::tearDown() { } /** 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 ); } } void perturbPolygon( SphericalPointDistribution::Polygon_t &_polygon, double _amplitude ) { for (SphericalPointDistribution::Polygon_t::iterator iter = _polygon.begin(); iter != _polygon.end(); ++iter) { Vector perturber; perturber.GetOneNormalVector((*iter)); perturber.Scale(_amplitude); *iter = *iter + perturber; (*iter).Normalize(); } } static bool areEqualToWithinBounds( const SphericalPointDistribution::Polygon_t &_polygon, const SphericalPointDistribution::Polygon_t &_otherpolygon, double _amplitude ) { // same size? if (_polygon.size() != _otherpolygon.size()) return false; // same points ? We just check witrh trivial mapping, nothing fancy ... bool status = true; SphericalPointDistribution::Polygon_t::const_iterator iter = _polygon.begin(); SphericalPointDistribution::Polygon_t::const_iterator otheriter = _otherpolygon.begin(); for (; iter != _polygon.end(); ++iter, ++otheriter) { status &= (*iter - *otheriter).Norm() < _amplitude; } return status; } /** UnitTest for areEqualToWithinBounds() */ void SphericalPointDistributionTest::areEqualToWithinBoundsTest() { // test with no points { SphericalPointDistribution::Polygon_t polygon; SphericalPointDistribution::Polygon_t expected = polygon; CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, std::numeric_limits::epsilon()*1e2) ); } // test with one point { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); SphericalPointDistribution::Polygon_t expected = polygon; CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, std::numeric_limits::epsilon()*1e2) ); } // test with two points { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t expected = polygon; CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, std::numeric_limits::epsilon()*1e2) ); } // test with two points in different order: THIS GOES WRONG: We only check trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t expected; expected += Vector(0.,1.,0.); expected += Vector(1.,0.,0.); CPPUNIT_ASSERT( !areEqualToWithinBounds(polygon, expected, std::numeric_limits::epsilon()*1e2) ); } // test with two different points { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t expected; expected += Vector(1.01,0.,0.); expected += Vector(0.,1.,0.); CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, 0.05) ); CPPUNIT_ASSERT( !areEqualToWithinBounds(polygon, expected, 0.005) ); } // test with different number of points { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.); polygon += Vector(0.,1.,0.); SphericalPointDistribution::Polygon_t expected; expected += Vector(0.,1.,0.); CPPUNIT_ASSERT( !areEqualToWithinBounds(polygon, expected, 0.05) ); } } /** 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 ); } // test with two points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-0.5, sqrt(3)*0.5,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<3>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, 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), RotationAxis.rotateVector(Vector(-0.5, sqrt(3)*0.5,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<3>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-0.5, sqrt(3)*0.5,0.), Vector(-0.5, -sqrt(3)*0.5,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<3>(); SphericalPointDistribution::Polygon_t expected; // empty cause none are vacant SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, 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), RotationAxis.rotateVector(Vector(-0.5, sqrt(3)*0.5,0.), 47.6/180*M_PI), RotationAxis.rotateVector(Vector(-0.5, -sqrt(3)*0.5,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<3>(); SphericalPointDistribution::Polygon_t expected; // empty cause none are vacant SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } } /** 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 ); } // test with two points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1./3.0, 2.0*M_SQRT2/3.0,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, matching trivially, also with slightly perturbed { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1./3.0, 2.0*M_SQRT2/3.0,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, 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), RotationAxis.rotateVector(Vector(-1./3.0, 2.0*M_SQRT2/3.0,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1./3.0, 2.0*M_SQRT2/3.0,0.), Vector(-1./3.0, -M_SQRT2/3.0, M_SQRT2/sqrt(3)); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, 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), RotationAxis.rotateVector(Vector(-1./3.0, 2.0*M_SQRT2/3.0,0.), 47.6/180*M_PI), RotationAxis.rotateVector(Vector(-1./3.0, -M_SQRT2/3.0, M_SQRT2/sqrt(3)), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<4>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } } /** 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 ); } // test with two points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<5>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, 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), RotationAxis.rotateVector(Vector(-1.,0.,0.), 47.6/180.*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<5>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180.*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); // the three remaining points sit on a plane that may be rotated arbitrarily // so we cannot simply check for equality between expected and remaining // hence, we just check that they are orthogonal to the first two points CPPUNIT_ASSERT_EQUAL( expected.size(), remaining.size() ); for (SphericalPointDistribution::Polygon_t::const_iterator fixiter = polygon.begin(); fixiter != polygon.end(); ++fixiter) { for (SphericalPointDistribution::Polygon_t::const_iterator iter = remaining.begin(); iter != remaining.end(); ++iter) { CPPUNIT_ASSERT( (*fixiter).IsNormalTo(*iter) ); } } } // test with three points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1., 0.0, 0.0), Vector(0.0, 1., 0.0); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<5>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, 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), RotationAxis.rotateVector(Vector(-1., 0.0, 0.0), 47.6/180*M_PI), RotationAxis.rotateVector(Vector(0.0, 1., 0.0), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<5>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } } /** 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 ); } // test with two points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<6>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second spoint SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, 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), RotationAxis.rotateVector(Vector(-1.,0.,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<6>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second spoint for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); // the four remaining points sit on a plane that may have been rotated arbitrarily // so we cannot simply check for equality between expected and remaining // hence, we just check that they are orthogonal to the first two points CPPUNIT_ASSERT_EQUAL( expected.size(), remaining.size() ); for (SphericalPointDistribution::Polygon_t::const_iterator fixiter = polygon.begin(); fixiter != polygon.end(); ++fixiter) { for (SphericalPointDistribution::Polygon_t::const_iterator iter = remaining.begin(); iter != remaining.end(); ++iter) { CPPUNIT_ASSERT( (*fixiter).IsNormalTo(*iter) ); } } } // test with three points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1., 0.0, 0.0), Vector(0.0, 1., 0.0); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<6>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, 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), RotationAxis.rotateVector(Vector(-1., 0.0, 0.0), 47.6/180*M_PI), RotationAxis.rotateVector(Vector(0.0, 1., 0.0), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<6>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } } /** 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 ); } // test with two points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<7>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, 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), RotationAxis.rotateVector(Vector(-1.,0.,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<7>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); // the five remaining points sit on a plane that may have been rotated arbitrarily // so we cannot simply check for equality between expected and remaining // hence, we just check that they are orthogonal to the first two points CPPUNIT_ASSERT_EQUAL( expected.size(), remaining.size() ); for (SphericalPointDistribution::Polygon_t::const_iterator fixiter = polygon.begin(); fixiter != polygon.end(); ++fixiter) { for (SphericalPointDistribution::Polygon_t::const_iterator iter = remaining.begin(); iter != remaining.end(); ++iter) { CPPUNIT_ASSERT( (*fixiter).IsNormalTo(*iter) ); } } } // test with three points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1., 0.0, 0.0), Vector(0.0, 1., 0.0); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<7>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, 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), RotationAxis.rotateVector(Vector(-1., 0.0, 0.0), 47.6/180*M_PI), RotationAxis.rotateVector(Vector(0.0, 1., 0.0), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<7>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } } /** 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 ); } // test with two points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1.,0.,0.); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<8>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with two points, 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), RotationAxis.rotateVector(Vector(-1.,0.,0.), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<8>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); // the six remaining points sit on two planes that may have been rotated arbitrarily // so we cannot simply check for equality between expected and remaining // hence, we just check that they are orthogonal to the first two points CPPUNIT_ASSERT_EQUAL( expected.size(), remaining.size() ); for (SphericalPointDistribution::Polygon_t::const_iterator fixiter = polygon.begin(); fixiter != polygon.end(); ++fixiter) { SphericalPointDistribution::Polygon_t::const_iterator expectiter = expected.begin(); SphericalPointDistribution::Polygon_t::const_iterator remainiter = remaining.begin(); for (;remainiter != remaining.end(); ++expectiter, ++remainiter) { // check that points in expected/remaining have same angle to the given ones // CPPUNIT_ASSERT_EQUAL( (*expectiter).Angle(*fixiter), (*remainiter).Angle(*fixiter) ); CPPUNIT_ASSERT( fabs( (*expectiter).Angle(*fixiter) - (*remainiter).Angle(*fixiter) ) < std::numeric_limits::epsilon()*1e4 ); } } } // test with three points, matching trivially { SphericalPointDistribution::Polygon_t polygon; polygon += Vector(1.,0.,0.), Vector(-1., 0.0, 0.0), Vector(-1./3.0, 2.0*M_SQRT2/3.0, 0.0); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<8>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } // test with three points, 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), RotationAxis.rotateVector(Vector(-1., 0.0, 0.0), 47.6/180*M_PI), RotationAxis.rotateVector(Vector(-1./3.0, 2.0*M_SQRT2/3.0, 0.0), 47.6/180*M_PI); SphericalPointDistribution::Polygon_t newpolygon = SPD.get<8>(); SphericalPointDistribution::Polygon_t expected = newpolygon; expected.pop_front(); // remove first point expected.pop_front(); // remove second point expected.pop_front(); // remove third point for (SphericalPointDistribution::Polygon_t::iterator iter = expected.begin(); iter != expected.end(); ++iter) *iter = RotationAxis.rotateVector(*iter, 47.6/180*M_PI); SphericalPointDistribution::Polygon_t remaining = SphericalPointDistribution::matchSphericalPointDistributions( polygon, newpolygon); CPPUNIT_ASSERT_EQUAL( expected, remaining ); // also slightly perturbed const double amplitude = 0.05; perturbPolygon(polygon, amplitude); CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); } }