Boost logo

Boost Users :

From: Nick Thompson (nathompson7_at_[hidden])
Date: 2019-05-29 17:24:19


Hi Giorgino,

The strange behavior at the end of the Catmull-Rom splines is a deficiency of the method. However, we are fortunate that this is not a big deficiency. This is because the Catmull-Rom splines are interpolated by functions of compact support, so a point can influence at most four segments (only two, if the point is on the boundary). Looking at your images, I personally don't think they look bad. But presumably since you are writing this, you want better!

I would recommend adding two ghost points. Draw a line between point 0 and point 1, and put the ghost point "in the mirror", i.e., place it where point 1 would appear if a mirror sat in the plane passing through P0 and orthogonal to the line joining point zero and point one. You might contend that this is an arbitrary choice, and it is! But the compact support of the basis functions means that the decision is not super important, and this choice will at least give reasonable-looking tangent vectors.

   Nick

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Wednesday, May 29, 2019 12:08 PM, Giorgino R via Boost-users <boost-users_at_[hidden]> wrote:

> Hi all,
>
> I am trying to interpolate some data with a catmull_rom spline available in boost math (interpolation). However, the resulting spline has a strange behavior; especially, at its ends (see the attached image).
> Just out of curiosity, I also tried to normalise my data to [0-1] range. However, the line has had even worse behavior (see the attached image).
> Below, the c++ code segment of the interpolation is depicted:
>
> std::vector<std::array<double, 2>> points_intr(16);
>
> points_intr[0] = { 1.263270, 0.774614 };
> points_intr[1] = { 1.876, 2.480 };
> points_intr[2] = { 1.651110, 4.550 };
> points_intr[3] = { 1.426340, 5.688 };
> points_intr[4] = { 1.429, 7.054 };
> points_intr[5] = { 2.073220, 8.377020 };
> points_intr[6] = { 3.910, 9.140 };
> points_intr[7] = { 6.430, 9.537 };
> points_intr[8] = { 8.950, 9.859 };
> points_intr[9] = { 11.470, 10.317 };
> points_intr[10] = { 12.730, 10.6456 };
> points_intr[11] = { 13.990, 11.0741 };
> points_intr[12] = { 15.335, 11.6928 };
> points_intr[13] = { 16.680, 12.5661 };
> points_intr[14] = { 18.3538, 14.830 };
> points_intr[15] = { 18.700, 16.056 };
>
> bm::catmull_rom<std::array<double, 2>>
> interpolator_cr(std::move(points_intr));
>
> std::vector<double> x_linspace_cr(100);
> std::vector<std::array<double, 2>> inter_points(100);
> linspace(1.263270, 18.700, 100, x_linspace_cr); // evaluation points along the line
>
> for (std::size_t i{0}; i < x_linspace_cr.size(); ++i)
> {
> inter_points[i] = interpolator_cr(x_linspace_cr[i]);
> }
>
> Should I have to add additional (ghost) points at both ends? If yes, is there any optimum way to calculate where exactly to poisition these points? I understand if I get the derivatives at both end I can calculate a straight line that the additional points should lie within. However, how should I calculate the distance from the end points?
>
> I hope I am not doing anything fundamentally wrong. Any help would be much appreciated.
>
> Many thanks!



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net