File indexing completed on 2025-01-18 09:48:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
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
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
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,
0095 EAST_NORTH
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,
0103 NORTH_EAST,
0104 EAST_SOUTH,
0105 EAST_NORTH
0106 };
0107 atr_ = tmp[dir.to_int()];
0108 }
0109
0110
0111 axis_transformation& operator=(const axis_transformation& a) {
0112 atr_ = a.atr_;
0113 return *this;
0114 }
0115
0116
0117 axis_transformation& operator=(const ATR& atr) {
0118 atr_ = atr;
0119 return *this;
0120 }
0121
0122
0123 bool operator==(const axis_transformation& a) const {
0124 return atr_ == a.atr_;
0125 }
0126
0127
0128 bool operator!=(const axis_transformation& a) const {
0129 return !(*this == a);
0130 }
0131
0132
0133 bool operator<(const axis_transformation& a) const {
0134 return atr_ < a.atr_;
0135 }
0136
0137
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;
0157 atr_ = (ATR)((nbit2 << 2) + (nbit1 << 1) + nbit0);
0158 return *this;
0159 }
0160
0161
0162 axis_transformation operator+(const axis_transformation& a) const {
0163 axis_transformation retval(*this);
0164 return retval+=a;
0165 }
0166
0167
0168
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
0178
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
0189
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
0206
0207 void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]) {
0208 int bit2 = ((int)this_array[0] & 2) != 0;
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
0215
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
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
0237 axis_transformation& invert() {
0238 int bit2 = ((atr_ & 4) != 0);
0239 int bit1 = ((atr_ & 2) != 0);
0240 int bit0 = ((atr_ & 1) != 0);
0241
0242 predicated_swap(bit2 != 0, bit0, bit1);
0243 bit1 = bit1 << 1;
0244 atr_ = (ATR)(atr_ & (32+16+8+4));
0245 atr_ = (ATR)(atr_ | bit0 | bit1);
0246 return *this;
0247 }
0248
0249
0250 axis_transformation inverse() const {
0251 axis_transformation retval(*this);
0252 return retval.invert();
0253 }
0254
0255 private:
0256 ATR atr_;
0257 };
0258
0259
0260
0261
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
0276 scale_factor_type get(orientation_2d orient) const {
0277 return scale_[orient.to_int()];
0278 }
0279
0280
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
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
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
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
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
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
0347
0348
0349
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
0386 bool operator==(const transformation& tr) const {
0387 return (atr_ == tr.atr_) && (p_ == tr.p_);
0388 }
0389
0390
0391 bool operator!=(const transformation& tr) const {
0392 return !(*this == tr);
0393 }
0394
0395
0396 bool operator<(const transformation& tr) const {
0397 return (atr_ < tr.atr_) || ((atr_ == tr.atr_) && (p_ < tr.p_));
0398 }
0399
0400
0401 transformation operator+(const transformation& tr) const {
0402 transformation<coordinate_type> retval(*this);
0403 return retval+=tr;
0404 }
0405
0406
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
0414 atr_ += tr.atr_;
0415 return *this;
0416 }
0417
0418
0419 axis_transformation get_axis_transformation() const {
0420 return atr_;
0421 }
0422
0423
0424 void set_axis_transformation(const axis_transformation& atr) {
0425 atr_ = atr;
0426 }
0427
0428
0429 template <typename point_type>
0430 void get_translation(point_type& p) const {
0431 assign(p, p_);
0432 }
0433
0434
0435 template <typename point_type>
0436 void set_translation(const point_type& p) {
0437 assign(p_, p);
0438 }
0439
0440
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
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
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 }
0474 }
0475
0476 #endif