File indexing completed on 2025-01-18 09:37:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GRAPH_TOPOLOGY_HPP
0011 #define BOOST_GRAPH_TOPOLOGY_HPP
0012
0013 #include <boost/config/no_tr1/cmath.hpp>
0014 #include <cmath>
0015 #include <boost/random/uniform_01.hpp>
0016 #include <boost/random/linear_congruential.hpp>
0017 #include <boost/math/constants/constants.hpp> // For root_two
0018 #include <boost/algorithm/minmax.hpp>
0019 #include <boost/config.hpp> // For BOOST_STATIC_CONSTANT
0020 #include <boost/math/special_functions/hypot.hpp>
0021
0022
0023
0024
0025
0026 namespace boost
0027 {
0028
0029
0030
0031
0032 template < std::size_t Dims > class convex_topology
0033 {
0034 public:
0035 struct point
0036 {
0037 BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims);
0038 point() {}
0039 double& operator[](std::size_t i) { return values[i]; }
0040 const double& operator[](std::size_t i) const { return values[i]; }
0041
0042 private:
0043 double values[Dims];
0044 };
0045
0046 public:
0047 struct point_difference
0048 {
0049 BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims);
0050 point_difference()
0051 {
0052 for (std::size_t i = 0; i < Dims; ++i)
0053 values[i] = 0.;
0054 }
0055 double& operator[](std::size_t i) { return values[i]; }
0056 const double& operator[](std::size_t i) const { return values[i]; }
0057
0058 friend point_difference operator+(
0059 const point_difference& a, const point_difference& b)
0060 {
0061 point_difference result;
0062 for (std::size_t i = 0; i < Dims; ++i)
0063 result[i] = a[i] + b[i];
0064 return result;
0065 }
0066
0067 friend point_difference& operator+=(
0068 point_difference& a, const point_difference& b)
0069 {
0070 for (std::size_t i = 0; i < Dims; ++i)
0071 a[i] += b[i];
0072 return a;
0073 }
0074
0075 friend point_difference operator-(const point_difference& a)
0076 {
0077 point_difference result;
0078 for (std::size_t i = 0; i < Dims; ++i)
0079 result[i] = -a[i];
0080 return result;
0081 }
0082
0083 friend point_difference operator-(
0084 const point_difference& a, const point_difference& b)
0085 {
0086 point_difference result;
0087 for (std::size_t i = 0; i < Dims; ++i)
0088 result[i] = a[i] - b[i];
0089 return result;
0090 }
0091
0092 friend point_difference& operator-=(
0093 point_difference& a, const point_difference& b)
0094 {
0095 for (std::size_t i = 0; i < Dims; ++i)
0096 a[i] -= b[i];
0097 return a;
0098 }
0099
0100 friend point_difference operator*(
0101 const point_difference& a, const point_difference& b)
0102 {
0103 point_difference result;
0104 for (std::size_t i = 0; i < Dims; ++i)
0105 result[i] = a[i] * b[i];
0106 return result;
0107 }
0108
0109 friend point_difference operator*(const point_difference& a, double b)
0110 {
0111 point_difference result;
0112 for (std::size_t i = 0; i < Dims; ++i)
0113 result[i] = a[i] * b;
0114 return result;
0115 }
0116
0117 friend point_difference operator*(double a, const point_difference& b)
0118 {
0119 point_difference result;
0120 for (std::size_t i = 0; i < Dims; ++i)
0121 result[i] = a * b[i];
0122 return result;
0123 }
0124
0125 friend point_difference operator/(
0126 const point_difference& a, const point_difference& b)
0127 {
0128 point_difference result;
0129 for (std::size_t i = 0; i < Dims; ++i)
0130 result[i] = (b[i] == 0.) ? 0. : a[i] / b[i];
0131 return result;
0132 }
0133
0134 friend double dot(const point_difference& a, const point_difference& b)
0135 {
0136 double result = 0;
0137 for (std::size_t i = 0; i < Dims; ++i)
0138 result += a[i] * b[i];
0139 return result;
0140 }
0141
0142 private:
0143 double values[Dims];
0144 };
0145
0146 public:
0147 typedef point point_type;
0148 typedef point_difference point_difference_type;
0149
0150 double distance(point a, point b) const
0151 {
0152 double dist = 0.;
0153 for (std::size_t i = 0; i < Dims; ++i)
0154 {
0155 double diff = b[i] - a[i];
0156 dist = boost::math::hypot(dist, diff);
0157 }
0158
0159
0160
0161 return dist;
0162 }
0163
0164 point move_position_toward(point a, double fraction, point b) const
0165 {
0166 point result;
0167 for (std::size_t i = 0; i < Dims; ++i)
0168 result[i] = a[i] + (b[i] - a[i]) * fraction;
0169 return result;
0170 }
0171
0172 point_difference difference(point a, point b) const
0173 {
0174 point_difference result;
0175 for (std::size_t i = 0; i < Dims; ++i)
0176 result[i] = a[i] - b[i];
0177 return result;
0178 }
0179
0180 point adjust(point a, point_difference delta) const
0181 {
0182 point result;
0183 for (std::size_t i = 0; i < Dims; ++i)
0184 result[i] = a[i] + delta[i];
0185 return result;
0186 }
0187
0188 point pointwise_min(point a, point b) const
0189 {
0190 BOOST_USING_STD_MIN();
0191 point result;
0192 for (std::size_t i = 0; i < Dims; ++i)
0193 result[i] = min BOOST_PREVENT_MACRO_SUBSTITUTION(a[i], b[i]);
0194 return result;
0195 }
0196
0197 point pointwise_max(point a, point b) const
0198 {
0199 BOOST_USING_STD_MAX();
0200 point result;
0201 for (std::size_t i = 0; i < Dims; ++i)
0202 result[i] = max BOOST_PREVENT_MACRO_SUBSTITUTION(a[i], b[i]);
0203 return result;
0204 }
0205
0206 double norm(point_difference delta) const
0207 {
0208 double n = 0.;
0209 for (std::size_t i = 0; i < Dims; ++i)
0210 n = boost::math::hypot(n, delta[i]);
0211 return n;
0212 }
0213
0214 double volume(point_difference delta) const
0215 {
0216 double n = 1.;
0217 for (std::size_t i = 0; i < Dims; ++i)
0218 n *= delta[i];
0219 return n;
0220 }
0221 };
0222
0223 template < std::size_t Dims, typename RandomNumberGenerator = minstd_rand >
0224 class hypercube_topology : public convex_topology< Dims >
0225 {
0226 typedef uniform_01< RandomNumberGenerator, double > rand_t;
0227
0228 public:
0229 typedef typename convex_topology< Dims >::point_type point_type;
0230 typedef typename convex_topology< Dims >::point_difference_type
0231 point_difference_type;
0232
0233 explicit hypercube_topology(double scaling = 1.0)
0234 : gen_ptr(new RandomNumberGenerator)
0235 , rand(new rand_t(*gen_ptr))
0236 , scaling(scaling)
0237 {
0238 }
0239
0240 hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0)
0241 : gen_ptr(), rand(new rand_t(gen)), scaling(scaling)
0242 {
0243 }
0244
0245 point_type random_point() const
0246 {
0247 point_type p;
0248 for (std::size_t i = 0; i < Dims; ++i)
0249 p[i] = (*rand)() * scaling;
0250 return p;
0251 }
0252
0253 point_type bound(point_type a) const
0254 {
0255 BOOST_USING_STD_MIN();
0256 BOOST_USING_STD_MAX();
0257 point_type p;
0258 for (std::size_t i = 0; i < Dims; ++i)
0259 p[i] = min BOOST_PREVENT_MACRO_SUBSTITUTION(
0260 scaling, max BOOST_PREVENT_MACRO_SUBSTITUTION(-scaling, a[i]));
0261 return p;
0262 }
0263
0264 double distance_from_boundary(point_type a) const
0265 {
0266 BOOST_USING_STD_MIN();
0267 BOOST_USING_STD_MAX();
0268 #ifndef BOOST_NO_STDC_NAMESPACE
0269 using std::abs;
0270 #endif
0271 BOOST_STATIC_ASSERT(Dims >= 1);
0272 double dist = abs(scaling - a[0]);
0273 for (std::size_t i = 1; i < Dims; ++i)
0274 dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(
0275 dist, abs(scaling - a[i]));
0276 return dist;
0277 }
0278
0279 point_type center() const
0280 {
0281 point_type result;
0282 for (std::size_t i = 0; i < Dims; ++i)
0283 result[i] = scaling * .5;
0284 return result;
0285 }
0286
0287 point_type origin() const
0288 {
0289 point_type result;
0290 for (std::size_t i = 0; i < Dims; ++i)
0291 result[i] = 0;
0292 return result;
0293 }
0294
0295 point_difference_type extent() const
0296 {
0297 point_difference_type result;
0298 for (std::size_t i = 0; i < Dims; ++i)
0299 result[i] = scaling;
0300 return result;
0301 }
0302
0303 private:
0304 shared_ptr< RandomNumberGenerator > gen_ptr;
0305 shared_ptr< rand_t > rand;
0306 double scaling;
0307 };
0308
0309 template < typename RandomNumberGenerator = minstd_rand >
0310 class square_topology : public hypercube_topology< 2, RandomNumberGenerator >
0311 {
0312 typedef hypercube_topology< 2, RandomNumberGenerator > inherited;
0313
0314 public:
0315 explicit square_topology(double scaling = 1.0) : inherited(scaling) {}
0316
0317 square_topology(RandomNumberGenerator& gen, double scaling = 1.0)
0318 : inherited(gen, scaling)
0319 {
0320 }
0321 };
0322
0323 template < typename RandomNumberGenerator = minstd_rand >
0324 class rectangle_topology : public convex_topology< 2 >
0325 {
0326 typedef uniform_01< RandomNumberGenerator, double > rand_t;
0327
0328 public:
0329 rectangle_topology(double left, double top, double right, double bottom)
0330 : gen_ptr(new RandomNumberGenerator)
0331 , rand(new rand_t(*gen_ptr))
0332 , left(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(left, right))
0333 , top(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom))
0334 , right(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(left, right))
0335 , bottom(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom))
0336 {
0337 }
0338
0339 rectangle_topology(RandomNumberGenerator& gen, double left, double top,
0340 double right, double bottom)
0341 : gen_ptr()
0342 , rand(new rand_t(gen))
0343 , left(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(left, right))
0344 , top(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom))
0345 , right(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(left, right))
0346 , bottom(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom))
0347 {
0348 }
0349
0350 typedef typename convex_topology< 2 >::point_type point_type;
0351 typedef typename convex_topology< 2 >::point_difference_type
0352 point_difference_type;
0353
0354 point_type random_point() const
0355 {
0356 point_type p;
0357 p[0] = (*rand)() * (right - left) + left;
0358 p[1] = (*rand)() * (bottom - top) + top;
0359 return p;
0360 }
0361
0362 point_type bound(point_type a) const
0363 {
0364 BOOST_USING_STD_MIN();
0365 BOOST_USING_STD_MAX();
0366 point_type p;
0367 p[0] = min BOOST_PREVENT_MACRO_SUBSTITUTION(
0368 right, max BOOST_PREVENT_MACRO_SUBSTITUTION(left, a[0]));
0369 p[1] = min BOOST_PREVENT_MACRO_SUBSTITUTION(
0370 bottom, max BOOST_PREVENT_MACRO_SUBSTITUTION(top, a[1]));
0371 return p;
0372 }
0373
0374 double distance_from_boundary(point_type a) const
0375 {
0376 BOOST_USING_STD_MIN();
0377 BOOST_USING_STD_MAX();
0378 #ifndef BOOST_NO_STDC_NAMESPACE
0379 using std::abs;
0380 #endif
0381 double dist = abs(left - a[0]);
0382 dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(dist, abs(right - a[0]));
0383 dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(dist, abs(top - a[1]));
0384 dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(dist, abs(bottom - a[1]));
0385 return dist;
0386 }
0387
0388 point_type center() const
0389 {
0390 point_type result;
0391 result[0] = (left + right) / 2.;
0392 result[1] = (top + bottom) / 2.;
0393 return result;
0394 }
0395
0396 point_type origin() const
0397 {
0398 point_type result;
0399 result[0] = left;
0400 result[1] = top;
0401 return result;
0402 }
0403
0404 point_difference_type extent() const
0405 {
0406 point_difference_type result;
0407 result[0] = right - left;
0408 result[1] = bottom - top;
0409 return result;
0410 }
0411
0412 private:
0413 shared_ptr< RandomNumberGenerator > gen_ptr;
0414 shared_ptr< rand_t > rand;
0415 double left, top, right, bottom;
0416 };
0417
0418 template < typename RandomNumberGenerator = minstd_rand >
0419 class cube_topology : public hypercube_topology< 3, RandomNumberGenerator >
0420 {
0421 typedef hypercube_topology< 3, RandomNumberGenerator > inherited;
0422
0423 public:
0424 explicit cube_topology(double scaling = 1.0) : inherited(scaling) {}
0425
0426 cube_topology(RandomNumberGenerator& gen, double scaling = 1.0)
0427 : inherited(gen, scaling)
0428 {
0429 }
0430 };
0431
0432 template < std::size_t Dims, typename RandomNumberGenerator = minstd_rand >
0433 class ball_topology : public convex_topology< Dims >
0434 {
0435 typedef uniform_01< RandomNumberGenerator, double > rand_t;
0436
0437 public:
0438 typedef typename convex_topology< Dims >::point_type point_type;
0439 typedef typename convex_topology< Dims >::point_difference_type
0440 point_difference_type;
0441
0442 explicit ball_topology(double radius = 1.0)
0443 : gen_ptr(new RandomNumberGenerator)
0444 , rand(new rand_t(*gen_ptr))
0445 , radius(radius)
0446 {
0447 }
0448
0449 ball_topology(RandomNumberGenerator& gen, double radius = 1.0)
0450 : gen_ptr(), rand(new rand_t(gen)), radius(radius)
0451 {
0452 }
0453
0454 point_type random_point() const
0455 {
0456 point_type p;
0457 double dist_sum;
0458 do
0459 {
0460 dist_sum = 0.0;
0461 for (std::size_t i = 0; i < Dims; ++i)
0462 {
0463 double x = (*rand)() * 2 * radius - radius;
0464 p[i] = x;
0465 dist_sum += x * x;
0466 }
0467 } while (dist_sum > radius * radius);
0468 return p;
0469 }
0470
0471 point_type bound(point_type a) const
0472 {
0473 BOOST_USING_STD_MIN();
0474 BOOST_USING_STD_MAX();
0475 double r = 0.;
0476 for (std::size_t i = 0; i < Dims; ++i)
0477 r = boost::math::hypot(r, a[i]);
0478 if (r <= radius)
0479 return a;
0480 double scaling_factor = radius / r;
0481 point_type p;
0482 for (std::size_t i = 0; i < Dims; ++i)
0483 p[i] = a[i] * scaling_factor;
0484 return p;
0485 }
0486
0487 double distance_from_boundary(point_type a) const
0488 {
0489 double r = 0.;
0490 for (std::size_t i = 0; i < Dims; ++i)
0491 r = boost::math::hypot(r, a[i]);
0492 return radius - r;
0493 }
0494
0495 point_type center() const
0496 {
0497 point_type result;
0498 for (std::size_t i = 0; i < Dims; ++i)
0499 result[i] = 0;
0500 return result;
0501 }
0502
0503 point_type origin() const
0504 {
0505 point_type result;
0506 for (std::size_t i = 0; i < Dims; ++i)
0507 result[i] = -radius;
0508 return result;
0509 }
0510
0511 point_difference_type extent() const
0512 {
0513 point_difference_type result;
0514 for (std::size_t i = 0; i < Dims; ++i)
0515 result[i] = 2. * radius;
0516 return result;
0517 }
0518
0519 private:
0520 shared_ptr< RandomNumberGenerator > gen_ptr;
0521 shared_ptr< rand_t > rand;
0522 double radius;
0523 };
0524
0525 template < typename RandomNumberGenerator = minstd_rand >
0526 class circle_topology : public ball_topology< 2, RandomNumberGenerator >
0527 {
0528 typedef ball_topology< 2, RandomNumberGenerator > inherited;
0529
0530 public:
0531 explicit circle_topology(double radius = 1.0) : inherited(radius) {}
0532
0533 circle_topology(RandomNumberGenerator& gen, double radius = 1.0)
0534 : inherited(gen, radius)
0535 {
0536 }
0537 };
0538
0539 template < typename RandomNumberGenerator = minstd_rand >
0540 class sphere_topology : public ball_topology< 3, RandomNumberGenerator >
0541 {
0542 typedef ball_topology< 3, RandomNumberGenerator > inherited;
0543
0544 public:
0545 explicit sphere_topology(double radius = 1.0) : inherited(radius) {}
0546
0547 sphere_topology(RandomNumberGenerator& gen, double radius = 1.0)
0548 : inherited(gen, radius)
0549 {
0550 }
0551 };
0552
0553 template < typename RandomNumberGenerator = minstd_rand > class heart_topology
0554 {
0555
0556
0557
0558
0559
0560
0561 struct point
0562 {
0563 point()
0564 {
0565 values[0] = 0.0;
0566 values[1] = 0.0;
0567 }
0568 point(double x, double y)
0569 {
0570 values[0] = x;
0571 values[1] = y;
0572 }
0573
0574 double& operator[](std::size_t i) { return values[i]; }
0575 double operator[](std::size_t i) const { return values[i]; }
0576
0577 private:
0578 double values[2];
0579 };
0580
0581 bool in_heart(point p) const
0582 {
0583 #ifndef BOOST_NO_STDC_NAMESPACE
0584 using std::abs;
0585 #endif
0586
0587 if (p[1] < abs(p[0]) - 2000)
0588 return false;
0589 if (p[1] <= -1000)
0590 return true;
0591 if (boost::math::hypot(p[0] - -500, p[1] - -500)
0592 <= 500. * boost::math::constants::root_two< double >())
0593 return true;
0594 if (boost::math::hypot(p[0] - 500, p[1] - -500)
0595 <= 500. * boost::math::constants::root_two< double >())
0596 return true;
0597 return false;
0598 }
0599
0600 bool segment_within_heart(point p1, point p2) const
0601 {
0602
0603 if ((p1[0] < 0) == (p2[0] < 0))
0604 return true;
0605 if (p1[0] == p2[0])
0606 return true;
0607 double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]);
0608 double intercept = p1[1] - p1[0] * slope;
0609 if (intercept > 0)
0610 return false;
0611 return true;
0612 }
0613
0614 typedef uniform_01< RandomNumberGenerator, double > rand_t;
0615
0616 public:
0617 typedef point point_type;
0618
0619 heart_topology()
0620 : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr))
0621 {
0622 }
0623
0624 heart_topology(RandomNumberGenerator& gen)
0625 : gen_ptr(), rand(new rand_t(gen))
0626 {
0627 }
0628
0629 point random_point() const
0630 {
0631 point result;
0632 do
0633 {
0634 result[0] = (*rand)()
0635 * (1000
0636 + 1000 * boost::math::constants::root_two< double >())
0637 - (500 + 500 * boost::math::constants::root_two< double >());
0638 result[1] = (*rand)()
0639 * (2000
0640 + 500
0641 * (boost::math::constants::root_two< double >()
0642 - 1))
0643 - 2000;
0644 } while (!in_heart(result));
0645 return result;
0646 }
0647
0648
0649
0650
0651 double distance(point a, point b) const
0652 {
0653 if (segment_within_heart(a, b))
0654 {
0655
0656 return boost::math::hypot(b[0] - a[0], b[1] - a[1]);
0657 }
0658 else
0659 {
0660
0661 return boost::math::hypot(a[0], a[1])
0662 + boost::math::hypot(b[0], b[1]);
0663 }
0664 }
0665
0666 point move_position_toward(point a, double fraction, point b) const
0667 {
0668 if (segment_within_heart(a, b))
0669 {
0670
0671 return point(a[0] + (b[0] - a[0]) * fraction,
0672 a[1] + (b[1] - a[1]) * fraction);
0673 }
0674 else
0675 {
0676 double distance_to_point_a = boost::math::hypot(a[0], a[1]);
0677 double distance_to_point_b = boost::math::hypot(b[0], b[1]);
0678 double location_of_point = distance_to_point_a
0679 / (distance_to_point_a + distance_to_point_b);
0680 if (fraction < location_of_point)
0681 return point(a[0] * (1 - fraction / location_of_point),
0682 a[1] * (1 - fraction / location_of_point));
0683 else
0684 return point(b[0]
0685 * ((fraction - location_of_point)
0686 / (1 - location_of_point)),
0687 b[1]
0688 * ((fraction - location_of_point)
0689 / (1 - location_of_point)));
0690 }
0691 }
0692
0693 private:
0694 shared_ptr< RandomNumberGenerator > gen_ptr;
0695 shared_ptr< rand_t > rand;
0696 };
0697
0698 }
0699
0700 #endif