1 /* 2 Copyright 2008 Intel Corporation 3 4 Use, modification and distribution are subject to the Boost Software License, 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 http://www.boost.org/LICENSE_1_0.txt). 7 */ 8 #ifndef BOOST_POLYGON_TRANSFORM_HPP 9 #define BOOST_POLYGON_TRANSFORM_HPP 10 #include "isotropy.hpp" 11 #include "point_3d_concept.hpp" 12 namespace boost { namespace polygon{ 13 // Transformation of Coordinate Systems 14 // Enum meaning: 15 // Select which direction_3d to change the positive direction of each 16 // axis in the old coordinate system to map it to the new coordiante system. 17 // The first direction_3d listed for each enum is the direction to map the 18 // positive horizontal direction to. 19 // The second direction_3d listed for each enum is the direction to map the 20 // positive vertical direction to. 21 // The third direction_3d listed for each enum is the direction to map the 22 // positive proximal direction to. 23 // The zero position bit (LSB) indicates whether the horizontal axis flips 24 // when transformed. 25 // The 1st postion bit indicates whether the vertical axis flips when 26 // transformed. 27 // The 2nd position bit indicates whether the horizontal and vertical axis 28 // swap positions when transformed. 29 // Note that the first eight values are the complete set of 2D transforms. 30 // The 3rd position bit indicates whether the proximal axis flips when 31 // transformed. 32 // The 4th position bit indicates whether the proximal and horizontal axis are 33 // swapped when transformed. It changes the meaning of the 2nd position bit 34 // to mean that the horizontal and vertical axis are swapped in their new 35 // positions, naturally. 36 // The 5th position bit (MSB) indicates whether the proximal and vertical axis 37 // are swapped when transformed. It is mutually exclusive with the 4th postion 38 // bit, making the maximum legal value 48 (decimal). It similarly changes the 39 // meaning of the 2nd position bit to mean that the horizontal and vertical are 40 // swapped in their new positions. 41 // Enum Values: 42 // 000000 EAST NORTH UP 43 // 000001 WEST NORTH UP 44 // 000010 EAST SOUTH UP 45 // 000011 WEST SOUTH UP 46 // 000100 NORTH EAST UP 47 // 000101 SOUTH EAST UP 48 // 000110 NORTH WEST UP 49 // 000111 SOUTH WEST UP 50 // 001000 EAST NORTH DOWN 51 // 001001 WEST NORTH DOWN 52 // 001010 EAST SOUTH DOWN 53 // 001011 WEST SOUTH DOWN 54 // 001100 NORTH EAST DOWN 55 // 001101 SOUTH EAST DOWN 56 // 001110 NORTH WEST DOWN 57 // 001111 SOUTH WEST DOWN 58 // 010000 UP NORTH EAST 59 // 010001 DOWN NORTH EAST 60 // 010010 UP SOUTH EAST 61 // 010011 DOWN SOUTH EAST 62 // 010100 NORTH UP EAST 63 // 010101 SOUTH UP EAST 64 // 010110 NORTH DOWN EAST 65 // 010111 SOUTH DOWN EAST 66 // 011000 UP NORTH WEST 67 // 011001 DOWN NORTH WEST 68 // 011010 UP SOUTH WEST 69 // 011011 DOWN SOUTH WEST 70 // 011100 NORTH UP WEST 71 // 011101 SOUTH UP WEST 72 // 011110 NORTH DOWN WEST 73 // 011111 SOUTH DOWN WEST 74 // 100000 EAST UP NORTH 75 // 100001 WEST UP NORTH 76 // 100010 EAST DOWN NORTH 77 // 100011 WEST DOWN NORTH 78 // 100100 UP EAST NORTH 79 // 100101 DOWN EAST NORTH 80 // 100110 UP WEST NORTH 81 // 100111 DOWN WEST NORTH 82 // 101000 EAST UP SOUTH 83 // 101001 WEST UP SOUTH 84 // 101010 EAST DOWN SOUTH 85 // 101011 WEST DOWN SOUTH 86 // 101100 UP EAST SOUTH 87 // 101101 DOWN EAST SOUTH 88 // 101110 UP WEST SOUTH 89 // 101111 DOWN WEST SOUTH 90 class axis_transformation { 91 public: 92 // Enum Names and values 93 // NULL_TRANSFORM = 0, BEGIN_TRANSFORM = 0, 94 // ENU = 0, EAST_NORTH_UP = 0, EN = 0, EAST_NORTH = 0, 95 // WNU = 1, WEST_NORTH_UP = 1, WN = 1, WEST_NORTH = 1, FLIP_X = 1, 96 // ESU = 2, EAST_SOUTH_UP = 2, ES = 2, EAST_SOUTH = 2, FLIP_Y = 2, 97 // WSU = 3, WEST_SOUTH_UP = 3, WS = 3, WEST_SOUTH = 3, 98 // NEU = 4, NORTH_EAST_UP = 4, NE = 4, NORTH_EAST = 4, SWAP_XY = 4, 99 // SEU = 5, SOUTH_EAST_UP = 5, SE = 5, SOUTH_EAST = 5, 100 // NWU = 6, NORTH_WEST_UP = 6, NW = 6, NORTH_WEST = 6, 101 // SWU = 7, SOUTH_WEST_UP = 7, SW = 7, SOUTH_WEST = 7, 102 // END_2D_TRANSFORM = 7, 103 // END = 8, EAST_NORTH_DOWN = 8, 104 // WND = 9, WEST_NORTH_DOWN = 9, 105 // ESD = 10, EAST_SOUTH_DOWN = 10, 106 // WSD = 11, WEST_SOUTH_DOWN = 11, 107 // NED = 12, NORTH_EAST_DOWN = 12, 108 // SED = 13, SOUTH_EAST_DOWN = 13, 109 // NWD = 14, NORTH_WEST_DOWN = 14, 110 // SWD = 15, SOUTH_WEST_DOWN = 15, 111 // UNE = 16, UP_NORTH_EAST = 16, 112 // DNE = 17, DOWN_NORTH_EAST = 17, 113 // USE = 18, UP_SOUTH_EAST = 18, 114 // DSE = 19, DOWN_SOUTH_EAST = 19, 115 // NUE = 20, NORTH_UP_EAST = 20, 116 // SUE = 21, SOUTH_UP_EAST = 21, 117 // NDE = 22, NORTH_DOWN_EAST = 22, 118 // SDE = 23, SOUTH_DOWN_EAST = 23, 119 // UNW = 24, UP_NORTH_WEST = 24, 120 // DNW = 25, DOWN_NORTH_WEST = 25, 121 // USW = 26, UP_SOUTH_WEST = 26, 122 // DSW = 27, DOWN_SOUTH_WEST = 27, 123 // NUW = 28, NORTH_UP_WEST = 28, 124 // SUW = 29, SOUTH_UP_WEST = 29, 125 // NDW = 30, NORTH_DOWN_WEST = 30, 126 // SDW = 31, SOUTH_DOWN_WEST = 31, 127 // EUN = 32, EAST_UP_NORTH = 32, 128 // WUN = 33, WEST_UP_NORTH = 33, 129 // EDN = 34, EAST_DOWN_NORTH = 34, 130 // WDN = 35, WEST_DOWN_NORTH = 35, 131 // UEN = 36, UP_EAST_NORTH = 36, 132 // DEN = 37, DOWN_EAST_NORTH = 37, 133 // UWN = 38, UP_WEST_NORTH = 38, 134 // DWN = 39, DOWN_WEST_NORTH = 39, 135 // EUS = 40, EAST_UP_SOUTH = 40, 136 // WUS = 41, WEST_UP_SOUTH = 41, 137 // EDS = 42, EAST_DOWN_SOUTH = 42, 138 // WDS = 43, WEST_DOWN_SOUTH = 43, 139 // UES = 44, UP_EAST_SOUTH = 44, 140 // DES = 45, DOWN_EAST_SOUTH = 45, 141 // UWS = 46, UP_WEST_SOUTH = 46, 142 // DWS = 47, DOWN_WEST_SOUTH = 47, END_TRANSFORM = 47 143 enum ATR { 144 NULL_TRANSFORM = 0, BEGIN_TRANSFORM = 0, 145 ENU = 0, EAST_NORTH_UP = 0, EN = 0, EAST_NORTH = 0, 146 WNU = 1, WEST_NORTH_UP = 1, WN = 1, WEST_NORTH = 1, FLIP_X = 1, 147 ESU = 2, EAST_SOUTH_UP = 2, ES = 2, EAST_SOUTH = 2, FLIP_Y = 2, 148 WSU = 3, WEST_SOUTH_UP = 3, WS = 3, WEST_SOUTH = 3, FLIP_XY = 3, 149 NEU = 4, NORTH_EAST_UP = 4, NE = 4, NORTH_EAST = 4, SWAP_XY = 4, 150 SEU = 5, SOUTH_EAST_UP = 5, SE = 5, SOUTH_EAST = 5, ROTATE_LEFT = 5, 151 NWU = 6, NORTH_WEST_UP = 6, NW = 6, NORTH_WEST = 6, ROTATE_RIGHT = 6, 152 SWU = 7, SOUTH_WEST_UP = 7, SW = 7, SOUTH_WEST = 7, FLIP_SWAP_XY = 7, END_2D_TRANSFORM = 7, 153 END = 8, EAST_NORTH_DOWN = 8, FLIP_Z = 8, 154 WND = 9, WEST_NORTH_DOWN = 9, 155 ESD = 10, EAST_SOUTH_DOWN = 10, 156 WSD = 11, WEST_SOUTH_DOWN = 11, 157 NED = 12, NORTH_EAST_DOWN = 12, 158 SED = 13, SOUTH_EAST_DOWN = 13, 159 NWD = 14, NORTH_WEST_DOWN = 14, 160 SWD = 15, SOUTH_WEST_DOWN = 15, 161 UNE = 16, UP_NORTH_EAST = 16, 162 DNE = 17, DOWN_NORTH_EAST = 17, 163 USE = 18, UP_SOUTH_EAST = 18, 164 DSE = 19, DOWN_SOUTH_EAST = 19, 165 NUE = 20, NORTH_UP_EAST = 20, 166 SUE = 21, SOUTH_UP_EAST = 21, 167 NDE = 22, NORTH_DOWN_EAST = 22, 168 SDE = 23, SOUTH_DOWN_EAST = 23, 169 UNW = 24, UP_NORTH_WEST = 24, 170 DNW = 25, DOWN_NORTH_WEST = 25, 171 USW = 26, UP_SOUTH_WEST = 26, 172 DSW = 27, DOWN_SOUTH_WEST = 27, 173 NUW = 28, NORTH_UP_WEST = 28, 174 SUW = 29, SOUTH_UP_WEST = 29, 175 NDW = 30, NORTH_DOWN_WEST = 30, 176 SDW = 31, SOUTH_DOWN_WEST = 31, 177 EUN = 32, EAST_UP_NORTH = 32, 178 WUN = 33, WEST_UP_NORTH = 33, 179 EDN = 34, EAST_DOWN_NORTH = 34, 180 WDN = 35, WEST_DOWN_NORTH = 35, 181 UEN = 36, UP_EAST_NORTH = 36, 182 DEN = 37, DOWN_EAST_NORTH = 37, 183 UWN = 38, UP_WEST_NORTH = 38, 184 DWN = 39, DOWN_WEST_NORTH = 39, 185 EUS = 40, EAST_UP_SOUTH = 40, 186 WUS = 41, WEST_UP_SOUTH = 41, 187 EDS = 42, EAST_DOWN_SOUTH = 42, 188 WDS = 43, WEST_DOWN_SOUTH = 43, 189 UES = 44, UP_EAST_SOUTH = 44, 190 DES = 45, DOWN_EAST_SOUTH = 45, 191 UWS = 46, UP_WEST_SOUTH = 46, 192 DWS = 47, DOWN_WEST_SOUTH = 47, END_TRANSFORM = 47 193 }; 194 195 // Individual axis enum values indicate which axis an implicit individual 196 // axis will be mapped to. 197 // The value of the enum paired with an axis provides the information 198 // about what the axis will transform to. 199 // Three individual axis values, one for each axis, are equivalent to one 200 // ATR enum value, but easier to work with because they are independent. 201 // Converting to and from the individual axis values from the ATR value 202 // is a convenient way to implement tranformation related functionality. 203 // Enum meanings: 204 // PX: map to positive x axis 205 // NX: map to negative x axis 206 // PY: map to positive y axis 207 // NY: map to negative y axis 208 // PZ: map to positive z axis 209 // NZ: map to negative z axis 210 enum INDIVIDUAL_AXIS { 211 PX = 0, 212 NX = 1, 213 PY = 2, 214 NY = 3, 215 PZ = 4, 216 NZ = 5 217 }; 218 axis_transformation()219 inline axis_transformation() : atr_(NULL_TRANSFORM) {} axis_transformation(ATR atr)220 inline axis_transformation(ATR atr) : atr_(atr) {} axis_transformation(const axis_transformation & atr)221 inline axis_transformation(const axis_transformation& atr) : atr_(atr.atr_) {} 222 explicit axis_transformation(const orientation_3d& orient); 223 explicit axis_transformation(const direction_3d& dir); 224 explicit axis_transformation(const orientation_2d& orient); 225 explicit axis_transformation(const direction_2d& dir); 226 227 // assignment operator 228 axis_transformation& operator=(const axis_transformation& a); 229 230 // assignment operator 231 axis_transformation& operator=(const ATR& atr); 232 233 // equivalence operator 234 bool operator==(const axis_transformation& a) const; 235 236 // inequivalence operator 237 bool operator!=(const axis_transformation& a) const; 238 239 // ordering 240 bool operator<(const axis_transformation& a) const; 241 242 // concatenation operator 243 axis_transformation operator+(const axis_transformation& a) const; 244 245 // concatenate this with that 246 axis_transformation& operator+=(const axis_transformation& a); 247 248 // populate_axis_array writes the three INDIVIDUAL_AXIS values that the 249 // ATR enum value of 'this' represent into axis_array 250 void populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const; 251 252 // it is recommended that the directions stored in an array 253 // in the caller code for easier isotropic access by orientation value get_directions(direction_2d & horizontal_dir,direction_2d & vertical_dir) const254 inline void get_directions(direction_2d& horizontal_dir, 255 direction_2d& vertical_dir) const { 256 bool bit2 = (atr_ & 4) != 0; 257 bool bit1 = (atr_ & 2) != 0; 258 bool bit0 = (atr_ & 1) != 0; 259 vertical_dir = direction_2d((direction_2d_enum)(((int)(!bit2) << 1) + !bit1)); 260 horizontal_dir = direction_2d((direction_2d_enum)(((int)(bit2) << 1) + !bit0)); 261 } 262 263 // it is recommended that the directions stored in an array 264 // in the caller code for easier isotropic access by orientation value get_directions(direction_3d & horizontal_dir,direction_3d & vertical_dir,direction_3d & proximal_dir) const265 inline void get_directions(direction_3d& horizontal_dir, 266 direction_3d& vertical_dir, 267 direction_3d& proximal_dir) const { 268 bool bit5 = (atr_ & 32) != 0; 269 bool bit4 = (atr_ & 16) != 0; 270 bool bit3 = (atr_ & 8) != 0; 271 bool bit2 = (atr_ & 4) != 0; 272 bool bit1 = (atr_ & 2) != 0; 273 bool bit0 = (atr_ & 1) != 0; 274 proximal_dir = direction_3d((direction_2d_enum)((((int)(!bit4 & !bit5)) << 2) + 275 ((int)(bit5) << 1) + 276 !bit3)); 277 vertical_dir = direction_3d((direction_2d_enum)((((int)((bit4 & bit2) | (bit5 & !bit2))) << 2)+ 278 ((int)(!bit5 & !bit2) << 1) + 279 !bit1)); 280 horizontal_dir = direction_3d((direction_2d_enum)((((int)((bit5 & bit2) | 281 (bit4 & !bit2))) << 2) + 282 ((int)(bit2 & !bit5) << 1) + 283 !bit0)); 284 } 285 286 // combine_axis_arrays concatenates this_array and that_array overwriting 287 // the result into this_array 288 static void combine_axis_arrays (INDIVIDUAL_AXIS this_array[], 289 const INDIVIDUAL_AXIS that_array[]); 290 291 // write_back_axis_array converts an array of three INDIVIDUAL_AXIS values 292 // to the ATR enum value and sets 'this' to that value 293 void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]); 294 295 // behavior is deterministic but undefined in the case where illegal 296 // combinations of directions are passed in. 297 axis_transformation& set_directions(const direction_2d& horizontal_dir, 298 const direction_2d& vertical_dir); 299 // behavior is deterministic but undefined in the case where illegal 300 // combinations of directions are passed in. 301 axis_transformation& set_directions(const direction_3d& horizontal_dir, 302 const direction_3d& vertical_dir, 303 const direction_3d& proximal_dir); 304 305 // transform the two coordinates by reference using the 2D portion of this 306 template <typename coordinate_type> 307 void transform(coordinate_type& x, coordinate_type& y) const; 308 309 // transform the three coordinates by reference 310 template <typename coordinate_type> 311 void transform(coordinate_type& x, coordinate_type& y, coordinate_type& z) const; 312 313 // invert the 2D portion of this 314 axis_transformation& invert_2d(); 315 316 // get the inverse of the 2D portion of this 317 axis_transformation inverse_2d() const; 318 319 // invert this axis_transformation 320 axis_transformation& invert(); 321 322 // get the inverse axis_transformation of this 323 axis_transformation inverse() const; 324 325 //friend std::ostream& operator<< (std::ostream& o, const axis_transformation& r); 326 //friend std::istream& operator>> (std::istream& i, axis_transformation& r); 327 328 private: 329 ATR atr_; 330 }; 331 332 333 // Scaling object to be used to store the scale factor for each axis 334 335 // For use by the transformation object, in that context the scale factor 336 // is the amount that each axis scales by when transformed. 337 // If the horizontal value of the Scale is 10 that means the horizontal 338 // axis of the input is multiplied by 10 when the transformation is applied. 339 template <typename scale_factor_type> 340 class anisotropic_scale_factor { 341 public: anisotropic_scale_factor()342 inline anisotropic_scale_factor() 343 #ifndef BOOST_POLYGON_MSVC 344 : scale_() 345 #endif 346 { 347 scale_[0] = 1; 348 scale_[1] = 1; 349 scale_[2] = 1; 350 } anisotropic_scale_factor(scale_factor_type xscale,scale_factor_type yscale)351 inline anisotropic_scale_factor(scale_factor_type xscale, scale_factor_type yscale) 352 #ifndef BOOST_POLYGON_MSVC 353 : scale_() 354 #endif 355 { 356 scale_[0] = xscale; 357 scale_[1] = yscale; 358 scale_[2] = 1; 359 } anisotropic_scale_factor(scale_factor_type xscale,scale_factor_type yscale,scale_factor_type zscale)360 inline anisotropic_scale_factor(scale_factor_type xscale, scale_factor_type yscale, scale_factor_type zscale) 361 #ifndef BOOST_POLYGON_MSVC 362 : scale_() 363 #endif 364 { 365 scale_[0] = xscale; 366 scale_[1] = yscale; 367 scale_[2] = zscale; 368 } 369 370 // get a component of the anisotropic_scale_factor by orientation 371 scale_factor_type get(orientation_3d orient) const; get(orientation_2d orient) const372 scale_factor_type get(orientation_2d orient) const { return get(orientation_3d(orient)); } 373 374 // set a component of the anisotropic_scale_factor by orientation 375 void set(orientation_3d orient, scale_factor_type value); set(orientation_2d orient,scale_factor_type value)376 void set(orientation_2d orient, scale_factor_type value) { set(orientation_3d(orient), value); } 377 378 scale_factor_type x() const; 379 scale_factor_type y() const; 380 scale_factor_type z() const; 381 void x(scale_factor_type value); 382 void y(scale_factor_type value); 383 void z(scale_factor_type value); 384 385 // concatination operator (convolve scale factors) 386 anisotropic_scale_factor operator+(const anisotropic_scale_factor& s) const; 387 388 // concatinate this with that 389 const anisotropic_scale_factor& operator+=(const anisotropic_scale_factor& s); 390 391 // transform this scale with an axis_transform 392 anisotropic_scale_factor& transform(axis_transformation atr); 393 394 // scale the two coordinates 395 template <typename coordinate_type> 396 void scale(coordinate_type& x, coordinate_type& y) const; 397 398 // scale the three coordinates 399 template <typename coordinate_type> 400 void scale(coordinate_type& x, coordinate_type& y, coordinate_type& z) const; 401 402 // invert this scale factor to give the reverse scale factor 403 anisotropic_scale_factor& invert(); 404 405 private: 406 scale_factor_type scale_[3]; 407 408 //friend std::ostream& operator<< (std::ostream& o, const Scale& r); 409 //friend std::istream& operator>> (std::istream& i, Scale& r); 410 }; 411 412 // Transformation object, stores and provides services for transformations 413 414 // Transformation object stores an axistransformation, a scale factor and a translation. 415 // The tranlation is the position of the origin of the new system of coordinates in the old system. 416 // The scale scales the coordinates before they are transformed. 417 template <typename coordinate_type> 418 class transformation { 419 public: 420 transformation(); 421 transformation(axis_transformation atr); 422 transformation(axis_transformation::ATR atr); 423 template <typename point_type> 424 transformation(const point_type& p); 425 template <typename point_type> 426 transformation(axis_transformation atr, const point_type& p); 427 template <typename point_type> 428 transformation(axis_transformation atr, const point_type& referencePt, const point_type& destinationPt); 429 transformation(const transformation& tr); 430 431 // equivalence operator 432 bool operator==(const transformation& tr) const; 433 434 // inequivalence operator 435 bool operator!=(const transformation& tr) const; 436 437 // ordering 438 bool operator<(const transformation& tr) const; 439 440 // concatenation operator 441 transformation operator+(const transformation& tr) const; 442 443 // concatenate this with that 444 const transformation& operator+=(const transformation& tr); 445 446 // get the axis_transformation portion of this get_axis_transformation() const447 inline axis_transformation get_axis_transformation() const {return atr_;} 448 449 // set the axis_transformation portion of this 450 void set_axis_transformation(const axis_transformation& atr); 451 452 // get the translation portion of this as a point3d 453 template <typename point_type> 454 void get_translation(point_type& translation) const; 455 456 // set the translation portion of this with a point3d 457 template <typename point_type> 458 void set_translation(const point_type& p); 459 460 // apply the 2D portion of this transformation to the two coordinates given 461 void transform(coordinate_type& x, coordinate_type& y) const; 462 463 // apply this transformation to the three coordinates given 464 void transform(coordinate_type& x, coordinate_type& y, coordinate_type& z) const; 465 466 // invert this transformation 467 transformation& invert(); 468 469 // get the inverse of this transformation 470 transformation inverse() const; 471 get_directions(direction_2d & horizontal_dir,direction_2d & vertical_dir) const472 inline void get_directions(direction_2d& horizontal_dir, 473 direction_2d& vertical_dir) const { 474 return atr_.get_directions(horizontal_dir, vertical_dir); } 475 get_directions(direction_3d & horizontal_dir,direction_3d & vertical_dir,direction_3d & proximal_dir) const476 inline void get_directions(direction_3d& horizontal_dir, 477 direction_3d& vertical_dir, 478 direction_3d& proximal_dir) const { 479 return atr_.get_directions(horizontal_dir, vertical_dir, proximal_dir); } 480 481 private: 482 axis_transformation atr_; 483 point_3d_data<coordinate_type> p_; 484 485 template <typename point_type> 486 void construct_dispatch(axis_transformation atr, point_type p, point_concept tag); 487 template <typename point_type> 488 void construct_dispatch(axis_transformation atr, point_type p, point_3d_concept tag); 489 template <typename point_type> 490 void construct_dispatch(axis_transformation atr, point_type rp, point_type dp, point_concept tag); 491 template <typename point_type> 492 void construct_dispatch(axis_transformation atr, point_type rp, point_type dp, point_3d_concept tag); 493 494 //friend std::ostream& operator<< (std::ostream& o, const transformation& tr); 495 //friend std::istream& operator>> (std::istream& i, transformation& tr); 496 }; 497 } 498 } 499 #include "detail/transform_detail.hpp" 500 #endif 501 502