关于GraphicsPath.Warp的理解

MSDN解释如下

Warp(PointF[], RectangleF, Matrix, WarpMode)

对此 GraphicsPath 应用由一个矩形和一个平行四边形定义的扭曲变换。

参数

destPoints    PointF[]

一个 PointF 结构的数组,该数组定义由 srcRect 定义的矩形将变换到的平行四边形。 该数组可以包含三个或四个元素。 如果该数组包含三个元素,则平行四边形的右下角位置的点可从前三个点导出。

srcRect      RectangleF

一个 RectangleF,表示将变换为 destPoints 定义的平行四边形的矩形。

matrix         Matrix

指定将应用于路径的几何变换的 Matrix

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()

 

 

posted @ 2022-11-15 10:00  chenlight  阅读(213)  评论(0)    收藏  举报