Create a function handle that is a sum of function handles
3 次查看(过去 30 天)
显示 更早的评论
Goodmorning everyone,
I have the following points
POINTS=[0.0194358127458200 0.0125146090698240 0.0120324235527160 0.00761174198214000 0.00660775699279100 0.00381485098617300 0.00195617023840500 0.000824508358196000 0.00121681256884900 0.000390389885216000 0.000444315057222000 0;
0 0.000452782917043000 0.000395689955442000 0.00121172812659200 0.000829869449880000 0.00195546440425700 0.00381482017361200 0.00661064156533300 0.00762496776011900 0.0120411026638820 0.0125098828784870 0.0189137987850580];
I need to create a function handle as follows.
I know that the center of the circumference that approximates better those points is function of R, and is found in the point [R,R]. The approximation error is then:
error=@(R) abs(norm([R-POINTS(1,i),R-POINTS(2,i)])-R));
This for every point.
I want to create the function handle that is the sum of all the errors like:
1) totdist=@(R) error1+error2+error3+...
I can create a single function function manually by summing every error like:
2) totdist=@(R) abs(norm([R-POINTS(1,1),R-POINTS(2,1)])-R))+abs(norm([R-POINTS(1,2),R-POINTS(2,2)])-R))+abs(norm([R-POINTS(1,3),R-POINTS(2,3)])-R))+...
However when the number of points become large, I would like to create the summing function 1) authomatically without manually summing 100 times as in 2).
The function must be used with "fminsearch" afterwards.
Is there a way to achieve this?
Thanks in advance for the answer.
1 个评论
Bjorn Gustavsson
2023-1-14
@Riccardo Mari: at least try to work through the suggestions to see what they do. Use simple test-cases.
回答(3 个)
Bjorn Gustavsson
2023-1-13
Your specification is a bit ambiguous to me, but if I interpret it such that you want to fit a function such that:
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1262165/image.png)
(I've used the additional condition that
and
, but this one can be easily relaxed). You can make a general solution something like this:
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1262170/image.png)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1262175/image.png)
f_x = @(R,theta,f_theta) R + f_theta(R,theta).*cos(theta);
f_y = @(R,theta,f_theta) R + f_theta(R,theta).*sin(theta);
err_fcn = @(R,X,Y,f_theta) sum( (X-f_x(R,atan2(Y-R,X-R),f_theta)).^2 + (Y-f_y(R,atan2(Y-R,X-R),f_theta)).^2);
f_theta = @(R,theta) R*ones(size(theta));
Rest = fminsearch(@(R) err_fcn(R,POINTS(1,:)',POINTS(2,:)',f_theta),20e-3);
This is a rather cumbersome way to make a simple circle-fitting-function, you will find multiple circle-fitting-functions on the file exchange: circle-fitting FEx contributions. If your circumference is a bit more complicated, even more complicated than an ellipse even, then you simply have to modify the f_theta function-handle accordingly. If the centre of the circumference is not exactly the same as the radius for example then you'll have to modify the above snippet a bit:
f_x = @(R,theta,f_theta) R(1) + f_theta(R(3),theta).*cos(theta);
f_y = @(R,theta,f_theta) R(2) + f_theta(R(3),theta).*sin(theta);
err_fcn = @(R,X,Y,f_theta) sum( (X-f_x(R,atan2(Y-R(2),X-R(1)),f_theta)).^2 + (Y-f_y(R,atan2(Y-R(2),X-R(1)),f_theta)).^2);
f_theta = @(R,theta) R*ones(size(theta));
Rest3 = fminsearch(@(R) err_fcn(R,POINTS(1,:)',POINTS(2,:)',f_theta),20e-3*[1 1 1]);
You can also allow for additional parameters to fit to, for example major and minor radius and angle of semi-major axis of an ellipse. But, this starts to become rather cluttered code for anonymous function-handles at this stage and somewhere here I tend to transition to proper matlab-functions in files, just to keep the code cleaner.
HTH
2 个评论
Bjorn Gustavsson
2023-1-13
编辑:Bjorn Gustavsson
2023-1-13
That's what my first example does. For general circle-fitting functions follow the link to the good file-exchange contributions that solve that problem for the more general case.
HTH
Matt J
2023-1-13
error=@(R) abs( vecnorm(POINTS-R) - R );
1 个评论
Matt J
2023-1-13
编辑:Matt J
2023-1-13
I have to measure the error in the distance as error=@(R) abs(norm([R-POINTS(1,i),R-POINTS(2,i)])-R)) .... So I have to apply this to every point in the list.
No, you do not have to implement a separate error function for every Point(:,i). There are vectorized functions which calculate all errors at once, which is what my answer has given you.
I want to find the radius that minimizes the total error.
If you know the center [x0,y0] of the circle already, the minimizing R is just the average of the empricial distances. There is no need for fminsearch.
R = mean(vecnorm(POINTS-[x0;y0]))
Riccardo Mari
2023-1-13
1 个评论
Matt J
2023-1-13
编辑:Matt J
2023-1-13
It's a bad solution. Very slow and inefficient. I urge you to reconsider the other proposals.
POINTS=rand(2,100000); R=0;
tic;
N=length(POINTS);
f=cell(N,1);
for i=1:N
f{i}=@(R) abs(norm([R-POINTS(1,i),R-POINTS(2,i)])-R);
end
totdist=@(R) summer(f,R);
version1=totdist(R); %calculation
toc;
tic
errorFcn=@(R) norm( vecnorm(POINTS-R) - R ,1);
version2=errorFcn(R);%calculation
toc
version1,version2 %same result
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!