如何从平面中的 3 个点(x,y,z)创建弧形路径?
how to create an arc path from 3 points(x, y, z) in plane?
我想在 n=3 个点上创建一个弧形轨迹 P(n)=(x, y, z),我决定在平面上的 3 个点上画一个圆。所以我有中心、半径、theta(x、y 平面中的角度)和 phi(绕 z 轴的角度),我知道 3 个点(x、y、z)的位置,如何提取 p1 之间的弧,这个圈子的p2和p3?我在 MATLAB 中实现了这个程序..
非常感谢。
math.stackexchange 上的这个答案给出了一个很好的简单公式来找到圆心(以及半径)
3D coordinates of circle center given three point on the circle. (@Sergio G.)
从另一个有用的 math.stackexchange 答案中,我们可以根据中心和原始 3.
中的两个 (non-colinear) 点定义该圆上的任何点
Parametric equation of a circle in 3D given center and two points on the circle? (@milbrandt)
最后,我们需要您的 3 个点的 3 个角度来定义圆弧,这可以通过 atan2
和在其他步骤中创建的分量向量来完成。
下面是完整的注释代码,它产生了这个图,并用于计算任何 3D 点的圆角,然后计算任何角度的圆周上的值。
% Original points
p1 = [1;0;2];
p2 = [0;0;0];
p3 = [1;2;2];
P = [p1,p2,p3];
% Get circle definition and 3D planar normal to it
p0 = getCentre(p1,p2,p3);
r = norm( p0 - p1 );
[n0,idx] = getNormal(p0,p1,p2,p3);
% Vectors to describe the plane
q1 = P(:,idx(1));
q2 = p0 + cross(n0,(p1-p0).').';
% Function to compute circle point at given angle
fc = @(a) p0 + cos(a).*(q1-p0) + sin(a).*(q2-p0);
% Get angles of the original points for the circle formula
a1 = angleFromPoint(p0,p1,q1,q2);
a2 = angleFromPoint(p0,p2,q1,q2);
a3 = angleFromPoint(p0,p3,q1,q2);
% Plot
figure(1); clf; hold on;
args = {'markersize',20,'displayname'};
plot3( P(1,:), P(2,:), P(3,:), '.', args{:}, 'Original Points' );
plot3( p0(1), p0(2), p0(3), '.k', args{:}, 'Centre' );
plotArc(fc,a1,a2); % plot arc from p1 to p2
plotArc(fc,a2,a3); % plot arc from p2 to p3
plotArc(fc,a3,a1); % plot arc from p3 to p1
grid on; legend show; view(-50,40);
function ang = angleFromPoint(p0,p,q1,q2)
% Get the circle angle for point 'p'
comp = @(a,b) dot(a,b)/norm(b);
ang = atan2( comp(p-p0,q2-p0), comp(p-p0,q1-p0) );
end
function plotArc(fc,a,b)
% Plot circle arc between angles 'a' and 'b' for circle function 'fc'
while a > b
a = a - 2*pi; % ensure we always go from a to b
end
aa = linspace( a, b, 100 );
c = fc(aa);
plot3( c(1,:), c(2,:), c(3,:), '.r', 'markersize', 5, 'handlevisibility', 'off' );
end
function p0 = getCentre(p1,p2,p3)
% Get centre of circle defined by 3D points 'p1','p2','p3'
v1 = p2 - p1;
v2 = p3 - p1;
v11 = dot( v1.', v1 );
v22 = dot( v2.', v2 );
v12 = dot( v1.', v2 );
b = 1/(2*(v11*v22-v12^2));
k1 = b * v22 * (v11-v12);
k2 = b * v11 * (v22-v12);
p0 = p1 + k1*v1 + k2*v2;
end
function [n0,idx] = getNormal(p0,p1,p2,p3)
% compute all 3 normals in case two points are colinear with centre
n12 = cross((p1 - p0),(p2 - p0));
n23 = cross((p3 - p0),(p2 - p0));
n13 = cross((p3 - p0),(p1 - p0));
n = [n12,n23,n13];
n = n./sign(n(1,:));
idx = find(~all(isnan(n)),2);
n = n(:,idx(1));
n0 = n / norm(n);
end
我想在 n=3 个点上创建一个弧形轨迹 P(n)=(x, y, z),我决定在平面上的 3 个点上画一个圆。所以我有中心、半径、theta(x、y 平面中的角度)和 phi(绕 z 轴的角度),我知道 3 个点(x、y、z)的位置,如何提取 p1 之间的弧,这个圈子的p2和p3?我在 MATLAB 中实现了这个程序.. 非常感谢。
math.stackexchange 上的这个答案给出了一个很好的简单公式来找到圆心(以及半径)
3D coordinates of circle center given three point on the circle. (@Sergio G.)
从另一个有用的 math.stackexchange 答案中,我们可以根据中心和原始 3.
中的两个 (non-colinear) 点定义该圆上的任何点Parametric equation of a circle in 3D given center and two points on the circle? (@milbrandt)
最后,我们需要您的 3 个点的 3 个角度来定义圆弧,这可以通过 atan2
和在其他步骤中创建的分量向量来完成。
下面是完整的注释代码,它产生了这个图,并用于计算任何 3D 点的圆角,然后计算任何角度的圆周上的值。
% Original points
p1 = [1;0;2];
p2 = [0;0;0];
p3 = [1;2;2];
P = [p1,p2,p3];
% Get circle definition and 3D planar normal to it
p0 = getCentre(p1,p2,p3);
r = norm( p0 - p1 );
[n0,idx] = getNormal(p0,p1,p2,p3);
% Vectors to describe the plane
q1 = P(:,idx(1));
q2 = p0 + cross(n0,(p1-p0).').';
% Function to compute circle point at given angle
fc = @(a) p0 + cos(a).*(q1-p0) + sin(a).*(q2-p0);
% Get angles of the original points for the circle formula
a1 = angleFromPoint(p0,p1,q1,q2);
a2 = angleFromPoint(p0,p2,q1,q2);
a3 = angleFromPoint(p0,p3,q1,q2);
% Plot
figure(1); clf; hold on;
args = {'markersize',20,'displayname'};
plot3( P(1,:), P(2,:), P(3,:), '.', args{:}, 'Original Points' );
plot3( p0(1), p0(2), p0(3), '.k', args{:}, 'Centre' );
plotArc(fc,a1,a2); % plot arc from p1 to p2
plotArc(fc,a2,a3); % plot arc from p2 to p3
plotArc(fc,a3,a1); % plot arc from p3 to p1
grid on; legend show; view(-50,40);
function ang = angleFromPoint(p0,p,q1,q2)
% Get the circle angle for point 'p'
comp = @(a,b) dot(a,b)/norm(b);
ang = atan2( comp(p-p0,q2-p0), comp(p-p0,q1-p0) );
end
function plotArc(fc,a,b)
% Plot circle arc between angles 'a' and 'b' for circle function 'fc'
while a > b
a = a - 2*pi; % ensure we always go from a to b
end
aa = linspace( a, b, 100 );
c = fc(aa);
plot3( c(1,:), c(2,:), c(3,:), '.r', 'markersize', 5, 'handlevisibility', 'off' );
end
function p0 = getCentre(p1,p2,p3)
% Get centre of circle defined by 3D points 'p1','p2','p3'
v1 = p2 - p1;
v2 = p3 - p1;
v11 = dot( v1.', v1 );
v22 = dot( v2.', v2 );
v12 = dot( v1.', v2 );
b = 1/(2*(v11*v22-v12^2));
k1 = b * v22 * (v11-v12);
k2 = b * v11 * (v22-v12);
p0 = p1 + k1*v1 + k2*v2;
end
function [n0,idx] = getNormal(p0,p1,p2,p3)
% compute all 3 normals in case two points are colinear with centre
n12 = cross((p1 - p0),(p2 - p0));
n23 = cross((p3 - p0),(p2 - p0));
n13 = cross((p3 - p0),(p1 - p0));
n = [n12,n23,n13];
n = n./sign(n(1,:));
idx = find(~all(isnan(n)),2);
n = n(:,idx(1));
n0 = n / norm(n);
end