/* * Copyright (c) 2014, Chris Rogers * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STFC nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <algorithm> #include "gtest/gtest.h" #include "opal_src/Utilities/MockComponent.h" #include "Physics/Physics.h" #include "Utilities/RingSection.h" #include "opal_test_utilities/SilenceTest.h" TEST(RingSectionTest, TestConstructDestruct) { OpalTestUtilities::SilenceTest silencer; RingSection ors; MockComponent* compNull = NULL; Vector_t vec0(0, 0, 0); EXPECT_EQ(ors.getComponent(), compNull); EXPECT_EQ(ors.getStartPosition(), vec0); EXPECT_EQ(ors.getStartNormal(), vec0); EXPECT_EQ(ors.getEndPosition(), vec0); EXPECT_EQ(ors.getEndNormal(), vec0); EXPECT_EQ(ors.getComponentPosition(), vec0); EXPECT_EQ(ors.getComponentOrientation(), vec0); EXPECT_EQ(ors.getVirtualBoundingBox(), std::vector<Vector_t>(4, vec0)); RingSection ors_comp; MockComponent comp; ors_comp.setComponent(&comp); // and implicit destructors; should not double free comp; } TEST(RingSectionTest, TestIsOnOrPastStartPlane) { OpalTestUtilities::SilenceTest silencer; RingSection ors; ors.setStartPosition(Vector_t(0., 1., 0.)); ors.setStartNormal(Vector_t(1., 0., 0.)); Vector_t vec1(1e-9, 1.e-9, 0.); Vector_t vec2(-1e-9, 1.e-9, 0.); Vector_t vec3(1e-9, -1.e-9, 0.); // other side of the ring Vector_t vec4(-1e-9, -1.e-9, 0.); // other side of the ring Vector_t vec5(1e-9, 1.e9, 0.); // large radius Vector_t vec6(-1e-9, 1.e9, 0.); // large radius EXPECT_TRUE(ors.isOnOrPastStartPlane(vec1)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec2)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec3)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec4)); EXPECT_TRUE(ors.isOnOrPastStartPlane(vec5)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec6)); ors.setStartNormal(Vector_t(-1., 0., 0.)); // rotate 180 degrees EXPECT_FALSE(ors.isOnOrPastStartPlane(vec1)); EXPECT_TRUE(ors.isOnOrPastStartPlane(vec2)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec3)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec4)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec5)); EXPECT_TRUE(ors.isOnOrPastStartPlane(vec6)); ors.setStartPosition(Vector_t(-1., -1., 0.)); ors.setStartNormal(Vector_t(1., -0.5, 0.)); Vector_t vec7(-1.1e-9, 1.e-9, 0.); // this side of the ring Vector_t vec8(-0.9e-9, 1.e-9, 0.); // other side of the ring Vector_t vec9(-0.5-1e-9, 0., 0.); // behind normal Vector_t vec10(-0.5+1e-9, 0., 0.); // in front of normal EXPECT_TRUE(ors.isOnOrPastStartPlane(vec7)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec8)); EXPECT_FALSE(ors.isOnOrPastStartPlane(vec9)); EXPECT_TRUE(ors.isOnOrPastStartPlane(vec10)); } TEST(RingSectionTest, TestIsPastEndPlane) { OpalTestUtilities::SilenceTest silencer; RingSection ors; ors.setEndPosition(Vector_t(0., 1., 0.)); ors.setEndNormal(Vector_t(1., 0., 0.)); Vector_t vec1(1e-9, 1.e-9, 0.); Vector_t vec2(-1e-9, 1.e-9, 0.); Vector_t vec3(1e-9, -1.e-9, 0.); // other side of the ring Vector_t vec4(-1e-9, -1.e-9, 0.); // other side of the ring Vector_t vec5(1e-9, 1.e9, 0.); // large radius Vector_t vec6(-1e-9, 1.e9, 0.); // large radius EXPECT_TRUE(ors.isPastEndPlane(vec1)); EXPECT_FALSE(ors.isPastEndPlane(vec2)); EXPECT_FALSE(ors.isPastEndPlane(vec3)); EXPECT_FALSE(ors.isPastEndPlane(vec4)); EXPECT_TRUE(ors.isPastEndPlane(vec5)); EXPECT_FALSE(ors.isPastEndPlane(vec6)); ors.setEndNormal(Vector_t(-1., 0., 0.)); // rotate 180 degrees EXPECT_FALSE(ors.isPastEndPlane(vec1)); EXPECT_TRUE(ors.isPastEndPlane(vec2)); EXPECT_FALSE(ors.isPastEndPlane(vec3)); EXPECT_FALSE(ors.isPastEndPlane(vec4)); EXPECT_FALSE(ors.isPastEndPlane(vec5)); EXPECT_TRUE(ors.isPastEndPlane(vec6)); ors.setEndPosition(Vector_t(-1., -1., 0.)); ors.setEndNormal(Vector_t(1., -0.5, 0.)); Vector_t vec7(-1.1e-9, 1.e-9, 0.); // this side of the ring Vector_t vec8(-0.9e-9, 1.e-9, 0.); // other side of the ring Vector_t vec9(-0.5-1e-9, 0., 0.); // behind normal Vector_t vec10(-0.5+1e-9, 0., 0.); // in front of normal EXPECT_TRUE(ors.isPastEndPlane(vec7)); EXPECT_FALSE(ors.isPastEndPlane(vec8)); EXPECT_FALSE(ors.isPastEndPlane(vec9)); EXPECT_TRUE(ors.isPastEndPlane(vec10)); } TEST(RingSectionTest, TestGetFieldValue) { OpalTestUtilities::SilenceTest silencer; RingSection ors; MockComponent comp; ors.setComponent(&comp); Vector_t centre(-1.33, +1.66, 0.); for (double theta = -3.*Physics::pi; theta < 3.*Physics::pi; theta += Physics::pi/6.) { Vector_t orientation(0., 0., theta); ors.setComponentOrientation(orientation); ors.setComponentPosition(centre); double c = cos(orientation(2)); double s = -sin(orientation(2)); for (double x = 0.01; x < 1.; x += 0.1) for (double y = 0.01; y < 1.; y += 0.1) for (double z = -0.01; z > -1.; z -= 0.1) { Vector_t offset(c*x+s*y, -s*x+c*y, z); Vector_t pos = centre+offset; Vector_t centroid, B, E; double t = 0; EXPECT_FALSE(ors.getFieldValue(pos, centroid, t, E, B)); Vector_t bfield(c*x+s*y, -s*x+c*y, z); for (int l = 0; l < 3; ++l) { EXPECT_NEAR(B(l), +bfield(l), 1e-6); EXPECT_NEAR(E(l), -bfield(l), 1e-6); } } } } bool sort_comparator(Vector_t v1, Vector_t v2) { if (fabs(v1(0) - v2(0)) < 1e-6) { if (fabs(v1(1) - v2(1)) < 1e-6) { return v1(2) > v2(2); } return v1(1) > v2(1); } return v1(0) > v2(0); } TEST(RingSectionTest, TestGetVirtualBoundingBox) { OpalTestUtilities::SilenceTest silencer; RingSection ors; ors.setStartPosition(Vector_t(3, -1, 99)); ors.setStartNormal(Vector_t(-4, -1, -1000)); ors.setEndPosition(Vector_t(2, 1, 77)); ors.setEndNormal(Vector_t(-1, 1, 655)); std::vector<Vector_t> bb = ors.getVirtualBoundingBox(); std::vector<Vector_t> bbRef; bbRef.push_back(Vector_t(0.99*sqrt(10)/(-sqrt(17))+3., 0.99*sqrt(10)*4./(+sqrt(17))-1., 99.)); bbRef.push_back(Vector_t(0.99*sqrt(10)/(+sqrt(17))+3., 0.99*sqrt(10)*4./(-sqrt(17))-1., 99.)); bbRef.push_back(Vector_t(0.99*sqrt(5)/(+sqrt(2))+2., 0.99*sqrt(5)/(+sqrt(2))+1., 77.)); bbRef.push_back(Vector_t(0.99*sqrt(5)/(-sqrt(2))+2., 0.99*sqrt(5)/(-sqrt(2))+1., 77.)); std::sort(bb.begin(), bb.end(), sort_comparator); std::sort(bbRef.begin(), bbRef.end(), sort_comparator); EXPECT_EQ(bb.size(), bbRef.size()); for (size_t i = 0; i < bb.size(); ++i) { for (size_t j = 0; j < 3; ++j) EXPECT_NEAR(bb[i](j), bbRef[i](j), 1e-6); } } RingSection buildORS(double r, double phi1, double phi2) { RingSection ors; ors.setStartPosition(Vector_t(sin(phi1)*r, cos(phi1)*r, 0.)); ors.setStartNormal(Vector_t(cos(phi1), -sin(phi1), 0.)); ors.setEndPosition(Vector_t(sin(phi2)*r, cos(phi2)*r, 0.)); ors.setEndNormal(Vector_t(cos(phi2), -sin(phi2), 0.)); return ors; } TEST(RingSectionTest, TestDoesOverlap) { OpalTestUtilities::SilenceTest silencer; double f1 = 1.0*Physics::pi/6.; double f2 = 0.5*Physics::pi/6.; double f3 = -0.5*Physics::pi/6.; double f4 = -1.0*Physics::pi/6.; double r = 3.; RingSection ors1 = buildORS(r, f1, f3); EXPECT_TRUE(ors1.doesOverlap(f2, f2)); EXPECT_FALSE(ors1.doesOverlap(f4, f4)); RingSection ors2 = buildORS(r, f1, f4); EXPECT_TRUE(ors2.doesOverlap(f2, f3)); RingSection ors3 = buildORS(r, f2, f3); EXPECT_TRUE(ors3.doesOverlap(f2, f3)); EXPECT_FALSE(ors3.doesOverlap(f1, f1)); EXPECT_FALSE(ors3.doesOverlap(f4, f4)); }