关于GraphicsPath.Warp的理解
MSDN解释如下
Warp(PointF[], RectangleF, Matrix, WarpMode)
对此 GraphicsPath 应用由一个矩形和一个平行四边形定义的扭曲变换。
参数
- destPoints PointF[]
一个 PointF 结构的数组,该数组定义由 srcRect
定义的矩形将变换到的平行四边形。 该数组可以包含三个或四个元素。 如果该数组包含三个元素,则平行四边形的右下角位置的点可从前三个点导出。
- srcRect RectangleF
一个 RectangleF,表示将变换为 destPoints
定义的平行四边形的矩形。
- warpMode WarpMode
一个 WarpMode 枚举,它指定此扭曲操作是使用透视模式还是双线性模式。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面通过一个实例学习一下
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 using System.Drawing.Drawing2D; 8 9 namespace WarpDemo 10 { 11 class WarpDemo:Form 12 { 13 static void Main(string[] args) 14 { 15 Application.Run(new WarpDemo()); 16 } 17 public WarpDemo() 18 { 19 Text = "Warp Demo"; 20 } 21 protected override void OnPaint(PaintEventArgs e) 22 { 23 // Create a path and add a rectangle. 24 GraphicsPath myPath = new GraphicsPath(); 25 //创建以(0,0)为原点的矩形 26 RectangleF srcRect = new RectangleF(0, 0, 100, 200); 27 myPath.AddRectangle(srcRect); 28 // Draw the source path (rectangle)to the screen. 29 //绘制矩形到屏幕上 30 e.Graphics.DrawPath(Pens.Black, myPath); 31 32 // Create a destination for the warped rectangle. 33 PointF point1 = new PointF(200, 200); 34 PointF point2 = new PointF(400, 250); 35 PointF point3 = new PointF(220, 400); 36 PointF[] destPoints = { point1, point2, point3 }; 37 // Create a translation matrix. 38 Matrix translateMatrix = new Matrix(); 39 //translateMatrix.Translate(100, 0); 40 // Warp the source path (rectangle). 41 myPath.Warp(destPoints, srcRect, 42 translateMatrix, 43 WarpMode.Perspective, 0.8f 44 ); 45 // Draw the warped path (rectangle) to the screen. 46 e.Graphics.DrawPath(new Pen(Color.Red), myPath); 47 48 //测试point1 point2 point3坐标点 49 e.Graphics.DrawLine(new Pen(Color.Violet), 0, 200, 200, 200); 50 e.Graphics.DrawLine(new Pen(Color.Violet), 200, 0, 200, 200); 51 e.Graphics.DrawLine(new Pen(Color.Violet), 400, 0, 400, 250); 52 e.Graphics.DrawLine(new Pen(Color.Violet), 0, 250, 400, 250); 53 e.Graphics.DrawLine(new Pen(Color.Violet), 220, 0, 220, 400); 54 e.Graphics.DrawLine(new Pen(Color.Violet), 0, 400, 220, 400); 55 } 56 } 57 }
上述代码的效果如上图所示,一个100*200的矩形,经过变换,变为右下角红色的“菱形”;
下面,通过书籍中的解释,理解一下上述的代码
要使用Warp,需要指定4个源坐标(注:上述代码的源坐标就是RectangleF srcRect = new RectangleF(0, 0, 100, 200);)和4个目标坐标(注:
PointF point1 = new PointF(200, 200);
PointF point2 = new PointF(400, 250);
PointF point3 = new PointF(220, 400);)
Warp方法会将4个源坐标映射到4个相应的目标坐标(注:
e.Graphics.DrawLine(new Pen(Color.Violet), 0, 200, 200, 200);
e.Graphics.DrawLine(new Pen(Color.Violet), 200, 0, 200, 200);
e.Graphics.DrawLine(new Pen(Color.Violet), 400, 0, 400, 250);
e.Graphics.DrawLine(new Pen(Color.Violet), 0, 250, 400, 250);
e.Graphics.DrawLine(new Pen(Color.Violet), 220, 0, 220, 400);
e.Graphics.DrawLine(new Pen(Color.Violet), 0, 400, 220, 400);)这几行代码就是用于验证目标坐标点的;
也就是说,上述代码将矩形srcRect,映射为point1 point2 point3坐标点定位的菱形。
------------------------------------------------------------------------------------------------------------------------------------------------------------
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 using System.Drawing.Drawing2D; 8 9 namespace PathWarping 10 { 11 class PathWarping:Form 12 { 13 MenuItem miWarpMode; 14 GraphicsPath path; 15 PointF[] aptfDest = new PointF[4]; 16 17 static void Main(string[] args) 18 { 19 Application.Run(new PathWarping()); 20 } 21 public PathWarping() 22 { 23 Text = "Path Warping"; 24 25 //Create menu创建菜单 26 Menu = new MainMenu(); 27 28 Menu.MenuItems.Add("&WarpMode"); 29 30 //测试Menu.MenuItems[0]的内容是什么? 31 Console.WriteLine(Menu.MenuItems[0]); 32 33 EventHandler ehClick = new EventHandler(MenuWarpModeOnClick); 34 35 miWarpMode = new MenuItem("&" + (WarpMode)0,ehClick); 36 miWarpMode.RadioCheck = true; 37 miWarpMode.Checked = true; 38 Menu.MenuItems[0].MenuItems.Add(miWarpMode); 39 40 MenuItem mi = new MenuItem("&" + (WarpMode)1,ehClick); 41 mi.RadioCheck = true; 42 Menu.MenuItems[0].MenuItems.Add(mi); 43 44 //Create path 45 path = new GraphicsPath(); 46 47 for (int i = 0; i <= 8; i++) 48 { 49 path.StartFigure(); 50 path.AddLine(0,100 * i, 800 ,100 *i); 51 path.StartFigure(); 52 53 path.AddLine(100 * i,0,100*i,800); 54 } 55 56 //Initialize point array 57 aptfDest[0] = new PointF(50,50); 58 aptfDest[1] = new PointF(200,50); 59 aptfDest[2] = new PointF(50,200); 60 aptfDest[3] = new PointF(200,200); 61 } 62 63 void MenuWarpModeOnClick(object obj, EventArgs e) 64 { 65 miWarpMode.Checked = false; 66 miWarpMode = (MenuItem)obj; 67 miWarpMode.Checked = true; 68 69 Invalidate(); 70 } 71 72 protected override void OnMouseDown(MouseEventArgs e) 73 { 74 Point pt; 75 76 if (e.Button == MouseButtons.Left) 77 { 78 if (ModifierKeys == Keys.None) 79 { 80 pt = Point.Round(aptfDest[0]); 81 } 82 else if (ModifierKeys == Keys.Shift) 83 { 84 pt = Point.Round(aptfDest[2]); 85 } 86 else 87 return; 88 } 89 else if (e.Button == MouseButtons.Right) 90 { 91 if (ModifierKeys == Keys.None) 92 { 93 pt = Point.Round(aptfDest[1]); 94 } 95 else if (ModifierKeys == Keys.Shift) 96 { 97 pt = Point.Round(aptfDest[3]); 98 } 99 else 100 return; 101 } 102 else 103 return; 104 Cursor.Position = PointToScreen(pt); 105 } 106 107 protected override void OnMouseMove(MouseEventArgs e) 108 { 109 Point pt = new Point(e.X,e.Y); 110 111 if (e.Button == MouseButtons.Left) 112 { 113 if (ModifierKeys == Keys.None) 114 { 115 aptfDest[0] = pt; 116 } 117 else if (ModifierKeys == Keys.Shift) 118 { 119 aptfDest[2] = pt; 120 } 121 else 122 return; 123 } 124 else if (e.Button == MouseButtons.Right) 125 { 126 if (ModifierKeys == Keys.None) 127 { 128 aptfDest[1] = pt; 129 } 130 else if (ModifierKeys == Keys.Shift) 131 { 132 aptfDest[3] = pt; 133 } 134 else 135 return; 136 } 137 else 138 return; 139 140 Invalidate(); 141 } 142 143 protected override void OnPaint(PaintEventArgs e) 144 { 145 Graphics grfx = e.Graphics; 146 GraphicsPath pathWarped = (GraphicsPath)path.Clone(); 147 WarpMode wm = (WarpMode)miWarpMode.Index; 148 149 //测试path.GetBounds值是多少? 150 Console.WriteLine(path.GetBounds().ToString()); 151 //测试aptfDest数组值是多少? 152 //Console.WriteLine("aptfDest[0] is {0}",aptfDest[0]); 153 //Console.WriteLine("aptfDest[1] is {0}", aptfDest[1]); 154 //Console.WriteLine("aptfDest[2] is {0}", aptfDest[2]); 155 //Console.WriteLine("aptfDest[3] is {0}", aptfDest[3]); 156 157 pathWarped.Warp(aptfDest, path.GetBounds(), new Matrix(), wm); 158 grfx.DrawPath(new Pen(Color.Green), pathWarped); 159 160 //测试原path路径的内容是什么 161 grfx.DrawPath(new Pen(Color.Red),path); 162 } 163 } 164 }
上述代码产生的结果如下
以上代码中,个人觉得需要重点理解一下path.GetBounds()