Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:48:04

0001 // Boost.Polygon library transform.hpp header file
0002 
0003 // Copyright (c) Intel Corporation 2008.
0004 // Copyright (c) 2008-2012 Simonson Lucanus.
0005 // Copyright (c) 2012-2012 Andrii Sydorchuk.
0006 
0007 // See http://www.boost.org for updates, documentation, and revision history.
0008 // Use, modification and distribution is subject to the Boost Software License,
0009 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0010 // http://www.boost.org/LICENSE_1_0.txt)
0011 
0012 #ifndef BOOST_POLYGON_TRANSFORM_HPP
0013 #define BOOST_POLYGON_TRANSFORM_HPP
0014 
0015 #include "isotropy.hpp"
0016 
0017 namespace boost {
0018 namespace polygon {
0019 // Transformation of Coordinate System.
0020 // Enum meaning:
0021 // Select which direction_2d to change the positive direction of each
0022 // axis in the old coordinate system to map it to the new coordiante system.
0023 // The first direction_2d listed for each enum is the direction to map the
0024 // positive horizontal direction to.
0025 // The second direction_2d listed for each enum is the direction to map the
0026 // positive vertical direction to.
0027 // The zero position bit (LSB) indicates whether the horizontal axis flips
0028 // when transformed.
0029 // The 1st postion bit indicates whether the vertical axis flips when
0030 // transformed.
0031 // The 2nd position bit indicates whether the horizontal and vertical axis
0032 // swap positions when transformed.
0033 // Enum Values:
0034 //   000 EAST NORTH
0035 //   001 WEST NORTH
0036 //   010 EAST SOUTH
0037 //   011 WEST SOUTH
0038 //   100 NORTH EAST
0039 //   101 SOUTH EAST
0040 //   110 NORTH WEST
0041 //   111 SOUTH WEST
0042 class axis_transformation {
0043  public:
0044   enum ATR {
0045 #ifdef BOOST_POLYGON_ENABLE_DEPRECATED
0046     EN = 0,
0047     WN = 1,
0048     ES = 2,
0049     WS = 3,
0050     NE = 4,
0051     SE = 5,
0052     NW = 6,
0053     SW = 7,
0054 #endif
0055     NULL_TRANSFORM = 0,
0056     BEGIN_TRANSFORM = 0,
0057     EAST_NORTH = 0,
0058     WEST_NORTH = 1, FLIP_X       = 1,
0059     EAST_SOUTH = 2, FLIP_Y       = 2,
0060     WEST_SOUTH = 3, FLIP_XY      = 3,
0061     NORTH_EAST = 4, SWAP_XY      = 4,
0062     SOUTH_EAST = 5, ROTATE_LEFT  = 5,
0063     NORTH_WEST = 6, ROTATE_RIGHT = 6,
0064     SOUTH_WEST = 7, FLIP_SWAP_XY = 7,
0065     END_TRANSFORM = 7
0066   };
0067 
0068   // Individual axis enum values indicate which axis an implicit individual
0069   // axis will be mapped to.
0070   // The value of the enum paired with an axis provides the information
0071   // about what the axis will transform to.
0072   // Three individual axis values, one for each axis, are equivalent to one
0073   // ATR enum value, but easier to work with because they are independent.
0074   // Converting to and from the individual axis values from the ATR value
0075   // is a convenient way to implement tranformation related functionality.
0076   // Enum meanings:
0077   // PX: map to positive x axis
0078   // NX: map to negative x axis
0079   // PY: map to positive y axis
0080   // NY: map to negative y axis
0081   enum INDIVIDUAL_AXIS {
0082     PX = 0,
0083     NX = 1,
0084     PY = 2,
0085     NY = 3
0086   };
0087 
0088   axis_transformation() : atr_(NULL_TRANSFORM) {}
0089   explicit axis_transformation(ATR atr) : atr_(atr) {}
0090   axis_transformation(const axis_transformation& atr) : atr_(atr.atr_) {}
0091 
0092   explicit axis_transformation(const orientation_2d& orient) {
0093     const ATR tmp[2] = {
0094       NORTH_EAST,  // sort x, then y
0095       EAST_NORTH   // sort y, then x
0096     };
0097     atr_ = tmp[orient.to_int()];
0098   }
0099 
0100   explicit axis_transformation(const direction_2d& dir) {
0101     const ATR tmp[4] = {
0102       SOUTH_EAST,  // sort x, then y
0103       NORTH_EAST,  // sort x, then y
0104       EAST_SOUTH,  // sort y, then x
0105       EAST_NORTH   // sort y, then x
0106     };
0107     atr_ = tmp[dir.to_int()];
0108   }
0109 
0110   // assignment operator
0111   axis_transformation& operator=(const axis_transformation& a) {
0112     atr_ = a.atr_;
0113     return *this;
0114   }
0115 
0116   // assignment operator
0117   axis_transformation& operator=(const ATR& atr) {
0118     atr_ = atr;
0119     return *this;
0120   }
0121 
0122   // equivalence operator
0123   bool operator==(const axis_transformation& a) const {
0124     return atr_ == a.atr_;
0125   }
0126 
0127   // inequivalence operator
0128   bool operator!=(const axis_transformation& a) const {
0129     return !(*this == a);
0130   }
0131 
0132   // ordering
0133   bool operator<(const axis_transformation& a) const {
0134     return atr_ < a.atr_;
0135   }
0136 
0137   // concatenate this with that
0138   axis_transformation& operator+=(const axis_transformation& a) {
0139     bool abit2 = (a.atr_ & 4) != 0;
0140     bool abit1 = (a.atr_ & 2) != 0;
0141     bool abit0 = (a.atr_ & 1) != 0;
0142     bool bit2 = (atr_ & 4) != 0;
0143     bool bit1 = (atr_ & 2) != 0;
0144     bool bit0 = (atr_ & 1) != 0;
0145     int indexes[2][2] = {
0146       { (int)bit2, (int)(!bit2) },
0147       { (int)abit2, (int)(!abit2) }
0148     };
0149     int zero_bits[2][2] = {
0150       {bit0, bit1}, {abit0, abit1}
0151     };
0152     int nbit1 = zero_bits[0][1] ^ zero_bits[1][indexes[0][1]];
0153     int nbit0 = zero_bits[0][0] ^ zero_bits[1][indexes[0][0]];
0154     indexes[0][0] = indexes[1][indexes[0][0]];
0155     indexes[0][1] = indexes[1][indexes[0][1]];
0156     int nbit2 = indexes[0][0] & 1;  // swap xy
0157     atr_ = (ATR)((nbit2 << 2) + (nbit1 << 1) + nbit0);
0158     return *this;
0159   }
0160 
0161   // concatenation operator
0162   axis_transformation operator+(const axis_transformation& a) const {
0163     axis_transformation retval(*this);
0164     return retval+=a;
0165   }
0166 
0167   // populate_axis_array writes the three INDIVIDUAL_AXIS values that the
0168   // ATR enum value of 'this' represent into axis_array
0169   void populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const {
0170     bool bit2 = (atr_ & 4) != 0;
0171     bool bit1 = (atr_ & 2) != 0;
0172     bool bit0 = (atr_ & 1) != 0;
0173     axis_array[1] = (INDIVIDUAL_AXIS)(((int)(!bit2) << 1) + bit1);
0174     axis_array[0] = (INDIVIDUAL_AXIS)(((int)(bit2) << 1) + bit0);
0175   }
0176 
0177   // it is recommended that the directions stored in an array
0178   // in the caller code for easier isotropic access by orientation value
0179   void get_directions(direction_2d& horizontal_dir,
0180                       direction_2d& vertical_dir) const {
0181     bool bit2 = (atr_ & 4) != 0;
0182     bool bit1 = (atr_ & 2) != 0;
0183     bool bit0 = (atr_ & 1) != 0;
0184     vertical_dir = direction_2d((direction_2d_enum)(((int)(!bit2) << 1) + !bit1));
0185     horizontal_dir = direction_2d((direction_2d_enum)(((int)(bit2) << 1) + !bit0));
0186   }
0187 
0188   // combine_axis_arrays concatenates this_array and that_array overwriting
0189   // the result into this_array
0190   static void combine_axis_arrays(INDIVIDUAL_AXIS this_array[],
0191                                   const INDIVIDUAL_AXIS that_array[]) {
0192     int indexes[2] = { this_array[0] >> 1, this_array[1] >> 1 };
0193     int zero_bits[2][2] = {
0194       { this_array[0] & 1, this_array[1] & 1 },
0195       { that_array[0] & 1, that_array[1] & 1 }
0196     };
0197     this_array[0] = (INDIVIDUAL_AXIS)((int)this_array[0] |
0198                                       ((int)zero_bits[0][0] ^
0199                                        (int)zero_bits[1][indexes[0]]));
0200     this_array[1] = (INDIVIDUAL_AXIS)((int)this_array[1] |
0201                                       ((int)zero_bits[0][1] ^
0202                                        (int)zero_bits[1][indexes[1]]));
0203   }
0204 
0205   // write_back_axis_array converts an array of three INDIVIDUAL_AXIS values
0206   // to the ATR enum value and sets 'this' to that value
0207   void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]) {
0208     int bit2 = ((int)this_array[0] & 2) != 0;  // swap xy
0209     int bit1 = ((int)this_array[1] & 1);
0210     int bit0 = ((int)this_array[0] & 1);
0211     atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0);
0212   }
0213 
0214   // behavior is deterministic but undefined in the case where illegal
0215   // combinations of directions are passed in.
0216   axis_transformation& set_directions(const direction_2d& horizontal_dir,
0217                                       const direction_2d& vertical_dir) {
0218     int bit2 = (static_cast<orientation_2d>(horizontal_dir).to_int()) != 0;
0219     int bit1 = !(vertical_dir.to_int() & 1);
0220     int bit0 = !(horizontal_dir.to_int() & 1);
0221     atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0);
0222     return *this;
0223   }
0224 
0225   // transform the three coordinates by reference
0226   template <typename coordinate_type>
0227   void transform(coordinate_type& x, coordinate_type& y) const {
0228     int bit2 = (atr_ & 4) != 0;
0229     int bit1 = (atr_ & 2) != 0;
0230     int bit0 = (atr_ & 1) != 0;
0231     x *= -((bit0 << 1) - 1);
0232     y *= -((bit1 << 1) - 1);
0233     predicated_swap(bit2 != 0, x, y);
0234   }
0235 
0236   // invert this axis_transformation
0237   axis_transformation& invert() {
0238     int bit2 = ((atr_ & 4) != 0);
0239     int bit1 = ((atr_ & 2) != 0);
0240     int bit0 = ((atr_ & 1) != 0);
0241     // swap bit 0 and bit 1 if bit2 is 1
0242     predicated_swap(bit2 != 0, bit0, bit1);
0243     bit1 = bit1 << 1;
0244     atr_ = (ATR)(atr_ & (32+16+8+4));  // mask away bit0 and bit1
0245     atr_ = (ATR)(atr_ | bit0 | bit1);
0246     return *this;
0247   }
0248 
0249   // get the inverse axis_transformation of this
0250   axis_transformation inverse() const {
0251     axis_transformation retval(*this);
0252     return retval.invert();
0253   }
0254 
0255  private:
0256   ATR atr_;
0257 };
0258 
0259 // Scaling object to be used to store the scale factor for each axis.
0260 // For use by the transformation object, in that context the scale factor
0261 // is the amount that each axis scales by when transformed.
0262 template <typename scale_factor_type>
0263 class anisotropic_scale_factor {
0264  public:
0265   anisotropic_scale_factor() {
0266     scale_[0] = 1;
0267     scale_[1] = 1;
0268   }
0269   anisotropic_scale_factor(scale_factor_type xscale,
0270                            scale_factor_type yscale) {
0271     scale_[0] = xscale;
0272     scale_[1] = yscale;
0273   }
0274 
0275   // get a component of the anisotropic_scale_factor by orientation
0276   scale_factor_type get(orientation_2d orient) const {
0277     return scale_[orient.to_int()];
0278   }
0279 
0280   // set a component of the anisotropic_scale_factor by orientation
0281   void set(orientation_2d orient, scale_factor_type value) {
0282     scale_[orient.to_int()] = value;
0283   }
0284 
0285   scale_factor_type x() const {
0286     return scale_[HORIZONTAL];
0287   }
0288 
0289   scale_factor_type y() const {
0290     return scale_[VERTICAL];
0291   }
0292 
0293   void x(scale_factor_type value) {
0294     scale_[HORIZONTAL] = value;
0295   }
0296 
0297   void y(scale_factor_type value) {
0298     scale_[VERTICAL] = value;
0299   }
0300 
0301   // concatination operator (convolve scale factors)
0302   anisotropic_scale_factor operator+(const anisotropic_scale_factor& s) const {
0303     anisotropic_scale_factor<scale_factor_type> retval(*this);
0304     return retval += s;
0305   }
0306 
0307   // concatinate this with that
0308   const anisotropic_scale_factor& operator+=(
0309       const anisotropic_scale_factor& s) {
0310     scale_[0] *= s.scale_[0];
0311     scale_[1] *= s.scale_[1];
0312     return *this;
0313   }
0314 
0315   // transform this scale with an axis_transform
0316   anisotropic_scale_factor& transform(axis_transformation atr) {
0317     direction_2d dirs[2];
0318     atr.get_directions(dirs[0], dirs[1]);
0319     scale_factor_type tmp[2] = {scale_[0], scale_[1]};
0320     for (int i = 0; i < 2; ++i) {
0321       scale_[orientation_2d(dirs[i]).to_int()] = tmp[i];
0322     }
0323     return *this;
0324   }
0325 
0326   // scale the two coordinates
0327   template <typename coordinate_type>
0328   void scale(coordinate_type& x, coordinate_type& y) const {
0329     x = scaling_policy<coordinate_type>::round(
0330         (scale_factor_type)x * get(HORIZONTAL));
0331     y = scaling_policy<coordinate_type>::round(
0332         (scale_factor_type)y * get(HORIZONTAL));
0333   }
0334 
0335   // invert this scale factor to give the reverse scale factor
0336   anisotropic_scale_factor& invert() {
0337     x(1/x());
0338     y(1/y());
0339     return *this;
0340   }
0341 
0342  private:
0343   scale_factor_type scale_[2];
0344 };
0345 
0346 // Transformation object, stores and provides services for transformations.
0347 // Consits of axis transformation, scale factor and translation.
0348 // The tranlation is the position of the origin of the new coordinate system of
0349 // in the old system. Coordinates are scaled before they are transformed.
0350 template <typename coordinate_type>
0351 class transformation {
0352  public:
0353   transformation() : atr_(), p_(0, 0) {}
0354   explicit transformation(axis_transformation atr) : atr_(atr), p_(0, 0) {}
0355   explicit transformation(axis_transformation::ATR atr) : atr_(atr), p_(0, 0) {}
0356   transformation(const transformation& tr) : atr_(tr.atr_), p_(tr.p_) {}
0357 
0358   template <typename point_type>
0359   explicit transformation(const point_type& p) : atr_(), p_(0, 0) {
0360     set_translation(p);
0361   }
0362 
0363   template <typename point_type>
0364   transformation(axis_transformation atr,
0365                  const point_type& p) : atr_(atr), p_(0, 0) {
0366     set_translation(p);
0367   }
0368 
0369   template <typename point_type>
0370   transformation(axis_transformation atr,
0371                  const point_type& referencePt,
0372                  const point_type& destinationPt) : atr_(), p_(0, 0) {
0373     transformation<coordinate_type> tmp(referencePt);
0374     transformation<coordinate_type> rotRef(atr);
0375     transformation<coordinate_type> tmpInverse = tmp.inverse();
0376     point_type decon(referencePt);
0377     deconvolve(decon, destinationPt);
0378     transformation<coordinate_type> displacement(decon);
0379     tmp += rotRef;
0380     tmp += tmpInverse;
0381     tmp += displacement;
0382     (*this) = tmp;
0383   }
0384 
0385   // equivalence operator
0386   bool operator==(const transformation& tr) const {
0387     return (atr_ == tr.atr_) && (p_ == tr.p_);
0388   }
0389 
0390   // inequivalence operator
0391   bool operator!=(const transformation& tr) const {
0392     return !(*this == tr);
0393   }
0394 
0395   // ordering
0396   bool operator<(const transformation& tr) const {
0397     return (atr_ < tr.atr_) || ((atr_ == tr.atr_) && (p_ < tr.p_));
0398   }
0399 
0400   // concatenation operator
0401   transformation operator+(const transformation& tr) const {
0402     transformation<coordinate_type> retval(*this);
0403     return retval+=tr;
0404   }
0405 
0406   // concatenate this with that
0407   const transformation& operator+=(const transformation& tr) {
0408     coordinate_type x, y;
0409     transformation<coordinate_type> inv = inverse();
0410     inv.transform(x, y);
0411     p_.set(HORIZONTAL, p_.get(HORIZONTAL) + x);
0412     p_.set(VERTICAL, p_.get(VERTICAL) + y);
0413     // concatenate axis transforms
0414     atr_ += tr.atr_;
0415     return *this;
0416   }
0417 
0418   // get the axis_transformation portion of this
0419   axis_transformation get_axis_transformation() const {
0420     return atr_;
0421   }
0422 
0423   // set the axis_transformation portion of this
0424   void set_axis_transformation(const axis_transformation& atr) {
0425     atr_ = atr;
0426   }
0427 
0428   // get the translation
0429   template <typename point_type>
0430   void get_translation(point_type& p) const {
0431     assign(p, p_);
0432   }
0433 
0434   // set the translation
0435   template <typename point_type>
0436   void set_translation(const point_type& p) {
0437     assign(p_, p);
0438   }
0439 
0440   // apply the 2D portion of this transformation to the two coordinates given
0441   void transform(coordinate_type& x, coordinate_type& y) const {
0442     y -= p_.get(VERTICAL);
0443     x -= p_.get(HORIZONTAL);
0444     atr_.transform(x, y);
0445   }
0446 
0447   // invert this transformation
0448   transformation& invert() {
0449     coordinate_type x = p_.get(HORIZONTAL), y = p_.get(VERTICAL);
0450     atr_.transform(x, y);
0451     x *= -1;
0452     y *= -1;
0453     p_ = point_data<coordinate_type>(x, y);
0454     atr_.invert();
0455     return *this;
0456   }
0457 
0458   // get the inverse of this transformation
0459   transformation inverse() const {
0460     transformation<coordinate_type> ret_val(*this);
0461     return ret_val.invert();
0462   }
0463 
0464   void get_directions(direction_2d& horizontal_dir,
0465                       direction_2d& vertical_dir) const {
0466     return atr_.get_directions(horizontal_dir, vertical_dir);
0467   }
0468 
0469  private:
0470   axis_transformation atr_;
0471   point_data<coordinate_type> p_;
0472 };
0473 }  // polygon
0474 }  // boost
0475 
0476 #endif  // BOOST_POLYGON_TRANSFORM_HPP