使用找到的答案here,我能画出一个漂亮的圆环。我想在这个圆环上绘制两个“圆圈”,第一个是标准的。第二个应该是有点随机的,也许就像一个梯子,理想情况下与第一个相反。它可能有点锯齿状,但应保留在格子的边缘,并应连接回自身。这是我到目前为止所拥有的
am = 1.;
rm = 3.;
t = linspace(-pi,pi,16);
p = linspace(0.,2.*pi,16);
[t,p] = meshgrid(p,t);
x = (rm + am.*cos(p)).*cos(t);
y = (rm + am.*cos(p)).*sin(t);
z = am.*sin(p);
hsurf = surf(x,y,z);
axis equal;
set(hsurf, 'FaceColor','interp','FaceAlpha',0.5,'EdgeAlpha',0.25);
hold on
plot3((rm+am.*cos(p)).*cos(t(8)),(rm+am.*cos(p)).*sin(t(8)),am.*sin(p), 'b', 'LineWidth',2);
我有标准循环,但无法获得锯齿状循环。我一直试图通过指定顶点来指定另一个循环,但它似乎不起作用。我可以通过指定顶点来指定此网格上的曲线吗?如果没有,有什么建议吗?感谢您提供的任何帮助。
编辑:抱歉前面含糊不清。下图显示了我想要的内容。请注意,右边的圆圈由上面的代码给出,而左手的“圆圈”是手工绘制的,这是我想要自动化的。
答案 0 :(得分:1)
如果您希望(锯齿状或非圆形)圆的顶点与曲面的点匹配,则无需重新计算任何点。您可以简单地重复使用曲面的某些点,选择定义所需形状的路径。
我将使用您的代码来定义初始撕裂,只需稍加修改:我将使用大写字母表示变量来定义矩阵(对于简单的变量,使用小写字母1D)向量)。所以你最初的撕裂变成了:
%% // define initial tore
am = 1.; rm = 3.;
t = linspace(-pi,pi,16);
p = linspace(0,2.*pi,16);
[T,P] = meshgrid(p,t);
X = (rm + am.*cos(P)).*cos(T);
Y = (rm + am.*cos(P)).*sin(T);
Z = am.*sin(P);
hsurf = surf(X,Y,Z,'FaceColor','interp','FaceAlpha',0.5,'EdgeAlpha',0.25);
axis equal ; hold on
没什么大不了的,但是在你按照等式定义圆的情况下,只允许一维矢量坐标。它可以使您的变量和工作区更清晰,并降低错误和尺寸错误的风险。
对于简单的圆,你可以像你一样重新定义坐标(为了清晰起见,这里开发)
%% // your simple circle - calculated
colID = 8 ;
xs = (rm+am.*cos(p)).*cos(t(colID)) ;
ys = (rm+am.*cos(p)).*sin(t(colID)) ;
zs = am.*sin(p) ;
hp = plot3(xs,ys,zs, 'b', 'LineWidth',2);
%// This was generating 2D arrays (matrices) for xs, ys and zs when you
%// were using the meshed version of T and P. Using only the vector version of
%// 't' and 'p' generate only vector coordinates. => cleaner and safer.
但是我想把你的注意力转向另一种方式,只需使用已定义的表面点。这(i)消除了对新计算的需要,并且(ii)确保圆的顶点将恰好匹配撕裂的一些顶点。
%% // another simple circle - extracted from the tore vertices
colID = 8 ;
xs = X(:,colID) ;
ys = Y(:,colID) ;
zs = Z(:,colID) ;
hpc = plot3(xs,ys,zs, 'b', 'LineWidth',2);
同样,为了清晰起见,还有额外的行,但是一旦了解了正在进行的操作,就可以压缩代码。产生圆的这两种不同方式产生以下数字:
为了便于说明,我突出显示了撕裂的顶点(小黑点),因此您可以看到圆顶点是否匹配。
现在对于锯齿状的圆圈,最后提出的方法将会引起更多的兴趣。正如您所观察到的,为了获得圆坐标,我们只需提取每个tore矩阵坐标的一列。我们使用colID
的固定值来检索。到" jagg"你的圆圈,我们只需要在列号中引入一个小的扰动,所以我们偶尔会检索相邻的顶点坐标。
以下代码生成围绕着凝视列ID的列ID。您可以定义最大总扩展量以及最大单个增量:
%% // generate index of columns to be retrieved
idxcol = zeros(size(X,1),1) ;
maxDeviation = 5 ; %// total maximum deviation to the initial center line
maxPerturbation = 2 ; %// max deviation for 1 increment
deviation = cumsum(randi([-maxPerturbation maxPerturbation],size(X,1),1)) ;
%// bound deviations to maximum values
deviation(deviation>maxDeviation) = maxDeviation ;
deviation(deviation<-maxDeviation) = -maxDeviation ;
startColID = 8 ;
colID = startColID + deviation ;
%// close the profile by repeating first point in the end if it's not closed already
if colID(end) ~= colID(1) ; colID(end) = colID(1) ; end
如果我们现在使用这些列的坐标,我们得到:
npt = size(colID,1) ;
xcj = zeros(npt) ; ycj = xcj ; zcj = xcj ;
for k=1:npt
xcj(k) = X( k , colID(k) ) ;
ycj(k) = Y( k , colID(k) ) ;
zcj(k) = Z( k , colID(k) ) ;
end
hpc = plot3(xcj,ycj,zcj, 'b', 'LineWidth',2);
这是一个围绕着撕裂的闭合轮廓,但是线条与曲面的线条不匹配,如图中所示。这是因为在x
索引的每次更改时都会发生从一个列ID到另一个列ID的转换。
为了纠正这个问题,我们可以使用stairs
函数:
%% // create a stepped profile
[xd,yd] = stairs(colID) ;
%% // display rectified jagged circle
npt = size(yd,1) ;
xcj = zeros(npt) ; ycj = xcj ; zcj = xcj ;
for k=1:npt
xcj(k) = X( xd(k) , yd(k) ) ;
ycj(k) = Y( xd(k) , yd(k) ) ;
zcj(k) = Z( xd(k) , yd(k) ) ;
end
hpc = plot3(xcj,ycj,zcj, 'b', 'LineWidth',2);
好多了......但是,当列ID移动同一个x
的多个索引时,我们仍然会错过锚点,以保持锯齿状的圆形轮廓与撕裂轮廓相匹配。如果你的基本列偏差增量大于1,你甚至会有更多的这些假象。
为了完全纠正这个问题,我们需要添加缺少的锚点。我无法找到内置函数来做到这一点所以我采用了很好的循环方式。如果你找到某种方法,请随意优化。
%% // recreate index vectors with all the necessary anchor points
colX(1,1) = xd(1) ;
colY(1,1) = yd(1) ;
k = 2 ;
for t=2:size(yd,1)
inc = sign(yd(t)-yd(t-1)) ; %// define increment of 1 with correct sign
ids = yd(t-1):inc:yd(t)-inc ; %// range of index to be covered
if isempty(ids) ; ids = yd(t) ; end %// catch corner cases
%// now add these points to the list
n = length(ids) ;
colX(k:k+n-1,1) = xd(t-1) ;
colY(k:k+n-1,1) = ids ;
k=k+n;
end
%// close profile (add last point in the cases where it is necessary)
if inc ~= 0
colX(end+1,1) = xd(end) ;
colY(end+1,1) = yd(end) ;
end
%% // display fully rectified jagged circle
npt = size(colX,1) ;
xcj = zeros(npt) ; ycj = xcj ; zcj = xcj ;
for k=1:npt
xcj(k) = X( colX(k) , colY(k) ) ;
ycj(k) = Y( colX(k) , colY(k) ) ;
zcj(k) = Z( colX(k) , colY(k) ) ;
end
现在我们不再有两个列ID之间的间隙,锯齿状圆圈的所有点都与表面轮廓的点匹配: