00001
00002
00003
00004 #include "common.h"
00005 #include "numfuncs.h"
00006
00007 #include <algorithm>
00008
00009 using namespace std;
00010
00011
00012
00013
00014 template<typename T>
00015 typename vector<T>::iterator
00016 get_interpolation_segment(vector<T> &bb, double x)
00017 {
00018
00019 static typename vector<T>::iterator pos = bb.begin();
00020 assert (size(bb) > 1);
00021 if (x <= bb.front().x)
00022 return bb.begin();
00023 if (x >= bb.back().x)
00024 return bb.end() - 2;
00025 if (pos < bb.begin() || pos >= bb.end())
00026 pos = bb.begin();
00027
00028 if (pos->x <= x) {
00029
00030 if (x <= (pos+1)->x)
00031 return pos;
00032
00033 pos++;
00034 if (pos->x <= x && (pos+1 == bb.end() || x <= (pos+1)->x))
00035 return pos;
00036 }
00037 pos = lower_bound(bb.begin(), bb.end(), T(x, 0)) - 1;
00038
00039 return pos;
00040 }
00041
00042 void prepare_spline_interpolation (vector<PointQ> &bb)
00043 {
00044
00045 const int n = bb.size();
00046 if (n == 0)
00047 return;
00048
00049 bb[0].q = 0;
00050 vector<double> u(n);
00051 for (int k = 1; k <= n-2; k++) {
00052 PointQ *b = &bb[k];
00053 double sig = (b->x - (b-1)->x) / ((b+1)->x - (b-1)->x);
00054 double t = sig * (b-1)->q + 2.;
00055 b->q = (sig - 1.) / t;
00056 u[k] = ((b+1)->y - b->y) / ((b+1)->x - b->x) - (b->y - (b-1)->y)
00057 / (b->x - (b - 1)->x);
00058 u[k] = (6. * u[k] / ((b+1)->x - (b-1)->x) - sig * u[k-1]) / t;
00059 }
00060 bb.back().q = 0;
00061 for (int k = n-2; k >= 0; k--) {
00062 PointQ *b = &bb[k];
00063 b->q = b->q * (b+1)->q + u[k];
00064 }
00065 }
00066
00067 double get_spline_interpolation(vector<PointQ> &bb, double x)
00068 {
00069 if (bb.empty())
00070 return 0.;
00071 if (bb.size() == 1)
00072 return bb[0].y;
00073 vector<PointQ>::iterator pos = get_interpolation_segment(bb, x);
00074
00075 double h = (pos+1)->x - pos->x;
00076 double a = ((pos+1)->x - x) / h;
00077 double b = (x - pos->x) / h;
00078 double t = a * pos->y + b * (pos+1)->y + ((a * a * a - a) * pos->q
00079 + (b * b * b - b) * (pos+1)->q) * (h * h) / 6.;
00080 return t;
00081 }
00082
00083 template <typename T>
00084 double get_linear_interpolation_(vector<T> &bb, double x)
00085 {
00086 if (bb.empty())
00087 return 0.;
00088 if (bb.size() == 1)
00089 return bb[0].y;
00090 typename vector<T>::iterator pos = get_interpolation_segment(bb, x);
00091 double a = ((pos + 1)->y - pos->y) / ((pos + 1)->x - pos->x);
00092 return pos->y + a * (x - pos->x);
00093 }
00094
00095 double get_linear_interpolation(vector<PointQ> &bb, double x)
00096 {
00097 return get_linear_interpolation_(bb, x);
00098 }
00099
00100 double get_linear_interpolation(vector<PointD> &bb, double x)
00101 {
00102 return get_linear_interpolation_(bb, x);
00103 }
00104
00105
00106
00107 static const double TINY = 1e-12;
00108
00109
00110 double rand_gauss()
00111 {
00112 static bool is_saved = false;
00113 static double saved;
00114 if (!is_saved) {
00115 double rsq, x1, x2;
00116 while(1) {
00117 x1 = rand_1_1();
00118 x2 = rand_1_1();
00119 rsq = x1 * x1 + x2 * x2;
00120 if (rsq >= TINY && rsq < 1)
00121 break;
00122 }
00123 double f = sqrt(-2. * log(rsq) / rsq);
00124 saved = x1 * f;
00125 is_saved = true;
00126 return x2 * f;
00127 }
00128 else {
00129 is_saved = false;
00130 return saved;
00131 }
00132 }
00133
00134 double rand_cauchy()
00135 {
00136 while (1) {
00137 double x1 = rand_1_1();
00138 double x2 = rand_1_1();
00139 double rsq = x1 * x1 + x2 * x2;
00140 if (rsq >= TINY && rsq < 1 && fabs(x1) >= TINY)
00141 return (x2 / x1);
00142 }
00143 }
00144
00145
00146 void SimplePolylineConvex::push_point(PointD const& p)
00147 {
00148 if (vertices_.size() < 2
00149 || is_left(*(vertices_.end() - 2), *(vertices_.end() - 1), p))
00150 vertices_.push_back(p);
00151 else {
00152
00153
00154 vertices_.pop_back();
00155 push_point(p);
00156 }
00157 }
00158