職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

マスター・オブ・円弧 #SVG

この記事は SVG Advent Calendar 2015 の25日目の記事です。
www.adventar.org
Advent Calendar の最後を締めくくるのに相応しい内容かどうかはわかりませんが、皆さんきっとSVGを描きたくなるはずです。

SVGとは?

SVGとは画像ファイルの形式の一つで、基本的にはベクター画像(引き伸ばしても荒れないアレ)です。画像なんだけど中身はXML、すなわちテキストファイルになっている、不思議で便利な画像です。いまここで初めてSVGの名前を聞いたという皆さんは、上記の Advent Calendar に掲載されている記事を読んだり、Wikipediaの記事 を読むと良いでしょう。

SVG手描きとは?

前述の通りSVGXMLであり、テキストです。
テキストであるということは、テキストエディタで作成したり編集したりすることが理論上可能であるということが言えます。
理論上可能なんだったら実際にやろうぜ!と考えるのが人間というものです。そういう背景から近年盛り上がってきているのが「SVG手描き」という趣味になります。テキストエディタで描きましょう。

(注意)一般的には、Adobe Illustrator などのツールで描いた画像をSVG形式で出力することが多いはずです。

こんな画像だって、SVGならテキストエディタでサクッと描けます。

ソースはこんな感じです。
これをコピーしてテキストエディタに貼り付け、拡張子「.svg」で保存させてからブラウザに読み込ませると同じように描画されるはずです。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="480px" height="360px" viewBox="0 0 480 360" xmlns="http://www.w3.org/2000/svg" version="1.1">
	<rect fill="white" stroke="black" stroke-width="2" x="0" y="0" width="480" height="360"/>
	<polygon fill="red" stroke="none" points="40,40 40,320 440,320 440,40 400,40 400,280 80,280 80,40"/>
</svg>

rect 要素が外枠の黒い細い線を、 polygon 要素が「凹」の字を描いています。
※別に筆者が凹んでいる訳ではないですからね?

慣れてくると、公式の SVG 1.1 の仕様 を見ながらであれば5分以内に上記の図形を描くことができるようになります。テキストエディタで。

path要素

SVGでは、さまざまな図形がサポートされており、簡単に図形を描くことができます。
例えば以下のような図形があります。

  • rect : 長方形。左上座標と幅と高さを指定して描く。
  • circle : 円(楕円ではない真円)。中心座標と半径を指定して描く。
  • ellipse : 楕円。中心座標とx方向半径、y方向半径とを指定して描く。(回転はアフィン変換で実現)
  • line : 線分。始点と終点を指定して描く。
  • polyline : 線分をつなぎあわせたもの。カクカク曲がる。
  • polygon : 多角形。各頂点の座標を指定して描く。

これらは非常に便利であり、かつ、後からSVGのソースを見たときに意図が分かりやすいため、非常に重宝します。これらの要素を使って描くことができるのであれば、ぜひそうするべきです。
ところが、これらの図形では表現できないものというのは数多く存在します。
そういった図形は、path要素 を使って描くことになります。
画像を描くプログラムを書いたことがある人であればわかるかもしれませんが、path要素で線を描くときは「ペン」の考え方が根底にあります。ペンは現在の座標という状態を持ちます。現在地点から目的地までの経路をどのように線を引くのか、というのをコマンドで指定していきます。便利ですよ〜。

曲線あれこれ

path 要素の d 属性で使うことができるコマンドには、以下のようなものがあります。
※ここでは大文字のコマンドを紹介していますが、それぞれのコマンドには小文字バージョンがあり、それは現在のペンの位置からの相対座標を指定することで描画させるものになります。

  • M : 線を引かずにペンを指定した座標のところへ移動させる
  • Z : 開始地点までの線分を引く(閉じた領域を作る)
  • L : 指定した座標までの線分を引く
  • H : 指定したx座標までの水平線を引く
  • V : 指定したy座標までの垂直な線を引く
  • C : 3次のベジェ曲線を引く
  • S : 3次のベジェ曲線を引くが、1個目の制御点の座標は直前に引いたベジェ曲線のものに応じる(本当はきちんとした定義があるので、公式ドキュメントをご覧ください)。
  • Q : 2次のベジェ曲線を引く
  • T : 2次のベジェ曲線を引くが、制御点の座標は直前に引いたベジェ曲線のものに応じる。
  • A : 円弧を描く

線分を描くコマンドは単純明快ですし、2種類のベジェ曲線も制御点が線に与える影響のことを知っていれば描くことが可能です。注意するのは目的地の座標よりも制御点の座標を先に書くということくらいです。
一方で、円弧はそうは行きません。

円弧を描く

円弧を描くときにどのようなパラメータが必要なのか挙げてみましょう。

  • rx : x方向の半径
  • ry : y方向の半径
  • x-axis-rotation : x軸からの回転角。0だと回転しない。
  • large-arc-flag : 長い方の円弧を描くなら1。短い方なら0。
  • sweep-flag : 時計回りに円弧を描くなら1。反時計回りにするなら0。
  • x : 目的地のx座標
  • y : 目的地のy座標

恐らく、「なにそれ」という感想を抱いた方も多いことでしょう。
large-arc-flag と sweep-flag の詳細については、言葉でいろいろ見るよりも図示されたものを見る方がずっと効率が良さそうなので、図を貼っておきます。


Example arcs02 - arc options in paths Pictures showing the result of setting large-arc-flag and sweep-flag to the four possible combinations of 0 and 1. Arc start Arc end large-arc-flag=0 sweep-flag=0 large-arc-flag=0 sweep-flag=1 large-arc-flag=1 sweep-flag=0 large-arc-flag=1 sweep-flag=1
origin : Paths – SVG 1.1 (Second Edition)
Copyright © 2011 W3C® (MIT, ERCIM, Keio), All Rights Reserved.


一方、普段私たちが円弧を描くときは、次のようなものを指定することを考えると思います。

  • 中心の座標
  • x, y それぞれの方向の半径
  • 開始角度と終了角度

確かにこちらの組み合わせの方が円弧を描く上で便利そうに見えますが、前述の通り、path要素はペンの概念のもとで描画させる仕組みになっていますので、開始座標は初めから指定されているのと、終点座標はズバリその値を明示的に指定した方が後続の線を引く上で有利なのです。だから、 rx, ry, x-axis-rotation, などの指定をする方が良いのです。

一通り背景を理解したところで、path 要素を使って円弧を描いてみましょう!
えっ、描けない?
描けない人の大多数は、パラメータの順番を暗記できていません。再度掲載しますので覚えてください!

  • rx : x方向の半径
  • ry : y方向の半径
  • x-axis-rotation : x軸からの回転角。0だと回転しない。
  • large-arc-flag : 長い方の円弧を描くなら1。短い方なら0。
  • sweep-flag : 時計回りに円弧を描くなら1。反時計回りにするなら0。
  • x : 目的地のx座標
  • y : 目的地のy座標


タイトルとして「マスター・オブ・円弧」を掲げましたが、マスターするには結局は単純な記憶が必要でした。
でも、こういう指定をすることができれば、円弧が通る道筋は一意に定まる、というイメージを抱くことができたのではないでしょうか?
あとは練習あるのみです。皆さんもテキストエディタで円弧のSVG図形を描き、人生を豊かにしていって下さい。

それではSVGファンの皆様、よいお年を!!

関西モバイルアプリ研究会 #関モバ 第9回 に参加してきた

関西モバイルアプリ研究会(通称 関モバ) #9 に参加してきました。
kanmoba.connpass.com

前回 に続いて2回目の参加で、今回は発表してきました。

会場への道のり

大阪市内から京都市内へJR京都線の新快速で移動していたのですが…


という事情で運転見合わせにハマりました。
偶然にも停車していたのが新大阪駅だったため、こんな大技を使うことに。
f:id:t_motooka:20151223140550j:plain
新大阪・京都間の新幹線の自由席特急券は(時期によるかもしれませんが)860円です。乗車券は別。どうしてもってときは積極的に使っていきましょう。結果的には、関モバの会場である はてなさん のオフィスには10分遅れくらいで到着することができました。

なお、新大阪駅の在来線改札内で切符を買おうとすると、新大阪まで来るのに使ってた乗車券が必要になるため、複数人数の自由席特急券+乗車券を買おうとすると非常に手間取ります。3人以上の大人数で移動するときは、一旦新大阪駅で改札外に出てから切符を買うと、スムーズな行程変更ができるかもしれません。

自分が発表した内容

サンプルコード

motooka/ColorBar · GitHub

どんな発表だったのか

iOS Simulator が表示している「色」がどのようにして表示されているのかを示す発表をしました。iOSアプリの画面が意図しない色で表示されてしまうトラブルを防いだり原因究明したりするのに役に立つことができれば幸いです。
サンプルコードは、 UITableViewの static cells で、背景を適当な色で塗り潰して表示させるだけのアプリです。StoryBoard上の static cells の表示と iOS Simulator 上の表示を見比べながら、システム環境設定のディスプレイ設定で、カラープロファイルを変えてみると、iOS Simulator 上の色は変わらずにStoryBoard上の色だけ変わるという現象が起きます。
これが何を意味するのか、といった推測や議論もありました。

他の皆さんの発表のうち、(酒などに消されずに)記憶に残っているもの

いくつかご紹介しておきましょう。

  • Swift で、 struct を使うべきなのか class を使うべきなのかの判断 参考(公式ドキュメント) The Swift Programming Language (Swift 2.1): Classes and Structures
  • Keynote での画像作成:これは大盛り上がり! いろんな画像が
  • PhotoKit を使う上での注意点と、古くからある Assets Library の使い分け。Assets Library にしかできないことはあるので、特性を考えて選択したい。
  • FastlaneAndroid開発に応用する事例
  • 生物の色覚の話と、人間の様々なタイプの色覚について。
  • iOSアプリのバージョン番号を決める上でのベストプラクティス:リジェクト時のこともきちんと考えよう!
  • iOSアプリの起動にかかる時間を計測する方法(詳しくはメモれてないけど、info.plist か何かにおまじないを書いたら取れるっぽい?)
  • Web API にまつわる問題点あれこれ
  • Reveal でデザインデバッグ。AppCodeとの組み合わせだと上手く運用できそう?
  • Androidアプリでの Now on Tap の動きについて。

感想

色覚についての にわタコさん の発表の直後に色についての発表ができて、色の話を続けてできたのは本当に良かったです。

さいごに

会場を提供してくださっている はてなさん に感謝!!!

関西モバイルアプリ研究会 初参加

関西モバイルアプリ研究会(通称 関モバ) #8 に参加してきました。kanmoba.connpass.com

これまでどうしても都合が合わなくて参加できなかったのですが、ようやく参加することができました。

どんな会なのか?

  • 平日の夜に集まる
  • 乾杯から始まる
  • iOS / Android を中心として、最高のモバイルアプリを作るための話をしたり聞いたり
  • LT形式(1つの発表は5分)

お聞きした話(ごく一部)&学び

  • iOS : readableContentGuide ちゃんと設定して、特に iPad Pro でのコンテンツを読み易くしよう stackoverflow.com
  • iOS : AVFoundation Programming Guide の日本語版、更新されてないものだと思い込んでたけど更新されてた
  • iOS : 複数種類のUITableViewCellをTableViewに入れる時にどうするのが良いか? → xib複数体制が良さげ
  • iOS : Apple Pencil で取れる情報 → 座標、ペンの傾き、強さ、etc...
  • iOS : フレームワークのバージョンの話(提出時にエラーになる話)
  • iOS : はてなさんの教科書は優れている github.com
  • Android : アプリで使う指紋認証
  • ビール一杯でも酔ってしまう
  • 聞き手の酔い具合などの事情により、記憶がiOS関連に偏るようなこともある

謝辞

会場を提供してくださっている はてなさん への感謝の気持ちが山のように積み上がっています。

おまけ

「関西」で始まって「会」で終わる組織の名前を声に出して読み上げようとすると、どうしても「関西電気保安協会」のメロディに乗せようとしてしまいます。
関西電気保安協会CM集 - YouTube
きっと皆さんも同じ現象に悩まされているはずです。

PostgreSQLカンファレンス2015 に参加してきた

PostgreSQLカンファレンスに参加してきたので、その感想文および備忘録を書いておく。

www.postgresql.jp
ハッシュタグ#pgcon15j

前回参加したのは、2011年のことだった。

なぜ参加しようと思ったのか?

  • 最近PostgreSQLを触る機会があんまり無くて焦ってたから
  • 近い将来、新規に導入する予定があるから意識を高めたかったから


以下、拝聴した講演のうちのいくつかを紹介したい。

基調講演その1: PostgreSQL 9.5

http://www.postgresql.jp/events/jpug-pgcon2015/detail#keynote_1

開発者のMichaelさんの、日本語での基調講演で、12月にリリースされるかもしれないPostgreSQL 9.5 の新機能などの話。

主な内容はこんな感じ。

  • Upsert : insert文の最後につける ON CONFLICT 句の使い方と用途事例
  • BRIN : 部分インデックス(と訳すのが正しいのかどうかは不明) Blockc Range INdex
  • RLS : Row Level Security
  • パフォーマンス改善
    • ソートの改善
    • マルチCPU(マルチコアじゃない)環境下での改善
  • Streaming Replication における WALアーカイブの取り扱いの改善(これは9.4までの挙動をあんまり知らないから、上手く飲み込めなかった)

性能、信頼性を大幅に向上した pgpool-II 最新バージョンについて

http://www.postgresql.jp/events/jpug-pgcon2015/detail#J1

自分が pgpool-II の導入を検討していろいろ調べてたのは、PostgreSQL8.x の時代。当時はPostgreSQL本体に Streaming Replication の機能が無くて pgpool-II が擬似(?)replicationの仕組みを提供してくれていた。しかしその方式は全てのPostgreSQLノードに対して同じ(だったっけ?)SQLを投げるというもので、ある種の「怖さ」があった。他にも単純に組めばSPOFになってしまうなどの問題もあった。あれから数年が経過し、Streaming Replication登場後の pgpool-II の変貌についてほとんど知らなかったので、参加した。

最新バージョン 3.5 (現在はalpha版がリリースされたところ)での様々な改善の中で最も興味深いのは Watchdog の改善。こういう運用に嬉しい機能が強化されていくのは嬉しい。

他にもいろいろ。
pgpool-II 3.5 development - pgpool Wiki

PostgreSQL セキュリティ総復習

http://www.postgresql.jp/events/jpug-pgcon2015/detail#M2

心に残ったものいくつか。

  • psql\dp コマンドの実行結果の見方
  • sql_firewall : SQL Injection から防御するための拡張(怪しいクエリはエラーにする)
  • 「抑止と予防には予算と労力を投じる割に、検知と回復ができてない」といった趣旨のお話:確かに。

何が違うのか?PostGIS と最新版 MySQLGIS 機能を徹底比較

http://www.postgresql.jp/events/jpug-pgcon2015/detail#K3

大雑把にはこんな感じの話だったように記憶している。

  • MySQLだと本体に built-in なので導入が超簡単で、高速な動作をする。だけど単純な処理しかできない。
  • PostGIS だと最初のセットアップに一手間かかって気をつけないと遅くなっちゃうけど、様々な機能が揃っている。
  • MySQL Workbench の地図プレビューは優秀!
  • PostGIS 開発のキッカケはDB技術者じゃなくて地形界隈の専門家の動きによるもの。
  • 2つのDBはデータ形式がまったく異なるので、数値や文字列だけからなるデータみたいに簡単にダンプをやりとりするようなことはできない。一工夫いる。
  • GeoJSON の取り込み:これはどちらか一方の取り込みが遅いから、早い方で取り込ませて、ダンプを一工夫させつつ他方に取り込ませる手法が良い、みたいな話だったが、どっちがどっちだったか忘れた。。

PGroonga の実装

http://www.postgresql.jp/events/jpug-pgcon2015/detail#M4

講師の方がユーモア溢れる方で良い雰囲気のセッションだったのだが、ここで会場挙手アンケートの結果をご覧頂きたい。

内容は、PostgreSQLとGroongaとをどうやって繋いでいるのか?というお話。
他の製品との機能や性能の比較などもあって面白かった。
全文検索の話になると「あっちは日本語サポートしてない」「こっちもだ」みたいになるので大変。
日本語全文検索やってる皆さんにはほんとに頭が上がらない。

LT

こんな話を拝聴した。

さいごに

CakePHP3で簡易監査ログ

情報システムを組み上げるときは「誰がいつ何をした」といった情報を残していくことが非常によくあります。この情報のことを監査ログと呼びますが、他にも呼び方があるかもしれません。英語では audit trail と言ったりしてたと思います。たぶん。

そのシステムがRDB(関係データベース)を用いたものである場合、監査ログそのものもRDB上に残すことがあります。
きちんとした監査ログにするためには、監査ログを格納するための専用のテーブルを設けます。そのテーブルはシステム全体で1個であることもあれば、システムが管理しているデータごとに設けていくこともあります。専用のテーブルを設けずに、いわゆる「論理削除」を積み重ねていってそれを監査ログ代わりにすることもあるでしょう(望ましいとは思えませんが)。
これらの手法は、正確な監査ログが取れるようになる代わりに、かなり手間がかかります。構築する情報システムにかける予算が少なかったり期間が短かったりすると、省略されることもしばしばあります。
省略するとは言っても完全に何も記録を取らないのは精神衛生上よくありませんので、簡易的な監査ログをとることになります。
何が簡易なのかと言うと、保持する情報を以下のものに限るのです。

  • 当該データを最初に登録した日時
  • 当該データを最初に登録した人
  • 当該データを最後に更新した日時
  • 当該データを最後に更新した人

これだけの情報が残っていれば、本当に僅かなものではありますが、何か調査するときの手がかりにはなります。

さて、かなり長い前置きになりましたが、ここからはCakePHPの話です。
CakePHPでは昔から(少なくとも 2.x 系から)、日時だけではありますが、簡易の監査ログをRDBに保存する仕組みがあります。テーブルに「modified」「created」といったタイムスタンプ型の列を用意しておくと、そこに自動で登録日時や更新日時をセットしてくれるのです。

Saving Your Data — CakePHP Cookbook 2.x documentation

登録/更新した人については、 AuthComponent::user('id') によってModel内のコードからでも当該HTTPリクエストのセッションに紐付いたユーザIDを取ることができたので、beforeSaveコールバックあたりを実装すれば保存できていました。

ところが、CakePHP 3.x になってから、上記の方法ではユーザIDを取得することができなくなってしまいました。このことはGitHub上でも話題になり、こんなissueが立てられています。github.com
良い設計ではないものを誘発するという理由で速攻でcloseされてしまっています。これまでの手法がそのような性質を帯びたものであることには一切異論は無いのですが、簡易監査ログを取ることにそんなにコスト(時間)かけられないというのも事実です。

じゃあ、悪い設計であることは重々承知の上で簡単な実装を作っちゃえ! ということで、ModelのBehaviorを作りました。ソースはGistに置いてるのをこの記事に埋め込んでます。
gist.github.com

作った後に気付いたのですが、素晴らしい先人たちはもっと良い実装を既にされていました。github.com
これはPluginとしての実装なので、こちらの方が使い易いという人も多いでしょう。しかもstaticおじさんと呼ばれる危険性を摘み取ってくれていますし。


こういったものを活用して、気軽に簡易監査ログを取れるようにして、健全な情報システムを構築していきましょう。