From 2d2e1a91b420a34fb075ef4add21bcea020d94f7 Mon Sep 17 00:00:00 2001 From: Nikos Karastathis <n.karastathis@kit.edu> Date: Mon, 25 Jan 2021 13:51:24 +0100 Subject: [PATCH] added and tested Path class in geometry --- corsika/detail/framework/geometry/Path.inl | 59 ++++++++++ corsika/framework/geometry/Path.hpp | 124 +++++++++++++++++++++ tests/framework/testGeometry.cpp | 63 ++++++++++- 3 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 corsika/detail/framework/geometry/Path.inl create mode 100644 corsika/framework/geometry/Path.hpp diff --git a/corsika/detail/framework/geometry/Path.inl b/corsika/detail/framework/geometry/Path.inl new file mode 100644 index 000000000..c8c05921f --- /dev/null +++ b/corsika/detail/framework/geometry/Path.inl @@ -0,0 +1,59 @@ +///* +// * (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. +// */ +// +//#pragma once +// +//#include <deque> +//#include <corsika/framework/geometry/Point.hpp> +// +//namespace corsika { +// +// inline void AddToEnd(Point const& point) { +// length_ += (point - points_.back()).getNorm(); +// points_.push_back(point); +// } +// +// +// inline void RemoveFromEnd() { +// auto lastpoint_ = points_.back(); +// points_.pop_back(); +// int dequesize_ = points_.size(); +// if (dequesize_ == 0 || dequesize_ == 1) { +// length_ = LengthType::zero(); +// } +// else if (dequesize_ == 2) { +// length_ = (points_.back() - points_.front()).getNorm(); +// } +// else { length_ -= (lastpoint_ - points_.back()).getNorm(); } +// } +// +// +// inline LengthType GetLength() const { +// return length_; +// } +// +// +// inline Point GetStart() const { +// return points_.front(); +// } +// +// +// inline Point GetEnd() const { +// return points_.back(); +// } +// +// +// inline Point GetPoint(std::size_t const index) const { +// return points_.at(index); +// } +// +// +// +// inline int GetNSegments() const { return points_.size() - 1; } +// +//} // namespace corsika \ No newline at end of file diff --git a/corsika/framework/geometry/Path.hpp b/corsika/framework/geometry/Path.hpp new file mode 100644 index 000000000..77b6966e5 --- /dev/null +++ b/corsika/framework/geometry/Path.hpp @@ -0,0 +1,124 @@ +/* + * (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. + */ + +#pragma once + +#include <deque> +#include <corsika/framework/geometry/Point.hpp> + +namespace corsika { + + /** + * This class represents a (potentially) curved path between two + * points using N >= 1 straight-line segments. + */ + class Path { + std::deque<Point> points_; ///< The points that make up this path. + LengthType length_= LengthType::zero(); ///< The length of the path. + public: + /** + * Create a Path with a given starting Point. + */ + Path(Point const& point) { + points_.push_front(point); + } + + /** + * Initialize a Path from an existing collection of Points. + */ + Path(std::deque<Point> const& points) + : points_(points) { + int dequesize_ = points.size(); + if (dequesize_ == 0 || dequesize_ == 1) { + length_ = LengthType::zero(); + } + else if (dequesize_ == 2) { + length_ = (points.back() - points.front()).getNorm(); + } + else { + for (auto point = points.begin(); point != points.end() - 1; ++point) { + auto point_next = *(point+1); + auto point_now = *(point); + length_ += (point_next - point_now).getNorm(); + } + } + } + + /** + * Add a new Point to the end of the path. + */ + void AddToEnd(Point const& point) { + length_ += (point - points_.back()).getNorm(); + points_.push_back(point); + } + + /** + * Remove a point from the end of the path. + */ + void RemoveFromEnd() { + auto lastpoint_ = points_.back(); + points_.pop_back(); + int dequesize_ = points_.size(); + if (dequesize_ == 0 || dequesize_ == 1) { + length_ = LengthType::zero(); + } + else if (dequesize_ == 2) { + length_ = (points_.back() - points_.front()).getNorm(); + } + else { length_ -= (lastpoint_ - points_.back()).getNorm(); } + } + + /** + * Get the total length of the path. + */ + LengthType GetLength() const { + return length_; + } + + /** + * Get the starting point of the path. + */ + Point GetStart() const { + return points_.front(); + } + + /** + * Get the end point of the path. + */ + Point GetEnd() const { + return points_.back(); + } + + /** + * Get a specific point of the path. + */ + Point GetPoint(std::size_t const index) const { + return points_.at(index); + } + + /** + * Return an iterator to the start of the Path. + */ + auto begin() { return points_.begin(); } + + /** + * Return an iterator to the end of the Path. + */ + auto end() { return points_.end(); } + + /** + * Get the number of steps in the path. + * + * This is one less than the number of points that + * defines the path. + */ + int GetNSegments() const { return points_.size() - 1; } + + }; // class Path + +} // namespace corsika \ No newline at end of file diff --git a/tests/framework/testGeometry.cpp b/tests/framework/testGeometry.cpp index 8153b3a4e..8ae12854d 100644 --- a/tests/framework/testGeometry.cpp +++ b/tests/framework/testGeometry.cpp @@ -14,12 +14,13 @@ #include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Helix.hpp> #include <corsika/framework/geometry/Point.hpp> +#include <corsika/framework/geometry/Path.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 +#include <PhysicalUnitsCatch2.hpp> // namespace corsika::testing using namespace corsika; using namespace corsika::testing; @@ -332,3 +333,63 @@ TEST_CASE("Point") { CHECK(p3.distance_to(p4) / 1_m == Approx(4)); CHECK(p5.distance_to(p6) / 1_m == Approx(1)); } + + + +TEST_CASE("Path") { + //define a known CS + CoordinateSystemPtr root = get_root_CoordinateSystem(); + + //define known points + Point p1(root, {0_m, 0_m, 0_m}); + Point p2(root, {0_m, 0_m, 1_m}); + Point p3(root, {0_m, 0_m, 2_m}); + Point p4(root, {0_m, 0_m, 3_m}); + Point p5(root, {0_m, 0_m, 4_m}); + //define paths + Path P1(p1); + Path P2({p1,p2}); + Path P3({p1, p2, p3}); + //define deque that include point(s) + std::deque<Point> l1 = {p1}; + std::deque<Point> l2 = {p1, p2}; + std::deque<Point> l3 = {p1, p2, p3}; + + //test the various path constructors + SECTION("Test Constructors") { + //check constructor for one point + CHECK(std::equal(P1.begin(), P1.end(), l1.begin(),[](Point a, Point b) + { return (a - b).getNorm() / 1_m < 1e-5;})); + //check constructor for collection of points + CHECK(std::equal(P3.begin(), P3.end(), l3.begin(),[](Point a, Point b) + { return (a - b).getNorm() / 1_m < 1e-5;})); + } + + //test the length and access methods + SECTION("Test GetLength() and modifications to Path") { + P1.AddToEnd(p2); + P2.RemoveFromEnd(); + //Check modifications to path + CHECK(std::equal(P1.begin(), P1.end(), l2.begin(),[](Point a, Point b) + { return (a - b).getNorm() / 1_m < 1e-5;})); + CHECK(std::equal(P2.begin(), P2.end(), l1.begin(),[](Point a, Point b) + { return (a - b).getNorm() / 1_m < 1e-5;})); + //Check GetStart(), GetEnd(), GetPoint() + CHECK((P3.GetEnd() - P3.GetStart()).getNorm() / 1_m == Approx(2)); + CHECK((P1.GetPoint(1) - p2).getNorm() / 1_m == Approx(0)); + //Check GetLength() + CHECK(P1.GetLength() / 1_m == Approx(1)); + CHECK(P2.GetLength() / 1_m == Approx(0)); + CHECK(P3.GetLength() / 1_m == Approx(2)); + P2.RemoveFromEnd(); + CHECK(P2.GetLength() / 1_m == Approx(0)); //Check the length of an empty path + P3.AddToEnd(p4); + P3.AddToEnd(p5); + CHECK(P3.GetLength() / 1_m == Approx(4)); + P3.RemoveFromEnd(); + CHECK(P3.GetLength() / 1_m == Approx(3)); //Check RemoveFromEnd() else case + //Check GetNSegments() + CHECK(P3.GetNSegments() - 3 == Approx(0)); + + } +} \ No newline at end of file -- GitLab