SSブログ

Bezier曲線によるレンズ形状近似 [レンズ形状をBezierで描く]

また例によって新しいことを始める。OpenCLはどうなったんだ、GigE Visionドライバはどうなったんだ、という批判は甘んじて受けよう。スタック深さが2あればいい。歳はとったけどそのくらいはある、つもりである。こっちをさくっと終わらせてOpenCLに戻ろう。そしてOpenCLでベイヤRGB変換ができたらGen<i>Camのプログラミングに戻ろう.....

1  動機

球面や非球面の式を与えて単一(軸対象なので実際には2本)のBezier曲線で近似したい。 それはOS XのNSView上に描いて、pdfで出力して、Illustratorで読み込みたいからである。

NSBezeirPathには円弧を描くメソッドはあるけど、もう少し一般化して非球面も同じメソッドで近似的に描きたい。

そもそもなんでそんなことを考えたかというと、ZEMAX(最近のバージョンはOpticStudioというのか)に対する不満から。仕事ではたまにレンズ設計をすることもあってそのためにZEMAXのライセンスを1本だけ会社で持ってもらっている(ちなみに最初はCodeVを要求したんだけど高価なのであっさり却下)。それを普段持ち歩いているMacBook Pro Retina13"にインストールしてParallels Desktop上で動かしている。

ZEMAXを使っているといろいろ不満があってストレスが溜まるんだけど、不満の一つに図の出力がビットマップしかない、ということ。CodeVはEPSでも出力ができて、印刷品質でスケーリングも正確な図面としてpdfにすることができた。たとえばちゃんとした論文に載せても恥ずかしくない。

ところがZEMAXはレンズ製造図面でさえビットマップしか出せない。レンズの光軸を含んだ断面を表示させて、そのビットマップに含まれた横方向のスケールを、表示されたサイズに拡大縮小すると、レンズの直径のほうが微妙におかしい。収差図やMTFなんかはテキストでも出力できるので、そこから数字を拾い読みしてMathematicaでプロットして、Illustratorで微調整ということができるけど、レンズの絵はそういうことができない。

もちろんレンズ設計用のソフトとしてはたいしたことではないし、ZEMAXに対する一番大きな不満はそんなことではないんだけど、イライラする。CodeVもいいかげんソフトウェア的にはレガシーだと思ってたけど、どうやらZEMAXも五十歩百歩らしい。僕の嫌いなぱわぽが大好きな人たちにとっとは日常のことなので平気だろうけど(思い出してしまった。僕がせっかくきれいにpdfにしたグラフをAdobe Readerからコピペしてぱわぽに貼り付けると、ただビットマップにした以上にぎちゃぎちゃになる。会社のみんなはぱわぽが大好きなのでみんなそうなる。ぱわぽなんてなくなればいいのに。くやしい)。

ということで、ずっと前に書いた光線追跡エンジンの出力用として書こう。

ちなみに光線追跡エンジンはMathematicaのものを書いてそれを答え合わせ用にしてObjective-Cで書いていた。とうぜんObjective-Cの方が千倍速いんだけど、そっちのほうはUIもなければフレームワークの形にまとめることもせずに、使いたいときはレンズ系をハードコード(レンズの曲率を変えたければコンパイルし直す)していたせいで、僕以外の誰の役にも立たないと思ったので、公開はしていない。

ここでレンズの近似曲線を描くだけではどうしようもないので、できれば光線追跡エンジンと一緒にして公開したいと考えている。そっちは乞うご期待。

2  3次のBezier曲線

Bezier曲線の定義は
0521eq01.png
である。媒介変数tが0から1までの値をとることで曲線が得られる。BN個の制御点の座標、Jn,jはバーンスタインの基底関数と呼ばれるtに関する関数で、(n/i) は2項係数である。

制御点の数NによってP(t)はtに関するN−1次の多項式になる。制御点のうち最初と最後はBezier曲線の始点と終点になる。

NSViewがサポートするBezier曲線は3次なので、制御点は4つある。

今回の目標を宣言すると
「3次Bezier曲線一つを使って光軸から最大高さまでの球面/非球面を近似する」
ということである。

2.1  球面の媒介変数表示と近似の方針

光軸を横方向(x軸)にとって、光学でよく表示に使われる球面の式を、Bezier曲線と同じように媒介変数表示すると、
0521fig03.png
ここで、ηsは曲率、hは最大光軸高さで、従ってtはBezier曲線と同じ(0,1)区間である。

この曲線の始点は{0,0}で、終点は{ηh2/(1+√{1−η2h2}),h}なので、4つの制御点のうち最初と最後は決まる。また光軸に対して対称なので始点ではy軸に接している(微係数のx成分は0)。ということで決めなければいけないのは{0,By1}と{Bx2,By2}の値3つである。

この3つを
  • 光軸(始点)での曲率
  • 最大高さでの傾き(1次の微係数)
  • 最大高さでの2回微分
で決めてしまうことにする。ほんとうは誤差最小を選びたいけど、それはめんどくさいのと、そこまでうるさいことをいう必要はないと思った。また、最大高さでの曲率を一致させる方がもっともらしい(球面の方は光軸での値と同じなので)けど、Bezier曲線以上に非球面のt=1での曲率の計算が大変だったのでやめた。
nice!(0)  コメント(2)  トラックバック(0) 

nice! 0

コメント 2

jun hirabayashi

「なんちゃってMathematica”はどうなったのでしょうか。> "OpenCLはどうなったんだ、GigE Visionドライバはどうなったんだ"
by jun hirabayashi (2015-05-23 04:46) 

decafish

うっ、触れてはならんことを....さてはニャントロ星人か!?

いえいえ、ちゃんと僕の手元ではOpenCLでBeyer-RGB変換をしたGigEカメラは動いていますし、「なんちゃってMathematica」の字句解析構文解析はyacc/lexに頼らずに手動で書いたクラスがGen<i>CamのSwissKnifeの数式評価していますし、3次元表示はMathematicaと全く同じlighting Modelで描けていますし...ただ、ちょっとクラッシュしたり動作がおかしくなったりするだけです。
だって、僕なんて可愛い方です。GNU Hurdはどうした、Apple Copland、OpenDocはなんだっけ、Taligentはどうなった?

うう、言い訳ですな...
優しく温かく長い目で見守ってやってください。
よろしくお願いします。
by decafish (2015-05-23 18:40) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。