Convert deg min sec to radian & back using boost 1_53_0

Am struggling with this a bit - the comments show what I am trying to do. I find there is a lack of examples in the boost documentation.

I found an example using ll_point in a geometry but that was obsolete. I guess I just need to get in the swing of how to declare & initialise these things. If anyone could do a quick example that would be great.

I already have my own functions which do this, but I wanted to have a go at using the library.

Thanks in advance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <iomanip>

//#include <boost/geometry.hpp>
//#include <boost/geometry/geometries/geometries.hpp>

#include <boost/units/cmath.hpp>
#include <boost/units/io.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/base_units/angle/degree.hpp>
#include <boost/units/base_units/angle/arcminute.hpp>
#include <boost/units/base_units/angle/arcsecond.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>
#include <boost/units/io.hpp>



#include "CGDA94.h"
//using namespace boost::geometry;
 //   namespace bg = boost::geometry;

using namespace boost::units;
using namespace boost::units::si;
using namespace boost::units::angle;


int main(/*int argc, char *argv[]*/) {

   //would like to convert deg min sec to radians and back again
   
   //quantity<plane_angle> FlindersSDeg = -0.375 * radians; //this works 0.375 radians
   //but how to do degrees?
   //quantity<plane_angle> FlindersSDeg = -37.0; //this doesn't work
   //nor this
   quantity<boost::units::angle::degree_base_unit> FlindersSDeg = -37.0 * angle::degree_base_unit;
   //quantity<degree_base_unit> FlindersSDeg2.value(-37.0);
   //quantity< angle::arcminute_base_unit> FlindersSMin = 57.0;
   //quantity< angle::arcsecond_base_unit> FlindersSSec = 3.72030;

   //trying not to do this
   constexpr double FlindersS = -(37.0 + (57.0/60.0) + (3.72030/3600.0));
   constexpr double FlindersE = (144.0 + (25.0/60.0) + (29.52440/3600.0));

   constexpr double BuningyongS = -1.0 * (37.0 + (39.0/60.0) + (10.15610/3600.0));
   constexpr double BuningyongE = (143.0 + (55.0/60.0) + (35.38390/3600.0));

   CGDA94 MyGDAPt(FlindersS, FlindersE, BuningyongS, BuningyongE);
return 0;
}


16:59:14: Running steps for project GeodeticConsole...
16:59:14: Configuration unchanged, skipping qmake step.
16:59:14: Starting: "/usr/bin/make" -w
make: Entering directory `/home/***/projects/Qt/GeodeticConsole-build-Desktop_Qt_5_0_1_GCC_64bit-Debug'
g++ -c -m64 -pipe -std=c++11 -Wall -Wextra -pedantic -g -Wall -W -D_REENTRANT -fPIE -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt5/5.0.1/gcc_64/mkspecs/linux-g++-64 -I../GeodeticConsole -I/usr/lib/qt5/5.0.1/gcc_64/include -I/usr/lib/qt5/5.0.1/gcc_64/include/QtGui -I/usr/lib/qt5/5.0.1/gcc_64/include/QtCore -I. -I. -o main.o ../GeodeticConsole/main.cpp
In file included from /usr/include/boost/units/dimensionless_quantity.hpp:20:0,
                 from /usr/include/boost/units/cmath.hpp:23,
                 from ../GeodeticConsole/main.cpp:7:
/usr/include/boost/units/quantity.hpp: In instantiation of 'class boost::units::quantity<boost::units::angle::degree_base_unit>':
../GeodeticConsole/main.cpp:36:52:   required from here
/usr/include/boost/units/quantity.hpp:92:9: error: no matching function for call to 'assertion_failed(mpl_::failed************ boost::mpl::not_<boost::units::detail::is_base_unit<boost::units::angle::degree_base_unit, void> >::************)'
/usr/include/boost/units/quantity.hpp:92:9: note: candidate is:
In file included from /usr/include/boost/mpl/aux_/na_assert.hpp:23:0,
                 from /usr/include/boost/mpl/arg.hpp:25,
                 from /usr/include/boost/mpl/placeholders.hpp:24,
                 from /usr/include/boost/mpl/apply.hpp:24,
                 from /usr/include/boost/mpl/aux_/iter_apply.hpp:17,
                 from /usr/include/boost/mpl/aux_/find_if_pred.hpp:14,
                 from /usr/include/boost/mpl/find_if.hpp:17,
                 from /usr/include/boost/mpl/find.hpp:17,
                 from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
                 from /usr/include/boost/mpl/contains.hpp:20,
                 from /usr/include/boost/math/policies/policy.hpp:10,
                 from /usr/include/boost/math/special_functions/math_fwd.hpp:28,
                 from /usr/include/boost/math/special_functions/fpclassify.hpp:19,
                 from /usr/include/boost/units/cmath.hpp:17,
                 from ../GeodeticConsole/main.cpp:7:
/usr/include/boost/mpl/assert.hpp:79:5: note: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
/usr/include/boost/mpl/assert.hpp:79:5: note:   template argument deduction/substitution failed:
In file included from /usr/include/boost/units/dimensionless_quantity.hpp:20:0,
                 from /usr/include/boost/units/cmath.hpp:23,
                 from ../GeodeticConsole/main.cpp:7:
/usr/include/boost/units/quantity.hpp:92:9: note:   cannot convert 'mpl_::assert_not_arg<boost::units::detail::is_base_unit<boost::units::angle::degree_base_unit, void> >(0u, 1)' (type 'mpl_::failed************ boost::mpl::not_<boost::units::detail::is_base_unit<boost::units::angle::degree_base_unit, void> >::************') to type 'mpl_::assert<false>::type {aka mpl_::assert<false>}'
../GeodeticConsole/main.cpp: In function 'int main()':
../GeodeticConsole/main.cpp:36:98: error: expected primary-expression before ';' token
../GeodeticConsole/main.cpp:36:52: warning: unused variable 'FlindersSDeg' [-Wunused-variable]
make: *** [main.o] Error 1
make: Leaving directory `/home/***/projects/Qt/GeodeticConsole-build-Desktop_Qt_5_0_1_GCC_64bit-Debug'
16:59:15: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project GeodeticConsole (kit: Desktop Qt 5.0.1 GCC 64bit)
When executing step 'Make'
Last edited on
I think this is what you're looking for:

1
2
3
4
5
6
#include <boost/units/systems/angle/degrees.hpp>

....


    quantity<boost::units::degree::plane_angle> FlindersSDeg = -37.0 * boost::units::degree::degree;
Thanks very much for your reply - but that didn't work I am afraid. These errors:

../GeodeticConsole/main.cpp: In function 'int main()':
../GeodeticConsole/main.cpp:49:13: error: 'degree' is not a member of 'boost::units'
../GeodeticConsole/main.cpp:49:13: note: suggested alternatives:
In file included from /usr/include/boost/geometry/geometry.hpp:19:0,
                 from /usr/include/boost/geometry.hpp:17,
                 from ../GeodeticConsole/main.cpp:4:
/usr/include/boost/geometry/core/cs.hpp:35:8: note:   'boost::geometry::degree'
/usr/include/boost/geometry/core/cs.hpp:35:8: note:   'boost::geometry::degree'
In file included from /usr/include/boost/geometry/util/math.hpp:20:0,
                 from /usr/include/boost/geometry/core/radian_access.hpp:28,
                 from /usr/include/boost/geometry/geometry.hpp:28,
                 from /usr/include/boost/geometry.hpp:17,
                 from ../GeodeticConsole/main.cpp:4:
/usr/include/boost/math/constants/constants.hpp:254:3: note:   'boost::math::constants::degree'
/usr/include/boost/math/constants/constants.hpp:254:3: note:   'boost::math::float_constants::degree'
/usr/include/boost/math/constants/constants.hpp:254:3: note:   'boost::math::double_constants::degree'
/usr/include/boost/math/constants/constants.hpp:254:3: note:   'boost::math::long_double_constants::degree'


I am trying some of the suggestions, but they are not working so far either.

The following works, but I am having trouble trying to do minutes & seconds as well and convert to radians & caonvert back again.

1
2
3
typedef model::point<double, 2, cs::spherical_equatorial<degree> > degree_point;

   degree_point FlindersSE(-37.0, 144.0);



EDIT
Am also trying to fool around with these:

1
2
3
4
5
6
7
8
quantity<degree_base_unit> FlindersSDeg;
   FlindersSDeg.from_value(37.0);

   quantity<arcminute_base_unit> FlindersSMin;
   FlindersSMin.from_value(57.0);

   quantity<arcsecond_base_unit> FlindersSSec;
   FlindersSSec.from_value(3.72030);
Last edited on
Bump - are you out there Cubbi?

No panic, you probably need a chance to get away from a computer!!

Meanwhile I probably need to RTM properly.
Well, as I understand, the error is from the static assert within the quantity class. This assert checks if the template parameter is not a base unit. So I assume that any of the constructions in your last edit will not work.

I compiled this using MSVS 2010 and it really compiles. Did you include the file that I provided in the code snippet? Looks like the compiler just cannot find the declaration of boost::units::degree::plane_angle.

Anyway, this seems to work - at least it correctly treats the relationship between arcminutes and degress:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <iomanip>

//#include <boost/geometry.hpp>
//#include <boost/geometry/geometries/geometries.hpp>

#include <boost/units/cmath.hpp>
#include <boost/units/io.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/base_units/angle/degree.hpp>
#include <boost/units/base_units/angle/arcminute.hpp>
#include <boost/units/base_units/angle/arcsecond.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>
#include <boost/units/io.hpp>


// From boost/libs/units/example/systems.cpp
#define BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(namespace_,unit_name_,dimension_)              \
    namespace boost {                                                                            \
    namespace units {                                                                            \
    namespace namespace_ {                                                                       \
    typedef make_system<unit_name_ ## _base_unit>::type    unit_name_ ## system_;                \
    typedef unit<dimension_ ## _dimension,unit_name_ ## system_> unit_name_ ## _ ## dimension_;  \
    static const unit_name_ ## _ ## dimension_    unit_name_ ## s;                               \
}                                                                                            \
}                                                                                            \
}                                                                                            \

BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(angle,degree,plane_angle)
BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(angle,arcminute,plane_angle)

using boost::units::quantity;
using namespace boost::units;

typedef quantity<angle::degree_plane_angle> degreeQuantity;
typedef quantity<angle::arcminute_plane_angle> arcminuteQuantity;

int main(/*int argc, char *argv[]*/) {

    auto FlindersSDeg = -37.0 * angle::degrees + degreeQuantity(15 * angle::arcminutes);
    auto arcminuteTest = 15 * angle::arcminutes;

    FlindersSDeg += degreeQuantity(arcminuteTest);

    std::cout << FlindersSDeg << std::endl;
    return 0;
}
Last edited on
@KRAkatau

Thanks heaps - that worked & was exactly what I was after - I now have a good example of how it works.

I will now have a go at making my own class which uses this, so I can use it with the geometry types. Something similar to this obsolete code I found:

http://www.boost.org/doc/libs/1_47_0/libs/geometry/doc/doxy/doxygen_input/sourcecode/doxygen_1.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void example_dms()
{
/*
Extension, other coordinate system:
// Construction with degree/minute/seconds
boost::geometry::dms<boost::geometry::east> d1(4, 53, 32.5);

// Explicit conversion to double.
std::cout << d1.as_value() << std::endl;

// Conversion to string, with optional strings
std::cout << d1.get_dms(" deg ", " min ", " sec") << std::endl;

// Combination with latitude/longitude and cardinal directions
{
    using namespace boost::geometry;
    point_ll<double, boost::geometry::cs::geographic<boost::geometry::degree> >        canberra(
        latitude<>(dms<south>(35, 18, 27)),
        longitude<>(dms<east>(149, 7, 27.9)));
    std::cout << canberra << std::endl;
}
*/
}


Good Work & thanks for your time & effort.
Bump - are you out there Cubbi? No panic, you probably need a chance to get away from a computer!!

I wish I could get away from the computers! I have this thread bookmarked, but there is work to do.
@Cubbi

No worries - it will soon be the weekend (unless you are working then as well). I don't want to hold up one of the important people from their work & you should be entitled to spend your leisure time as you wish.

I am amazed that guys like yourself & others work all day in IT then spend time on forums as well.

KRAkatau has provided a good solution & I am having a go at extending it a bit.

BTW, I don't mean to restrict the list of who answers my questions - I only sprang the last question in the last post. I realise there are various people capable of answering & they too may be at work or elsewhere.

It would be handy if there was something to similar to the obsolete code above. I am not sure how to go about doing something similar, but in absence of knowing how to properly, I will start with making my own class to at least have dms in 1 compact statement. There was a section in documentation that talked about that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// the ideal gas law in si units
template<class Y>
quantity<si::amount,Y>
idealGasLaw(const quantity<si::pressure,Y>& P,
            const quantity<si::volume,Y>& V,
            const quantity<si::temperature,Y>& T)
{
    using namespace boost::units::si;

    using namespace constants::codata;
    return (P*V/(R*T));
}

/// test ideal gas law
quantity<temperature>   T = (273.+37.)*kelvin;
quantity<pressure>      P = 1.01325e5*pascals;
quantity<length>        r = 0.5e-6*meters;
quantity<volume>        V = (4.0/3.0)*3.141592*pow<3>(r);
quantity<amount>        n(idealGasLaw(P,V,T));



I am such a newbie with boost, that I am now trying different ways to convert to radians. I knew that I thought it would be easy, and I thought that I knew it would be easy !! I am trying to use quantity<si::plane_angle>to convert with because that is in radians. Maybe it's because the degrees value isn't scalar.

Any way - all of you have a beer for me after work :)

Edit I forgot to mention I asked about this on StackOverflow as well - will use that to convert to dms.

http://stackoverflow.com/questions/16465922/use-boost-to-convert-degrees-minutes-seconds-radians-boost-1-48-0


Last edited on
Ok, I have it working with KRAkatau's solution as well as that from Scott Jones at SO.

It seems a shame about the obsolete code - that had most of what I wanted. Maybe there is a way of doing the same thing in the new version of boost. Edit: I can see how to do that with my own DMS function and a geographical model point.

This is what I have so far - am not anticipating any problems with Scott Jones' code. And one would have to say that his is a lot easier than all this code - for a such a simple thing. Although I did say I wanted to learn to use the boost library, so it has been a worthwhile exercise. And I have yet to try the other parts of boost.

Edit: So it seems that this particular use case is so simple, I am better off writing my own code. However that isn't true if I wanted to do something more complex like calc the distance between two Lat / Long coords.

I will leave this post open for a couple of days in case there are some better ideas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
#include <iostream>
#include <iomanip>
#include <cmath>

#include <boost/units/cmath.hpp>
#include <boost/units/io.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/base_units/angle/degree.hpp>
#include <boost/units/base_units/angle/arcminute.hpp>
#include <boost/units/base_units/angle/arcsecond.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>
#include <boost/units/io.hpp>


// From boost/libs/units/example/systems.cpp
#define BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(namespace_,unit_name_,dimension_)              \
    namespace boost {                                                                            \
    namespace units {                                                                            \
    namespace namespace_ {                                                                       \
    typedef make_system<unit_name_ ## _base_unit>::type    unit_name_ ## system_;                \
    typedef unit<dimension_ ## _dimension,unit_name_ ## system_> unit_name_ ## _ ## dimension_;  \
    static const unit_name_ ## _ ## dimension_    unit_name_ ## s;                               \
}                                                                                            \
}                                                                                            \
}                                                                                            \

BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(angle,degree,plane_angle)
BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(angle,arcminute,plane_angle)
BOOST_UNITS_DEFINE_SINGLE_UNIT_SYSTEM(angle,arcsecond,plane_angle)

using boost::units::quantity;
using namespace boost::units;

typedef quantity<angle::degree_plane_angle> degQ;
typedef quantity<angle::arcminute_plane_angle> arcminQ;
typedef quantity<angle::arcsecond_plane_angle> arcsecQ;

int main() {

   auto FlindersSDeg = -( 37.0 * angle::degrees + degQ(57 * angle::arcminutes) \
                          + degQ(3.72030 * angle::arcseconds) );
    //auto arcminuteTest = 15 * angle::arcminutes; //this works

   double FlindersSDegDbl = FlindersSDeg.value();

    //FlindersSDeg += degQ(arcminuteTest); //this works

   //convert to radians
   quantity<si::plane_angle,double> FlindersSRadDbl = static_cast<quantity<si::plane_angle>>(FlindersSDeg);

   std::cout << std::setprecision(9);
    std::cout << "FlindersSDeg " << FlindersSDeg << std::endl;
    std::cout << "FlindersSDegDbl " << FlindersSDegDbl << std::endl;
    std::cout << "FlindersSDeg sin " << sin(FlindersSDeg)  << std::endl;
    std::cout << "FlindersSDegDbl sin " << sin(FlindersSDegDbl * M_PI / 180.0)  << std::endl;
    std::cout << "FlindersSRadDbl  " << FlindersSRadDbl  << std::endl;
    std::cout << "FlindersSRadDbl sin " << sin(FlindersSRadDbl)  << std::endl;
    return 0;
}

Last edited on
Topic archived. No new replies allowed.