3

シリンダーにキャップがあり、任意のサイズと方向にできるように、シリンダー関数を一般化する関数を作成しています。ただし、シリンダーの外観では、ジャムが発生しています。キャップが正しく見えるようにするには、湾曲した部分に 1 つのシェーディング セットが必要であり、キャップには別のシェーディング セットが必要です。(そして、あなたが尋ねる前に、3つの面を作ることはオプションではありません)

関連するコードは次のとおりです。

    surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');

コード全体を見たい場合に備えて。

ご協力ありがとうございました、

ジョン

    function varargout = DrawCylinder(x,y,z,r,h,aVec,bVec,cVec,ccolor, npts)
    % DrawCylinder Generate a three-dimensional cylinder
    %
    % DrawCylinder(x,y,z,a,b,c,aVec,bVec,CVec,ccolor, npts) 
    % creates a surface plot of a cylinder whose center is at (x,y,z), has
    % semiaxes of length a, b, and c.  The unit vectors associated with each
    % semixis are aVec, bVec, and cVec and must be size 3 x 1 (column vector)
    % with size of npts + 1.
    %
    % H = DrawCylinder(...) creates the surface plot and returns the handle H to each
    % graphical object created.
    %
    % [X Y Z] = DrawCylinder(...) does not generate the surface plot and returns
    % the data necessary to create the surface using:
    % SURF(X,Y,Z);
    %
    % [X Y Z C] = DrawCylinder(...) does not generate the surface plot and returns
    % the data necessary to create the surface using:
    % SURF(X,Y,Z,C,'cdataMapping','direct');

    %CREATE SURFACE FOR CYLINDER
    [xCyl,yCyl,zCyl]=cylinder(1,npts);

    xSurf=[zeros(1,max(size(xCyl)));xCyl;zeros(1,max(size(xCyl)))];
    ySurf=[zeros(1,max(size(yCyl)));yCyl;zeros(1,max(size(yCyl)))];
    zSurf=[zeros(1,max(size(zCyl)));zCyl;ones(1,max(size(zCyl)))] - 0.5;

    xSurf = xSurf*r;
    ySurf = ySurf*r;
    zSurf = zSurf*h;

    %ROTATE CYLINDER
    %Make sure aVec,bVec, and cVec are column unit vectors:
    if all(size(aVec)==[1,3])
        aVec=aVec';
    end
    if all(size(bVec)==[1,3])
        bVec=bVec';
    end
    if all(size(cVec)==[1,3])
        cVec=cVec';
    end
    aVec=aVec/norm(aVec); %Make unit vectors
    bVec=bVec/norm(bVec);
    cVec=cVec/norm(cVec);

    rot = [aVec,bVec,cVec]; %The rotation matrix

    [iMax, jMax] = size(xSurf);

    for i=1:iMax
        for j=1:jMax
            rotatedPt = rot*[xSurf(i,j);ySurf(i,j);zSurf(i,j)];
            xSurf(i,j) = rotatedPt(1);
            ySurf(i,j) = rotatedPt(2);
            zSurf(i,j) = rotatedPt(3);
        end
    end

    %TRANSLATE CYLINDER
    xSurf = xSurf + x;
    ySurf = ySurf + y;
    zSurf = zSurf + z;

    c = ccolor*ones(size(xSurf));
    if nargout == 0
        surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');
    elseif nargout == 1
        varargout = {surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');};
    elseif nargout == 3
        varargout = {xSurf ySurf zSurf};
    elseif nargout == 4
        varargout = {xSurf ySurf zSurf c};
    end

    end

2012 年 8 月 18 日編集:

あなたが見ることができるように。

これは私が得ているものです...

これは私が得ているものです

そして、これは私が欲しいものです...

そして、これは私が欲しいものです

4

1 に答える 1

1

「シェード」とは、エンドキャップの色を意味するだけで、より複雑な効果ではないと確信しています. それが非常に簡単な場合は、グレースケールで例を挙げます

変化する

c = ccolor*ones(size(xSurf));

c = (ccolor/255)*ones(size(xSurf));
c([1 3],:)=max(0,(ccolor-10))/255;

最初の行cは、正規化された ccolor で行列を初期化します (8 ビットのグレースケール ccolor 入力を期待して、0..1 に正規化します)。2 番目の行は、キャップ (行 1 と 3) をわずかに暗い色に変更し、0 を底にして、シリンダー サーフェス (行 2 と 4) だけを残します。

結果が正しく表示されるようにするには、 nargout==0 条件を次のように変更する必要があります。

surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');
colormap(gray(256));
caxis([0 1]);

colormap は、8 ビット グレー スケールと同様に、カラーマップを設定するだけです。caxis コマンドはかなり重要です。Matlabの表面ドキュメントによると

MATLAB は、このデータに対して線形変換を実行して、現在のカラーマップから色を取得します。

私たちの目的にとって、それは悪いことです。値が 2 つしかないため、最小値は 0 に、最大値は 1 に変更されます。これにより、ccolor 入力が事実上無視され、2 つの黒いキャップを持つ白い円柱が得られます。を使用caxis([0 1])すると、フル スケールとその中の ccolor の位置が保持されます。

アップデート:

あなたが望んでいたことを誤解しているように聞こえますが、あなたが望む効果に非常に近いものを達成する最も簡単な方法は、次のように「MeshStyle」を「row」に設定することです:

surface(xSurf,ySurf,zSurf,c,'EdgeColor','k','FaceLighting','phong','MeshStyle','row');

これにより、次の結果が得られます。capped_cylinder

中心点はまだありますが、その効果を生み出す最も簡単な方法です。

于 2012-08-18T17:08:53.283 に答える