From: Luca Turchet on
Dear Roger,
thanks a lot.
I tried to understand how that functions proposed by John work, but I was not successiful in applying them for my purposes ;-(
I would like to have just an example of the code to use, in order to understand how I can use those functions in my case.

For that reason I opted for the solution you proposed. BTW, I implemented it well?
It is correct?

It is for sure my fault if I have not understood fully how those functions work. I will look at them better now, and I hope to find a solution as soon as possible.

Any suggestion or code example is really appreciated ;-)

Luca

P.S. @John: I forgot to tell you "thanks" for the precious advice.



"Roger Stafford" <ellieandrogerxyzzy(a)mindspring.com.invalid> wrote in message <hs4eog$dhh$1(a)fred.mathworks.com>...
> "Luca Turchet" <tur(a)imi.aau.dk> wrote in message <hs42df$eo0$1(a)fred.mathworks.com>...
> > Hi all,
> > I think I got it.
> > .......
>
> I think you should follow John's excellent advice, Luca. It sounds the best to me, since you have a curve y = f(x) with a known formula for its derivative, f'(x). The differential equation you would be solving with 'ode45' is:
>
> dx/ds = 1/sqrt(1+f'(x).^2) .
>
> You integrate with respect to arc length s as your independent variable, starting with x as the x-coordinate of point A at s = 0, and you stop when s has reached the distance you wish to travel along the curve to point B. What could be simpler?
>
> Roger Stafford
From: Roger Stafford on
"Luca Turchet" <tur(a)imi.aau.dk> wrote in message <hs4g1p$5jm$1(a)fred.mathworks.com>...
> Dear Roger,
> thanks a lot.
> I tried to understand how that functions proposed by John work, but I was not successiful in applying them for my purposes ;-(
> I would like to have just an example of the code to use, in order to understand how I can use those functions in my case.
>
> For that reason I opted for the solution you proposed. BTW, I implemented it well?
> It is correct?
>
> It is for sure my fault if I have not understood fully how those functions work. I will look at them better now, and I hope to find a solution as soon as possible.
>
> Any suggestion or code example is really appreciated ;-)
>
> Luca
>
> P.S. @John: I forgot to tell you "thanks" for the precious advice.

Bruno gave you a good hint as to why your 'find' might come up empty when he said "especially when the function has a large slope". Since you have asked me if your code is correct, perhaps he will forgive me if I spill the beans. The problem is that in the inequalities

Z>distance & Z < distance + step_increment

you might easily be so unlucky that all Z's are either less than "distance" or greater than "distance+step_increment", since they have larger increments than "step_increment", especially if the slope is still high. Instead of the double inequality, you should be using 'find' with the 'first' option and just your first inequality.

Also you need to be sure and select the upper end of the X vector so that it exceeds A_x by at least as much as the quantity "distance" to ensure that a sufficiently large Z will attained. Right now you just have a 15. It should be A_x+distance.

One last point. The B_x you have selected gives an arc length beyond the desired distance, and you need to adjust it backwards appropriately. That is, B_x needs to be reduced back towards the previous X value in proportion to the amount back toward the previous Z value of the desired "distance" value.

Well, one last, last point. By all means use John's 'ode45' method. It is by far the cleanest of all the ideas that have been put forth here. Don't use mine. It was thought up on the spur of the moment.

Roger Stafford
From: John D'Errico on
"Roger Stafford" <ellieandrogerxyzzy(a)mindspring.com.invalid> wrote in message <hs4lah$756$1(a)fred.mathworks.com>...

> Well, one last, last point. By all means use John's 'ode45' method. It is by far the cleanest of all the ideas that have been put forth here. Don't use mine. It was thought up on the spur of the moment.
>

This is not too difficult to do. Just follow the advice
we have offered.

For example...

Given the function f(x) = sin(x), can I find a point along
the curve that lies exactly 25 units in arc length along
that curve? I won't do it using a Gaussian, as that is your
problem to solve. I will do it several ways though, so you
can see the approach.

First, I'll use my arc length interpolation routines. I know
that if I go out as far as 25 units on the x axis, the arc
length along the curve itself must be longer than 25 units.
(Any curve must be longer than the straight line distance.)

Pick 100 points arbitrarily along that curve.

x = linspace(0,25,100);
y = sin(x);

What is the arc length itself? Use a cubic spline for accuracy
here.

totallength = arclength(x,y,'spline')
totallength =
30.374051851635

It turns out that this curve is a bit longer than the distance
along the x axis, but not massively so. Plot the points.

plot(x,y,'o')
axis equal

Now, find that point that is a distance of 25 units along
the curve.

xy = interparc(25/totallength,x,y,'spline')
xy =
20.5883445841352 0.985863637123116

So at (x,y) = (20.5883445841352 , 0.985863637123116)
the arc length along the curve should be 25.

Of course, this is not exact, since it uses a spline interpolant,
then integrates along that spline. We can do this far more
accurately by an integration using ode45.

The derivative of sin(x) is cos(x). So the differential equation
we should solve, parameterized in terms of x, is...

dSdx = sqrt(1 + cos(x)^2)

Where S(0) = 0. How do we solve it using ode45?

fun = @(x,y) sqrt(1 + cos(x)^2);
res = ode45(fun,[0,25],0);

What is the total arc length of the curve?

res.y(end)
ans =
30.3786473265496

As you should see, it is quite close to that reported by
my own arclength function, which used an integral
along a parametric spline curve.

But how do we find that point which lies at exactly
25 units along that curve? Easiest is just to start the
solver at S(0) = -25. Then I'll just look for a zero
crossing. Save this function as an m-file on your
search path.

% ===============================
function [value,isterminal,direction] = ode_events(t,y)
% ode event trap, looking for zero crossings of y.
value = y;
isterminal = ones(size(y));
direction = ones(size(y));
% ===============================

Now, call ode45.

opts = odeset('events',@ode_events);
res = ode45(fun,[0,25],-25,opts);

Look at the result.

res
res =
solver: 'ode45'
extdata: [1x1 struct]
x: [0 2.5 5 7.5 10 12.5 15 17.5 20 20.5870891327006]
y: [1x10 double]
xe: 20.5870891327006
ye: 7.7715611723761e-16
ie: 1
stats: [1x1 struct]
idata: [1x1 struct]

The value of res.xe is that point where the arclength to
that point is exactly 25 units. Again, it is pretty close to
that reported by interparc. The difference is in the
approximation of the curve by a spline. Had we sampled
the curve at 200 points or more, the error would be
smaller.

John
From: Luca Turchet on
Hi all,
I think I have been able to use the John method.
Here I post the code. I ask you an opinion. At the end I ask also a MATLAB syntax help:



I define a function in the file distance_integral.m (the definition of the files gaussian.m and gaussian_der.m has been given in the previous posts):


function [dxds] = distance_integral(s,x)

mu = 0;%mu
sigma = 2;%sigma

dxds = 1/sqrt(1 + gaussian_der(x, mu, sigma).^2);



Then I use such function within ODE:


%Gaussian parameters
mu = 0;%mu
sigma = 2;%sigma


%Point A coordinates
A_x = -0.4;
A_y = gaussian(A_x, mu, sigma);

distance = 1.2;%wanted distance from A to B


Sspan = [0 distance]; % Solve from s=0 to s=distance
IC = A_x; % y(s=0) = A_x

[S X] = ode45(@distance_integral,Sspan,IC); % Solve ODE



B_X = X(length(X))
B_Y = gaussian(B_x, mu, sigma);


%PLOT of the gaussian curve
starting_point_x = -15;
end_point_x = 15;

step_increment = 0.001;
X = [starting_point_x:step_increment:end_point_x];
Y = gaussian(X, m, s);
plot(X,Y)

hold on;
plot(A_x,A_y,'ro');
plot(B_x,B_y,'k*');
hold off;


What do you think? It seems correct to me.


Now I have a syntax problem managing the function handles: I would like to pass
to the function handled the values of mu and sigma. I tried this but I get an error:

[S X] = ode45(@(s,x) distance_integral(s,x,mu,sigma),Sspan,IC)


The function in the file distance_integral.m is:


function [dxds] = distance_integral(s,x,mu,sigma)

dxds = 1/sqrt(1 + gaussian_der(x, mu, sigma).^2);







Any suggestion?


Please let me know!

Cheers







"Roger Stafford" <ellieandrogerxyzzy(a)mindspring.com.invalid> wrote in message <hs4lah$756$1(a)fred.mathworks.com>...
> "Luca Turchet" <tur(a)imi.aau.dk> wrote in message <hs4g1p$5jm$1(a)fred.mathworks.com>...
> > Dear Roger,
> > thanks a lot.
> > I tried to understand how that functions proposed by John work, but I was not successiful in applying them for my purposes ;-(
> > I would like to have just an example of the code to use, in order to understand how I can use those functions in my case.
> >
> > For that reason I opted for the solution you proposed. BTW, I implemented it well?
> > It is correct?
> >
> > It is for sure my fault if I have not understood fully how those functions work. I will look at them better now, and I hope to find a solution as soon as possible.
> >
> > Any suggestion or code example is really appreciated ;-)
> >
> > Luca
> >
> > P.S. @John: I forgot to tell you "thanks" for the precious advice.
>
> Bruno gave you a good hint as to why your 'find' might come up empty when he said "especially when the function has a large slope". Since you have asked me if your code is correct, perhaps he will forgive me if I spill the beans. The problem is that in the inequalities
>
> Z>distance & Z < distance + step_increment
>
> you might easily be so unlucky that all Z's are either less than "distance" or greater than "distance+step_increment", since they have larger increments than "step_increment", especially if the slope is still high. Instead of the double inequality, you should be using 'find' with the 'first' option and just your first inequality.
>
> Also you need to be sure and select the upper end of the X vector so that it exceeds A_x by at least as much as the quantity "distance" to ensure that a sufficiently large Z will attained. Right now you just have a 15. It should be A_x+distance.
>
> One last point. The B_x you have selected gives an arc length beyond the desired distance, and you need to adjust it backwards appropriately. That is, B_x needs to be reduced back towards the previous X value in proportion to the amount back toward the previous Z value of the desired "distance" value.
>
> Well, one last, last point. By all means use John's 'ode45' method. It is by far the cleanest of all the ideas that have been put forth here. Don't use mine. It was thought up on the spur of the moment.
>
> Roger Stafford
From: Roger Stafford on
"John D'Errico" <woodchips(a)rochester.rr.com> wrote in message <hs54cv$3jk$1(a)fred.mathworks.com>...
> ........
> dSdx = sqrt(1 + cos(x)^2)
> ..........
> But how do we find that point which lies at exactly
> 25 units along that curve? Easiest is just to start the
> solver at S(0) = -25. Then I'll just look for a zero
> crossing. Save this function as an m-file on your
> search path.
> ........

John, why wouldn't it be a lot easier to use 'ode45' to solve the differential equation

dxds = 1/sqrt(1+cos(x)^2)

as I mentioned earlier? Then you use s as the independent variable in 'ode45' from s = 0 to s = "desired distance", with x starting at the x value of point A. That way you don't have to go to the trouble of searching for a "crossing event" along the way.

Roger Stafford