diff --git a/include/boost/astronomy/coordinate/arithmetic.hpp b/include/boost/astronomy/coordinate/arithmetic.hpp index 2a4b0247..aca1a361 100644 --- a/include/boost/astronomy/coordinate/arithmetic.hpp +++ b/include/boost/astronomy/coordinate/arithmetic.hpp @@ -21,15 +21,19 @@ file License.txt or copy at https://www.boost.org/LICENSE_1_0.txt) #include #include +#include +#include + #include #include #include #include -namespace boost { namespace astronomy { namespace coordinate { - namespace bg = boost::geometry; namespace bu = boost::units; +using namespace boost::numeric::ublas; + +namespace boost { namespace astronomy { namespace coordinate { //!Returns the cross product of cartesian_representation(representation1) and representation2 template @@ -283,6 +287,40 @@ auto dot(Representation1 const& representation1, Representation2 const& represen } +//! Returns scalar product of the cartesian vector with a factor +template +cartesian_representation +multiply(cartesian_representation const& vector, double factor) +{ + bg::model::point + < + typename cartesian_representation::type, + 3, + bg::cs::cartesian + > tempPoint; + + bg::set<0>(tempPoint, vector.get_x().value() * factor); + bg::set<1>(tempPoint, vector.get_y().value() * factor); + bg::set<2>(tempPoint, vector.get_z().value() * factor); + + return cartesian_representation(tempPoint); +} + + +//! Returns scalar product of given vector other than cartesian with a factor +template +auto multiply(Coordinate const& vector, double factor) +{ + Coordinate tempVector; + + tempVector.set_lat(vector.get_lat()); + tempVector.set_lon(vector.get_lon()); + tempVector.set_dist(vector.get_dist() * factor); + + return tempVector; +} + + //! Returns magnitude of the cartesian vector template < @@ -330,42 +368,13 @@ auto magnitude(Coordinate const& vector) } -//! Returns the unit vector of vector given -template -cartesian_representation -unit_vector(cartesian_representation const& vector) -{ - bg::model::point - < - typename cartesian_representation::type, - 3, - bg::cs::cartesian - > tempPoint; - auto mag = magnitude(vector); //magnitude of vector - - //performing calculations to find unit vector - bg::set<0>(tempPoint, vector.get_x().value() / mag.value()); - bg::set<1>(tempPoint, - vector.get_y().value() / - static_cast::quantity2>(mag).value()); - bg::set<2>(tempPoint, - vector.get_z().value() / - static_cast::quantity3>(mag).value()); - - return cartesian_representation(tempPoint); -} - -//! Returns unit vector of given vector other than Cartesian +//! Returns unit vector of given vector template auto unit_vector(Coordinate const& vector) { - Coordinate tempVector; - - tempVector.set_lat(vector.get_lat()); - tempVector.set_lon(vector.get_lon()); - tempVector.set_dist(1.0 * typename Coordinate::quantity3::unit_type()); + auto mag = magnitude(vector); //magnitude of vector - return tempVector; + return multiply(vector, 1/mag.value()); } @@ -427,6 +436,64 @@ Representation1 sum } +//! Returns difference of representation1 and representation2 +template +Representation1 difference +( + Representation1 const& representation1, + Representation2 const& representation2 +) +{ + /*!both the coordinates/vector are first converted into + cartesian coordinate system then difference of cartesian + vectors is converted into the type of first argument and returned*/ + + /*checking types if it is not subclass of + base_representaion then compile time erorr is generated*/ + //BOOST_STATIC_ASSERT_MSG((boost::astronomy::detail::is_base_template_of + // < + // boost::astronomy::coordinate::base_representation, + // Representation1 + // >::value), + // "First argument type is expected to be a representation class"); + //BOOST_STATIC_ASSERT_MSG((boost::astronomy::detail::is_base_template_of + // < + // boost::astronomy::coordinate::base_representation, + // Representation2 + // >::value), + // "Second argument type is expected to be a representation class"); + + /*converting both coordinates/vector into cartesian system*/ + bg::model::point + < + typename std::conditional + < + sizeof(typename Representation2::type) >= + sizeof(typename Representation1::type), + typename Representation2::type, + typename Representation1::type + >::type, + 3, + bg::cs::cartesian + > result; + + auto cartesian1 = make_cartesian_representation(representation1); + auto cartesian2 = make_cartesian_representation(representation2); + + typedef decltype(cartesian1) cartesian1_type; + + //performing calculation to find the sum + bg::set<0>(result, (cartesian1.get_x().value() - + static_cast(cartesian2.get_x()).value())); + bg::set<1>(result, (cartesian1.get_y().value() - + static_cast(cartesian2.get_y()).value())); + bg::set<2>(result, (cartesian1.get_z().value() - + static_cast(cartesian2.get_z()).value())); + + return Representation1(result); +} + + //! Returns mean of representation1 and representation2 template Representation1 mean @@ -476,5 +543,33 @@ Representation1 mean return Representation1(result); } + +//! Returns multiplication of a matrix with the cartesian representation +template +cartesian_representation +matrix_multiply(cartesian_representation const& representation, matrix mul) +{ + matrix vec = matrix(3,1); + + vec(0,0) = representation.get_x().value(); + vec(1,0) = representation.get_y().value(); + vec(2,0) = representation.get_z().value(); + + vec = prod(mul, vec); + + bg::model::point + < + typename cartesian_representation::type, + 3, + bg::cs::cartesian + > ans; + bg::set<0>(ans, vec(0,0)); + bg::set<1>(ans, vec(1,0)); + bg::set<2>(ans, vec(2,0)); + + return cartesian_representation(ans); +} + + }}} // namespace boost::astronomy::coordinate #endif // !BOOST_ASTRONOMY_COORDINATE_ARITHMETIC_HPP diff --git a/test/coordinate/cartesian_representation.cpp b/test/coordinate/cartesian_representation.cpp index d0ed94c0..78ee819b 100644 --- a/test/coordinate/cartesian_representation.cpp +++ b/test/coordinate/cartesian_representation.cpp @@ -245,6 +245,22 @@ BOOST_AUTO_TEST_CASE(cartesian_representation_dot_product) ::type>>::value)); } +BOOST_AUTO_TEST_CASE(cartesian_representation_scalar_multiplication) +{ + auto point1 = make_cartesian_representation(25.0 * meter, 36.0 * si::centi * meter, 90.0 * si::kilo * meter); + + auto result = boost::astronomy::coordinate::multiply(point1, 2); + + BOOST_CHECK_CLOSE(result.get_x().value(), 50.0, 0.001); + BOOST_CHECK_CLOSE(result.get_y().value(), 72.0, 0.001); + BOOST_CHECK_CLOSE(result.get_z().value(), 180.0, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_CASE(cartesian_representation_unit_vector) { auto point1 = make_cartesian_representation(25.0*meter, 36.0*meter, 90.0*meter); @@ -294,6 +310,25 @@ BOOST_AUTO_TEST_CASE(cartesian_representation_sum) BOOST_TEST((std::is_same>::value)); } +BOOST_AUTO_TEST_CASE(cartesian_representation_difference) +{ + auto point1 = make_cartesian_representation + (10.0 * meter, 20.0 * si::kilo * meters, 30.0 * meter); + auto point2 = make_cartesian_representation + (50.0 * si::centi * meter, 60.0 * meter, 30.0 * meter); + + auto result = boost::astronomy::coordinate::difference(point1, point2); + + BOOST_CHECK_CLOSE(result.get_x().value(), 9.5, 0.001); + BOOST_CHECK_CLOSE(result.get_y().value(), 19.94, 0.001); + BOOST_CHECK_CLOSE(result.get_z().value(), 0, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_CASE(cartesian_representation_mean) { auto point1 = make_cartesian_representation @@ -313,4 +348,26 @@ BOOST_AUTO_TEST_CASE(cartesian_representation_mean) BOOST_TEST((std::is_same>::value)); } +BOOST_AUTO_TEST_CASE(cartesian_representation_matrix_multiplication) +{ + auto point = make_cartesian_representation + (10.0 * meter, 20.0 * si::kilo * meters, 30.0 * si::centi * meter); + + matrix m(3, 3); + for (unsigned i = 0; i < m.size1(); ++i) + for (unsigned j = 0; j < m.size2(); ++j) + m(i, j) = 3 * i + j; + + auto result = boost::astronomy::coordinate::matrix_multiply(point, m); + + BOOST_CHECK_CLOSE(result.get_x().value(), 80.0, 0.001); + BOOST_CHECK_CLOSE(result.get_y().value(), 260.0, 0.001); + BOOST_CHECK_CLOSE(result.get_z().value(), 440.0, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/coordinate/spherical_equatorial_representation.cpp b/test/coordinate/spherical_equatorial_representation.cpp index af2acb5e..1b650170 100644 --- a/test/coordinate/spherical_equatorial_representation.cpp +++ b/test/coordinate/spherical_equatorial_representation.cpp @@ -237,6 +237,22 @@ BOOST_AUTO_TEST_CASE(spherical_equatorial_representation_dot_product) ::type>>::value)); } +BOOST_AUTO_TEST_CASE(spherical_equatorial_representation_scalar_multiplication) +{ + auto point1 = make_spherical_equatorial_representation(25.0 * bud::degrees, 30.0 * bud::degrees, 90.0*meter); + + auto result = boost::astronomy::coordinate::multiply(point1, 2); + + BOOST_CHECK_CLOSE(result.get_lat().value(), 25.0, 0.001); + BOOST_CHECK_CLOSE(result.get_lon().value(), 30.0, 0.001); + BOOST_CHECK_CLOSE(result.get_dist().value(), 180.0, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_CASE(spherical_equatorial_representation_unit_vector) { auto point1 = make_spherical_equatorial_representation(25.0 * bud::degrees, 30.0 * bud::degrees, 90.0*meter); @@ -283,6 +299,23 @@ BOOST_AUTO_TEST_CASE(spherical_equatorial_representation_sum) BOOST_TEST((std::is_same>::value)); } +BOOST_AUTO_TEST_CASE(spherical_equatorial_representation_difference) +{ + auto point1 = make_spherical_equatorial_representation(15.0 * bud::degrees, 30.0 * bud::degrees, 10.0 * meters); + auto point2 = make_spherical_equatorial_representation(30.0 * bud::degrees, 45.0 * bud::degrees, 20.0 * meters); + + auto result = boost::astronomy::coordinate::difference(point2, point1); + + BOOST_CHECK_CLOSE(result.get_lat().value(), 51.206, 0.001); + BOOST_CHECK_CLOSE(result.get_lon().value(), 55.8705, 0.001); + BOOST_CHECK_CLOSE(result.get_dist().value(), 11.0443, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_CASE(spherical_equatorial_representation_mean) { auto point1 = make_spherical_equatorial_representation(15.0 * bud::degrees, 30.0 * bud::degrees, 10.0 * meter); diff --git a/test/coordinate/spherical_representation.cpp b/test/coordinate/spherical_representation.cpp index f9df7091..0d2270a3 100644 --- a/test/coordinate/spherical_representation.cpp +++ b/test/coordinate/spherical_representation.cpp @@ -236,6 +236,22 @@ BOOST_AUTO_TEST_CASE(spherical_representation_dot_product) ::type>>::value)); } +BOOST_AUTO_TEST_CASE(spherical_representation_scalar_multiplication) +{ + auto point1 = make_spherical_representation(25.0 * bud::degrees, 30.0 * bud::degrees, 90.0*meter); + + auto result = boost::astronomy::coordinate::multiply(point1, 2); + + BOOST_CHECK_CLOSE(result.get_lat().value(), 25.0, 0.001); + BOOST_CHECK_CLOSE(result.get_lon().value(), 30.0, 0.001); + BOOST_CHECK_CLOSE(result.get_dist().value(), 180.0, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_CASE(spherical_representation_unit_vector) { auto point1 = make_spherical_representation(25.0 * bud::degrees, 30.0 * bud::degrees, 90.0*meter); @@ -282,6 +298,23 @@ BOOST_AUTO_TEST_CASE(spherical_representation_sum) BOOST_TEST((std::is_same>::value)); } +BOOST_AUTO_TEST_CASE(spherical_representation_difference) +{ + auto point1 = make_spherical_representation(15.0 * bud::degrees, 30.0 * bud::degrees, 10.0 * meters); + auto point2 = make_spherical_representation(30.0 * bud::degrees, 45.0 * bud::degrees, 20.0 * meters); + + auto result = boost::astronomy::coordinate::difference(point1, point2); + + BOOST_CHECK_CLOSE(result.get_lat().value(), -142.089, 0.001); + BOOST_CHECK_CLOSE(result.get_lon().value(), 120.245, 0.001); + BOOST_CHECK_CLOSE(result.get_dist().value(), 10.8834, 0.001); + + //checking whether quantity stored is as expected or not + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); + BOOST_TEST((std::is_same>::value)); +} + BOOST_AUTO_TEST_CASE(spherical_representation_mean) { auto point1 = make_spherical_representation(15.0 * bud::degrees, 30.0 * bud::degrees, 10.0 * meter);