「DotSpacial」では、地図の回転ができなかったので、地図の回転を行った場合のメモです。
地図の回転ボタンは「DotSpatial.Plugins.ScaleBar」などのプラグインを参考にし、事前に用意しておきます。
画像の回転
1.回転角度の追加
画面から指定された回転角度を保持します。「DotSpacial」では、回転角度を保持していないので新に回転角度のプロパティを追加します。
|
1 2 3 4 5 6 7 8 9 10 |
public class MapFrame : LayerFrame, IMapFrame { private int _rotateAngle; public int RotateAngle { get { return _rotateAngle; } set { _rotateAngle = value;} } } |
2.回転した地図の描画
回転角度が設定された場合は、地図画像を回転し、描画します。
ただし、そのまま画像を回転させてしまうと、回転させた際に、画像が切れてしまうので、「DotSpacial」のバッファ領域を拡大します。
バッファ領域は、MapFrame._extendBufferをtrueに設定することで、バッファ領域が3倍に拡張されます。
バッファ領域を拡大した後、画像を回転し、回転した画像を、画面に描画します。画像の回転の注意点としては、画像の回転をそのまま実施すると、図形の左上頂点から回転が始まるので、画像を中心点に移動させてから、回転し、回転後に元の位置に戻します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class MapFrame : LayerFrame, IMapFrame { public void Draw(PaintEventArgs pe) { if (_buffer == null) { return; } Rectangle clip = pe.ClipRectangle; if (clip.IsEmpty){ clip = _parent.ClientRectangle;} Rectangle clipView = ParentToView(clip); if (clip.Width == 0 || clip.Height == 0){ return;} if (clipView.Width == 0 || clipView.Height == 0){ return;} try { var rotateImg = _buffer; if (this._rotateAngle > 0){ rotateImg = this.RotateImage(_buffer, clip, clipView); } pe.Graphics.DrawImage(rotateImg, clip, clipView, GraphicsUnit.Pixel); } catch { // There was an exception (probably because of sizing issues) so don't bother with the chunk timer. } // base.OnPaint(pe); } public Bitmap RotateImage(Image img, Rectangle clip, Rectangle clipView) { var rotateImg = new Bitmap(img.Width, img.Height); var rotateRec = new Rectangle(0, 0, img.Width, img.Height); var g = Graphics.FromImage(rotateImg); g.FillRectangle(Brushes.LightGray, rotateRec); g.TranslateTransform(img.Width / 2, img.Height / 2); g.RotateTransform(this._rotateAngle); g.TranslateTransform(-img.Width / 2, -img.Height / 2); g.DrawImage(img, rotateRec, rotateRec, GraphicsUnit.Pixel); g.Dispose(); return rotateImg; } } |
パン(地図移動)処理の対応
回転角度が設定された場合は、地図ドラッグ後の座標位置が変わってしまうので、パン(地図移動)処理の対応も行います。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
public class MapFunctionPan : MapFunction { protected override void OnMouseUp(GeoMouseArgs e) { if (e.Button == MouseButtons.Left && IsDragging) { IsDragging = false; _preventDrag = true; if (e.Map.MapFrame.RotateAngle > 0) { var dragEnd = new Point(e.X, e.Y); var rotatePoint = this.RotatePoint(dragEnd, _dragStart, e.Map.MapFrame.RotateAngle); Point diff = new Point { X = _dragStart.X - rotatePoint.X, Y = _dragStart.Y - rotatePoint.Y }; e.Map.MapFrame.View = new Rectangle(_source.X + diff.X, _source.Y + diff.Y, _source.Width, _source.Height); } e.Map.MapFrame.ResetExtents(); _preventDrag = false; Map.IsBusy = false; BusySet = false; } _dragStart = Point.Empty; base.OnMouseUp(e); } public Point RotatePoint(Point p1, Point p2, double rangle) { var angle = 0 - rangle; double radians = (Math.PI / 180) * angle; double sin = Math.Sin(radians); double cos = Math.Cos(radians); p1.X -= p2.X; p1.Y -= p2.Y; double xnew = p1.X * cos - p1.Y * sin; double ynew = p1.X * sin + p1.Y * cos; Point newPoint = new Point((int)xnew + p2.X, (int)ynew + p2.Y); return newPoint; } } |
処理イメージは以下の通り。

画面から、回転させる角度を設定します。

地図が回転します。

ラベルもそのまま回転します。
