// TBezierInterpolation.cpp #include <vector> #include <iostream> #include <cmath> using namespace std; #define EPSILON 1.0e-5 #define RESOLUTION 32 class Point2D { public: double x, y; Point2D() { x = y = 0.0; }; Point2D(double _x, double _y) { x = _x; y = _y; }; Point2D operator +(const Point2D &point) const { return Point2D(x + point.x, y + point.y); }; Point2D operator -(const Point2D &point) const { return Point2D(x - point.x, y - point.y); }; Point2D operator *(double v) const { return Point2D(x * v, y * v); }; void operator +=(const Point2D &point) { x += point.x; y += point.y; }; void operator -=(const Point2D &point) { x -= point.x; y -= point.y; }; void normalize() { double l = sqrt(x * x + y * y); x /= l; y /= l; } }; class Segment { public: Point2D points[4]; void calc(double t, Point2D &p) { double t2 = t * t; double t3 = t2 * t; double nt = 1.0 - t; double nt2 = nt * nt; double nt3 = nt2 * nt; p.x = nt3 * points[0].x + 3.0 * t * nt2 * points[1].x + 3.0 * t2 * nt * points[2].x + t3 * points[3].x; p.y = nt3 * points[0].y + 3.0 * t * nt2 * points[1].y + 3.0 * t2 * nt * points[2].y + t3 * points[3].y; }; }; bool calculateSpline(const vector<Point2D> &values, vector<Segment> &bezier) { int n = values.size() - 1; if (n < 2) return false; bezier.resize(n); Point2D tgL; Point2D tgR; Point2D cur; Point2D next = values[1] - values[0]; next.normalize(); double l1, l2, tmp, x; --n; for (int i = 0; i < n; ++i) { bezier[i].points[0] = bezier[i].points[1] = values[i]; bezier[i].points[2] = bezier[i].points[3] = values[i + 1]; cur = next; next = values[i + 2] - values[i + 1]; next.normalize(); tgL = tgR; tgR = cur + next; tgR.normalize(); if (abs(values[i + 1].y - values[i].y) < EPSILON) { l1 = l2 = 0.0; } else { tmp = values[i + 1].x - values[i].x; l1 = abs(tgL.x) > EPSILON ? tmp / (2.0 * tgL.x) : 1.0; l2 = abs(tgR.x) > EPSILON ? tmp / (2.0 * tgR.x) : 1.0; } if (abs(tgL.x) > EPSILON && abs(tgR.x) > EPSILON) { tmp = tgL.y / tgL.x - tgR.y / tgR.x; if (abs(tmp) > EPSILON) { x = (values[i + 1].y - tgR.y / tgR.x * values[i + 1].x - values[i].y + tgL.y / tgL.x * values[i].x) / tmp; if (x > values[i].x && x < values[i + 1].x) { if (tgL.y > 0.0) { if (l1 > l2) l1 = 0.0; else l2 = 0.0; } else { if (l1 < l2) l1 = 0.0; else l2 = 0.0; } } } } bezier[i].points[1] += tgL * l1; bezier[i].points[2] -= tgR * l2; } l1 = abs(tgL.x) > EPSILON ? (values[n + 1].x - values[n].x) / (2.0 * tgL.x) : 1.0; bezier[n].points[0] = bezier[n].points[1] = values[n]; bezier[n].points[2] = bezier[n].points[3] = values[n + 1]; bezier[n].points[1] += tgR * l1; return true; } int main() { vector<Point2D> testValues; vector<Segment> spline; Point2D p; testValues.push_back(Point2D(0, 0)); testValues.push_back(Point2D(20, 0)); testValues.push_back(Point2D(45, -47)); testValues.push_back(Point2D(53, 335)); testValues.push_back(Point2D(57, 26)); testValues.push_back(Point2D(62, 387)); testValues.push_back(Point2D(74, 104)); testValues.push_back(Point2D(89, 0)); testValues.push_back(Point2D(95, 100)); testValues.push_back(Point2D(100, 0)); calculateSpline(testValues, spline); for (auto s : spline) { for (int i = 0; i < RESOLUTION; ++i) { s.calc((double)i / (double)RESOLUTION, p); cout << p.x << " " << p.y << endl; } } cout << testValues.back().x << " " << testValues.back().y << endl; return 0; }
Standard input is empty
0 0 0.057373 0 0.224609 0 0.494385 0 0.859375 0 1.31226 0 1.8457 0 2.45239 0 3.125 0 3.8562 0 4.63867 0 5.46509 0 6.32812 0 7.22046 0 8.13477 0 9.06372 0 10 0 10.9363 0 11.8652 0 12.7795 0 13.6719 0 14.5349 0 15.3613 0 16.1438 0 16.875 0 17.5476 0 18.1543 0 18.6877 0 19.1406 0 19.5056 0 19.7754 0 19.9426 0 20 0 21.136 -0.803974 22.2034 -1.79807 23.2066 -2.96757 24.1504 -4.29773 25.0392 -5.77386 25.8777 -7.38121 26.6704 -9.10506 27.4219 -10.9307 28.1367 -12.8434 28.8196 -14.8284 29.4749 -16.8711 30.1074 -18.9566 30.7216 -21.0703 31.322 -23.1974 31.9133 -25.3233 32.5 -27.4332 33.0867 -29.5123 33.678 -31.546 34.2784 -33.5195 34.8926 -35.4181 35.5251 -37.227 36.1804 -38.9317 36.8633 -40.5172 37.5781 -41.969 38.3296 -43.2723 39.1223 -44.4123 39.9608 -45.3744 40.8496 -46.1438 41.7934 -46.7057 42.7966 -47.0456 43.864 -47.1486 45 -47 45.3635 -45.8203 45.7051 -42.5527 46.0261 -37.3367 46.3281 -30.3116 46.6125 -21.6168 46.8809 -11.3917 47.1345 0.224322 47.375 13.0919 47.6038 27.0717 47.8223 42.0243 48.032 57.8103 48.2344 74.2903 48.4309 91.3251 48.623 108.775 48.8123 126.501 49 144.363 49.1877 162.223 49.377 179.941 49.5691 197.376 49.7656 214.391 49.968 230.846 50.1777 246.6 50.3962 261.516 50.625 275.453 50.8655 288.273 51.1191 299.835 51.3875 310 51.6719 318.63 51.9739 325.584 52.2949 330.723 52.6365 333.908 53 335 53.1818 334.113 53.3525 331.528 53.5131 327.36 53.6641 321.72 53.8063 314.723 53.9404 306.481 54.0673 297.107 54.1875 286.716 54.3019 275.418 54.4111 263.329 54.516 250.561 54.6172 237.227 54.7155 223.441 54.8115 209.315 54.9061 194.963 55 180.497 55.0939 166.032 55.1885 151.68 55.2845 137.554 55.3828 123.768 55.484 110.434 55.5889 97.6663 55.6981 85.5773 55.8125 74.2805 55.9327 63.8889 56.0596 54.5158 56.1937 46.2742 56.3359 39.2773 56.4869 33.6383 56.6475 29.4703 56.8182 26.8865 57 26 57.2272 27.0354 57.4407 30.0536 57.6413 34.9225 57.8301 41.5099 58.0078 49.6836 58.1755 59.3115 58.3341 70.2612 58.4844 82.4008 58.6273 95.5979 58.7639 109.72 58.895 124.636 59.0215 140.213 59.1443 156.318 59.2644 172.821 59.3827 189.587 59.5 206.486 59.6173 223.385 59.7356 240.152 59.8557 256.655 59.9785 272.761 60.105 288.339 60.2361 303.256 60.3727 317.38 60.5156 330.579 60.6659 342.72 60.8245 353.672 60.9922 363.302 61.1699 371.478 61.3587 378.068 61.5593 382.94 61.7728 385.961 62 387 62.5453 386.379 63.0576 384.544 63.5392 381.565 63.9922 377.508 64.4188 372.444 64.8213 366.439 65.2018 359.563 65.5625 351.882 65.9056 343.467 66.2334 334.384 66.548 324.703 66.8516 314.492 67.1464 303.818 67.4346 292.75 67.7184 281.356 68 269.705 68.2816 257.866 68.5654 245.905 68.8536 233.891 69.1484 221.894 69.452 209.98 69.7666 198.219 70.0944 186.678 70.4375 175.426 70.7982 164.531 71.1787 154.061 71.5812 144.085 72.0078 134.671 72.4608 125.888 72.9424 117.802 73.4547 110.484 74 104 74.7029 96.6122 75.4044 89.5532 76.1032 82.8167 76.7979 76.3966 77.487 70.2866 78.1693 64.4807 78.8434 58.9726 79.5078 53.7562 80.1613 48.8252 80.8024 44.1736 81.4297 39.7951 82.042 35.6835 82.6378 31.8327 83.2157 28.2366 83.7744 24.8888 84.3125 21.7833 84.8286 18.9138 85.3214 16.2743 85.7895 13.8584 86.2314 11.6601 86.646 9.67317 87.0316 7.89141 87.3871 6.30865 87.7109 4.91873 88.0018 3.71546 88.2584 2.69266 88.4793 1.84417 88.6631 1.1638 88.8084 0.64537 88.9139 0.282713 88.9783 0.0696488 89 0 89.2726 0.297909 89.5288 1.14382 89.7696 2.50116 89.9961 4.33339 90.2094 6.60393 90.4106 9.27623 90.6009 12.3137 90.7812 15.6799 90.9528 19.3381 91.1167 23.2518 91.274 27.3845 91.4258 31.6995 91.5732 36.1604 91.7173 40.7306 91.8592 45.3735 92 50.0525 92.1408 54.7311 92.2827 59.3728 92.4268 63.9409 92.5742 68.3989 92.726 72.7103 92.8833 76.8385 93.0472 80.7468 93.2188 84.3989 93.3991 87.7581 93.5894 90.7878 93.7906 93.4514 94.0039 95.7125 94.2304 97.5345 94.4712 98.8808 94.7274 99.7148 95 100 95.2345 99.712 95.4685 98.8749 95.7016 97.5252 95.9332 95.6995 96.1631 93.4346 96.3906 90.7669 96.6153 87.733 96.8368 84.3697 97.0547 80.7136 97.2684 76.8011 97.4775 72.669 97.6816 68.3539 97.8802 63.8923 98.0728 59.321 98.259 54.6764 98.4383 49.9953 98.6103 45.3142 98.7745 40.6698 98.9305 36.0986 99.0777 31.6373 99.2158 27.3225 99.3443 23.1908 99.4627 19.2789 99.5706 15.6232 99.6675 12.2606 99.753 9.22745 99.8266 6.56051 99.8878 4.29636 99.9362 2.47163 99.9713 1.12291 99.9928 0.28683 100 0