CCanvas Classを使ったメーターの描写
コンテンツ一覧
- イントロダクション
- 1. 座標とアンカー
- 2. 計測器要素
- 3. 関数
- 3.1. GaugeCreate
- 3.2. GaugeSetCaseParameters
- 3.3. GaugeSetScaleParameters
- 3.4. GaugeSetMarkParameters
- 3.5. GaugeSetMarkLabelFont
- 3.6. GaugeSetLegendParameters
- 3.7. GaugeSetRangeParameters
- 3.8. GaugeSetNeedleParameters
- 3.9. GaugeRedraw
- 3.10. GaugeNewValue
- 3.11. GaugeDelete
- 3.12. GaugeCalcLocation
- 3.13. GaugeRelocation
- 4. アナグラム
- 4.1. ENUM_CASE_BORDER_STYLE
- 4.2. ENUM_CASE_STYLE
- 4.3. ENUM_GAUGE_LEGEND
- 4.4. ENUM_MARK_STYLE
- 4.5. ENUM_MUL_SCALE
- 4.6. ENUM_NCENTER_STYLE
- 4.7. ENUM_NEEDLE_FILL
- 4.8. ENUM_REL_MODE
- 4.9. ENUM_SCALE_STYLE
- 4.10. ENUM_SIZE
- 5. マクロによる代用
- 6. CCanvas Classの修正
- 7. アプリケーション例
- 8. リソース耐久評価
- 結論
イントロダクション
CCanvasクラスについて知ったとき、今回の件についてひらめきました。そして、もし実際に何かに利用するとしたら、メーターインジケーターを描写するというアイディアに至りました。最初に開発したものはひどいものでしたが、新要素などにより、次第に見た目も良くなりました。結果的に、インジケーターやEAに簡単に実装できるメーターの簡易なライブラリになりました。今回の記事では、メーターの構造の説明、ビジュアルの描写と設定の関数、強度の評価を行います。
図1. メーター
1. 座標とアンカー
チャートにメーターを表示する方法には2通りあります。: 絶対位置と相対位置。
絶対的なポジショニングの場合、角からのX軸、Y軸の距離での指定になります。
相対的なポジショニングの場合、座標の原点は、相対的な位置の指定されたタイプに応じて作成されます。鉛直タイプを選択すると、原点が基準オブジェクトの下または上に配置されます。(上部または下部アンカーがそれぞれ選択されている場合)水平タイプを選択すると、アンカーからの左または右に配置されます。この場合、指定された座標は元の原点からの差を表します。プラスの差は、関連のオブジェクトから遠ざけます。マイナスの差は、関連のオブジェクトの内部に入り込みます。
関連オブジェクトは他のメーターによって表示させます。どちらのオブジェクトも同じアンカーコーナーを使います。
図2 は相対配置の一例です。
図2. メーターの相対配置
各メーターの設定を見てみましょう。:
- "gg01" メーター: 相対位置はできません。水平オフセット — 40, 鉛直オフセット — 40.
- "gg02" メーター: 相対配置 — 水平関連オブジェクト — "gg01". 座標のローカルの原点からの水平オフセット(ポイントA) — 15, 鉛直オフセット — 0.
- "gg03" メーター: 相対配置 — 鉛直, 関連オブジェクト — "gg01". ローカルの座標原点からの水平オフセット (ポイントB) — 0, 鉛直オフセット — 15.
- "gg04"メーター: 相対配置 — 鉛直, 関連オブジェクト — "gg02". 水平座標のローカル原点(点C)からのオフセット — 50, 垂直オフセット — 15.
相対的な位置決めを行うと、チャートの入力設定メーターを含むいくつかのインジケータがある場合、容易です。1ゲージのサイズを変更すると、他のゲージの座標も自動的に計算されます.
GaugeCreate()関数は、位置決めタイプと座標を設定します。
2. 計測器要素
ダイヤルゲージは2つのグラフィカルオブジェクトで構成されています。そのうちの1つは、スケールレイヤーと呼ばれています。もう一つはニードルレイヤーと呼ばれています。どちらのグラフィカルオブジェクトも、同じ座標を持っています。ニードルレイヤーはスケールレイヤーの上に配置されます。入力パラメータに設定されたメーターの名前は、両方のオブジェクトの名前の接頭辞として働きます. 例えば、メーターの名前が"Gauge01"の場合、スケールレイヤーは "Gauge01_s"となり、ニードルレイヤーは"Gauge01_n"となります。
図3は、メーターの構造です。
図3. メーターの構造
スケールレイヤーが含むもの:
- ボーダー(1)
- 目盛マーク (5, 6, 7)
- 目盛のラベル (4)
- 強調された範囲 (2, 12)
- 文字 (3, 10, 11)
文字は意図に応じて区別します:
- メーター表示 (3)
- 単位(11)
- 現在値 (10)
- スケールラベルの倍率 (省略)
メモリは下記に分けます:
- メジャー (7)
- ミドル (5)
- マイナー (6)
メジャー目盛りだけがラベル付きです。目盛り単位は、整数で設定します。ミドル単位は、メジャーの中間マークの指定した数に応じて計算されます。マイナー単位は、ミドルのものとの間のマイナーマークの指定した数に応じて計算されます。マイナーとミドルの目盛りは省略可能です。
ニードルレイヤーが含むもの:
- 針 (8)
- 針の中心 (9)
図3は、いくつかのメーター要素の大きさを示しています。:
- d — メーターの外部輪郭の直径に対応するメーターサイズ
- b — ボーダーサイズ
- g — ボーダーとスケール要素の間のスペースのサイズ
- c — 針の中心のサイズ
NB. メーターの直径のサイズはピクセル単位で設定されています。("d" 図3). 他のすべての要素とフォントは、条件毎に設定され、その大きさは直径の割合として計算されます。サイズ変更を容易にするために行われます。直径を変更した場合、他のすべてのサイズが比例し再計算されます。. 演算係数は、マクロ置換セクションにリスト化され、ユーザーが後から変更することができます。
円形とセクター:メーターの本体形状には2つのタイプがあります。<A0>スケールの範囲</ A0>の角度が180度未満である場合に扇形の方が便利です。
図4. メーターの形状
図4は、一周のメーター(a)と2つの扇形状のゲージを示しています(b、c)。GaugeSetCaseParameters() 関数は、望んだ形状を設定するために使用されます。
これは、メーターの最も重要な要素です。データの読みやすさは、その外観が重要です。メーターは過度に複雑だと困りますが、しかし、十分な情報を含む必要があります。メーターの極端な値はもちろん、メジャーマークには、特別な注意表示が必要です。GaugeSetScaleParameters() 関数は、スケールの範囲、その回転と極値(最小値と最大値)を設定することができます。最小値は左(ダイレクトオーダー)または右(逆順)に設定することができます.
スケールレンジは、両極の2つの値による角度です。これは、図5の通りです。
図5. スケールレンジ
スケールの回転は上向きと垂直ゲージの中心から来る線からのスケール範囲の角度二等分線の偏角です。これは図6の通りです。
図6. 回転角
スケール範囲の角度と回転角度を組み合わせることにより、非常に柔軟な方法でゲージ外観の設定をすることができます。図4(c)は、90度の範囲、45度の回転を実証したものです。
最大値と最小スケール値は、表示された変数の許容値の範囲に応じて選択される重要なパラメータです。ゼロマークは、利便性に応じて省略することができます。400から600までの範囲での変数が変わる場合、ゼロからスケールを描画しても意味がありません。図7は、いくつかの最大の例と最小スケール値です。
図7. 最大最小スケール
- a) 0 から500までの値 ダイレクトオーダー
- b) -200 から400までの値 ダイレクトオーダー
- c) -400 から 0 までの値 ダイレクトオーダー
- d) 500 から 0 までの値 逆順
- e) 200 から 800 までの値 ダイレクトオーダー
- f) 0 から -800 までの値 逆順
目盛り設定は、マークのサイズと整列メソッドの選択にあります。
整列は次のようにします:
- スケールの内側
- スケールの外側
- センター
図8は、整列の目盛線の例です:
- a — センター
- b — 内側
- c — 外側
GaugeSetMarkParameters()関数は、設定で使います。
マークのラベルの位置は、GaugeSetScaleParameters()関数を使用して調整されます。
図8(a)は、スケール内部図8(b)及び図8(c)の位置決めの例です。
ラベルはあまり多くのスペースを占有しないので、すべての表示する値は、分割される係数multiplierを使用することを推奨します。乗算値は、0.0001から10000までの値にすることができます。図4(c)は、1桁の数字の代わりに、3桁の数字を使かえる100に等しい乗数を適用した例です。図1は、ラベル内の小数点とゼロを使用することを許可されていないATRに、0.0001を使用する状況を示しています。GaugeSetScaleParameters()関数は乗算値をセットします。
図8. マークとラベルの配置
文字は、補足情報を表示するためのものであり、四種類のものが可能です。:
- メーター説明
- 単位
- 現在値
- 乗算値
任意の文字を非表示にすることができます。メーターの説明はデフォルトで表示されます。
文字の位置決めは、角と半径で設定します。角は度数で設定し、その値はメーターの中心からくる上方向の鉛直にあるラインと、メーターの中心と文字の中心を結ぶ仮想セグメントの角に等しくなります。半径は、条件毎に設定します。0 から 10の値を取ります。0が針中心の半径に対応し、10はスケールの外側半径に対応します。
図9は、凡例です。
- "利益"の文字(メーター説明)は次の座標があります。:角 - 0、半径 - 3。
- "0.00"の文字(現在値)には、次の座標があります:角 - 225、半径 - 4.
- "USD"の文字(測定単位)は、座標は次の通りです:角 - 215、半径 - 8。
GaugeSetLegendParameters()関数は、文字パラメータを設定するために使用します。
図9. 文字座標
NB. 文字は、スケール上に固定されておらず、その角度は、スケール、回転角度と接続されていません。
強調表示されたデータ範囲は、任意のメーターの固有の要素を表します。値が異常な値または特別な範囲に入ったことを確認するために役立ちます。GaugeSetRangeParameters()関数は、4つの強調表示された範囲に設定することができます。このためには、ハイライト用に極端な値と色を設定する必要があります。図1は、二つの強調表示された範囲での利益の指標を示しています。:緑色の範囲は、400から200が利益を固定するための時間で、オレンジの範囲は-400-200から大きなドローダウンの警告です。
GaugeSetNeedleParameters() 関数は、針の中心部の大きさや面積の塗りの種類を設定します。ニードルレイヤーが完全にデータ更新後に毎回再描画されるように、エリアタイプはインジケータの感度に影響を与えます。図10は、エリアの塗りつぶしの例を示しています。
- アンチエイリアシアルゴリズムを使用して針を描写(a)
- アンチエイリアスアルゴリズムを使用することなく、針を描写(b)
- アンチエイリアスで針を満たさない(c)
図10. 針のエリアの塗りつぶし方法
それぞれの方法の長所と短所は、CCanvasクラスとリソースの感度評価のセクションで説明します。
3. 関数
テーブル1は、メーターを描写する関数と見た目の設定のリストです。
関数 | 見た目 |
---|---|
GaugeCalcLocation | メーターの中心座標の計算 |
GaugeCreate | メーターの生成 |
GaugeDelete | メーターの削除 |
GaugeNewValue | 針の位置と値を更新 |
GaugeRedraw | メーターの再描写 |
GaugeRelocation | チャート上のゲージオブジェクトの位置の変更 |
GaugeSetCaseParameters | メーターパラメータの設定 |
GaugeSetLegendParameters | 文字パラメータの設定 |
GaugeSetMarkLabelFont | 目盛りフォントの設定 |
GaugeSetMarkParameters | 目盛りパラメーターの設定 |
GaugeSetNeedleParameters | 針パラメータの設定 |
GaugeSetRangeParameters | 範囲パラメータの設定 |
GaugeSetScaleParameters | スケールパラメータの設定 |
テーブル1. 関数リスト
それぞれの関数の詳細を見てみましょう。初期化時に、それらを呼び出す推奨の順番です。
メーターの生成
bool GaugeCreate( string name, // メーター名 GAUGE_STR &g, // メーター構造の参照 int x, // アンカーコーナーからの水平インデント int y, // アンカーコーナーからの鉛直インデント int size, // メーターサイズ string ObjRel, //位置が設定されているグラフィカルオブジェクト名 ENUM_REL_MODE rel_mode, // 相対配置 ENUM_BASE_CORNER corner, // アンカーコーナー bool back, //背景のオブジェクト uchar scale_transparency, //スケール透明度 uchar needle_transparency //針透明度 );
パラメータ
名称
[in] メーター名メーターを構成するグラフィカルオブジェクトの名前の接頭辞として使用
g
[out] メーター構造の参照
x
[in] X軸に沿ったアンカーコーナーからの距離(ピクセル単位)相対的な位置決めの場合 — 座標のローカル原点からの距離.
y
[in] Y軸に沿ったアンカーコーナーからの距離(ピクセル単位)相対的な位置決めの場合 — 座標のローカル原点からの距離.
size
[in] メーターのサイズ直径
ObjRel
[in] 位置が設定されている他のグラフィカルオブジェクトの名称. 相対的な位置が設定されている場合にのみ関連が残ります。
rel_mode
[in] 相対配置のメソッド. ENUM_REL_MODEのリストの値を持ちえます。
コーナー
[in] グラフィカルオブジェクトをアンカーするチャートのコーナーENUM_BASE_CORNERのリストの値を持ちます。
バック
[in] 背景のオブジェクト
scale_transparency
[in] スケール透明度0 から 255まで取ります。
needle_transparency
[in] 針の透明度0 から 255まで取ります。
Return value
スケールレイヤーとニードルレイヤーのオブジェクトが作成されている場合はtrueを返します. それ以外の場合は falseを返します。
メーターのパラメータの設定
void GaugeSetCaseParameters( GAUGE_STR &g, // メーター構造の参照 ENUM_CASE_STYLE style, // ボディスタイル color ccol, // ボディカラー ENUM_CASE_BORDER_STYLE bstyle, // ボーダースタイル color bcol, // ボーダーカラー ENUM_SIZE border_gap_size // ボーダーとスケール要素のサイズ);
パラメータ
g
[out] メーター構造の参照
style
[in] スタイルENUM_CASE_STYLEのリストの値を取ります。
ccol
[in] ボディカラー
bstyle
[in] ボーダースタイルENUM_CASE_BORDER_STYLEのリストの値を取ります。
bcol
[in] ボーダーカラー
gap_size
[in] 境界線の内部ラインと最寄りのスケール要素(図3の"g")との間の領域. ENUM_SIZEのリストの値を取ります。
スケールパラメータのセット.
void GaugeSetScaleParameters( GAUGE_STR &g, // メーター構造の参照 int range, // スケールレンジ int rotation, // ローテーションのアングル double min, // 最小値 (左) double max, // 最大値 (右) ENUM_MUL_SCALE mul, // スケールラベルの乗算値 ENUM_SCALE_STYLE style, // スケールのスタイル color col, // スケールカラー bool display_arc // スケールラインの表示 );
パラメータ
g
[out] メーター構造の参照
range
[in] スケールレンジ. スケールの極端な二つの値による角度として設定します。これは 30 から 320 まで取ります。 (図5).
rotation
[in] スケールローテーションアングル (図6).
min
[in] 直接的に値を割りあてる場合の最小値。
max
[in] 直接的に値を割り当てる場合の最大値
mul
[in] スケールラベルの乗算値ENUM_MUL_SCALEのリストの値を取ります。
style
[in] スケールスタイルENUM_SCALE_STYLEのリストの値を取ります。
col
[in] スケールカラー
display_arc=false
[in] スケールラインの表示
スケール目盛りパラメータの設定
void GaugeSetMarkParameters( GAUGE_STR &g, // メーター構造の参照 ENUM_MARK_STYLE style, // スケールマークのスタイル ENUM_SIZE size, // マークのサイズ double major_tmi, // メジャーマーク間隔 int middle_tmarks, // メジャー間のミドルマークの数 int minor_tmarks // ミドル間のマイナーの数 );
パラメータ
g
[out] メーター構造の参照
style
[in] スケール目盛りのスタイルENUM_MARK_STYLEのリストの値を取ります。
size
[in] マークサイズENUM_SIZEのリストの値を取ります。
major_tmi
[in] メジャー目盛りのステップメジャーマークは、関連する値を持つラベルが付与されています。
middle_tmarks
[in] メジャー間のミドルマークの数プラスの値を取ります。サイズに制限はありません。0に設定すると、ミドルマークは表示されません。
minor_tmarks
[in] ミドル間のマイナーマークの数(ミドルのメジャーマーク間が表示されない場合)。プラスの値を取ります。サイズに制限はありません。0に設定した場合、マイナーマークは表示されません。
目盛ラインのフォント設定
void GaugeSetMarkLabelFont( GAUGE_STR &g, // メーター構造の参照 ENUM_SIZE font_size, // フォントサイズ string font, // フォント bool italic, // イタリック bool bold, // ボールド color col // カラー );
パラメータ
g
[out] メーター構造の参照
font_size
[in] 目盛りラベルのフォントサイズENUM_SIZEのリストの値を取ります。
font
[in] フォント
italic
[in] イタリック
bold
[in] ボールド
col
[in] フォントカラー
文字パラメータの設定
void GaugeSetLegendParameters( GAUGE_STR &g, // メーター構造の参照 ENUM_GAUGE_LEGEND gl, // 文字タイプ bool enable, // 文字の表示 string str, // string (補完的なパラメータ) int radius, // 座標 - 半径 double angle, // 座標 - 角 uint font_size, // フォントサイズ string font, // フォント bool italic, // イタリック bool bold, // ボールド color col // カラー );
パラメータ
g
[out] メーター構造の参照
gl
[in] 文字タイプENUM_GAUGE_LEGENDの値を取ります。
enable
[in] 文字の表示
str
[in] これは、LEGEND_DESCRIPTIONまたはLEGEND_UNITSの文字のために表示される文字列ですこのパラメータは、LEGEND_MUL型の文字では無視されます。LEGEND_VALUEの文字の小数点以下の桁数"0" から "8"の値を取ります。他の値を"0"として認識されます例として、"2"は、2つの小数点以下の桁数を意味します。"hello"という文字列は、0小数点以下の桁数です。
radius
[in] 半径座標単位の文字の中心とメーターの中心部からの距離(図9)
angle
[in] アングル座標その値は上方と垂直にゲージの中心から来るラインと、ゲージの中心と文字のセンター(図9)を結ぶ仮想セグメント間の角度に等しいです。
font_size
[in] 文字のフォントサイズ
font
[in] フォント
italic
[in] イタリック
bold
[in] ボールド
col
[in] フォントカラー
ハイライト領域のパラメータの設定
void GaugeSetRangeParameters( GAUGE_STR &g, // メーター構造の参照 int index, //レンジインデックス bool enable, // レンジ表示 double start, // 初期値 double end, // 最終値 color col // カラー );
パラメータ
g
[out] メーター構造の参照
index
[in] レンジインデックス0 から 3の値を取ります。
enable
[in] レンジの表示
start
[in] 初期値
end
[in] 最終値
col
[in] レンジをハイライトする色
ニードルパラメータの設定
void GaugeSetNeedleParameters( GAUGE_STR &g, // メーター構造の参照 ENUM_NCENTER_STYLE ncenter_style, //針のセンタースタイル color ncenter_col, //針のセンターカラー color needle_col, //針の色 ENUM_NEEDLE_FILL needle_fill //針のメソッド );
パラメータ
g
[out] メーター構造の参照
ncenter_style
[in] 針のセンターのスタイルENUM_NCENTER_STYLEのリストの値を取ります。
ncenter_col
[in] ニードルのセンターカラー
needle_col
[in] 針の色
needle_fill
[in] 針のメソッドENUM_NEEDLE_FILLのリストの値を取ります。
メーターの再描写この関数は、変更を適用するために、任意のパラメータを変更した後に呼び出す必要があります。
void GaugeRedraw( GAUGE_STR &g // メーターの構造の参照 );
パラメータ
g
[in] メーター構造の参照
針と表示された値の更新
void GaugeNewValue( GAUGE_STR &g, // メーター構造の参照 double v // 変数 );
パラメータ
g
[in] メーター構造の参照
v
[in] 変数の現在値
メーターを構成するグラフィカルオブジェクトの削除OnDeinit() ハンドラから呼び出す関数のコール
void GaugeDelete( GAUGE_STR &g // メーター構造の参照 );
パラメータ
g
[in] メーター構造の参照
メーターオブジェクトの座標の計算相対配置 が利用できない場合、常に同じ座標を返します。それ以外、参照オブジェクトがその位置やサイズを変更した場合、座標が以前の値と異なることがあります。
bool GaugeCalcLocation( GAUGE_STR& g // メーター構造の参照 );
パラメータ
g
[in] メーター構造の参照
Return value
値が前のものとは異なる場合trueを返します。それ以外の場合は falseを返します。関数がtrueを返した場合、計算されたパラメータを適用する関数GaugeRelocation()を呼び出します。
チャートの指定されたスポットにメーターを構成するグラフィカルオブジェクトを配置します。相対的な位置が設定され、関数 GaugeCalcLocation()がtrueを返した場合に、必要です。
void GaugeRelocation( GAUGE_STR &g // メーター構造の参照 );
パラメータ
g
[in] メーター構造の参照
4. アナグラム
表2は関数のパラメータとして利用するリストです。
項目 | 説明 |
---|---|
ENUM_CASE_BORDER_STYLE | ボーダースタイル |
ENUM_CASE_STYLE | ボディスタイル |
ENUM_GAUGE_LEGEND | 文字タイプ |
ENUM_MARK_STYLE | スケール目盛りのスタイル |
ENUM_MUL_SCALE | 目盛りラベルの乗算値 |
ENUM_NCENTER_STYLE | 針の中心部のスタイル |
ENUM_NEEDLE_FILL | 針のエリアのメソッド |
ENUM_REL_MODE | 相対配置のメソッド |
ENUM_SCALE_STYLE | スケールスタイル |
ENUM_SIZE | サイズ |
表2. 項目リスト
4.1. ENUM_CASE_BORDER_STYLE
ボーダースタイル値は表3にリストしています。
識別子 | 説明 |
---|---|
CASE_BORDER_NONE | ボーダーなし |
CASE_BORDER_THIN | 細いボーダー |
CASE_BORDER_THICK | 太いボーダー |
表3. ENUM_CASE_BORDER_STYLEの値
4.2. ENUM_CASE_STYLE
ボディスタイル値は表4にリストしています。
識別子 | 説明 |
---|---|
CASE_ROUND | 円のボディ |
CASE_SECTOR | セクタータイプボディ |
表4ENUM_CASE_STYLEの値
4.3. ENUM_GAUGE_LEGEND
文字タイプ値は表5にリストしています。
識別子 | 説明 |
---|---|
LEGEND_DESCRIPTION | メーター説明 |
LEGEND_UNITS | 目盛り単位 |
LEGEND_MUL | スケールラベルの乗算値 |
LEGEND_VALUE | 変数の現在値 |
表5. ENUM_GAUGE_LEGENDの値
4.4. ENUM_MARK_STYLE
スケールメモリのスタイル値は表6にリストしています。
識別子 | 説明 |
---|---|
MARKS_INNER | 内縁によってマークを揃える |
MARKS_MIDDLE | 中心によってマークを揃える |
MARKS_OUTER | 外枠によってマークを揃える |
表6ENUM_MARK_STYLEの値
4.5. ENUM_MUL_SCALE
スケール目盛りラベルの乗算値値は表7にリストしています。
識別子 | 意味 | 表示 |
---|---|---|
MUL_10000 | 10000 | х10k |
MUL_1000 | 1000 | х1k |
MUL_100 | 100 | х100 |
MUL_10 | 10 | х10 |
MUL_1 | 1 | 非表示 |
MUL_01 | 0.1 | /10 |
MUL_001 | 0.01 | /100 |
MUL_0001 | 0.001 | /1k |
MUL_00001 | 0.0001 | /10k |
表7ENUM_MUL_SCALEの値
4.6. ENUM_NCENTER_STYLE
針の中心部のスタイル値は表8にリストされています。
識別子 | 説明 |
---|---|
NDCS_NONE | 針の中心部を非表示 |
NDCS_SMALL | 小さく表示 |
NDCS_LARGE | 大きく表示 |
表8. ENUM_NCENTER_STYLEの値
4.7. ENUM_NEEDLE_FILL
針のエリアの塗り方値は表9にリストされています。.
識別子 | 説明 |
---|---|
NEEDLE_FILL | アンチエイリアスを使わずに塗りつぶし |
NEEDLE_FILL_AA | アンチエイリアスを使って塗りつぶし |
NEEDLE_NOFILL_AA | アンチエイリアスを適用するが塗りつぶさない |
表9. ENUM_NEEDLE_FILLの値
4.8. ENUM_REL_MODE
相対配置のやり方値は表10にリストされています。
識別子 | 説明 |
---|---|
RELATIVE_MODE_NONE | 相対配置をしない |
RELATIVE_MODE_HOR | 水平 |
RELATIVE_MODE_VERT | 鉛直 |
RELATIVE_MODE_DIAG | 斜め |
表10. ENUM_REL_MODEの値
4.9. ENUM_SCALE_STYLE
スケールスタイル値は表11にリストされています。
識別子 | 説明 |
---|---|
SCALE_INNER | スケール内の目盛りラベル |
SCALE_OUTER | スケール外の目盛りラベル |
表11. ENUM_SCALE_STYLEの値
4.10. ENUM_SIZE
サイズ値は表12にリストされています。
識別子 | 説明 |
---|---|
SIZE_SMALL | 小さい |
SIZE_MIDDLE | 中 |
SIZE_LARGE | 大きい |
表12. ENUM_SIZEの値
5. マクロによる代用
サイズの係数:
#define DIAM_TO_NDCSL_RATIO 5 //直径のパーセンテージとしての針の中心径(小) #define DIAM_TO_NDCSB_RATIO 7.5 //直径のパーセンテージとしての針の中心径(大) //--- #define DIAM_TO_BD_SIZE_S 2 //直径のパーセンテージとしての境界線の幅(小) #define DIAM_TO_BD_SIZE_B 5 //直径のパーセンテージとしての境界線の幅(大) //--- #define DIAM_TO_BD_GAP_S 2.0 //直径のパーセンテージとして計(小)の内側の要素に対するボーダーからのスペース #define DIAM_TO_BD_GAP_M 3.0 //直径のパーセンテージとしてのメーター (ミドル)の内側の要素に対すボーダーからスペース #define DIAM_TO_BD_GAP_L 7.0 //直径のパーセンテージとしてのメーター (大) (ミドル)の内側の要素に対すボーダーからスペース //--- #define DIAM_TO_MSZ_MJ_S 3.3 //直径のパーセンテージとしてメジャースケール(小)の目盛りのサイズ #define DIAM_TO_MSZ_MD_S 2.3 //直径のパーセンテージとして中規模(小)の目盛りのサイズ #define DIAM_TO_MSZ_MN_S 1.3 //直径のパーセンテージとしてマイナースケール(小)の目盛りのサイズ //--- #define DIAM_TO_MSZ_MJ_M 6.5 //直径のパーセンテージとしてメジャースケール(中央)の目盛りのサイズ #define DIAM_TO_MSZ_MD_M 4.8 //直径のパーセンテージとして中規模(中央)の目盛りのサイズ #define DIAM_TO_MSZ_MN_M 3.0 //直径のパーセンテージとしてマイナースケール(中央)目盛りのサイズ //--- #define DIAM_TO_MSZ_MJ_L 10.0 //直径のパーセンテージとしてメジャースケール(大)の目盛りのサイズ #define DIAM_TO_MSZ_MD_L 7.5 //直径のパーセンテージとして中規模(大)の目盛りのサイズ #define DIAM_TO_MSZ_MN_L 5.0 //直径のパーセンテージとしてマイナースケール(大)の目盛りのサイズ //--- #define DIAM_TO_MFONT_SZ_S 4 //直径の割合としてスケール(小)の目盛りのラベルのフォントサイズ #define DIAM_TO_MFONT_SZ_M 6.5 //直径の割合としてスケール(中央)の目盛りのラベルのフォントサイズ #define DIAM_TO_MFONT_SZ_L 10 //直径の割合としてスケール(大)の目盛りラベルのフォントサイズ
デフォルトカラー:
#define DEF_COL_SCALE clrBlack #define DEF_COL_MARK_FONT clrBlack #define DEF_COL_CASE clrMintCream #define DEF_COL_BORDER clrLightSteelBlue #define DEF_COL_LAB clrDarkGray #define DEF_COL_NCENTER clrLightSteelBlue #define DEF_COL_NEEDLE clrDimGray
6. CCanvas Classの修正
6.1. アンチエイリアスアルゴリズムを用いたセグメントの描写
LineAA メソッドは、アンチエイリアシングアルゴリズムを使用してセグメントを描画することができます。しかし、円形目盛りを描画するときに、一つの問題が浮上します。直交座標系に極座標からセグメントの最初と最後の点の座標を変換すると、整数に切り上げなければならない小数が発生します。したがってマークは図11(b)に示されているように曲がって見えます。
このような理由により、x1、y1、x2、y2の入力パラメータの種類が倍に変更されているという事実によって、LineAAとは異なる方法LineAA2を追加しました。よって、座標の端数を出し、図11(c)のようにはっきりと見せ、問題を取り除くことができます。
//+------------------------------------------------------------------+ //| アンチエイリアスの線を引きます (with style) v.2 | //+------------------------------------------------------------------+ void CCanvas::LineAA2(const double x1,const double y1,const double x2,const double y2,const uint clr,const uint style) { //--- ラインは、画像の境界の外にあります if((x1<0 && x2<0) || (y1<0 && y2<0)) return; if(x1>=m_width && x2>=m_width) return; if(y1>=m_height && y2>=m_height) return; //--- check if(x1==x2 && y1==y2) { PixelSet(int(x1),int(y1),clr); return; } //--- 線のスタイルを設定 if(style!=UINT_MAX) LineStyleSet(style); //--- 試算 double dx=x2-x1; double dy=y2-y1; double xy=sqrt(dx*dx+dy*dy); double xx=x1; double yy=y1; uint mask=1<<m_style_idx; //--- セットピクセル dx/=xy; dy/=xy; do { if((m_style&mask)==mask) PixelSetAA(xx,yy,clr); xx+=dx; yy+=dy; mask<<=1; if(mask==0x1000000) mask=1; } while(fabs(x2-xx)>=fabs(dx) && fabs(y2-yy)>=fabs(dy)); }
図11は、描画スケールマークの様々な方法の例です。:
図11. スケールの描写方法 (200%倍)
Fillメソッドは、アンチエイリアシングアルゴリズムを使用することなく、描画セグメントによって囲まれた領域を塗りつぶすように意図されています。LineAAメソッドで描かれた線分に囲まれた領域を埋めるために、この方法を使用する場合は、領域は図12に見られるように、不完全に塗りつぶされる(a)。
図12. アンチエイリアスエッジによる塗りつぶし (倍率200%)
よって、Fill2の方法を追加します。違いは、異なる背景色で境界を塗りつぶすということです。これは、 Fillメソッドを使用して行うことができない、場所を埋めることができます. 図12(b)はその例です。
//+------------------------------------------------------------------+ //| 閉領域を塗りつぶす(v.2) | //+------------------------------------------------------------------+ void CCanvas::Fill2(int x,int y,const uint clr) { //--- チェック if(x<0 || x>=m_width || y<0 || y>=m_height) return; //--- int index=y*m_width+x; uint old_clr=m_pixels[index]; //--- 交換が必要かどうかを確認 if(old_clr==clr) return; //--- 深くネストされた再帰呼び出しをシミュレートするために、擬似スタックを使用 int stack[]; uint count=1; int idx; int total=ArraySize(m_pixels); //--- スタック用のメモリを割り当て if(ArrayResize(stack,total)==-1) return; stack[0]=index; m_pixels[index]=clr; for(uint i=0;i<count;i++) { index=stack[i]; x=index%m_width; //---左の隣接点 idx=index-1; if(x>0 && m_pixels[idx]!=clr) { stack[count]=idx; if(m_pixels[idx]==old_clr) count++; m_pixels[idx]=clr; } //--- トップ隣接点 idx=index-m_width; if(idx>=0 && m_pixels[idx]!=clr) { stack[count]=idx; if(m_pixels[idx]==old_clr) count++; m_pixels[idx]=clr; } //--- 右隣のポイント idx=index+1; if(x<m_width-1 && m_pixels[idx]!=clr) { stack[count]=idx; if(m_pixels[idx]==old_clr) count++; m_pixels[idx]=clr; } //---下の隣接点 idx=index+m_width; if(idx<total && m_pixels[idx]!=clr) { stack[count]=idx; if(m_pixels[idx]==old_clr) count++; m_pixels[idx]=clr; } } //--- メモリの解放 ArrayFree(stack); }
しかし、この方法にも欠点があります。小さな鋭角が存在する場合、一部は図12(c)に示されているように、白色のままでです。しかし、この問題から抜け出す道を発見しました。
1)まず、全体のキャンバス(ニードルレイヤー)は、針部分のために意図された色で満たされています:
n.canvas.Fill(10, 10, ColorToARGB(n.needle.c, n.transparency));
2)その後、 LINEA A2メソッドを使用して、3つのセグメントで針を描きます:
n.canvas.LineAA2(db_xbuf[0], db_ybuf[0], db_xbuf[1], db_ybuf[1], 0); n.canvas.LineAA2(db_xbuf[1], db_ybuf[1], db_xbuf[2], db_ybuf[2], 0); n.canvas.LineAA2(db_xbuf[2], db_ybuf[2], db_xbuf[0], db_ybuf[0], 0);
3)この後、 Fill2メソッドを使用して、透明色と針の周りの領域を塗りつぶします:
n.canvas.Fill2(10, 10, 0);
この方法は、最良のものではありませんが、適切な針を描画することができます.
図13. それぞれの手法による針の塗りつぶし
図13は、様々な方法を使用して塗りつぶされた針を示しています。
- 3つのセグメントで、構成a)の針がLINEA A2メソッドを使用して描画され、 Fill2</ a1>の方法を用いて塗りつぶされています。
- b) FillTriangleメソッドを使って描かれた針
- c) LineA A2メソッドを使用して描かれた、3セグメントで構成された塗りつぶされていない針
ご覧のように、図13(b)に示す針は90度で割り切れる角度に近い角の場合、カクカクしています。加えて、極座標から直交座標系に変換する際の座標の四捨五入によって、針が中心からずれていることがわかります。しかし同時にこの方法は、リソースの意味では最も実用的です。(この件に関しては後述)。図13(c)に示された針は、上記の二つの方法でのトレードオフであります。 LineA A2メソッドが、エリア塗りつぶしなしを使用して描かれた三つのセグメントから構成されています。
7. アプリケーション例
それでは、いくつかの例を介して、メーターライブラリを適用してみましょう.
最もシンプルな例から始めます。この例では、EAやインジケータにメーターを追加するための基本的なセットを示しています。
//+------------------------------------------------------------------+ //| profit_gauge_indicator.mq5 | //| Copyright 2015, Decanium | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Decanium" #property version "1.00" #property indicator_plots 0 #property indicator_chart_window #include <Gauge\gauge_graph.mqh> input string inp_gauge_name="gg01"; // インジケーター名 input int inp_x = 40; //水平オフセット input int inp_y = 40; // 鉛直オフセット input int inp_size=300; // インジケーターサイズ input string inp_ObjRel=""; // 相対配置の場合にはベースとなるインジケーターの名前 input ENUM_REL_MODE inp_rel_mode=RELATIVE_MODE_NONE; // 相対配置モード input ENUM_BASE_CORNER inp_corner=CORNER_LEFT_UPPER; // アンカーコーナー input bool inp_back=false; // インジケータは、バックグラウンドで動作します input uchar inp_scale_transparency=0; // 透明度 level, 0..255 input uchar inp_needle_transparency=0; // 針の透明度, 0..255 //--- メーター構造の宣言 GAUGE_STR g0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- メーターの生成 if(GaugeCreate(inp_gauge_name,g0,inp_x,inp_y,inp_size,inp_ObjRel,inp_rel_mode, inp_corner,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- メーターの描写 GaugeRedraw(g0); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- メーターの削除 GaugeDelete(g0); ChartRedraw(); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //--- 読み込みの更新 double profit=AccountInfoDouble(ACCOUNT_PROFIT); GaugeNewValue(g0,profit); //--- return(rates_total); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- if(id==CHARTEVENT_CHART_CHANGE) { if(GaugeCalcLocation(g0)==true) GaugeRelocation(g0); } } //+------------------------------------------------------------------+
まず、メーターの構造を宣言する必要があります。 GaugeCreate()メソッドを使用してゲージを作成した初期化関数で、描画関数- GaugeRedraw()を呼び出します。GaugeNewValue() は、読み込みの更新に使います。この例では、OnCalculate()ハンドラからコールしています。
メーターは図14に示されているとおりです。
図14. メーターのデフォルトの外観
次に、スケールの範囲および回転角度を設定する機能を追加します。入力のリストに2つのパラメータを追加します。
input int inp_scale_range=270; // スケール範囲, 30..320 度 input int inp_rotation=45; // スケールローテーション, 0..359 度
スケールのパラメータを設定するための関数の呼び出しで初期化コードを拡張します。
//--- スケールの設定 スケールのパラメータやマーク GaugeSetScaleParameters(g0,inp_scale_range,inp_rotation,-200,400,MUL_1,SCALE_INNER,clrBlack);
新しいパラメータの補充
- 新しい最大値と最小値 (それぞれ-200、 400)
- 目盛ラベルの乗数(MUL_1)
- scale style (SCALE_INNER — graduation labels are inside)
- ラベルの色 (clrBlack)
スケール極端な値を変更したので、メジャーマークのステップを修正することが望ましいです。テキストを除外して、100が最適値です。2つのメジャーと4つのマイナーマーク間に、1つのミドルマークを配置します。よって、10のマーク間の最小ステップになります。
GaugeSetMarkParameters(g0,MARKS_INNER,SIZE_MIDDLE,100,1,4);
今、2つのデータ領域をハイライトしています。200で始まり、400で終わる範囲を有するインデックス0は、clrLimeGreenで強調表示されています。-100で始まり、-200で終わる範囲を有するインデックス1は、clrCoralで強調表示されます。
//--- スケールでの範囲を強調 GaugeSetRangeParameters(g0,0,true,200,400,clrLimeGreen); GaugeSetRangeParameters(g0,1,true,-100,-200,clrCoral);
次に、表示文字を設定します。メーターの説明、測定単位と小数点以下1桁で現在の値を決定します。ひとつひとつ見てみましょう。
メーター説明:
GaugeSetLegendParameters(g0,LEGEND_DESCRIPTION,true,"Profit",3,0,14,"Arial",false,false);
表示文字"Profit", 半径 3, 角 0, フォント 14
単位:
GaugeSetLegendParameters(g0,LEGEND_UNITS,true,"USD",8,215,10,"Arial",true,false);
文字は "USD", 半径 8, 角 215, フォント10
現在値:
GaugeSetLegendParameters(g0,LEGEND_VALUE,true,"1",4,225,20,"Arial",true,false);
文字"1"は表示の形式(小数点以下1桁)を意味します。座標: 半径4, 角255. フォントサイズ20
いくつかの追加設定を行った後、メーターは図15のようになります。
図15. 追加設定後のメーターの外観
次に、より複雑な例、すなわちダッシュボードインジケーターに移ります。図1がそれです。このインジケーターは、現在利益、スプレッド、フリーマージンをパーセンテージで、さらに、ATRと Force Indexと RSI表示します。
まず、メーター構造配列を宣言します。
//--- メーターの構造体配列の宣言 GAUGE_STR gg[6];
次に、ゲージを生成、調整します。
マージンレベルのインジケータが左下に配置されます。これは絶対座標を持つことになり、他のすべてのインジケーターが、このインジケータまたは隣接に係る配置にされます。
//--- gg00メーターの生成 if(GaugeCreate("gg00",gg[0],5,-90,240,"",RELATIVE_MODE_NONE, CORNER_LEFT_LOWER,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- ボディパラメータの設定 GaugeSetCaseParameters(gg[0],CASE_SECTOR,DEF_COL_CASE,CASE_BORDER_THIN,DEF_COL_BORDER,SIZE_MIDDLE); //--- スケールのパラメータやマークの設定 GaugeSetScaleParameters(gg[0],120,35,800,2000,MUL_100,SCALE_INNER,clrBlack); GaugeSetMarkParameters(gg[0],MARKS_INNER,SIZE_MIDDLE,200,1,4); GaugeSetMarkLabelFont(gg[0],SIZE_MIDDLE,"Arial",false,false,DEF_COL_MARK_FONT); //--- スケールを強調 GaugeSetRangeParameters(gg[0],0,true,1400,2000,clrLimeGreen); GaugeSetRangeParameters(gg[0],1,true,1000,800,clrCoral); //--- テキストラベルの設定 GaugeSetLegendParameters(gg[0],LEGEND_DESCRIPTION,true,"Margin lvl",4,15,12,"Arial",false,false); GaugeSetLegendParameters(gg[0],LEGEND_VALUE,true,"0",3,80,16,"Arial",true,false); GaugeSetLegendParameters(gg[0],LEGEND_MUL,true,"",4,55,8,"Arial",true,false); //--- 針パラメータの設定 GaugeSetNeedleParameters(gg[0],NDCS_SMALL,DEF_COL_NCENTER,DEF_COL_NEEDLE,NEEDLE_FILL_AA);
一番下の行を配置します。次は現在損益インジケーターです。
//--- gg01メーターの生成 if(GaugeCreate("gg01",gg[1],-80,20,320,"gg00",RELATIVE_MODE_HOR, CORNER_LEFT_LOWER,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- ボディパラメータの設定 GaugeSetCaseParameters(gg[1],CASE_SECTOR,DEF_COL_CASE,CASE_BORDER_THIN,DEF_COL_BORDER,SIZE_MIDDLE); //--- スケールのパラメータやマークの設定 GaugeSetScaleParameters(gg[1],200,0,-400,400,MUL_1,SCALE_INNER,clrBlack); GaugeSetMarkParameters(gg[1],MARKS_INNER,SIZE_MIDDLE,100,1,4); GaugeSetMarkLabelFont(gg[1],SIZE_MIDDLE,"Arial",false,false,DEF_COL_MARK_FONT); //--- スケールの強調 GaugeSetRangeParameters(gg[1],0,true,200,400,clrLimeGreen); GaugeSetRangeParameters(gg[1],1,true,-200,-400,clrCoral); //--- テキストラベルの設定 GaugeSetLegendParameters(gg[1],LEGEND_DESCRIPTION,true,"Profit",3,0,16,"Arial",false,false); GaugeSetLegendParameters(gg[1],LEGEND_UNITS,true,"USD",3,-90,10,"Arial",true,false); GaugeSetLegendParameters(gg[1],LEGEND_VALUE,true,"1",3,90,12,"Arial",true,false); //--- 針パラメータの設定 GaugeSetNeedleParameters(gg[1],NDCS_SMALL,DEF_COL_NCENTER,DEF_COL_NEEDLE,NEEDLE_FILL_AA);
スプレッドインジケータは下段に配置します。
//--- gg02メーターの生成 if(GaugeCreate("gg02",gg[2],-80,-20,240,"gg01",RELATIVE_MODE_HOR, CORNER_LEFT_LOWER,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- ボディパラメータの設定 GaugeSetCaseParameters(gg[2],CASE_SECTOR,DEF_COL_CASE,CASE_BORDER_THIN,DEF_COL_BORDER,SIZE_MIDDLE); //--- スケールのパラメータやマークの設定 GaugeSetScaleParameters(gg[2],120,-35,60,0,MUL_1,SCALE_INNER,clrBlack); GaugeSetMarkParameters(gg[2],MARKS_INNER,SIZE_MIDDLE,10,1,4); GaugeSetMarkLabelFont(gg[2],SIZE_MIDDLE,"Arial",false,false,DEF_COL_MARK_FONT); //--- スケールの強調 GaugeSetRangeParameters(gg[2],0,true,35,10,clrLimeGreen); GaugeSetRangeParameters(gg[2],1,true,50,60,clrCoral); //--- テキストラベルの設定 GaugeSetLegendParameters(gg[2],LEGEND_DESCRIPTION,true,"Spread",4,-15,14,"Arial",false,false); GaugeSetLegendParameters(gg[2],LEGEND_VALUE,true,"0",3,-80,16,"Arial",true,false); //--- 針パラメータの設定 GaugeSetNeedleParameters(gg[2],NDCS_SMALL,DEF_COL_NCENTER,DEF_COL_NEEDLE,NEEDLE_FILL_AA);
ATRインジケーターは、 (左上) フリーマージンインジケーターの隣に配置します。
//--- gg03メーターの生成 ATR if(GaugeCreate("gg03",gg[3],30,0,180,"gg00",RELATIVE_MODE_VERT, CORNER_LEFT_LOWER,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- ボディパラメータの設定 GaugeSetCaseParameters(gg[3],CASE_ROUND,DEF_COL_CASE,CASE_BORDER_THIN,DEF_COL_BORDER,SIZE_MIDDLE); //--- スケールのパラメータやマークの設定 GaugeSetScaleParameters(gg[3],270,45,0.001,0.004,MUL_00001,SCALE_INNER,clrBlack); GaugeSetMarkParameters(gg[3],MARKS_INNER,SIZE_LARGE,0.001,9,3); GaugeSetMarkLabelFont(gg[3],SIZE_LARGE,"Arial",false,false,DEF_COL_MARK_FONT); //--- highlighting ranges on the scale GaugeSetRangeParameters(gg[3],0,true,0.002,0.001,clrYellow); //--- テキストラベルの設定 GaugeSetLegendParameters(gg[3],LEGEND_DESCRIPTION,true,"ATR",7,-140,26,"Arial",false,false); //GaugeSetLegendParameters(gg[3],LEGEND_UNITS,true,"USD",8,180,5,"Arial",true,false); GaugeSetLegendParameters(gg[3],LEGEND_VALUE,true,"5",2,180,14,"Arial",true,false); GaugeSetLegendParameters(gg[3],LEGEND_MUL,true,"",2,0,20,"Arial",true,false); //--- 針パラメーターの設定 GaugeSetNeedleParameters(gg[3],NDCS_SMALL,DEF_COL_NCENTER,DEF_COL_NEEDLE,NEEDLE_FILL_AA);
RSIインジケーターはスプレッドインジケーターの上に配置します。
//--- gg04メーターの生成 RSI if(GaugeCreate("gg04",gg[4],-30,0,180,"gg02",RELATIVE_MODE_VERT, CORNER_LEFT_LOWER,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- ボディパラメーターの設定 GaugeSetCaseParameters(gg[4],CASE_ROUND,DEF_COL_CASE,CASE_BORDER_THIN,DEF_COL_BORDER,SIZE_MIDDLE); //--- スケールのパラメータやマークを設定 GaugeSetScaleParameters(gg[4],270,45,0,100,MUL_10,SCALE_INNER,clrBlack); GaugeSetMarkParameters(gg[4],MARKS_INNER,SIZE_LARGE,10,1,4); GaugeSetMarkLabelFont(gg[4],SIZE_LARGE,"Arial",false,false,DEF_COL_MARK_FONT); //--- テキストラベルの設定 GaugeSetLegendParameters(gg[4],LEGEND_DESCRIPTION,true,"RSI",7,-140,26,"Arial",false,false); GaugeSetLegendParameters(gg[4],LEGEND_VALUE,true,"2",2,180,16,"Arial",true,false); GaugeSetLegendParameters(gg[4],LEGEND_MUL,true,"",2,0,20,"Arial",true,false); //--- 針パラメーターの設定 GaugeSetNeedleParameters(gg[4],NDCS_SMALL,DEF_COL_NCENTER,DEF_COL_NEEDLE,NEEDLE_FILL_AA);
フォースインジケーターは現在損益の上に配置します。
//--- gg05 メーターの生成, Force if(GaugeCreate("gg05",gg[5],-10,60,180,"gg03",RELATIVE_MODE_HOR, CORNER_LEFT_LOWER,inp_back,inp_scale_transparency,inp_needle_transparency)==false) return(INIT_FAILED); //--- ボディパラメーターの設定 GaugeSetCaseParameters(gg[5],CASE_ROUND,DEF_COL_CASE,CASE_BORDER_THIN,DEF_COL_BORDER,SIZE_MIDDLE); //--- スケールのパラメータやマークを設定 GaugeSetScaleParameters(gg[5],270,45,-4,4,MUL_1,SCALE_INNER,clrBlack); GaugeSetMarkParameters(gg[5],MARKS_INNER,SIZE_LARGE,1,1,4); GaugeSetMarkLabelFont(gg[5],SIZE_LARGE,"Arial",false,false,DEF_COL_MARK_FONT); //--- スケールの強調 GaugeSetRangeParameters(gg[5],0,true,-1,-4,clrMediumSeaGreen); GaugeSetRangeParameters(gg[5],1,true,1,4,clrCrimson); //--- テキストラベルの設定 GaugeSetLegendParameters(gg[5],LEGEND_DESCRIPTION,true,"Force",7,-140,20,"Arial",false,false); GaugeSetLegendParameters(gg[5],LEGEND_VALUE,true,"5",2,180,14,"Arial",true,false); GaugeSetLegendParameters(gg[5],LEGEND_MUL,true,"",3,0,10,"Arial",true,false); //--- 針パラメーターの設定 GaugeSetNeedleParameters(gg[5],NDCS_SMALL,DEF_COL_NCENTER,DEF_COL_NEEDLE,NEEDLE_FILL_AA);
メーターは定期的に再描写させることができます。
//--- メーターの描写 for(int i=0; i<6;i++) { GaugeRedraw(gg[i]); GaugeNewValue(gg[i],0); }
OnCalculate()が起きたとき、現在値を再計算し、GaugeNewValue()インジケーターをコールします。
//--- 読み込みの更新 //--- スプレッド GaugeNewValue(gg[2],spread[rates_total-1]); //--- 現在損益 double profit=AccountInfoDouble(ACCOUNT_PROFIT); GaugeNewValue(gg[1],profit); //--- マージンレベル double margin_level=AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); GaugeNewValue(gg[0],margin_level); //--- ATRインジケーター calculated=BarsCalculated(handle_ATR); if(calculated>0) { double ival[1]; if(CopyBuffer(handle_ATR,0,0,1,ival)<0) Print("ATR CopyBuffer error"); else GaugeNewValue(gg[3],ival[0]); } //--- RSI calculated=BarsCalculated(handle_RSI); if(calculated>0) { double ival[1]; if(CopyBuffer(handle_RSI,0,0,1,ival)<0) Print("RSI CopyBuffer error"); else GaugeNewValue(gg[4],ival[0]); } //--- Force calculated=BarsCalculated(handle_Force); if(calculated>0) { double ival[1]; if(CopyBuffer(handle_Force,0,0,1,ival)<0) Print("Force Index CopyBuffer error"); else GaugeNewValue(gg[5],ival[0]); }
注意点として、OnChartEvent()からGaugeRelocation() を呼び出しても意味がありません。相対配置がここで使用されているが、位置または大きさが変更された場合、メーターが一斉に初期化されるように、メーターの座標を再計算する必要はありません。
8. リソース耐久評価
ニードルレイヤーは完璧に毎時、測定値の更新値を再描画します。いくつかのケースでは、非常に多く、毎秒に数回起こり得ます。針を描くリソース強度の問題は非常に深刻な問題です。様々な塗りつぶし方法を使用して針を描画するため、CPUのオーバーヘッドを評価するための小さなスクリプトを書きます。
//+------------------------------------------------------------------+ //| test_fill.mq5 | //| Copyright 2015, Decanium | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Decanium" #property version "1.00" #include <Canvas/Canvas2.mqh> CCanvas canvas; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { Print("***** start test *****"); //--- string ObjName="test"; ObjectDelete(0,ObjName); canvas.CreateBitmapLabel(ObjName,10,10,400,400,COLOR_FORMAT_ARGB_NORMALIZE); //--- int x[3]={200,185,215}; int y[3]={70, 250,250}; int cycles=1000; uint col=ColorToARGB(clrRed,255); uint c1,c2; //--- アンチエイリアシングエッジで塗りつぶすテスト canvas.Erase(); c1=GetTickCount(); for(int i=0; i<cycles; i++) { canvas.Fill(10, 10, col); canvas.LineAA2(x[0], y[0], x[1], y[1], 0); canvas.LineAA2(x[1], y[1], x[2], y[2], 0); canvas.LineAA2(x[2], y[2], x[0], y[0], 0); canvas.Fill2(10, 10, 0); } c2=GetTickCount(); canvas.Update(true); Print("Filled AA: ",c2-c1," ms, ",cycles," cycles, ", DoubleToString(double(c2-c1)/double(cycles),2)," ms per cycle"); //--- 塗りつぶしなしのアンチエイリアスのテスト canvas.Erase(); c1=GetTickCount(); for(int i=0; i<cycles; i++) { canvas.LineAA2(x[0], y[0], x[1], y[1], col); canvas.LineAA2(x[1], y[1], x[2], y[2], col); canvas.LineAA2(x[2], y[2], x[0], y[0], col); } c2=GetTickCount(); canvas.Update(true); Print("Not filled AA: ",c2-c1," ms, ",cycles," cycles, ", DoubleToString(double(c2-c1)/double(cycles),2)," ms per cycle"); //--- アンチエイリアスなしのテスト canvas.Erase(); c1=GetTickCount(); for(int i=0; i<cycles; i++) { canvas.FillTriangle(x[0],y[0],x[1],y[1],x[2],y[2],col); canvas.LineAA2(x[0], y[0], (x[1]+x[2])/2, y[1], col); } c2=GetTickCount(); canvas.Update(true); Print("Filled: ",c2-c1," ms, ",cycles," cycles, ", DoubleToString(double(c2-c1)/double(cycles),2)," ms per cycle"); } //+------------------------------------------------------------------+
このスクリプトは、サイクル間に針を1000回の描画しするメソッドを起動し、このプロセスのために費やした時間をミリ秒単位で測定します。
図16. リソース耐久テストの結果
結果からもわかるように、アンチエイリアスエッジかつ塗りつぶしの針は、アンチエイリアスなしの塗りつぶしの針よりも数百倍の量があり、塗りつぶしなしと比べて10倍の開きがあります。この場合、見た目の良さにはそれだの対価が必要になるということです。
結論
この記事では、メーターを表示させるのに必要な関数について記述しました。ライブラリ作成の主な目的は、図面と幾何の詳細を掘り下げることなく、EAやインジケータにメーターをシンプルに追加するということでした。しかし、この目的・目標に達したかどうかはあなた次第です。
リソース強度には特に注目が必要です。OnCalculate()で時間のかかる計算をすると、ターミナルが一時的に停止する瞬間が発生してしまいます。よって、針の描写には妥協案を採用することを推奨します。(塗りつぶしなしでアンチエイリアス).
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1699
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索