/* Copyright 2008 Intel Corporation Use, modification and distribution are subject to 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). */ #ifndef BOOST_POLYGON_TRANSFORM_HPP #define BOOST_POLYGON_TRANSFORM_HPP #include "isotropy.hpp" #include "point_3d_concept.hpp" namespace boost { namespace polygon{ // Transformation of Coordinate Systems // Enum meaning: // Select which direction_3d to change the positive direction of each // axis in the old coordinate system to map it to the new coordiante system. // The first direction_3d listed for each enum is the direction to map the // positive horizontal direction to. // The second direction_3d listed for each enum is the direction to map the // positive vertical direction to. // The third direction_3d listed for each enum is the direction to map the // positive proximal direction to. // The zero position bit (LSB) indicates whether the horizontal axis flips // when transformed. // The 1st postion bit indicates whether the vertical axis flips when // transformed. // The 2nd position bit indicates whether the horizontal and vertical axis // swap positions when transformed. // Note that the first eight values are the complete set of 2D transforms. // The 3rd position bit indicates whether the proximal axis flips when // transformed. // The 4th position bit indicates whether the proximal and horizontal axis are // swapped when transformed. It changes the meaning of the 2nd position bit // to mean that the horizontal and vertical axis are swapped in their new // positions, naturally. // The 5th position bit (MSB) indicates whether the proximal and vertical axis // are swapped when transformed. It is mutually exclusive with the 4th postion // bit, making the maximum legal value 48 (decimal). It similarly changes the // meaning of the 2nd position bit to mean that the horizontal and vertical are // swapped in their new positions. // Enum Values: // 000000 EAST NORTH UP // 000001 WEST NORTH UP // 000010 EAST SOUTH UP // 000011 WEST SOUTH UP // 000100 NORTH EAST UP // 000101 SOUTH EAST UP // 000110 NORTH WEST UP // 000111 SOUTH WEST UP // 001000 EAST NORTH DOWN // 001001 WEST NORTH DOWN // 001010 EAST SOUTH DOWN // 001011 WEST SOUTH DOWN // 001100 NORTH EAST DOWN // 001101 SOUTH EAST DOWN // 001110 NORTH WEST DOWN // 001111 SOUTH WEST DOWN // 010000 UP NORTH EAST // 010001 DOWN NORTH EAST // 010010 UP SOUTH EAST // 010011 DOWN SOUTH EAST // 010100 NORTH UP EAST // 010101 SOUTH UP EAST // 010110 NORTH DOWN EAST // 010111 SOUTH DOWN EAST // 011000 UP NORTH WEST // 011001 DOWN NORTH WEST // 011010 UP SOUTH WEST // 011011 DOWN SOUTH WEST // 011100 NORTH UP WEST // 011101 SOUTH UP WEST // 011110 NORTH DOWN WEST // 011111 SOUTH DOWN WEST // 100000 EAST UP NORTH // 100001 WEST UP NORTH // 100010 EAST DOWN NORTH // 100011 WEST DOWN NORTH // 100100 UP EAST NORTH // 100101 DOWN EAST NORTH // 100110 UP WEST NORTH // 100111 DOWN WEST NORTH // 101000 EAST UP SOUTH // 101001 WEST UP SOUTH // 101010 EAST DOWN SOUTH // 101011 WEST DOWN SOUTH // 101100 UP EAST SOUTH // 101101 DOWN EAST SOUTH // 101110 UP WEST SOUTH // 101111 DOWN WEST SOUTH class axis_transformation { public: // Enum Names and values // NULL_TRANSFORM = 0, BEGIN_TRANSFORM = 0, // ENU = 0, EAST_NORTH_UP = 0, EN = 0, EAST_NORTH = 0, // WNU = 1, WEST_NORTH_UP = 1, WN = 1, WEST_NORTH = 1, FLIP_X = 1, // ESU = 2, EAST_SOUTH_UP = 2, ES = 2, EAST_SOUTH = 2, FLIP_Y = 2, // WSU = 3, WEST_SOUTH_UP = 3, WS = 3, WEST_SOUTH = 3, // NEU = 4, NORTH_EAST_UP = 4, NE = 4, NORTH_EAST = 4, SWAP_XY = 4, // SEU = 5, SOUTH_EAST_UP = 5, SE = 5, SOUTH_EAST = 5, // NWU = 6, NORTH_WEST_UP = 6, NW = 6, NORTH_WEST = 6, // SWU = 7, SOUTH_WEST_UP = 7, SW = 7, SOUTH_WEST = 7, // END_2D_TRANSFORM = 7, // END = 8, EAST_NORTH_DOWN = 8, // WND = 9, WEST_NORTH_DOWN = 9, // ESD = 10, EAST_SOUTH_DOWN = 10, // WSD = 11, WEST_SOUTH_DOWN = 11, // NED = 12, NORTH_EAST_DOWN = 12, // SED = 13, SOUTH_EAST_DOWN = 13, // NWD = 14, NORTH_WEST_DOWN = 14, // SWD = 15, SOUTH_WEST_DOWN = 15, // UNE = 16, UP_NORTH_EAST = 16, // DNE = 17, DOWN_NORTH_EAST = 17, // USE = 18, UP_SOUTH_EAST = 18, // DSE = 19, DOWN_SOUTH_EAST = 19, // NUE = 20, NORTH_UP_EAST = 20, // SUE = 21, SOUTH_UP_EAST = 21, // NDE = 22, NORTH_DOWN_EAST = 22, // SDE = 23, SOUTH_DOWN_EAST = 23, // UNW = 24, UP_NORTH_WEST = 24, // DNW = 25, DOWN_NORTH_WEST = 25, // USW = 26, UP_SOUTH_WEST = 26, // DSW = 27, DOWN_SOUTH_WEST = 27, // NUW = 28, NORTH_UP_WEST = 28, // SUW = 29, SOUTH_UP_WEST = 29, // NDW = 30, NORTH_DOWN_WEST = 30, // SDW = 31, SOUTH_DOWN_WEST = 31, // EUN = 32, EAST_UP_NORTH = 32, // WUN = 33, WEST_UP_NORTH = 33, // EDN = 34, EAST_DOWN_NORTH = 34, // WDN = 35, WEST_DOWN_NORTH = 35, // UEN = 36, UP_EAST_NORTH = 36, // DEN = 37, DOWN_EAST_NORTH = 37, // UWN = 38, UP_WEST_NORTH = 38, // DWN = 39, DOWN_WEST_NORTH = 39, // EUS = 40, EAST_UP_SOUTH = 40, // WUS = 41, WEST_UP_SOUTH = 41, // EDS = 42, EAST_DOWN_SOUTH = 42, // WDS = 43, WEST_DOWN_SOUTH = 43, // UES = 44, UP_EAST_SOUTH = 44, // DES = 45, DOWN_EAST_SOUTH = 45, // UWS = 46, UP_WEST_SOUTH = 46, // DWS = 47, DOWN_WEST_SOUTH = 47, END_TRANSFORM = 47 enum ATR { NULL_TRANSFORM = 0, BEGIN_TRANSFORM = 0, ENU = 0, EAST_NORTH_UP = 0, EN = 0, EAST_NORTH = 0, WNU = 1, WEST_NORTH_UP = 1, WN = 1, WEST_NORTH = 1, FLIP_X = 1, ESU = 2, EAST_SOUTH_UP = 2, ES = 2, EAST_SOUTH = 2, FLIP_Y = 2, WSU = 3, WEST_SOUTH_UP = 3, WS = 3, WEST_SOUTH = 3, FLIP_XY = 3, NEU = 4, NORTH_EAST_UP = 4, NE = 4, NORTH_EAST = 4, SWAP_XY = 4, SEU = 5, SOUTH_EAST_UP = 5, SE = 5, SOUTH_EAST = 5, ROTATE_LEFT = 5, NWU = 6, NORTH_WEST_UP = 6, NW = 6, NORTH_WEST = 6, ROTATE_RIGHT = 6, SWU = 7, SOUTH_WEST_UP = 7, SW = 7, SOUTH_WEST = 7, FLIP_SWAP_XY = 7, END_2D_TRANSFORM = 7, END = 8, EAST_NORTH_DOWN = 8, FLIP_Z = 8, WND = 9, WEST_NORTH_DOWN = 9, ESD = 10, EAST_SOUTH_DOWN = 10, WSD = 11, WEST_SOUTH_DOWN = 11, NED = 12, NORTH_EAST_DOWN = 12, SED = 13, SOUTH_EAST_DOWN = 13, NWD = 14, NORTH_WEST_DOWN = 14, SWD = 15, SOUTH_WEST_DOWN = 15, UNE = 16, UP_NORTH_EAST = 16, DNE = 17, DOWN_NORTH_EAST = 17, USE = 18, UP_SOUTH_EAST = 18, DSE = 19, DOWN_SOUTH_EAST = 19, NUE = 20, NORTH_UP_EAST = 20, SUE = 21, SOUTH_UP_EAST = 21, NDE = 22, NORTH_DOWN_EAST = 22, SDE = 23, SOUTH_DOWN_EAST = 23, UNW = 24, UP_NORTH_WEST = 24, DNW = 25, DOWN_NORTH_WEST = 25, USW = 26, UP_SOUTH_WEST = 26, DSW = 27, DOWN_SOUTH_WEST = 27, NUW = 28, NORTH_UP_WEST = 28, SUW = 29, SOUTH_UP_WEST = 29, NDW = 30, NORTH_DOWN_WEST = 30, SDW = 31, SOUTH_DOWN_WEST = 31, EUN = 32, EAST_UP_NORTH = 32, WUN = 33, WEST_UP_NORTH = 33, EDN = 34, EAST_DOWN_NORTH = 34, WDN = 35, WEST_DOWN_NORTH = 35, UEN = 36, UP_EAST_NORTH = 36, DEN = 37, DOWN_EAST_NORTH = 37, UWN = 38, UP_WEST_NORTH = 38, DWN = 39, DOWN_WEST_NORTH = 39, EUS = 40, EAST_UP_SOUTH = 40, WUS = 41, WEST_UP_SOUTH = 41, EDS = 42, EAST_DOWN_SOUTH = 42, WDS = 43, WEST_DOWN_SOUTH = 43, UES = 44, UP_EAST_SOUTH = 44, DES = 45, DOWN_EAST_SOUTH = 45, UWS = 46, UP_WEST_SOUTH = 46, DWS = 47, DOWN_WEST_SOUTH = 47, END_TRANSFORM = 47 }; // Individual axis enum values indicate which axis an implicit individual // axis will be mapped to. // The value of the enum paired with an axis provides the information // about what the axis will transform to. // Three individual axis values, one for each axis, are equivalent to one // ATR enum value, but easier to work with because they are independent. // Converting to and from the individual axis values from the ATR value // is a convenient way to implement tranformation related functionality. // Enum meanings: // PX: map to positive x axis // NX: map to negative x axis // PY: map to positive y axis // NY: map to negative y axis // PZ: map to positive z axis // NZ: map to negative z axis enum INDIVIDUAL_AXIS { PX = 0, NX = 1, PY = 2, NY = 3, PZ = 4, NZ = 5 }; inline axis_transformation() : atr_(NULL_TRANSFORM) {} inline axis_transformation(ATR atr) : atr_(atr) {} inline axis_transformation(const axis_transformation& atr) : atr_(atr.atr_) {} explicit axis_transformation(const orientation_3d& orient); explicit axis_transformation(const direction_3d& dir); explicit axis_transformation(const orientation_2d& orient); explicit axis_transformation(const direction_2d& dir); // assignment operator axis_transformation& operator=(const axis_transformation& a); // assignment operator axis_transformation& operator=(const ATR& atr); // equivalence operator bool operator==(const axis_transformation& a) const; // inequivalence operator bool operator!=(const axis_transformation& a) const; // ordering bool operator<(const axis_transformation& a) const; // concatenation operator axis_transformation operator+(const axis_transformation& a) const; // concatenate this with that axis_transformation& operator+=(const axis_transformation& a); // populate_axis_array writes the three INDIVIDUAL_AXIS values that the // ATR enum value of 'this' represent into axis_array void populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const; // it is recommended that the directions stored in an array // in the caller code for easier isotropic access by orientation value inline void get_directions(direction_2d& horizontal_dir, direction_2d& vertical_dir) const { bool bit2 = (atr_ & 4) != 0; bool bit1 = (atr_ & 2) != 0; bool bit0 = (atr_ & 1) != 0; vertical_dir = direction_2d((direction_2d_enum)(((int)(!bit2) << 1) + !bit1)); horizontal_dir = direction_2d((direction_2d_enum)(((int)(bit2) << 1) + !bit0)); } // it is recommended that the directions stored in an array // in the caller code for easier isotropic access by orientation value inline void get_directions(direction_3d& horizontal_dir, direction_3d& vertical_dir, direction_3d& proximal_dir) const { bool bit5 = (atr_ & 32) != 0; bool bit4 = (atr_ & 16) != 0; bool bit3 = (atr_ & 8) != 0; bool bit2 = (atr_ & 4) != 0; bool bit1 = (atr_ & 2) != 0; bool bit0 = (atr_ & 1) != 0; proximal_dir = direction_3d((direction_2d_enum)((((int)(!bit4 & !bit5)) << 2) + ((int)(bit5) << 1) + !bit3)); vertical_dir = direction_3d((direction_2d_enum)((((int)((bit4 & bit2) | (bit5 & !bit2))) << 2)+ ((int)(!bit5 & !bit2) << 1) + !bit1)); horizontal_dir = direction_3d((direction_2d_enum)((((int)((bit5 & bit2) | (bit4 & !bit2))) << 2) + ((int)(bit2 & !bit5) << 1) + !bit0)); } // combine_axis_arrays concatenates this_array and that_array overwriting // the result into this_array static void combine_axis_arrays (INDIVIDUAL_AXIS this_array[], const INDIVIDUAL_AXIS that_array[]); // write_back_axis_array converts an array of three INDIVIDUAL_AXIS values // to the ATR enum value and sets 'this' to that value void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]); // behavior is deterministic but undefined in the case where illegal // combinations of directions are passed in. axis_transformation& set_directions(const direction_2d& horizontal_dir, const direction_2d& vertical_dir); // behavior is deterministic but undefined in the case where illegal // combinations of directions are passed in. axis_transformation& set_directions(const direction_3d& horizontal_dir, const direction_3d& vertical_dir, const direction_3d& proximal_dir); // transform the two coordinates by reference using the 2D portion of this template void transform(coordinate_type& x, coordinate_type& y) const; // transform the three coordinates by reference template void transform(coordinate_type& x, coordinate_type& y, coordinate_type& z) const; // invert the 2D portion of this axis_transformation& invert_2d(); // get the inverse of the 2D portion of this axis_transformation inverse_2d() const; // invert this axis_transformation axis_transformation& invert(); // get the inverse axis_transformation of this axis_transformation inverse() const; //friend std::ostream& operator<< (std::ostream& o, const axis_transformation& r); //friend std::istream& operator>> (std::istream& i, axis_transformation& r); private: ATR atr_; }; // Scaling object to be used to store the scale factor for each axis // For use by the transformation object, in that context the scale factor // is the amount that each axis scales by when transformed. // If the horizontal value of the Scale is 10 that means the horizontal // axis of the input is multiplied by 10 when the transformation is applied. template class anisotropic_scale_factor { public: inline anisotropic_scale_factor() #ifndef BOOST_POLYGON_MSVC : scale_() #endif { scale_[0] = 1; scale_[1] = 1; scale_[2] = 1; } inline anisotropic_scale_factor(scale_factor_type xscale, scale_factor_type yscale) #ifndef BOOST_POLYGON_MSVC : scale_() #endif { scale_[0] = xscale; scale_[1] = yscale; scale_[2] = 1; } inline anisotropic_scale_factor(scale_factor_type xscale, scale_factor_type yscale, scale_factor_type zscale) #ifndef BOOST_POLYGON_MSVC : scale_() #endif { scale_[0] = xscale; scale_[1] = yscale; scale_[2] = zscale; } // get a component of the anisotropic_scale_factor by orientation scale_factor_type get(orientation_3d orient) const; scale_factor_type get(orientation_2d orient) const { return get(orientation_3d(orient)); } // set a component of the anisotropic_scale_factor by orientation void set(orientation_3d orient, scale_factor_type value); void set(orientation_2d orient, scale_factor_type value) { set(orientation_3d(orient), value); } scale_factor_type x() const; scale_factor_type y() const; scale_factor_type z() const; void x(scale_factor_type value); void y(scale_factor_type value); void z(scale_factor_type value); // concatination operator (convolve scale factors) anisotropic_scale_factor operator+(const anisotropic_scale_factor& s) const; // concatinate this with that const anisotropic_scale_factor& operator+=(const anisotropic_scale_factor& s); // transform this scale with an axis_transform anisotropic_scale_factor& transform(axis_transformation atr); // scale the two coordinates template void scale(coordinate_type& x, coordinate_type& y) const; // scale the three coordinates template void scale(coordinate_type& x, coordinate_type& y, coordinate_type& z) const; // invert this scale factor to give the reverse scale factor anisotropic_scale_factor& invert(); private: scale_factor_type scale_[3]; //friend std::ostream& operator<< (std::ostream& o, const Scale& r); //friend std::istream& operator>> (std::istream& i, Scale& r); }; // Transformation object, stores and provides services for transformations // Transformation object stores an axistransformation, a scale factor and a translation. // The tranlation is the position of the origin of the new system of coordinates in the old system. // The scale scales the coordinates before they are transformed. template class transformation { public: transformation(); transformation(axis_transformation atr); transformation(axis_transformation::ATR atr); template transformation(const point_type& p); template transformation(axis_transformation atr, const point_type& p); template transformation(axis_transformation atr, const point_type& referencePt, const point_type& destinationPt); transformation(const transformation& tr); // equivalence operator bool operator==(const transformation& tr) const; // inequivalence operator bool operator!=(const transformation& tr) const; // ordering bool operator<(const transformation& tr) const; // concatenation operator transformation operator+(const transformation& tr) const; // concatenate this with that const transformation& operator+=(const transformation& tr); // get the axis_transformation portion of this inline axis_transformation get_axis_transformation() const {return atr_;} // set the axis_transformation portion of this void set_axis_transformation(const axis_transformation& atr); // get the translation portion of this as a point3d template void get_translation(point_type& translation) const; // set the translation portion of this with a point3d template void set_translation(const point_type& p); // apply the 2D portion of this transformation to the two coordinates given void transform(coordinate_type& x, coordinate_type& y) const; // apply this transformation to the three coordinates given void transform(coordinate_type& x, coordinate_type& y, coordinate_type& z) const; // invert this transformation transformation& invert(); // get the inverse of this transformation transformation inverse() const; inline void get_directions(direction_2d& horizontal_dir, direction_2d& vertical_dir) const { return atr_.get_directions(horizontal_dir, vertical_dir); } inline void get_directions(direction_3d& horizontal_dir, direction_3d& vertical_dir, direction_3d& proximal_dir) const { return atr_.get_directions(horizontal_dir, vertical_dir, proximal_dir); } private: axis_transformation atr_; point_3d_data p_; template void construct_dispatch(axis_transformation atr, point_type p, point_concept tag); template void construct_dispatch(axis_transformation atr, point_type p, point_3d_concept tag); template void construct_dispatch(axis_transformation atr, point_type rp, point_type dp, point_concept tag); template void construct_dispatch(axis_transformation atr, point_type rp, point_type dp, point_3d_concept tag); //friend std::ostream& operator<< (std::ostream& o, const transformation& tr); //friend std::istream& operator>> (std::istream& i, transformation& tr); }; } } #include "detail/transform_detail.hpp" #endif