前回からの続きで、今回ので満足できるところまでできた
変形後の要素の4頂点をグリッド頂点にスナップ
変形(20度回転)後の要素の四隅の頂点を順番にを100,100の位置にスナップ移動させている
できたなあ
一年前に失敗したのと同じ考え方なんだけど、書き方を変えてみたら期待どおりの動きにできた
今回の動画もマウスの調子が良くないから何回も撮り直した
今回のアプリのダウンロード先
一年前と同じ考え方
この左上頂点の場合はBが一番近い、これを左上頂点の目標グリッドとして
これを各4頂点調べるから
4*4=16通りの中で一番近いところへ移動させる
各4頂点の目標グリッドなどの情報を入れておくStructure(構造体)を
Public Structure MyTargetGridPointData
Dim TargetGridPoint As Point
Dim Distance As Double
Dim IsValid As Boolean
Dim DiffPoint As Point
End Structure
こんなふうに作っておいて
あとは
Private Function GetNearGridPointDistance(xy As Double, gridSize As Integer) As Double
Dim m As Double = xy Mod gridSize
If m > gridSize / 2 Then
Return xy + gridSize - m
Else
Return xy - m
End If
End Function
Private Function GetNearestGridPoint(dp As Point, gridSize As Integer) As Point
Dim x As Double = GetNearGridPointDistance(dp.X, gridSize)
Dim y As Double = GetNearGridPointDistance(dp.Y, gridSize)
Return New Point(x, y)
End Function
Private Function GetDistance(p1 As Point, p2 As Point) As Double
Dim x As Double = p1.X - p2.X
Dim y As Double = p1.Y - p2.Y
Dim rd As Double = Math.Sqrt(x ^ 2 + y ^ 2)
Return rd
End Function
Private Function GetPointData(gridSize As Integer, transformedPoint As Point, mMove As Point) As MyTargetGridPointData
Dim tPoint As New MyTargetGridPointData
With tPoint
.TargetGridPoint = GetNearestGridPoint(transformedPoint + mMove, gridSize)
.Distance = GetDistance(transformedPoint + mMove, .TargetGridPoint)
.IsValid = True
.DiffPoint = transformedPoint - .TargetGridPoint
End With
Return tPoint
End Function
Private Function GetMyTargetGrid4Point2(gridSize As Integer, mMove As Point,
TopLeftXY As Point, TopRightXY As Point, BottomRightXY As Point, BottomLeftXY As Point) As MyTargetGridPointData
Dim TLData As MyTargetGridPointData = GetPointData(gridSize, TopLeftXY, mMove)
Dim TRData As MyTargetGridPointData = GetPointData(gridSize, TopRightXY, mMove)
Dim BRData As MyTargetGridPointData = GetPointData(gridSize, BottomRightXY, mMove)
Dim BLData As MyTargetGridPointData = GetPointData(gridSize, BottomLeftXY, mMove)
Dim dataList As New List(Of MyTargetGridPointData) From {TLData, TRData, BRData, BLData}
Dim sl As New SortedList(Of Double, MyTargetGridPointData)
For i As Integer = 0 To 3
Try
sl.Add(dataList(i).Distance, dataList(i))
Catch ex As Exception
End Try
Next
Return sl.Values(0)
End Function
これをDragDeltaイベントのところで
Dim GridSize As Integer = sldGrid.Value'グリッドサイズ
Dim hChange As Double = e.HorizontalChange'マウス横移動距離
Dim vChange As Double = e.VerticalChange'マウス縦移動距離
Dim pData As MyTargetGridPointData = GetMyTargetGrid4Point2(GridSize, New Point(hChange, vChange), MyExThumb.MyTransformedTopLeft, MyExThumb.MyTransformedTopRight, MyExThumb.MyTransformedBottomRight, MyExThumb.MyTransformedBottomLeft)
If pData.IsValid Then
If pData.DiffPoint.X <> 0 Then MyExThumb.MyLeft -= pData.DiffPoint.X
If pData.DiffPoint.Y <> 0 Then MyExThumb.MyTop -= pData.DiffPoint.Y
End If
MyExThumbはThumbを継承して作ったクラスで
MyExThumb.MyLeftプロパティは値変更のところで
Canvas.SetLeftを実行している
こんなふうに書いたらうまく行ったけど、なんかよくわかっていないんだよねえ、暑くて考えることができない
SortedListにデータ追加するところを書き換えた
一番近い距離のものを取得するのにSortedListクラスを使うのも一年前と同じなんだけど、少し書き直した
SortedListはkeyと
Valueを対でデータを追加していく、そうするとkeyの値の順番で自動で並び替えて登録される、なのでkeyに距離を指定すれば距離順に並ぶので簡単に一番近いものが取得できる
けど、同じ値のkeyは登録しようとしてもできない(エラーになる)ので、もし別の場所で同じ距離の頂点データが出たときには、その頂点は無視して次のデータへ行くようにする処理にしたのが赤背景のところ62~78行目
おまけで
変形後の要素の4辺or4頂点をグリッドスナップ
っていうのもできた
変形後の要素がぴったり収まる枠(青枠)の上辺と左辺がグリッドスナップしている状態
ここから下に移動させると
左下頂点がグリッド頂点にスナップ!
ここから下に移動させると
右上頂点がグリッドラインにスナップ
次は
青枠下辺がグリッドラインにスナップ
こんなふうに頂点や枠を近くのグリッドラインや頂点にスナップする
動きが細かすぎて使うかどうかはわからないけどこういうのもできた
この処理は前回の記事のコードの延長みたいなもので難しくないはずなんだけど今見たらよくわかんないや
暑いと頭動かない
只今(午後9時43分)の室温33.3、湿度54
でも昨日、一昨日に比べたら少しマシだなあ
前回の記事
2016/05/14
一年前の記事、このときはいまいちな結果だった