
Hi Michael,
When working in 3d simulations it is necessary to transform vectors to different spaces. Bugs sometimes crop up when, for instance, adding a object space vector to a world space vector or adding a vector from object a's object space to one from object b's object space. It would be nice to catch such inconsistencies at compile-time. I have a feeling a units-like library would be able to handle this but I have no idea how it would work.
Here are two ways to do it, with the quantity wrapping the vector or the vector containing quantities: // mcs::units - A C++ library for zero-overhead dimensional analysis and // unit/quantity manipulation and conversion // // Copyright (C) 2003-2007 Matthias Christian Schabel // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // unit_example_15.cpp #include <iostream> #include <boost/array.hpp> #include <boost/units/quantity.hpp> namespace boost { namespace units { namespace wo { struct world_space_tag : public ordinal<1> { }; struct object_space_tag : public ordinal<2> { }; typedef fundamental_dimension<world_space_tag>::type world_space_type; typedef fundamental_dimension<object_space_tag>::type object_space_type; /// placeholder class defining test unit system struct system { }; /// unit typedefs typedef unit<system,dimensionless_type> dimensionless; typedef unit<system,world_space_type> world_space_unit; typedef unit<system,object_space_type> object_space_unit; static const world_space_unit world_space; static const object_space_unit object_space; } // namespace wo } // namespace units } // namespace boost int main(void) { using namespace boost::units; using namespace boost::units::wo; { typedef boost::array<double,3> vector; const vector vec1 = { 0, 0, 0 }, vec2 = { 1, 1, 1 }; quantity<world_space_unit,vector> wsv1(vec1*world_space), wsv2(vec2*world_space); quantity<object_space_unit,vector> osv1(vec1*object_space), osv2(vec2*object_space); quantity<world_space_unit,vector> wsv3(wsv1); quantity<object_space_unit,vector> osv3(osv1); // compile-time error if either of these is uncommented // quantity<world_space_unit,vector> wsv4(osv1); // quantity<object_space_unit,vector> osv4(wsv1); } { typedef quantity<world_space_unit> world_space_quantity; typedef quantity<object_space_unit> object_space_quantity; typedef boost::array<world_space_quantity,3> world_space_vector; typedef boost::array<object_space_quantity,3> object_space_vector; world_space_vector wsv1 = { 0*world_space, 0*world_space, 0*world_space }, wsv2 = { 1*world_space, 1*world_space, 1*world_space }; object_space_vector osv1 = { 0*object_space, 0*object_space, 0*object_space }, osv2 = { 1*object_space, 1*object_space, 1*object_space }; world_space_vector wsv3(wsv1); object_space_vector osv3(osv1); // compile-time error if either of these is uncommented // world_space_vector wsv4(osv1); // object_space_vector osv4(wsv1); } return 0; } You should be able to drop any well-defined vector class into this and have it work... Naturally, you can also define your own conversion function (see conversion.hpp for the default implementation). Because quantities obey the laws of dimensional analysis, the only operations supported by them are addition, subtraction, multiplication, division, and rational powers and roots. If you want to do other things, you will need to extract the raw value_type using the value() member function... Another way to do this would be to define two unit systems, the world unit system and the object unit system and define conversions between the two of them. For this sort of application, there are many paths to Rome. The right one probably depends on the details of the application. Cheers, Matthias