コンテンツへスキップ

twitterやSNSのアイコンをもっと綺麗にしたい!と思っている方は多いはず。そこで、私が立体の新アイコンを作った際の方法をまとめました。無料ツールなども紹介しています。

twitterやSNSのアイコンをもっと綺麗にしたい!と思っている方は多いはず。そこで、私が立体の新アイコンを作った際の方法をまとめました。無料ツールなども紹介しています。windows10です。

目次

  • 目的
  • 3DCADとは
  • ツール紹介1 : 3DCAD
  • ツール紹介2 : 画像加工用ツール
  • 使い方の概要
  • 作成したモデル
  • 実際のアイコン

目的

アイコンはアカウントの顔です。が、 私はしばらくこんなアイコンを使って居ました。 綺麗にしたい。

大学のテスト期間中にパワポで作った物で、なかなか気に入って居ました。これからも使っていきたい、とはいえ、雑すぎる。もしや、最近使い始めたCADを使えば良いのができるんじゃ!? ...と言うわけで、(練習がてら)これを綺麗に3D化した新アイコンを作りたいと思います。

この記事は、私が3DCADで作成した新アイコンを簡単に解説し、まとめたものです。

3DCADとは

3DCAD とは、縦、横、奥行きの 3 つの次元をもった 3 次元モデルを作成するこ とができるCADです。ではCADというのは何かというと、コンピュータによる設計支援するツールのことです。

3DCADは以下のような特徴を持ちます。

  • 形状が分かりやすい
  • 作成と編集が容易である
  • 技術計算が速やかにできる

立体図面を描いたり、3D プリンター 用の作成データを作成したり、シミュレーションに使用したり、様々な場面で活用されています。

アイコンを作るうえで重要なのはレンダリングという機能です。 アルミやプラスチックなど素材を指定することで 、商品の完成予定 画像などを速やかに美しく作成することができます。

ツール紹介1: 3DCAD

私が使ったことがあるソフトを3つ紹介します。正直慣れればどれも使いやすいと思います。

SolidWorks

私の知るかぎり一番多くの人が利用している3DCADです。企業や学校で使用している事が多いですが、有料なので個人で使っている方の話はほとんど聞きません。特徴は以下の通り。

  • すべて部品、アセンブリ(組み立て)、図面という単位で構成される 。
  • SolidWorks は履歴型の CAD であり、履歴から編集することができる 。
  • 互いに関連性を持っており、例えば部品を編集した場合、その部品を使用しているアセンブリも自動的に編集される 。

SolidWorks公式HP

Fusion360, AutoCAD

2つは異なるソフトですが、どちらもAutodesk社の製品です。Autodeskさんのすごいところは、 普通に使ったら年間20万円程度かかる高性能ソフトが 学生・教員はどちらも無料で利用できるという事!本当にありがとうございます!!

AutoCAD 教育 AUTODESK公式

Fusion360 学生 AUTODESK公式

DESIGN NOW Fusion360が学べる情報サイト -AUTODESK

ツール紹介2: 画像加工用ツール

この章はおまけ的ポジションです。

windowsのスクショ+ペイント

キーボードに「Prt Sc」というキーがあると思います。これはprint screenのことで、単なるスクショです。押したらペイントなどの画像編集ツールを開いて、「Ctrl」+「v 」で貼り付けます。その後、トリミングなど。

snipping Tool

部分的にスクショするためのツールです。windowsに始めから入っていると思います。スタートメニューで検索すれば出てくるかと思います。新規作成をクリックすると画面全体が静止して白っぽくなります。その状態でクリック+ドラックして範囲を指定するとその部分を画像として保存できます。

Snipping Tool

使い方の概要

3DCADの共通した使用方法をざっくり解説します。

基本的には3ステップ。1,スケッチ、2,押し出し、3,微調整 です。

1,スケッチ。平面を選択して、下書きをします。

スケッチA,円
スケッチB,複雑な形

2,押し出し。スケッチをベースに押し出したりくりぬいたり開店させたり、様々な方法で立体にします。

押し出しA,押し出し
押し出しB,回転

3,微調整。角を丸めたりして微調整します。押し出した後の面にさらにスケッチを描いたりすることもできます。

微調整 直径の違う円柱をなめらかにする場合

作成したモデル

パーツです。

目玉
目の外側
尻尾

上を組み立てて行きます。本当は不確定な要素が無いようにするべきですが、今の目標はアイコンの写真を撮ることなのでかなり雑にやっています。

顔 (怖い)

各パーツに素材を指定して完成です!素材データは予めCADに入っているので選択するだけでOKです。色も指定できます。

完成

これをレンダリングしてプレビューを見てみます。私が使ったソフトはかなり古いですが、そこそこ綺麗なのではないでしょうか。

後ろ
逆側

実際のアイコン

実際の様子です。元画像のぼんやりした印象を見事に引き継いでいますね。

Scilab/Xcosが必要になったので入れて使ってみます。動作の確認として、MATLABでやったのと同じ解析をしてみました。

Scilab/Xcosが必要になったので入れて使ってみます。windows10,Scilab6.0.2です。動作の確認として、MATLABでやったのと同じ解析をしてみました。

目次

  • 導入
    • scilabとは
    • Xcosとは
  • インストール
  • 使ってみる
    • ブロックを並べる
    • 設定
    • シミュレーション
    • 構文
      • polyとは
      • syslinとは
      • bodeとは
      • dampとは
  • MATLAB/SimlinkとScilab/Xocsの比較
    • MATLAB/Simlink
    • Scilab/Xcos

導入

Scilabとは

Scilabはフリーのオープンソフトウェアで、端的に言ってしまえばMATLABのフリー版です。様々な数値解析ができます。

詳しくは公式にて

MATLABに関してはこちらの記事をご覧ください。=>MATLAB使い方個人的まとめ

Xcos

動的な連続/離散時間システムのモデリングやシミュレーションができます。 MATLABにとってのSimlinkです。グラフィカルにブロックを並べることでモデリングでき、コンパイルやシミュレーションもまとめてできる優れものです。

X2C(https://www.lcm.at/virtuelle-entwicklung/x2c/)

インストール

公式ページ: Download Scilab 6.0.2 -scilab

言語設定でjapaneseを選択し、デフォルトのままfullバージョンでインストールします。

インストールページのスクショ

使ってみる

MATLABと同様に、コマンドウィンドウ、Xcosウィンドウ、SimNoteのウィンドウをそれぞれ使って解析を行います。アプリケーション/Xcosで起動するとXcosウィンドウとライブラリが現れます。

Scilabの画面
Xcos

ブロックを並べてブロック線図を作り、sin波を表示させてみます。

ブロックを並べる

まずは信号源、出力/表示などからsin波発生器、CSCOPE、CLOCKを見つけて右クリックかドラッグでXcos上に配置し、矢印をドラッグして配線します。 スコープは赤い矢印があるものを選びましょう。これはイベントシミュレーションを駆動するイベント信号になります。

ブロック図の作成

設定

それぞれのブロックで右クリックすると項目が現れて、その中からブロックパラメータを開きます。 CFSCOPEを設定します。[参考1]

  • Color or mark vector: スコープで表示するグラフ線の色またはマークの連続によるグラフを指定する。入力信号数にかかわらず8セットの数字が必要。数字が正のとき、連続線で色が指定でき、負のとき、マーク形状が指定できる。(plot2dコマンドに準ずる)
  • Output window number: グラフ・ウィンドウ番号の指定。
  • Output window position: グラフ・ウィンドウの表示位置指定。左上の位置をx,yのドットで示す。
  • Output window size: グラフ・ウィンドウの表示サイズをドット数で指定。
  • Ymin: グラフ・ウィンドウのY軸最小値
  • Ymax: グラフ・ウィンドウのY軸最大値
  • Refresh period: グラフ・ウィンドウのX軸(時間)最大値 シミュレーション設定時間がこの値より大きい場合、グラフをクリアし再度続きの時間から描画する。基本的使い方では、シミュレーション時間と一致させる。
  • Buffer size: 入力データを一時的に蓄えておくメモリ領域のサイズを指定。グラフ表示速度に大きく影響するので、変化を観察したい場合以外は、少なくともRefresh period以上に設定する。最小は2。
  • Accept herited events: (inherited?) 継承の無効(0)・有効(1)を指定。1にするとイベント・ポート赤が削除される。アクティベーションが上流で行われる場合、継承が可能。

SCOPEの積算時間を10に、最小値~最大値を-10~10にしました。 クロックとsin発生器のパラメータも設定します。初期化時間を0.0に、ゲイン(振幅)5にします。

シミュレーションの設定

シミュレーション

シミュレーションを開始します。シミュレーション/パラメータ設定から、[参考1]

  • Final integration time: シミュレーション終了時間[単位は任意]
  • Real time scaling: 正の実数nを入力すると、シミュレーション設定単位時間tがn×t秒としてシミュレーションが実行される。n=1とした場合、シミュレーションの設定単位時間が1秒として解析表示される。
  • Integrator absolute tolerance: ソルバーの絶対誤差公差
  • Integrator relative tolerance: ソルバーの相対誤差公差
  • Tolerance on time: ODE(常微分方程式)ソルバーの最小時間公差
  • Max integration time interval: ソルバー呼び出しの最大時間間隔。"too many calls"というエラーメッセージが出た場合、値を小さくする。(解析精度を落とす。)
  • Solver 0(CVODE) - 100(IDA): 数値ソルバーの選択。
  • maximum step size: ソルバーがとる最大時間ステップ

最終積算時間を1.0E1.0、すなわち10sにしました。 AEBならA*10^Bになります。

document/test_0620/image.scgはこのようになりました。指定した通りに動いていることが確認できます。

document/ test_0620/image.scg の出力

構文

ビギナーのための科学技術計算ソフト(Scilab)の使い方講座 3. 付録: Scilab言語の基本構文 -SimCircuit

Scilab コンソールの使い方の基本

「;」を後ろにつけると結果を表示しないみたいですね。

polyとは

[参考2]によれば、ploy関数は以下のように書きます。

p=poly(実数もしくは行列,"変数")
-->a=[-3 -4];
-->p=poly(a,"x")
 p  = 

            2
   12 +7x +x 

コンソールに上のように入力すると、12+7x+x^2を返します。((x+3)(x+4)=0, のときx=-3,-4) pを多項式変数として扱う事ができます。

-->s=poly(0,'s')
s =

    s
polyをコンソールに入力したときの出力

syslinとは

[参考3]によれば、syslin関数は以下のように書きます。

q=syslin(連続時間システムc or離散時間システムd,多項式)
--> s=poly(0,'s');

--> P=syslin('c',1/(s+1))
 P  = 

           
     1     
   ------  
           
   1 + s   

bodeとは

[参考4]によれば、syslin関数は以下のように書きます。

bode(syslinで定義された線形システムの多項式,x軸の最小値,x軸の最大値,x軸の刻み,['コメント'])

コメントにタイトルなどをかきます。 こだわらないなら関数のみ与えればOKです。

dampとは

[参考5]によれば、syslin関数は以下のように書きます。

[wn,z] = damp(連続時間のsys関数)

MATLAB/SimlinkとScilab/Xcosの比較

某授業のレポート1でやった問題の伝達関数を使って確認していきます。

問題: オープンループの伝達関数L(s)が以下の時の、回ループと閉ループでのボーデ線図をそれぞれ表示します。

$$L(s)=\frac{0.1}{s(s+0.5)(s+1)}$$

MATLAB

  • オープンループ

$$L(s)=\frac{0.1}{s^3+1.5s^2+0.5s}$$

MATLABオープンループでのボーデ線図

位相余裕:59° 利得余裕:17.5dB

  • フィードバック $$L(s)=\frac{0.1}{s^3 + 1.5s^2 + 0.5s + 0.1}$$

A. 周波数応答

MATLABフィードバックでのボーデ線図

B. ステップ応答

設定がうまくいかず、ぎこちないですがこんな感じ。最終値は1です。

MATLABフィードバックでのステップ応答

Scilab

  • オープンループ

複数行のコマンドを何度も使用する場合、アプリケーション/SciNoteに書くとスクリプトのようにまとめて実行できます。 見やすさのために出力なしで実行しました。

SciNoteを使用している様子

A. 周波数応答

まずはコマンドで実行してみます。

コード

s=poly(0,'s');
p=syslin('c',0.1/(s*(s+0.5)*(s+1)))
bode(p)
show_margins(p)
[gm,fp]=g_margin(p) disp("ゲイン余裕[dB]") disp(gm) disp("位相交差角周波数[Hz]") disp(fp) 
[pm,fg]=p_margin(p) disp("位相余裕[°]") disp(pm) disp("ゲイン交差角周波数[Hz]") disp(fg) 

出力

ゲイン余裕[dB]

   17.501225

 位相交差角周波数[Hz]

   0.1125395

 位相余裕[°]

   59.289834

 ゲイン交点角周波数[Hz]

   0.0293667

ゲイン余裕:位相が-180°と交差する周波数(位相交差角周波数)においてゲインが0dBより何dB小さいか

位相余裕:ゲインが0dBと交差する周波数(ゲイン交差角周波数)

オープンループボーデ線図は

Scilab オープンループでのボーデ線図

MATLABと一致してますね。

B. ステップ応答

Scilab オープンループでのステップ応答
  • フィードバック

A. 周波数応答

コマンドからやります。フィードバックした場合の伝達関数G(s)は以下のようになるので

$$G(s)=\frac{L(s)}{1+L(s)}$$

コード

s=poly(0,'s');
p=syslin('c',0.1/(s*(s+0.5)*(s+1)))
g=p/(1+p)
disp(g)
bode(g)
show_margins(g)
[gm,fp]=g_margin(g) disp("ゲイン余裕[dB]") disp(gm) disp("位相交差角周波数[Hz]") disp(fp) 
[pm,fg]=p_margin(g) disp("位相余裕[°]") disp(pm) disp("ゲイン交差角周波数[Hz]") disp(fg) 
[wn,z] = damp(g); disp("固有周波数[Hz]") disp(wn) disp("減衰係数") disp(z) 

出力

                           
            0.1            
   ----------------------  
                    2   3  
   0.1 + 0.5s + 1.5s + s   

 ゲイン余裕[dB]

   16.258267

 位相交差角周波数[Hz]

   0.1125395

 位相余裕[°]

   114.71226

 ゲイン交差角周波数[Hz]

   0.0313482

 固有周波数[Hz]

   0.2964606
   0.2964606
   1.1378001

 減衰係数

   0.6108736
   0.6108736
   1.

同じ曲線を描いていることを確認しました。

Scilab フィードバックでのボーデ線図

B. ステップ応答

最終値1で、100秒まで計算しています。

Scilab フィードバックでのステップ応答

コードは[参考6]を参考にさせて頂きました。

雑記

  • Xcosのライブラリで固まったらEscキーを押しましょう!ドラッグより右クリックの方がいいです。
  • 周波数応答を調べるとき、関数に伝達関数を与えています。なのでXcosでブロック線図を描こうと思ったらブロックを並べて伝達関数を計算させて、それを取得して関数に入れる、という手順を踏むと思うので回りくどいです。ここでやった例はすぐ伝達関数を計算できるので、コマンドでやった方が早いと思いました。
  • 何気に変数ブラウザ便利ですね。

参考

1.ビギナーのための科学技術計算ソフト(Scilab)の使い方講座 2.3 Xcosによるシミュレーション・ツールとしての使い方 (GUI型ブロック線図入力モジュール) -SimCircuit

2. Scilab関数の説明:polyとは

3. Scilab関数の説明:syslinとは

4. Scilabでのボード線図の描き方

5. damp -scilab

6. scilabで制御系設計

windows10 , Visual Studio,C++で画像処理のハフ変換をやります。ついでにLiDARというセンサで取得した画像データから壁を検知してみます。

windows10 , Visual Studio2019,C++で画像処理のハフ変換をやります。ついでにLiDARというセンサで取得した画像データから壁を検知してみます。

目的

  • C++開発環境
  • visual studio でC++をやる
  • openCVのインストール
  • hough変換とは
  • コード
  • LiDAR
  • 参考

visual studio でC++をやる

Visual Studio のインストール -Microsoft

インストーラにしたがってインストールします。何ができる環境を作るかを選べるようですが、私は残りの記憶容量が少ないのでコンソールアプリだけにします。後で追加でインストールすることが出来ます。

起動してコンソールアプリを選択します。デフォルトでhello worldが出力できるようになっているみたいですね。

ビルド/ソリューションのビルド(Shift+Ctrl+B)して、デバック/デバッグなしで開始 をクリックすると、コンソール上で実行されます。 あるいは上の△を押しても実行できます。

今回はUnityでゲームを作ったりするわけではないので、これでOKです。では、ハフ変換をしていきたいと思います。

C++ コンソール アプリ プロジェクトのビルドと実行 -Microsoft

OpenCVのインストール

opencv/opencv から最新版をdownload。ファイルを7zipか何かで展開し、openCV41とか名前を変更しつつCドライブなど適当なところに配置します。C:\Users\user\Documents\opencv41にしました。

プロジェクト/(プロジェクト名)のプロパティ から構成マネージャーを起動します。(上のバーでもいけますし、使いやすいようにいろんなとこにあるらしい)。

VC++からインクルードディレクトリを編集します。

  • ソリューション構成 → Release(Debug も可)
  • ソリューションプラットフォーム → x64
  • 構成プロパティ/デバッグ:環境 → PATH=% C:\Users\user\Documents\opencv41 %\build\x64\vc15\bin;%PATH%
  • 構成プロパティ/VC++ ディレクトリ:インクルード ディレクトリ → C:\Users\user\Documents\opencv41\build\include
  • 構成プロパティ/VC++ ディレクトリ:ライブラリ ディレクトリ → % C:\Users\user\Documents\opencv41%\build\x64\vc15\lib
  • 構成プロパティ/リンカー/入力:追加の依存ファイル → opencv_world410.lib

参考サイト( OpenCV 4.1.0Visual Studio 2019から使用する時の手順 -qiita )のとおり、下記のコードをビルド・実行します。

zeros()の第一、第二引き数にサイズを与えます。申し訳ありませんが画像を作ったあとに値を変えたので、500、600は正しくありません。おそらく単位はピクセルだと思います。

#include <opencv2/opencv.hpp>

using namespace cv;
int main()
{
	Mat image = Mat::zeros(500, 600, CV_8UC3);
	imshow("", image);
	waitKey(0);
}

このような画像が出てくればopencvインストールが成功しています。

hough変換とは

ハフ変換とは、画像処理の1つで、計算処理を通して並んだ点から直線や円を認識する事です。この記事では直線を検知することを目的として使用しています。

画像は、1つ1つの画素に色の情報を与えた2次元配列で表されます。座標軸上のある点、すなわち画素を通る直線は、xy直交座標では(x,y)で表されますが、ここではθとρを用いて $$ \rho = xcos\theta + ysin\theta $$

で表すことも出来ます。ここで、ρは座標原点から直線へ降ろした垂線の長さ、θは垂線とx軸の角度を示します。

図1: ρとθによる表現

あるx_0とy_0に関して、ρとθを変更していくと、その点を通る様々な線(図2)を描くことができます。

図2: ある点についてρ、θを変更した場合の直線群

このときρ-θ平面上に曲線を描くことが出来ます。(図3)

図3: 図2の写像のイメージ

このことは、画素空間(xy平面上)の点が ρ-θ 平面上の曲線射影されたことを意味します。 様々な点(x,y)に関してそれぞれ ρ-θ 軸上に軌跡をプロットし、多数の軌跡が重なった点があると、その点(ρ,θ)は多くの画素が通る直線であるということになります。(図4)。

図4: 多数の点を通る直線のイメージ

以上のように、数学的な処理をすることで直線を検知することができます。これがハフ変換です。この方法は、画ぞが連続していなくても直線を検出でき、雑音に強いもので、発見以来、改良・拡張がなされています。

ハフ変換は白黒画像でなくてはいけませんので、白黒画像にするためのエッジ検出関数もセットで使用します。

cv::Canny(const Mat& image, Mat& edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false);

threshold1 と threshold2 の内,小さい方の値がエッジの接続に利用され,大きい方の値が明確なエッジの初期セグメントを検出するのに利用されます。 threshold1 は threshold2 の2倍から3倍の間が推奨されています。この二つは順番を並び替えても等価になります。

apertureSize は Sobel() オペレータのアパーチャサイズ(カーネルサイズ)を指定します。これはフィルタを選択しているみたいです。デフォルトの3を指定します。 L2gradient は 画像勾配の強度を求める計算方法を指定します。Falseがデフォルトです。この二つは特に理由が無ければ変更しない大丈夫です。

thresholdの値はいろいろ実験して決めました。

参考本: コンピュータ画像処理 田村秀行 ohm社

OpenV C++版のハフ変換の関数はこの関数です。

cv::HoughLinesP(
			edge,           // 8ビット,シングルチャンネル2値入力画像.この画像は関数により書き換えられる可能性がある.
			lines,          //出力先、ベクトル
			1,              //距離分解能、ピクセル
			CV_PI / 180.0,  //角度分解能、ラジアン
			80,             //しきい値。この値を超えている直線が出力される
			30,             //最小の線分長さ。たぶんピクセル
			10              //2点が同一線分上にあると見なす場合に許容される最大距離。たぶんピクセル。
		);
  • edge: 8ビット,シングルチャンネル2値入力画像です。
  • lines: 出力先、ベクトル
  • 1: 距離分解能、ピクセル
  • CV_PI / 180.0: 角度分解能、ラジアン
  • 80: しきい値。この値を超えている直線が出力される
  • 30: 最小の線分長さ。たぶんピクセル
  • 10: 2点が同一線分上にあると見なす場合に許容される最大距離。たぶんピクセル。

コード

山登りしたときの山小屋の写真を使用します。コードは丸パクです。ありがとうございます。( OpenCV 2値画像から線分を検出 -Maverick Project より)


#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

int main(int argc, char **argv){
	int hr = -1;
	try {
        //変数の指定
		cv::Mat src, edge, dst; //OpenCVの2次元行列型Mat
		std::vector<cv::Vec4i> lines; //?たぶんベクトル

        //画像の読み込み
		img = cv::imread("images\\P1030554.JPG", cv::IMREAD_GRAYSCALE);//imread関数によって画像をsrcに格納。カラーで読み込むならIMREAD_UNCHANGEDを、グレースケールで読み込むならIMREAD_GRAYSCALE
		cv::namedWindow("img", 1);//
		imshow("img", img);//imgの表示。グレースケールになった後の画像を確認
       
        //輪郭抽出
		cv::Canny(img, edge, 50, 200, 3);//2値化する関数
		
        //画像領域確保
        dst = cv::Mat::zeros(img.rows, img.cols, CV_8UC3);
        
        //img[0]->dst[2],img[0] -> dst[1], img[0] -> dst[0].コピー元とコピー先を指定
		int fromTo[] = { 0,2,0,1,0,0 };
        
        //チャンネル数?を増やしてコピー
        cv::mixChannels(&img, 1, &dst, 1, fromTo, 3);
        
        //線分検出
		cv::HoughLinesP(
			edge,           // 8ビット,シングルチャンネル2値入力画像.この画像は関数により書き換えられる可能性がある.
			lines,          //出力先、ベクトル
			1,              //距離分解能、ピクセル
			CV_PI / 180.0,  //角度分解能、ラジアン
			80,             //しきい値。この値を超えている直線が出力される
			30,             //最小の線分長さ。たぶんピクセル
			10              //2点が同一線分上にあると見なす場合に許容される最大距離。たぶんピクセル。
		);
        
        //線分描画
		for (auto line : lines) {
			cv::line(dst, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), cv::Scalar(0, 0, 255), 1);//線の色と太さを指定(B,G,R,太さ)
		}

		cv::namedWindow("dst", 1);
		cv::imshow("dst", dst);
		cv::waitKey(0);
		hr = 0;
	}
	catch (cv::Exception ex) {
		std::cout << ex.err << std::endl;
	}
    //ウインドウの破棄
	cv::destroyAllWindows();
	
    return hr;
}
入力画像のグレースケール
ハフ変換の出力結果

LiDAR

LiDAR(ライダー)とは、距離センサがぐるぐる回るヤツです。レーザー光を掃射し、物体に跳ね返ってくるでの時間を計測するものです。距離情報と時間(あるいは角度?)情報が流れてきます。

というわけで、とあるLiDAR画像を取ってきました。

ライダーの画像でやってみた。

cv::HoughLinesP(
			edge,
			lines,
			1,
			CV_PI / 180.0,
			20,
			15,
			3
		);

		for (auto line : lines) {
			cv::line(dst, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), cv::Scalar(0, 255, 0), 3);
		}

これ、実空間ではこんな感じなので、壁が感じてられますね。なんとなく。OK。

参考