Determine positions of projected points onto an ellipse
10 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Salad Box
am 15 Dez. 2022
Kommentiert: Salad Box
am 20 Dez. 2022
Hi,
I have a set of data points (blue dots below) and I woule like to project them onto an ellipse (with known a, b, x0, y0, and radian or tilt).
I wonder how I can determine the position of each projected points on the ellipse. Any advices/code/peudo code would be lovely. Thank you.
Akzeptierte Antwort
Matt J
am 16 Dez. 2022
Bearbeitet: Matt J
am 16 Dez. 2022
Use the ellipseprj function below. It requires the download of trustregprob from the file exchange
ab = [2 1]; %ellipse radii
xy0 = [1 1]; %ellipse center
rad=5; R = [cos(rad), -sin(rad); sin(rad),cos(rad)]; %ellipse tilt
xysamp = randn(2,5); %random points to be projected onto the ellipse
xyproj = ellipseprj( R'*diag(1./ab.^2)*R , xy0, xysamp); %the projected points
%%%Visualize
t = linspace(0,2*pi,50)';
xyc = xy0 + ab.*[cos(t), sin(t)]*R; %points for plotting the ellipse
plot(xyc(:,1),xyc(:,2),'b-')
axis equal
grid on
hold on
plot(xysamp(1,:),xysamp(2,:),'ro') %plot random points
plot(xyproj(1,:),xyproj(2,:),'ks') %plot their projections
line([xysamp(1,:);xyproj(1,:)],[xysamp(2,:);xyproj(2,:)],'color','g')
hold off
function Xp=ellipseprj(Q,xc,X0)
%Projects given 2D points onto 2D ellipse
%
% Xp=ellipseprj(Q,xc,X0)
%
%IN:
%
% Q,xc: Ellipse equation matrices. Q is 2x2 and xc is 2x1 such that
% ellipse equation is (y-xc).'*Q*(y-xc)=1
% X0: 2xN matrix of points to be projected
%
%OUT:
%
% Xp: 2xN matrix of projected points
N=size(X0,2);
xc=xc(:);
[Rt,D]=eig(Q);
Rt=real(Rt); D=real(D);
iD=diag(1./diag(D));
iDsqrt=sqrt(iD);
b=-iDsqrt*Rt.'*bsxfun(@minus,xc,X0);
Yp=nan(size(X0));
for i=1:N
Yp(:,i)=trustregprob(iD,b(:,i),1);
end
Xp=bsxfun(@plus, Rt*iDsqrt*Yp,xc);
end
5 Kommentare
Matt J
am 20 Dez. 2022
@Salad Box, In addition to what John said, it is a pretty basic calculus exercise to compute the tangent to the ellipse at B, and to verify numerically that the tangent is orthogonal to (A-B). I encourage doing that in addition to any visual tests.
Weitere Antworten (2)
John D'Errico
am 16 Dez. 2022
Bearbeitet: John D'Errico
am 16 Dez. 2022
Simple. Just download my distance2curve utility, found on the file exchange.
For some example data, I'm not sure what you meant by radian as a variable.
t = linspace(0,2*pi,50)';
ab = [2 1];
xy0 = [1 1];
rotmat = @(R) [cos(R), -sin(R);sin(R),cos(R)];
xyc = xy0 + ab.*[cos(t), sin(t)]*rotmat(5);
plot(xyc(:,1),xyc(:,2),'b-')
axis equal
grid on
Now for a given set of points,
xy0 = randn(10,2);
xyproj = distance2curve(xyc,xy0);
hold on
plot(xy0(:,1),xy0(:,2),'ro')
plot(xyproj(:,1),xyproj(:,2),'rs')
line([xy0(:,1),xyproj(:,1)]',[xy0(:,2),xyproj(:,2)]','color','g')
Each point is projected to the nearest point on the ellipse.
distance2curve is found for free download from the file exchange, here:
Torsten
am 16 Dez. 2022
Bearbeitet: Torsten
am 16 Dez. 2022
a = 2;
b = 1; % main axes
x0 = 1;
y0 = 1; % translation
alpha = 5; % rotation angle of ellipse in degrees
px = randn(1,10);
py = randn(1,10); % Sample points to be projected
syms theta xp yp xp_given yp_given
% Generate ellipse equation dependent on theta
x = a*cos(theta);
y = b*sin(theta);
% Solve for theta that minimizes the distance
f = (x-xp)^2 + (y-yp)^2;
df = diff(f,theta);
sol_theta = solve(df==0,theta,'MaxDegree',4)
% Transform given points (xp_given,yp_given) to coordinate system of the centered ellipse
% and project on it
P_slash = [cosd(-alpha) -sind(-alpha);sind(-alpha) cosd(-alpha)]*[xp_given - x0 ; yp_given - y0];
sol_theta = subs(sol_theta,[xp yp],[P_slash(1) P_slash(2)])
% Transform projected points back to given ellipse
Px_proj = cosd(alpha)*subs(x,theta,sol_theta) - sind(alpha)*subs(y,theta,sol_theta) + x0;
Py_proj = sind(alpha)*subs(x,theta,sol_theta) + cosd(alpha)*subs(y,theta,sol_theta) + y0;
% Numerical example
for i = 1:numel(px)
px_proj = double(subs(Px_proj,[xp_given yp_given],[px(i) py(i)]));
py_proj = double(subs(Py_proj,[xp_given yp_given],[px(i) py(i)]));
idx = abs(imag(px_proj))<1e-6 & abs(imag(py_proj))<1e-6;
px_proj = px_proj(idx);
py_proj = py_proj(idx);
d = sqrt((px(i)-px_proj).^2 + (py(i)-py_proj).^2);
[dist(i),index] = min(d);
pxp(i) = px_proj(index);
pyp(i) = py_proj(index);
end
%Graphical presentation
thetanum = 0:2*pi/100:2*pi;
xx = a*cos(thetanum);
yy = b*sin(thetanum);
xxx = xx*cosd(alpha) - yy*sind(alpha);
yyy = xx*sind(alpha) + yy*cosd(alpha);
xxx = xxx + x0;
yyy = yyy + y0;
plot(xxx,yyy)
hold on
arrayfun(@(i)plot([px(i), real(pxp(i))],[py(i), real(pyp(i))]),1:numel(px))
axis equal
grid on
2 Kommentare
Torsten
am 16 Dez. 2022
Bearbeitet: Torsten
am 16 Dez. 2022
px and py should be your data points.
You must admit 0 <= theta < 2*pi to determine the optimal projection point on the ellipse, but the graphical part is only for illustration - it's not a necessary part of the code.
Inputs are - as said -
a = 2;
b = 1; % main axes
x0 = 1;
y0 = 1; % translation
alpha = 5; % rotation angle of ellipse in degrees
px = randn(1,10);
py = randn(1,10); % Sample points to be projected
and outputs are pxp and pyp - the x-and y-coordinates of the points on the ellipse nearest to the (px /py) - and maybe (if it's of interest) the array "dist" which contains the Euclidean distance between the given data points and their counterparts on the ellipse.
Siehe auch
Kategorien
Mehr zu Functions finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!