diff --git a/corsika/detail/framework/geometry/Cubic.inl b/corsika/detail/framework/geometry/Box.inl similarity index 63% rename from corsika/detail/framework/geometry/Cubic.inl rename to corsika/detail/framework/geometry/Box.inl index 5e64f3abaf8fdbf8cc88ad5b9bfc75529312b019..d5b942ec64ecd22021dedc53ddcf4ee1870a8f5f 100644 --- a/corsika/detail/framework/geometry/Cubic.inl +++ b/corsika/detail/framework/geometry/Box.inl @@ -1,14 +1,12 @@ - - namespace corsika { - inline bool Cubic::contains(Point const& p) const { + inline bool Box::contains(Point const& p) const { if ((abs(p.getX(cs_)) < x_) && (abs(p.getY(cs_)) < y_) && (abs(p.getZ(cs_)) < z_)) return true; else return false; } - inline std::string Cubic::asString() const { + inline std::string Box::asString() const { std::ostringstream txt; txt << "center=" << center_ << ", x-axis=" << DirectionVector{cs_, {1, 0, 0}} << ", y-axis: " << DirectionVector{cs_, {0, 1, 0}} @@ -16,4 +14,9 @@ namespace corsika { return txt.str(); } + template <typename TDim> + inline void Box::rotate(QuantityVector<TDim> const& axis, double const angle) { + cs_ = make_rotation(cs_, axis, angle); + } + } // namespace corsika \ No newline at end of file diff --git a/corsika/detail/modules/ObservationCubic.inl b/corsika/detail/modules/ObservationCubic.inl deleted file mode 100644 index 1504c67bc454336bd8af9bb55d09ce4e784e0d16..0000000000000000000000000000000000000000 --- a/corsika/detail/modules/ObservationCubic.inl +++ /dev/null @@ -1,151 +0,0 @@ -/* - * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -namespace corsika { - - template <typename TTracking, typename TOutput> - ObservationCubic<TTracking, TOutput>::ObservationCubic( - Point const& center, CoordinateSystemPtr cs, LengthType const x, LengthType const y, - LengthType const z, bool deleteOnHit) - : Cubic(center, cs, x, y, z) - , deleteOnHit_(deleteOnHit) - , energy_(0_GeV) - , count_(0) {} - - template <typename TTracking, typename TOutput> - template <typename TParticle, typename TTrajectory> - inline ProcessReturn ObservationCubic<TTracking, TOutput>::doContinuous( - TParticle& particle, TTrajectory& step, bool const stepLimit) { - /* - The current step did not yet reach the ObservationCubic, do nothing now and - wait: - */ - if (!stepLimit) { - // @todo this is actually needed to fix small instabilities of the leap-frog - // tracking: Note, this is NOT a general solution and should be clearly - // revised with a more robust tracking. #ifdef DEBUG - if (deleteOnHit_) { - // since this is basically a bug, it cannot be tested LCOV_EXCL_START - LengthType const check = 1_m; // TODO, do I need to check? - if (check < 0_m) { - CORSIKA_LOG_WARN("PARTICLE AVOIDED ObservationCubic {}", check); - CORSIKA_LOG_WARN("Temporary fix: write and remove particle."); - } else - return ProcessReturn::Ok; - // LCOV_EXCL_STOP - } else - // #endif - return ProcessReturn::Ok; - } - - HEPEnergyType const energy = particle.getEnergy(); - Point const pointOfIntersection = step.getPosition(1); - DirectionVector const dirction = particle.getDirection(); - - // add our particles to the output file stream - this->write(particle.getPID(), energy, pointOfIntersection.getX(cs_), - pointOfIntersection.getY(cs_), pointOfIntersection.getZ(cs_), - dirction.getX(cs_), dirction.getY(cs_), dirction.getZ(cs_), - particle.getTime()); - - CORSIKA_LOG_TRACE("Particle detected absorbed={}", deleteOnHit_); - - if (deleteOnHit_) { - count_++; - energy_ += energy; - return ProcessReturn::ParticleAbsorbed; - } else { - return ProcessReturn::Ok; - } - } - - template <typename TTracking, typename TOutput> - template <typename TParticle, typename TTrajectory> - inline LengthType ObservationCubic<TTracking, TOutput>::getMaxStepLength( - TParticle const& particle, TTrajectory const& trajectory) { - - CORSIKA_LOG_TRACE("getMaxStepLength, particle={}, pos={}, dir={}, cubic={}", - particle.asString(), particle.getPosition(), - particle.getDirection(), asString()); - - auto const intersection = - TTracking::intersect(particle, static_cast<Cubic const>(*this)); - - TimeType const timeOfIntersection = intersection.getEntry(); - CORSIKA_LOG_TRACE("timeOfIntersection={}", timeOfIntersection); - if (timeOfIntersection < TimeType::zero()) { - return std::numeric_limits<double>::infinity() * 1_m; - } - if (timeOfIntersection > trajectory.getDuration()) { - return std::numeric_limits<double>::infinity() * 1_m; - } - double const fractionOfIntersection = timeOfIntersection / trajectory.getDuration(); - CORSIKA_LOG_TRACE("ObservationCubic: getMaxStepLength dist={} m, pos={}", - trajectory.getLength(fractionOfIntersection) / 1_m, - trajectory.getPosition(fractionOfIntersection)); - return trajectory.getLength(fractionOfIntersection); - } - - template <typename TTracking, typename TOutput> - inline void ObservationCubic<TTracking, TOutput>::showResults() const { - CORSIKA_LOG_INFO( - " ******************************\n" - " ObservationCubic: \n" - " energy at cubic (GeV) : {}\n" - " no. of particles at cubic : {}\n" - " ******************************", - energy_ / 1_GeV, count_); - } - - template <typename TTracking, typename TOutput> - inline YAML::Node ObservationCubic<TTracking, TOutput>::getConfig() const { - using namespace units::si; - - // construct the top-level node - YAML::Node node; - - // basic info - node["type"] = "ObservationCubic"; - node["units"] = "m"; // add default units for values - - // save each component in its native coordinate system - auto const root_cs = get_root_CoordinateSystem(); - node["center"].push_back(center_.getX(root_cs) / 1_m); - node["center"].push_back(center_.getY(root_cs) / 1_m); - node["center"].push_back(center_.getZ(root_cs) / 1_m); - - // the x-axis vector - DirectionVector const x_axis = DirectionVector{cs_, {1, 0, 0}}; - node["x-axis"].push_back(x_axis.getX(root_cs).magnitude()); - node["x-axis"].push_back(x_axis.getY(root_cs).magnitude()); - node["x-axis"].push_back(x_axis.getZ(root_cs).magnitude()); - - // the y-axis vector - DirectionVector const y_axis = DirectionVector{cs_, {0, 1, 0}}; - node["y-axis"].push_back(y_axis.getX(root_cs).magnitude()); - node["y-axis"].push_back(y_axis.getY(root_cs).magnitude()); - node["y-axis"].push_back(y_axis.getZ(root_cs).magnitude()); - - // the x-axis vector - DirectionVector const z_axis = DirectionVector{cs_, {0, 0, 1}}; - node["z-axis"].push_back(z_axis.getX(root_cs).magnitude()); - node["z-axis"].push_back(z_axis.getY(root_cs).magnitude()); - node["z-axis"].push_back(z_axis.getZ(root_cs).magnitude()); - - node["delete_on_hit"] = deleteOnHit_; - - return node; - } - - template <typename TTracking, typename TOutput> - inline void ObservationCubic<TTracking, TOutput>::reset() { - energy_ = 0_GeV; - count_ = 0; - } - -} // namespace corsika diff --git a/corsika/detail/modules/tracking/TrackingStraight.inl b/corsika/detail/modules/tracking/TrackingStraight.inl index a54155f6f3d42c6f78471180f90b07c59ad943ca..f596cd133947dba431f878183602b507a77cd2a0 100644 --- a/corsika/detail/modules/tracking/TrackingStraight.inl +++ b/corsika/detail/modules/tracking/TrackingStraight.inl @@ -82,12 +82,11 @@ namespace corsika::tracking_line { } template <typename TParticle> - inline Intersections Tracking::intersect(TParticle const& particle, - Cubic const& cubic) { + inline Intersections Tracking::intersect(TParticle const& particle, Box const& box) { Point const& position = particle.getPosition(); VelocityVector const velocity = particle.getMomentum() / particle.getEnergy() * constants::c; - CoordinateSystemPtr const& cs = cubic.getCoordinateSystem(); + CoordinateSystemPtr const& cs = box.getCoordinateSystem(); LengthType x0 = position.getX(cs); LengthType y0 = position.getY(cs); LengthType z0 = position.getZ(cs); @@ -95,7 +94,7 @@ namespace corsika::tracking_line { SpeedType vy = velocity.getY(cs); SpeedType vz = velocity.getZ(cs); CORSIKA_LOG_TRACE( - "particle in cubic coordinate: position: ({:.3f}, {:.3f}, " + "particle in box coordinate: position: ({:.3f}, {:.3f}, " "{:.3f}) m, veolocity: ({:.3f}, {:.3f}, {:.3f}) m/ns", x0 / 1_m, y0 / 1_m, z0 / 1_m, vx / (1_m / 1_ns), vy / (1_m / 1_ns), vz / (1_m / 1_ns)); @@ -109,9 +108,9 @@ namespace corsika::tracking_line { return std::make_pair(t2, t1); }; - auto [tx_max, tx_min] = get_intersect_min_max(x0, vx, cubic.getX()); - auto [ty_max, ty_min] = get_intersect_min_max(y0, vy, cubic.getY()); - auto [tz_max, tz_min] = get_intersect_min_max(z0, vz, cubic.getZ()); + auto [tx_max, tx_min] = get_intersect_min_max(x0, vx, box.getX()); + auto [ty_max, ty_min] = get_intersect_min_max(y0, vy, box.getY()); + auto [tz_max, tz_min] = get_intersect_min_max(z0, vz, box.getZ()); TimeType t_exit = std::min(std::min(tx_max, ty_max), tz_max); TimeType t_enter = std::max(std::max(tx_min, ty_min), tz_min); @@ -119,7 +118,7 @@ namespace corsika::tracking_line { CORSIKA_LOG_DEBUG("t_enter: {} ns, t_exit: {} ns", t_enter / 1_ns, t_exit / 1_ns); if ((t_exit > t_enter)) { if (t_enter < 0_s && t_exit > 0_s) - CORSIKA_LOG_DEBUG("numericallyInside={}", cubic.contains(position)); + CORSIKA_LOG_DEBUG("numericallyInside={}", box.contains(position)); else if (t_enter < 0_s && t_exit < 0_s) CORSIKA_LOG_DEBUG("oppisite direction"); return Intersections(std::move(t_enter), std::move(t_exit)); @@ -133,9 +132,8 @@ namespace corsika::tracking_line { if (Sphere const* sphere = dynamic_cast<Sphere const*>(&volumeNode.getVolume()); sphere) { return Tracking::intersect<TParticle>(particle, *sphere); - } else if (Cubic const* cubic = dynamic_cast<Cubic const*>(&volumeNode.getVolume()); - cubic) { - return Tracking::intersect<TParticle>(particle, *cubic); + } else if (Box const* box = dynamic_cast<Box const*>(&volumeNode.getVolume()); box) { + return Tracking::intersect<TParticle>(particle, *box); } else { throw std::runtime_error( "The Volume type provided is not supported in " diff --git a/corsika/detail/modules/writers/ObservationCubicWriterParquet.inl b/corsika/detail/modules/writers/ObservationCubicWriterParquet.inl deleted file mode 100644 index 1a79a4b0d851ee7bb1b507e55bcd1d13d57c1b0c..0000000000000000000000000000000000000000 --- a/corsika/detail/modules/writers/ObservationCubicWriterParquet.inl +++ /dev/null @@ -1,66 +0,0 @@ -/* - * (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -namespace corsika { - - inline ObservationCubicWriterParquet::ObservationCubicWriterParquet() - : output_() {} - - inline void ObservationCubicWriterParquet::startOfLibrary( - boost::filesystem::path const& directory) { - - // setup the streamer - output_.initStreamer((directory / "particles.parquet").string()); - - // enable compression with the default level - output_.enableCompression(); - - // build the schema - output_.addField("pdg", parquet::Repetition::REQUIRED, parquet::Type::INT32, - parquet::ConvertedType::INT_32); - output_.addField("energy", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("x", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("y", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("z", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("nx", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("ny", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("nz", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - output_.addField("t", parquet::Repetition::REQUIRED, parquet::Type::FLOAT, - parquet::ConvertedType::NONE); - - // and build the streamer - output_.buildStreamer(); - } - - inline void ObservationCubicWriterParquet::endOfShower() { ++shower_; } - - inline void ObservationCubicWriterParquet::endOfLibrary() { output_.closeStreamer(); } - - inline void ObservationCubicWriterParquet::write( - Code const& pid, HEPEnergyType const& energy, LengthType const& x, - LengthType const& y, LengthType const& z, double nx, double ny, double nz, - TimeType const& t) { - // write the next row - we must write `shower_` first. - *(output_.getWriter()) << shower_ << static_cast<int>(get_PDG(pid)) - << static_cast<float>(energy / 1_GeV) - << static_cast<float>(x / 1_m) << static_cast<float>(y / 1_m) - << static_cast<float>(z / 1_m) << static_cast<float>(nx) - << static_cast<float>(ny) << static_cast<float>(nz) - << static_cast<float>(t / 1_ns) << parquet::EndRow; - } - -} // namespace corsika diff --git a/corsika/framework/geometry/Cubic.hpp b/corsika/framework/geometry/Box.hpp similarity index 77% rename from corsika/framework/geometry/Cubic.hpp rename to corsika/framework/geometry/Box.hpp index d0aee3f1cd221032ea50ee82cab0db45336f0df6..729e64ebc28ee2ac5ba4967486d60c3bd42777fd 100644 --- a/corsika/framework/geometry/Cubic.hpp +++ b/corsika/framework/geometry/Box.hpp @@ -6,19 +6,19 @@ #include <corsika/framework/geometry/IVolume.hpp> namespace corsika { - class Cubic : public IVolume { + class Box : public IVolume { public: // a CoordinateSystemPtr to specify the orintation of coordinate - Cubic(Point const& center, CoordinateSystemPtr cs, LengthType const x, - LengthType const y, LengthType const z) + Box(Point const& center, CoordinateSystemPtr cs, LengthType const x, + LengthType const y, LengthType const z) : center_(center) , cs_(make_translation(cs, center.getCoordinates(cs))) , x_(x) , y_(y) , z_(z) {} - Cubic(Point const& center, CoordinateSystemPtr cs, LengthType const side) + Box(Point const& center, CoordinateSystemPtr cs, LengthType const side) : center_(center) , cs_(make_translation(cs, center.getCoordinates(cs))) , x_(side / 2) @@ -30,12 +30,16 @@ namespace corsika { Point const& getCenter() const { return center_; }; CoordinateSystemPtr const getCoordinateSystem() const { return cs_; } + LengthType const getX() const { return x_; } LengthType const getY() const { return y_; } LengthType const getZ() const { return z_; } std::string asString() const; + template <typename TDim> + void rotate(QuantityVector<TDim> const& axis, double const angle); + protected: Point center_; CoordinateSystemPtr cs_; // local coordinate system with center_ in coordinate (0, 0, @@ -47,4 +51,4 @@ namespace corsika { } // namespace corsika -#include <corsika/detail/framework/geometry/Cubic.inl> +#include <corsika/detail/framework/geometry/Box.inl> diff --git a/corsika/modules/ObservationCubic.hpp b/corsika/modules/ObservationCubic.hpp deleted file mode 100644 index f7179bf117f0651126634212340e3ab29d80a55d..0000000000000000000000000000000000000000 --- a/corsika/modules/ObservationCubic.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include <corsika/framework/geometry/Cubic.hpp> - -#include <corsika/modules/writers/ObservationCubicWriterParquet.hpp> -#include <corsika/framework/process/ContinuousProcess.hpp> - -namespace corsika { - - /** - @ingroup Modules - @{ - - The ObservationCubic writes PDG codes, energies, and distances of particles to the - central point of the plane into its output file. The particles are considered - "absorbed" afterwards. - - **Note/Limitation:** as discussed in - https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/-/issues/397 - you cannot put two ObservationCubics exactly on top of each - other. Even if one of them is "permeable". You have to put a - small gap in between the two plane in such a scenario, or develop - another more specialized output class. - */ - template <typename TTracking, typename TOutputWriter = ObservationCubicWriterParquet> - class ObservationCubic - : public Cubic, - public ContinuousProcess<ObservationCubic<TTracking, TOutputWriter>>, - public TOutputWriter { - - public: - ObservationCubic(Point const& center, CoordinateSystemPtr cs, LengthType const x, - LengthType const y, LengthType const z, bool = true); - - template <typename TParticle, typename TTrajectory> - ProcessReturn doContinuous(TParticle& vParticle, TTrajectory& vTrajectory, - bool const stepLimit); - - template <typename TParticle, typename TTrajectory> - LengthType getMaxStepLength(TParticle const&, TTrajectory const& vTrajectory); - - void showResults() const; - void reset(); - HEPEnergyType getEnergy() const { return energy_; } - YAML::Node getConfig() const; - - private: - bool const deleteOnHit_; - HEPEnergyType energy_; - unsigned int count_; - }; - //! @} -} // namespace corsika - -#include <corsika/detail/modules/ObservationCubic.inl> \ No newline at end of file diff --git a/corsika/modules/tracking/TrackingStraight.hpp b/corsika/modules/tracking/TrackingStraight.hpp index 31b2fad4ffbdf42b268c4f9992aa254135ee05d6..336e4f0bccf1b6d1b2c045ad3298a28ab9575a0a 100644 --- a/corsika/modules/tracking/TrackingStraight.hpp +++ b/corsika/modules/tracking/TrackingStraight.hpp @@ -12,7 +12,7 @@ #include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Plane.hpp> #include <corsika/framework/geometry/Sphere.hpp> -#include <corsika/framework/geometry/Cubic.hpp> +#include <corsika/framework/geometry/Box.hpp> #include <corsika/framework/geometry/Vector.hpp> #include <corsika/framework/geometry/StraightTrajectory.hpp> #include <corsika/framework/geometry/Intersections.hpp> @@ -52,7 +52,7 @@ namespace corsika::tracking_line { static Intersections intersect(TParticle const& particle, Sphere const& sphere); template <typename TParticle> - static Intersections intersect(TParticle const& particle, Cubic const& cubic); + static Intersections intersect(TParticle const& particle, Box const& box); //! find intersection of Volume node with Track of particle template <typename TParticle, typename TBaseNodeType> diff --git a/corsika/modules/writers/ObservationCubicWriterParquet.hpp b/corsika/modules/writers/ObservationCubicWriterParquet.hpp deleted file mode 100644 index 97e518c8d3da9e9272dce572cf46cbfdc4429d55..0000000000000000000000000000000000000000 --- a/corsika/modules/writers/ObservationCubicWriterParquet.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -#include <corsika/output/BaseOutput.hpp> -#include <corsika/output/ParquetStreamer.hpp> -#include <corsika/framework/core/ParticleProperties.hpp> -#include <corsika/framework/core/PhysicalUnits.hpp> - -namespace corsika { - - class ObservationCubicWriterParquet : public BaseOutput { - - ParquetStreamer output_; ///< The primary output file. - - public: - /** - * Construct an ObservationPlane. - * - * @param name The name of this output. - */ - ObservationCubicWriterParquet(); - - /** - * Called at the start of each library. - */ - void startOfLibrary(boost::filesystem::path const& directory) final override; - - /** - * Called at the end of each shower. - */ - void endOfShower() final override; - - /** - * Called at the end of each library. - * - * This must also increment the run number since we override - * the default behaviour of BaseOutput. - */ - void endOfLibrary() final override; - - protected: - /** - * Write a particle to the file. - */ - void write(Code const& pid, HEPEnergyType const& energy, LengthType const& x, - LengthType const& y, LengthType const& z, double nx, double ny, double nz, - TimeType const& t); - - }; // class ObservationCubicWriterParquet - -} // namespace corsika - -#include <corsika/detail/modules/writers/ObservationCubicWriterParquet.inl> diff --git a/tests/framework/testGeometry.cpp b/tests/framework/testGeometry.cpp index 19c311881c728524aa7256464f30d7ed52975d55..67242751c413312db71e6861c2a5aa74f8929336 100644 --- a/tests/framework/testGeometry.cpp +++ b/tests/framework/testGeometry.cpp @@ -10,15 +10,16 @@ #include <cmath> #include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/geometry/Box.hpp> #include <corsika/framework/geometry/CoordinateSystem.hpp> -#include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Helix.hpp> -#include <corsika/framework/geometry/Point.hpp> +#include <corsika/framework/geometry/LeapFrogTrajectory.hpp> +#include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Path.hpp> +#include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/RootCoordinateSystem.hpp> #include <corsika/framework/geometry/Sphere.hpp> #include <corsika/framework/geometry/StraightTrajectory.hpp> -#include <corsika/framework/geometry/LeapFrogTrajectory.hpp> #include <PhysicalUnitsCatch2.hpp> // namespace corsike::testing @@ -282,6 +283,51 @@ TEST_CASE("Geometry Sphere") { } } +TEST_CASE("Geometry Box") { + CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); + Point center(rootCS, {0_m, 0_m, 5_m}); + Box box(center, rootCS, 4_m, 5_m, 6_m); + + SECTION("getCenter") { + CHECK((box.getCenter().getCoordinates(rootCS) - center.getCoordinates()) + .getNorm() + .magnitude() == Approx(0).margin(absMargin)); + CHECK(box.getX() / 4_m == Approx(1)); + CHECK(box.getY() / 5_m == Approx(1)); + CHECK(box.getZ() / 6_m == Approx(1)); + } + + SECTION("isInside") { + CHECK_FALSE(box.contains(Point(rootCS, {4.5_m, 0_m, 0_m}))); + CHECK(box.contains(Point(rootCS, {0_m, 4.5_m, 0_m}))); + } + + SECTION("internal coordinate") { + CoordinateSystemPtr const internalCS = box.getCoordinateSystem(); + auto coordinate = center.getCoordinates(internalCS); + CHECK(coordinate.getX() / 1_m == Approx(0)); + CHECK(coordinate.getY() / 1_m == Approx(0)); + CHECK(coordinate.getZ() / 1_m == Approx(0)); + } + + SECTION("rotation") { + QuantityVector<length_d> const axis_z{0_m, 0_m, 1_m}; + box.rotate(axis_z, 90); + CHECK(box.contains(Point(rootCS, {4.5_m, 0_m, 0_m}))); + CHECK_FALSE(box.contains(Point(rootCS, {0_m, 4.5_m, 0_m}))); + } + + SECTION("from different coordinate") { + CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); + QuantityVector<length_d> const axis_z{0_m, 0_m, 1_m}; + auto rotatedCS = make_rotation(rootCS, axis_z, 90); + Point center(rootCS, {0_m, 0_m, 5_m}); + Box box(center, rotatedCS, 4_m, 5_m, 6_m); + CHECK(box.contains(Point(rootCS, {4.5_m, 0_m, 0_m}))); + CHECK_FALSE(box.contains(Point(rootCS, {0_m, 4.5_m, 0_m}))); + } +} + TEST_CASE("Geometry Trajectories") { CoordinateSystemPtr rootCS = get_root_CoordinateSystem(); Point r0(rootCS, {0_m, 0_m, 0_m});