BITMAPを切り取ってPictureBoxへ高速表示する基礎を学んだので、応用編として、動的にきりとってダイナミックな動きをもったRTKグラフを作ってみました。一瞬の動作ですが、実はこの動きを実現するために3STEPにわたる前処理で計算された制御パラメータが黒子として働いております。
RTKデータ解析用グラフィック機能開発ーその1ー<自動追尾機能便利>
RTKデータ解析用グラフィック機能開発ーその2ー<ソースBITMAP表示基礎>
RTKデータ解析用グラフィック機能開発ーその3ー<自動追尾機能の中身>
RTKデータ解析用グラフィック機能開発ーその4ー<ターンの解析手法>
RTKデータ解析用グラフィック機能開発ーその5ー<8か月の集大成>
※2021年7月12日スキーの曲げセンサ開発開始しました。
【ロードセル】銅板でロードセル作ってみたその1<曲げ測定用>
●自動追尾機能に必要な前処理STEP1,2,3の備忘録
STEP1:ターン弧の検出
スキー滑走は複数のターンのつなぎ合わせです。1個ずつ検出して、最終的にターン構造体でターンに関わる全パラメータを作成します。
ターンの検出方法はこちらの記事に詳細あります。
ターンの切り替え点(NutralPoint)を速度ベクトル角の微分の正負変化点で検出してます。プログラムではSub Nutral()で計算してます。
STEP2:ターン座標を回転させてフォールラインで正規化する
これが重要な処理で、BitMapのX座標に対して、ターンのデータが1:1で照合できるようにターンデータ範囲の最初のNutralPointと最後のNutralPointを結んだ直線(フォールラインFallLine)をX軸とするように座標を回転させてXY座標変換します。回転してBITMAPにプロットされたターングラフをターン単位の区切りとして大きな点を打ってターンを見えるようにする処理のためにSub Nutral()内で
NutralR(RTKデータ番号)NutarlL(RTKデータ番号)という左右の配列を用意しました。値は、Nutralポイントでない時はゼロ、左ターンの開始点はー1、右ターンの開始点は1と定義しておきます。
下図はフォールラインで水平に回転して座標変換されています。
STEP3:BITMAP座標とRTKデータの照合配列を持つ
BITMAPにしてしまうとRTKのデータとプロット点の関係が判らなくなって
しまうので、ソースBITMAPを作成する時点で、BITMAP値とRTKデータの関係を照合できるいくつかの配列を作成して保持しました。
1:ビットマップ座標と実データの関係を配列でもつ
RX(Nutralポイント番号)=ソースBITMAPのX座標
を保持して、スライダーがうごかされたら、スライド値のX値がどのNutralポイント番号の
範囲に含まれるか検索して、そのスライダ位置でのターン番号を得る処理をしている
下記の直線回帰の場合は、ズレが大きくなる欠点があってやめました。
1:回転座標とRTKデータ番号の直線回帰
Sub bitXlinear()で回帰計算してます。
上図でX軸とグラフが1:1になっているので、RTKデータとX座標の直線回帰を して傾きを求めて、X軸座標からRTKデータ番号を算出関数を生成
下図のように線形相関係数は0.9964とほぼ線形を保っている。
RTKデータ番号=A*RX座標+B という式になる
座標名:X(Long経度)Y(Lat緯度)
RX(回転したLong経度)RY(回転したLat緯度)
2:RY座標値の補間
Sub FyHokan()で補間計算してます。
Bitmap座標は、RTKデータ値より細かい座標なのでBitamapの
X値に対してRTKデータ(RY)が粗い変化をしてしまうので、
RYを補間して、滑らかに変化するような補間計算をしてます。
Fy(bitmapのX座標)=RY補間値
●追尾処理部
Sub Bmp1_FixTrim(byVal SlideVal as Integer,byVal rNlin as Integer)
で追尾グラフ描画してます。
プログラムで使っているパラメータの意味は、解説図をご覧ください。
動作は水平スクロールバーの値変化で駆動します。SlideVal値がX座標値でその値からプロットデータのY座標Fy(x)を取得してグラフの切り取り枠の原点を上下変更します。
GISTにSUB部分だけ掲載してあります。
https://gist.github.com/dj1711572002/4e454e0d6f0c1af46d3de7dd3ad88079
‘**************************************************************************************************************** ‘先端データを読んで切り取りXY座標を制御しながら先端固定モードで描画 ‘**************************************************************************************************************** Private Sub Bmp1_FixTrim(ByVal SlideVal As Integer, ByVal rNlin As Integer) ‘———————————————————————————————— ‘—–HscrollBar値で切り取り前進動画————————————————————- ‘———————————————————————————————— Dim BP1 As New Pen(Color.Red, 1) Dim BP2 As New Pen(Color.LawnGreen, 1) Dim BP3 As New Pen(Color.Black) Dim scrollN As Integer = Math.Truncate(SlideVal / PictureBox1.Width) Dim cWidth As Integer = SlideVal Mod PictureBox1.Width Dim sY As Integer Dim dY As Integer = 0 ‘desRectのオフセットY位置 Dim rN As Integer = rNlin – Val(TextBox4.Text) ’—-Y座標から枠の上下位置を算出する—— If Fy(SlideVal) > 300 Then ‘sY = RY(rN) – 300 sY = CInt(Fy(SlideVal)) – 300 dY = 0 Else sY = 0 ‘ dY = (300 – RY(rN)) dY = 300 – CInt(Fy(SlideVal)) End If ‘———————————————- currentX = CInt(PictureBox1.Width * scrollN) currentY = sY ‘============Rectangleの定義部===================================== Dim srcRect As New Rectangle(PictureBox1.Width * scrollN, sY, cWidth, 600) ‘切り取り部分定義 Dim desRect As New Rectangle(0, dY, srcRect.Width, srcRect.Height) ‘============================================================= ’差し込み用Bitamap bmap2を作成 bmap2 = New Bitmap(PictureBox1.Width, PictureBox1.Height) ‘Graphics g2で描画した結果はbmap2へ書き込まれる宣言 g2 = Graphics.FromImage(bmap2) ‘bmap1から指定サイズで切り取ってg2:bmap2へ書き込む g2.DrawImage(bmap1, desRect, srcRect, GraphicsUnit.Pixel) g2.Dispose() ’書き込み完了したのでg2は不要’Y軸を180度回転させて上下反転して上を北に変更 ‘======PictureBox1へ差し込み実行============ End Sub |
●以後
備忘録をしっかりしてあるので、これをベースにいろいろな応用を考えていきます。
動くもののIOTを表現する方法として、身につけられたほうが良いと存じます。