transform と deviceorientation における回転の表現 (HTML)

CSS の transform プロパティと JavaScript の deviceorientation イベントではともに 3D の回転状態 (姿勢、傾き) が登場しますが、
その扱い方に差があるため検証しました。
deviceorientation は、デバイスのジャイロ センサーが回転状態を通知することで発生するイベントです。

HTML の 3 次元座標系では、2 次元スクリーン座標系の x 軸および y 軸に加えて、スクリーンに垂直な z 軸が存在します。
デバイス (スマートフォンなど) を水平に持ち、北を向いた状態を基準に考えます。

このとき、CSS の transform プロパティと JavaScript の deviceorientation イベントにおける、
回転に関する性質の違いを下の表にまとめました。例えば z 軸を中心とする回転の角度は、現在は北を向いていたとしたら、
transform では東側 (時計回り) を向くと正、deviceorientation では西側を向くと正になります。

  transform deviceorientation
座標系 左手系 右手系
x 軸 右が正 右が正
y 軸 下 (手前) が正 上 (奥) が正
z 軸 (画面が水平のとき) 鉛直の上が正 鉛直の上が正
回転角度 回転軸の正方向に左ねじを進める場合が正 回転軸の正方向に右ねじを進める場合が正

 

検証のため、CSS の transform プロパティと JavaScript の deviceorientation イベントを利用して、
デバイスの回転状態を画面内の立方体オブジェクトに同期させるサンプルを作成しました。

DeviceOrientation

ジャイロ センサーを搭載した端末であれば、こちらのテストページで確認できます。
HTML のソースは以下の通りです。

以下は、各技術についての説明です。

transform プロパティ

transform プロパティで rotateX などを利用して回転状態を指定する場合、次に示すように複数の回転を重ね合わせることができます。

CSS:
transform: rotateX(45deg) rotateY(30deg) rotateZ(60deg);

JavaScript:
element.style.transform = "rotateX(45deg) rotateY(30deg) rotateZ(60deg)";

ただし、座標系ごと回転させながら左から順に適用します (オイラー角)。
これは、以前に 3D における回転の表現と相互変換で書いた通り、元の座標系のまま右から順に適用する、と考えても同じです。

以下に rotateX(45deg)rotateY(45deg) を組み合わせた例を載せておきます。

初期状態

rotateX(45deg) (左)        rotateX(45deg) rotateY(45deg) (右)

rotateY(45deg) (左)        rotateY(45deg) rotateX(45deg) (右)

deviceorientation イベント

window.addEventListenerdeviceorientation に対するイベントリスナーを登録します。
デバイスの回転状態が変化すると、イベントリスナーが呼び出されます。

引数の alpha, beta, gamma はそれぞれ z 軸、x 軸、y 軸を中心とした回転の角度を表し、
座標系ごと回転させながらこの順に重ね合わせたものが回転状態を表します。
それぞれの値の範囲は次の通りです。

  • z 軸: 0 ≦ alpha < 360
    • 北を向いたとき、alpha = 0
  • x 軸: -180 ≦ beta < 180
  • y 軸: -90 ≦ gamma < 90

 

回転状態の同期

以上から、デバイスの回転状態を画面内のオブジェクトに同期させるには次のようにします。

cubeEl.style.transform = `rotateZ(${-e.alpha}deg) rotateX(${-e.beta}deg) rotateY(${e.gamma}deg)`;

正負の符号に注意します。
結果として、z 軸および x 軸における回転角度の正負は異なり、y 軸では同じになります。

 

作成したサンプル
参照
transform
deviceorientation
広告

半角カタカナなどを変換するライブラリ

半角カタカナからひらがなへの変換や、Shift_JIS の文字エンコーディングへのプロパティなど、
日本で利用される機能を集めたライブラリ Zipangu を制作しました。
以前にハッカソンで日本の郵便番号を検索するための Postal Codes JP Web API を制作しており、そこからのスピンオフです。

ターゲット フレームワークを .NET Standard 2.0 および .NET Framework 4.0 以降としています。
したがって、.NET Core 2.0、UWP 10.0.16299 などでも利用可能です。

機能

文字の変換

  • ASCII 文字 → 全角 ASCII 文字
  • 全角 ASCII 文字 → ASCII 文字
  • ひらがな → カタカナ
  • カタカナ → ひらがな
  • 半角カタカナ → ひらがな
  • 半角カタカナ → カタカナ

.NET Framework に以前から存在する Microsoft.VisualBasic.dll の Strings.StrConv メソッドとは、一部の仕様を変更しています。
例えば、「ヴ」をひらがなに変換した結果が「ゔ」になるようにしています。
仕様の詳細はこちらに記述しました:

文字エンコーディング
各文字エンコーディング (文字コード) のインスタンスにアクセスするためのプロパティを提供します。

  • Shift_JIS (932)
  • ISO-2022-JP (50220)
  • EUC-JP (51932)

利用方法

セットアップ
プロジェクトに NuGet で Zipangu をインストールします。

コード (C#)
このライブラリの使用例を以下に示します。

 

バージョン情報
  • .NET Standard 2.0
  • .NET Framework 4.0
参照
カテゴリー: .NET Core, ライブラリ. タグ: . Leave a Comment »

Roslyn の構文解析を使ってデバッガーを自作する

// C# Advent Calendar 2018 の 23 日目の記事です。

デバッガーのようなものを自作してみました。

動機

  • 普段は Visual Studio を使っているが、デバッグ時に手動でステップ実行するのが面倒
    • ループなどでステップ数が多い場合
    • 分岐の様子や変数の状態を軽くチェックしたい場合

解決案

  • ステップの時間間隔だけを指定して、デバッガーを自動で実行させる
    • 変数の一覧が表示される
    • 時間間隔をリアルタイムで調節できる
  • .NET Compiler Platform (Roslyn) の構文解析の機能を使い、各ステップの間にデバッグ用のコードを差し込めば実現できそう

結果

というわけで、WPF でプロトタイプ「Tick-tack Debugger」を作ってみた結果、このようになりました。
例として、ニュートン法で平方根を求めています。 (クリックで拡大)

 

解説

以下は概略の技術解説です。
WPF アプリを作成する前に、まず .NET Framework 上のコンソール アプリで実験してみます。
C# の構文解析を使うには、NuGet で Microsoft.CodeAnalysis.CSharp をインストールします。

デバッグ対象となるソースコードにデバッグ コードを挿入し、それを動的にコンパイルして実行する、という方針です。
コンソール アプリのソースコードを以下に示します (全体のソリューションは SyntaxTreeSample にあります)。

SyntaxHelper クラスでは、デバッグ対象の C# ソースコードを構文ツリー (SyntaxTree) に変換して走査し、
各ステートメントの前にデバッグ用のコード行を挿入していきます。

CSharpSyntaxTree.ParseText メソッドを使うことで、ソースコードを構文ツリーに変換できます。
また、メソッド・ステートメント・式など、すべてのノードを表す親クラスは SyntaxNode クラスであり、

  • Parent プロパティ: 親
  • Ancestors メソッド: 祖先
  • ChildNodes メソッド: 子
  • DescendantNodes メソッド: 子孫

が存在することを知っておけば、だいたいの探索ができるでしょう。

この他に、デバッグ用のコードから呼び出されるメソッドを定義するクラス ライブラリとして DebuggerLib を作成しています。
各ステートメントの位置、およびその直前で存在する変数とその値を通知するために、このライブラリを経由させます。

Program クラスでは、生成されたデバッグ用のソースコードをファイルに保存したら、
System.CodeDom.Compiler 名前空間の CodeDomProvider を使ってこれをコンパイルし、
そのエントリ ポイント (Main メソッド) を呼び出します。
また、デバッグ コードが実行されたときのイベントハンドラーを登録しておき、
Thread.Sleep メソッドを使って、指定した時間だけ停止させます。

これで、デバッグ対象の元のソースコードが次の Program.cs だとすると、
デバッグ用のソースコードとして下の Program.g.cs が生成されます。

作成したコンソール アプリを実行すると、次の図のようになります (時間間隔は 0.3 秒)。

 

以上をもとに、WPF アプリでデバッグ ツールを作成しました。
左側の C# ソースコードの部分は TextBox で、編集もできます。
デバッグ実行時は、各ステートメントを選択状態にすることでハイライトしています。
右側の変数一覧が表示される部分は DataGrid です。

(図は円周率を求める例)

今回は上記の方法でプロトタイプを作ってみましたが、
デバッグ コードの挿入やコンパイルに関しては、よりスマートな方法があるのではないかと思います。

注意点
  • 考えられうるすべてのステートメントには対応できていません。また、Main メソッドしか構文解析していません。
  • コンパイル時に生成されるアセンブリ (EXE) は、%TEMP% フォルダー (ユーザーの AppData\Local\Temp) に保存されていきます。
  • TextBox で、IsInactiveSelectionHighlightEnabled を True に設定しても利かないことがあります。
    また、選択状態のハイライトがずれることがあります。
    RichTextBox で Run などを使うのがよいかもしれません。

 

作成したサンプル
バージョン情報
参照

T4 でクラスやプロパティを自動生成する

Text Template Transformation Toolkit (T4) はテンプレート エンジンの一つで、主に Visual Studio で使われているものです。
これを使うと、ソースコードやデータの集合などのファイルを自動生成できます。

今回は例として、次のような Markdown を記述したら、
それに対応するクラスやプロパティを C# のソースコードとして生成することを考えます。

この Markdown の仕様を次のように定めます。

  • 空行は無視
  • 箇条書きでない行がクラス名
  • その下に続く箇条書きはプロパティ
    • 「- Type PropertyName」の形式
    • プロパティ名が省略された場合は、型名と同じ
  • クラス名およびプロパティ名は、PascalCase, camelCase のどちらを指定してもよい

以下では、このような .md ファイルを入力として、
プロパティおよびコンストラクターを持つ部分クラスを .cs ファイルに出力するように T4 で実装していきます。

まず、プロジェクトに上記の .md ファイルを追加しておきます。
そしてプロジェクトに「テキスト テンプレート (.tt)」 を追加します。

Add New Item

追加された .tt ファイルを、仕様に従って次のように実装します。

注意点は以下の通りです。

  • 初期状態では出力の拡張子が .txt になっているため、.cs に変更する
  • プロジェクト内のファイルのパスを取得するには、hostspecific="true" を指定して Host.ResolvePath メソッドを使う
  • <#= #> :テキストの出力
  • <# #> :コードを書ける、変数を使える
  • <#+ #> :メソッド、クラスなどを定義できる

.tt ファイルを保存したときに処理が実行されます。
または、.tt ファイルを右クリックして [カスタム ツールの実行] を選択すれば実行されます。

Run Custom Tool

これで、以下のように RecordTypes.cs が生成されます。

 

作成したサンプル

テストしたバージョン

  • Visual Studio 2017

参照

カテゴリー: ツール. タグ: , . Leave a Comment »

.NET Core 向けビルド スクリプト

ビルド用 PowerShell スクリプトの Build Release (GitHub) を .NET Framework プロジェクト形式向けに提供していましたが、
今回は .NET Core プロジェクト形式向けのビルドツールを追加しました。

ツールの内容:

(1) Version 1up

アセンブリのバージョン (x.y.z の z の部分) を 1 だけ増加させます。
.NET Core プロジェクト形式では、プロジェクト ファイル (.csproj) でバージョンを書き換えます。

(2) Zip Release

プロジェクトを Release でビルドして、ZIP ファイルを作成します。
ビルド前にアセンブリのバージョンを増加させます。

(3) NuGet Packup

プロジェクトを Release でビルドして、NuGet パッケージを作成します。
ビルド前にアセンブリのバージョンを増加させます。

これらのツール (PowerShell スクリプト) を使う方法としては、Visual Studio の「外部ツール」に登録するのが便利だと思います。
前回にビルド用のスクリプトを Visual Studio の外部ツールに登録する方法について書きましたが、
.NET Core 版の手順も改めて以下に書いておきます。

セットアップ

Build-Release/Downloads (GitHub) からツールの最新版をダウンロードして任意のフォルダーに展開します。

Explorer

Visual Studio のメニューで [ツール] – [外部ツール] を選択して各スクリプトを追加していきます。

  • タイトル: 任意
  • コマンド: powershell.exe
  • 引数: -ExecutionPolicy Unrestricted "C:\scripts_folder\KTools.xxx.ps1"
  • 初期ディレクトリ: $(ProjectDir)
    • 右の ▶ ボタンで選択できる
    • Version 1up では $(SolutionDir) でもよい
  • 出力ウィンドウを使用: オン

External Tools

 

プロジェクトの作成

.NET Core 向けのプロジェクト テンプレートを選択してプロジェクトを作成します。

New Project

.NET Framework プロジェクトではバージョン番号などを AssemblyInfo.cs に記述しますが、
.NET Core プロジェクトではプロジェクト ファイル (.csproj) に記述します。
初期状態ではバージョンが設定されていない (その場合は 1.0.0 と判定される) ため、
プロジェクトのプロパティで [パッケージ バージョン] の値を設定しておきます。

Project Property

上記の設定をして保存すると、.csproj ファイルの <Version> に反映されます。

.csproj

なお、.NET Core のプロジェクト形式でも、

<TargetFramework>net45</TargetFramework>

のようにすれば .NET Framework をターゲットにすることができます。
詳細は .NET Core と .NET Standard を参照してください。

 

ツールの実行:

(1) Version 1up

対象のプロジェクト内のファイルを開いた状態で、メニューからスクリプトを選択すると実行されます。

External Tools Menu

実行すると、ログが Visual Studio に出力されます。

Version 1up Output

 

(2) Zip Release

同様に、メニューから Zip Release を実行します。
zip フォルダーに ZIP ファイルが作成されます。

Zip Release

 

(3) NuGet Packup

クラス ライブラリ プロジェクトを対象に NuGet Packup を実行します。
pkg フォルダーに NuGet パッケージが作成されます。

NuGet Packup

 

注意点

  • .NET Framework プロジェクト形式向けには NuGet 経由でプロジェクトに PowerShell スクリプトを追加する
    方法 (KTools.ZipRelease) も提供していますが、.NET Core プロジェクト形式では NuGet で同様の方法で追加できませんでした。

 

前回: ビルド用のスクリプトを Visual Studio の外部ツールに登録する

テスト済バージョン
Visual Studio 2017

参照
Build Release (GitHub)
外部ツールの管理
.nuspec File Reference for NuGet

カテゴリー: ALM, ツール. タグ: , . 3 Comments »

ビルド用のスクリプトを Visual Studio の外部ツールに登録する

以前にビルドして ZIP にする PowerShell スクリプトを作成しましたが、
そのときはプロジェクトごとに NuGet でインストールする方法を前提としていました。
今回は各スクリプトを Visual Studio の外部ツールとして登録する方法も便利だとわかったため、その利用手順を紹介します。

設定手順:

  • Build-Release/Downloads (GitHub) から最新版をダウンロードして、任意のフォルダーに PowerShell スクリプトを展開する
  • Visual Studio のメニューで [ツール] – [外部ツール] を選択して各スクリプトを追加する
    • タイトル: 任意
    • コマンド: powershell.exe
    • 引数: -ExecutionPolicy Unrestricted "C:\scripts_folder\KTools.xxx.ps1"
    • 初期ディレクトリ: $(ProjectDir)
      • 右の ▶ ボタンで選択できる
      • KTools.VersionIncrement.ps1 は $(SolutionDir) でもよい
    • 出力ウィンドウを使用: オン

ExternalTools

 

以上の設定で、「プロジェクト フォルダー上で PowerShell スクリプトを実行する」ためのメニューが
Visual Studio の [ツール] メニューに追加されました。
実行するには、対象のプロジェクトのファイルを開いているときにメニューからそれらを選択します。

ExternalTools-Menu

[出力ウィンドウを使用] がオンに設定されていると、ログが Visual Studio に出力されます。

ExternalTools-Output

ExternalTools-Zip

 

このように Visual Studio の外部ツールを利用することで、
バージョンアップ、Release ビルド、ZIP 作成が Visual Studio から簡単にできるようになりました。

このツールは .NET Framework プロジェクト形式向けに提供していますが、
次回は .NET Core プロジェクト形式向けのツールを追加します。

次回: .NET Core 向けビルド スクリプト

テスト済バージョン
Visual Studio 2017

参照
Build Release (GitHub)
外部ツールの管理
Visual Studioの外部ツール機能を活用してみよう
ビルドして ZIP にする PowerShell スクリプト

カテゴリー: ALM, ツール. タグ: , . 3 Comments »

URL エンコーディング

URL エンコーディングの定義と、それを扱うための .NET Framework のライブラリを検証しました。

パーセント エンコーディングと URL エンコーディング

パーセント エンコーディングとは、文字列を UTF-8 でエンコードし、各バイトをパーセント記号 % とその 16 進数を用いて表すことです。
例えば、"/""%2F" に、"あ""%E3%81%82" に変換されます。

URL エンコーディングとは、URI の中で使われている記号と混在しないように一部の文字列をパーセント エンコーディングにより
変換することです。両者の言葉を区別せずに使うこともあります。

URL エンコーディング

RFC 3986 では、文字は次のように分類されます。

  • 非予約文字
    • エンコードしなくても利用できる文字
    • アルファベット、数字、および 4 種類の記号 -._~
  • 予約文字
    • URI で意味を持つ記号
    • 18 種類の記号 !#$&'()*+,/:;=?@[]
  • その他の文字
    • エンコードが必要な文字
    • 11 種類の記号 " %<>\^`{|} 、その他のすべての文字 (日本語など)

URL エンコーディングは、主に次の 2 通りで利用されます。

  • URI の各セグメント (クエリ文字列を除く)
    • https://tempuri.org/messages/Hello%20World%21messagesHello%20World%21 の部分
    • 非予約文字以外をパーセント エンコーディング
      • ただし、Web フレームワーク個別の仕様により、パーセント エンコーディングしても使用を制限されることがある
  • URI のクエリ文字列や、POST などで送信するときの本文 (フォーム)
    • key=value&message=Hello+World%21keyHello+World%21 の部分
    • 非予約文字以外をパーセント エンコーディングし、さらに %20 (スペース) を + に変換
    • MIME タイプ application/x-www-form-urlencoded と定義されている

 

.NET Framework のライブラリ

.NET Framework では、URL エンコーディングのために次の方法が用意されています。

  • System.Uri.EscapeDataString メソッド
    • RFC 3986 に従って非予約文字以外をパーセント エンコーディング
  • System.Uri.EscapeUriString メソッド
    • RFC 3986 に従って非予約文字・予約文字以外をパーセント エンコーディング
    • 既に全体が URI の形式になっているときに利用する
      • クエリ文字列も同様の規則で変換される。application/x-www-form-urlencoded には変換されない
  • System.Uri インスタンスの AbsoluteUri プロパティ
    • 基本的に Uri.EscapeUriString メソッドと同じだが、下記の点が異なる
    • %XX の形式になっているかどうかで扱いが異なる
      • https://tempuri.org/%2https://tempuri.org/%252
      • https://tempuri.org/%25https://tempuri.org/%25 のまま
    • クエリ文字列でない部分の \/ に変換される
  • System.Net.WebUtility.UrlEncode メソッド
    • RFC 2396 (旧版) に近い仕様で非予約文字以外をパーセント エンコーディングし、さらに %20 (スペース) を + に変換
  • System.Web.HttpUtility.UrlEncode メソッド
    • System.Net.WebUtility.UrlEncode メソッドと同じだが、小文字になる
  • System.Net.Http.FormUrlEncodedContent クラス
    • key-value データをまとめて application/x-www-form-urlencoded に変換

 

Uri.AbsoluteUri

 

.NET では System.Uri.EscapeDataString メソッドSystem.Uri.EscapeUriString メソッド
System.Net.Http.FormUrlEncodedContent クラスを使えばよいでしょう。

アプリケーションから HTTP 接続をするために System.Net.Http.HttpClient クラスを使うことが多いと思いますが、
接続先の URI を string で渡しても、HttpClient の内部では Uri インスタンスで扱われます。
したがって、URI を HttpClient に渡す前に、セグメントもクエリ文字列も URL エンコーディングしておくのがよさそうです。

 

作成したサンプル

バージョン情報

  • .NET Framework 4.5

参照

カテゴリー: .NET Framework, サービス. タグ: , . Leave a Comment »