立体的な🐌かたつむりを描く

・　パスカルのかたつむりが立体に
・　光源の設置
・　表面反射の設定

# まず２次元の、かたつむり
パスカルの🐌かたつむり　については<a href = "https://qiita.com/emikosh/items/535ef04501162ed7ca1b">前回の記事</a>をご覧ください

<a href = "https://ja.wikipedia.org/wiki/%E3%83%91%E3%82%B9%E3%82%AB%E3%83%AB%E3%81%AE%E8%9D%B8%E7%89%9B%E5%BD%A2">パスカルの蝸牛形(Wikipedia)</a>

<a href = "https://en.wikipedia.org/wiki/Lima%C3%A7on">Limaçon of Pascal (Wikipedia English) </a>

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/3b776d71-bce1-c1ed-0897-5ac39fd4edf5.png">

MATLABを使って、極座標系で描いたときはこんなふうになります。これは２次元座標の上のかたつむりですが、これを元に３次元のかたつむりをつくっていきます。

さあ、どうやって作ろう？

```MATLAB:2d

clear;

t = 0: .001: 2 * pi;
func = @(a,b,t) a * cos(t) + b;
r = func(3, 1, t);

plot(r .* cos(t), r .* sin(t), 'LineWidth', 2);
axis equal;
axis off;
```

# ３次元のかたつむり
３次元目を作るのに、Z軸を足す必要があります。Z軸には何か変数をあてがってあげないといけませんが、まずはふつうに　θ　（上のコード内での変数では t ）を Z軸にしてみました。

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/2bb75b7f-7c62-4926-05ac-49873e6d236c.png">

ところが、くるくる回してみると明らかなように、端が切れてます。つなぎたいです。

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/e49cf9f2-b319-f189-124f-77794eac1fac.gif">

図の中の ● は、原点 (0, 0, 0）です。動画がいまひとつカクカクしていて、頼りないのはお許しくださいませ


```MATLAB:3d
clear;
close all;

t = 0: 0.1: 2 * pi + 0.1;
func = @(a,b,t) a * cos(t) + b;
r = func(3, 1, t);

f = figure;
f.Color = 'w';
hold on;
plot3(r.*cos(t), r.*sin(t), t, 'LineWidth', 2);
plot3(0, 0, 0, 'o', 'LineWidth', 2, 'Color', [0 0 0], 'MarkerSize', 4);
ax = gca;
ax.View = [64.9016   90.0000];
axis off;
```

# 端をつなげる
端と端がつながるように、Z軸を三角関数 sin(t) にしました。ここは、cos関数 でも　sin関数　でもどちらでもよく、cos関数だとまたぜんぜん違うものになります

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/4db9c363-84bb-a6e9-ea23-d20636fdd04e.gif">

動画にあるように、端が上手くつながっているのがわかると思います

```MATLAB:variation1
clear;
close all;

t = 0: 0.1: 2 * pi + 0.1;
func = @(a,b,t) a * cos(t) + b;
r = func(3, 1, t);

f = figure;
f.Color = 'w';
hold on;
plot3(r.*cos(t), r.*sin(t), sin(t), 'LineWidth', 2);
plot3(0, 0, 0, 'o', 'LineWidth', 2, 'Color', [0 0 0], 'MarkerSize', 4);
ax = gca;
ax.View = [47.3978  -11.2584];
axis off;
grid on;
```

# 竹細工風
もうちょっと工夫をしてみたい気がします。次は parula というカラーマップを使ってちょっと色鮮やかな竹細工風の立体を作ってみました。カラーの指定をしなくても描けますが、デフォルトだと指定色がたくさん出てきてしまうので、parula の、青から黄色の連続したカラーを使ってみました。

ちなみに、parulaは、本来は鳥の名前で、色とりどりの<a href = "https://en.wikipedia.org/wiki/Parula">アメリカにいる鳥のこと</a>だそうです。直接見たことはないのですが、興味がある方向けには下のWikipediaのサイトに説明があります

<a href = "https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E3%83%A0%E3%82%B7%E3%82%AF%E3%82%A4%E7%A7%91">アメリカムシクイ科の鳥(Parula)について</a>

<a href = "https://en.wikipedia.org/wiki/Color_blindness">カラーマップのParulaについての説明（English）</a>

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/045f0343-0b37-6700-7eba-edd61bf6e98c.gif">

上手いこと竹細工のようになりました。原点から線を引いてあり、線の色を parula のグラデーションで変えてあります。

```MATLAB:variation2
clear;
close all;

t = 0: 0.1: 2 * pi + 0.1;
func = @(a,b,t) a * cos(t) + b;
r = func(3, 1, t);
cm = colormap("parula");

f = figure;
f.Color = 'w';
hold on;
plot3(r.*cos(t), r.*sin(t), sin(t), 'LineWidth', 2);
for k = 1:length(t)
    plot3([0, r(k)* cos(t(k))],  [0, r(k) * sin(t(k))],  [0, sin(t(k))],...
    'LineWidth', 2, 'Color', cm(k * 4, :));
end
plot3(0, 0, 0, 'o', 'LineWidth', 2, 'Color', [0 0 0], 'MarkerSize', 4);
ax = gca;
ax.View = [47.3978  -11.2584];
axis off;
```

# ライティング・シェーディング
さて、ここからが本番（？）です。空間の中に照明を設置して、立体かたつむりに照明を当てていきます。かたつむりの殻は、上の竹細工で作った枠に、和紙を張るようにして、三角の patch と呼ばれる面を貼っていきます。

ライティングおよびシェーディングで、光線の加減をつけていきます。図では、わかりやすいように、光源の位置に、丸を付けておきました。

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/d748a6be-388b-2499-297e-bc310e5cc025.gif">

この図形は、もともと上の竹細工と同じもので、本来もっと面が荒いのですが、下のコードの中にある、gouraud という指定をすることで、滑らかな曲面を作ってくれます。

```MATLAB:variation3
clear;
close all;

t = 0: 0.1: 2 * pi + 0.2;
func = @(a,b,t) a * cos(t) + b;
r = func(3, 1, t);

col = uisetcolor

x = r .* cos(t);
y = r .* sin(t);
z = cos( t);

f = figure;
f.Color = 'w';
hold on;
for k = 1:length(t)-1
    p = patch ([0, x(k) , x(k + 1)], [0, y(k),  y(k + 1)], [0, z(k), z(k + 1)], col);
    p.SpecularStrength = .3;
    p.DiffuseStrength = .5;
    p.EdgeColor = 'w';
    p.EdgeAlpha = .1;
end

Lt = light( "Style","local","Position",[2,  -3, 0]);
plot3(Lt.Position(1), Lt.Position(2), Lt.Position(3), 'o');
lighting gouraud;
ax = gca;
ax.View = [110.6585   22.7281];
axis off;
```

# さらに変形
このままだと形が今一つ面白くない感じがして、不満が残ったので、Z軸方向にもう一工夫してみました。そうしたら、こんな編み笠ふうになりました。

<img width = 480 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333980/9d6ff127-a99f-0dbf-4b9d-fafbd0039bf2.gif">

```MATLAB:variation4
clear;
close all;

f = figure;
f.Color = 'w';
hold on;
t = 0: 0.1: 2 * pi + 0.2;
func = @(a,b,t) a * cos(t) + b;
r = func(3, 1, t);

col = uisetcolor

x = r .* cos(t);
y = r .* sin(t);
z = cos(2 * t) * 3;

for k = 1:length(t)-1
    p = patch ([0, x(k) , x(k + 1)], [0, y(k),  y(k + 1)], [0, z(k), z(k + 1)], col);
    p.SpecularStrength = .5;
    p.DiffuseStrength = .5;
    p.EdgeColor = 'w';
    p.EdgeAlpha = .1;
end

Lt = light( "Style","local","Position",[2,  -3, -2]);
plot3(Lt.Position(1), Lt.Position(2), Lt.Position(3), 'o');
lighting gouraud;

axis equal;
ax = gca;
ax.View = [68.7268   44.0383];
camzoom(1.8);
axis off;
```


# おわりに
パスカルのかたつむりを変形して作ると、もっといろいろと変な形のものが作れたのですが、とりあえずはここでおしまいにします。ちなみに、こうして作った３次元情報は、.stl ファイルにしてCAD用のソフトに渡すことができます。

自分自身はCAD技術者ではないのですが、過去に３次元モデルを扱ったことがあります。現実の世界にある物と、ソフト内のデータが組み合わさった場面を目にすると、なんとも言えない感じがして、不思議な感覚がわいてきます。