IAP GITLAB

Skip to content
Snippets Groups Projects
testGeometry.cc 4.8 KiB
Newer Older
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one
                          // cpp file
#include <catch2/catch.hpp>
#include <corsika/geometry/CoordinateSystem.h>
#include <corsika/geometry/Helix.h>
#include <corsika/geometry/LineTrajectory.h>
#include <corsika/geometry/Point.h>
#include <corsika/geometry/Sphere.h>
#include <corsika/geometry/Trajectory.h>
#include <corsika/units/PhysicalUnits.h>
#include <cmath>
using namespace corsika::geometry;
using namespace corsika::units;
TEST_CASE("transformations between CoordinateSystems") {
  CoordinateSystem rootCS;
  REQUIRE(CoordinateSystem::GetTransformation(rootCS, rootCS)
              .isApprox(EigenTransform::Identity()));
  corsika::QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m};
  Point p1(rootCS, coordinates);
  corsika::QuantityVector<magnetic_flux_density_d> components{1. * tesla, 0. * tesla,
                                                              0. * tesla};
  Vector<magnetic_flux_density_d> v1(rootCS, components);
  REQUIRE((p1.GetCoordinates() - coordinates).norm().magnitude() == Approx(0));
  REQUIRE((p1.GetCoordinates(rootCS) - coordinates).norm().magnitude() == Approx(0));

  SECTION("unconnected CoordinateSystems") {
    CoordinateSystem rootCS2;
    REQUIRE_THROWS(CoordinateSystem::GetTransformation(rootCS, rootCS2));
  }

  SECTION("translations") {
    corsika::QuantityVector<length_d> const translationVector{0_m, 4_m, 0_m};

    CoordinateSystem translatedCS = rootCS.translate(translationVector);

    REQUIRE(translatedCS.GetReference() == &rootCS);

    REQUIRE((p1.GetCoordinates(translatedCS) + translationVector).norm().magnitude() ==
            Approx(0));

    // Vectors are not subject to translations
    REQUIRE(
        (v1.GetComponents(rootCS) - v1.GetComponents(translatedCS)).norm().magnitude() ==
        Approx(0));

    Point p2(translatedCS, {0_m, 0_m, 0_m});
    REQUIRE(((p2 - p1).GetComponents() - translationVector).norm().magnitude() ==
            Approx(0));
  }

  SECTION("multiple translations") {
    corsika::QuantityVector<length_d> const tv1{0_m, 5_m, 0_m};
    CoordinateSystem cs2 = rootCS.translate(tv1);

    corsika::QuantityVector<length_d> const tv2{3_m, 0_m, 0_m};
    CoordinateSystem cs3 = rootCS.translate(tv2);

    corsika::QuantityVector<length_d> const tv3{0_m, 0_m, 2_m};
    CoordinateSystem cs4 = cs3.translate(tv3);

    REQUIRE(cs4.GetReference()->GetReference() == &rootCS);

    REQUIRE(CoordinateSystem::GetTransformation(cs3, cs2).isApprox(
        rootCS.translate({3_m, -5_m, 0_m}).GetTransform()));
    REQUIRE(CoordinateSystem::GetTransformation(cs2, cs3).isApprox(
        rootCS.translate({-3_m, +5_m, 0_m}).GetTransform()));
  }

  SECTION("rotations") {
    corsika::QuantityVector<length_d> const axis{0_m, 0_m, 1_km};
    double const angle = 90. / 180. * M_PI;

    CoordinateSystem rotatedCS = rootCS.rotate(axis, angle);
    REQUIRE(rotatedCS.GetReference() == &rootCS);

    REQUIRE(v1.GetComponents(rotatedCS)[1].magnitude() ==
            Approx((-1. * tesla).magnitude()));

    // vector norm invariant under rotation
    REQUIRE(v1.GetComponents(rotatedCS).norm().magnitude() ==
            Approx(v1.GetComponents(rootCS).norm().magnitude()));
  }

  SECTION("multiple rotations") {
    corsika::QuantityVector<length_d> const zAxis{0_m, 0_m, 1_km};
    corsika::QuantityVector<length_d> const yAxis{0_m, 7_nm, 0_m};
    corsika::QuantityVector<length_d> const xAxis{2_m, 0_nm, 0_m};

    double const angle = 90. / 180. * M_PI;

    CoordinateSystem rotated1 = rootCS.rotate(zAxis, angle);
    CoordinateSystem rotated2 = rotated1.rotate(yAxis, angle);
    CoordinateSystem rotated3 = rotated2.rotate(zAxis, -angle);

    CoordinateSystem combined = rootCS.rotate(xAxis, -angle);

    auto comp1 = v1.GetComponents(rootCS);
    auto comp3 = v1.GetComponents(combined);
    REQUIRE((comp1 - comp3).norm().magnitude() == Approx(0));
  }
TEST_CASE("Sphere") {
  CoordinateSystem rootCS;
  Point center(rootCS, {0_m, 3_m, 4_m});
  Sphere sphere(center, 5_m);

  SECTION("isInside") {
    REQUIRE_FALSE(sphere.isInside(Point(rootCS, {100_m, 0_m, 0_m})));
    REQUIRE(sphere.isInside(Point(rootCS, {2_m, 3_m, 4_m})));
  }

TEST_CASE("Trajectories") {
  CoordinateSystem rootCS;
  Point r0(rootCS, {0_m, 0_m, 0_m});

  SECTION("Line") {
    Vector<SpeedType::dimension_type> v0(rootCS,
                                         {1_m / second, 0_m / second, 0_m / second});

    LineTrajectory lineTrajectory(r0, v0);
    REQUIRE((lineTrajectory.GetPosition(2_s).GetCoordinates() -
             corsika::QuantityVector<length_d>(2_m, 0_m, 0_m))
                .norm()
                .magnitude() == Approx(0));

    BaseTrajectory* base = &lineTrajectory;
    REQUIRE(lineTrajectory.GetPosition(2_s).GetCoordinates() ==
            base->GetPosition(2_s).GetCoordinates());
  }
}