欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑

程序员文章站 2022-05-29 09:14:36
前言 公司项目需要做个画线缩放,我司称之为瞳距缩放,简而言之就是:2张图,从第一张图画一条线,再从第二个图画一条线,第二条线以第一条为基准,延长到一致的长度,并同比缩放图片;文字太枯燥,请先实例图 例子1:以皮卡丘为例,我要把路飞的拳头缩放到皮卡丘头那么大 例子2:以皮卡丘的基准,缩小路飞,与其身高 ......

前言

公司项目需要做个画线缩放,我司称之为瞳距缩放,简而言之就是:2张图,从第一张图画一条线,再从第二个图画一条线,第二条线以第一条为基准,延长到一致的长度,并同比缩放图片;文字太枯燥,请先实例图

例子1:以皮卡丘为例,我要把路飞的拳头缩放到皮卡丘头那么大

画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑

例子2:以皮卡丘的基准,缩小路飞,与其身高一致

画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑

 

好了,相比看了上面的2个效果图,就明白了大致意思,这个demo可以获得,canvas里面的line如何顺着线条方向,无限延伸的解决方案,以及画线缩放等...

会运用到高中数学知识,三角函数知识点,所以不熟悉的朋友,需要先温习,这样吧,我带大家温习下,反正工作忙完了,写博客和网友分享经验是最愉悦的事儿...

 

三角函数必要知识点温习

画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑

tan:对边 / 临边      tana = bc / ac

sin:对边 / 斜边    sina = bc / ab

cos:临边 / 斜边     cosa = ac / ab

已知边 bc 、ac,求角a的度数    ∠a = math.atan(bc / ac);   这是最关键的,获取a的角度就解决了所有,起初我还是想了很久的,年龄一大,以前的事就记不得了,划重点这里

好了,三角函数的知识温习到这里就足矣了,想象一下,把这个三角形放到程序的坐标系中,细细品,假如用户随意画的线就是ab,在画好的基础上进行延长.......细细品....

 

画线缩放,难点就是,如何让第二条线延长

请看图

画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑

已知了a点b点的坐标,通过坐标系,就能换算出bc边和ac的长度

运用三角函数,∠a的度数就等于:math.atan(bc / ac);

拿到的∠a,一切都变得好说了

比如,ab=100

sina = bc / ab      ----->         sina = bc / 100     ---->   bc = sina * 100

bc = 100 * math.sin(∠a)

cosa = ac / ab  ---->   cosa = ac / 100  ---->  ac = cosa * 100

ac = 100 * math.cos(∠a)

bc、ac边都拿到,相信朋友们能转换成point了

 

好了,上面都是知识点,很枯燥,程序员还是看代码吧,总归是要代码实现的

 1 <window x:class="pupildistancedemo.mainwindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:pupildistancedemo"
 7         mc:ignorable="d"
 8         windowstartuplocation="centerscreen"
 9         title="瞳距缩放" height="450" width="800">
10     <grid>
11         <canvas background="#0d1728" x:name="canvas">
12             <image source="2.jpg" x:name="img1" stretch="fill" width="300"  canvas.top="100" canvas.left="50" />
13             <image source="1.jpg" x:name="img2" stretch="fill" width="200" canvas.top="100" canvas.left="400" />
14         </canvas>
15         <stackpanel orientation="horizontal">
16             <button margin="5" verticalalignment="top" click="button_click">启动瞳距</button>
17             <button margin="5" verticalalignment="top" click="button_click_1">关闭瞳距</button>
18             <button margin="5" verticalalignment="top" click="button_click_2">瞳距计算</button>
19             <button margin="5" verticalalignment="top" click="button_click_3">重置</button>
20             <stackpanel verticalalignment="top">
21                 <textblock text="{binding elementname=img2,path=actualwidth}" foreground="red" />
22                 <textblock text="{binding elementname=img2,path=actualheight}" foreground="red" />
23             </stackpanel>
24         </stackpanel>
25     </grid>
26 </window>
  1 using system;
  2 using system.collections.generic;
  3 using system.linq;
  4 using system.text;
  5 using system.threading.tasks;
  6 using system.windows;
  7 using system.windows.controls;
  8 using system.windows.data;
  9 using system.windows.documents;
 10 using system.windows.input;
 11 using system.windows.media;
 12 using system.windows.media.imaging;
 13 using system.windows.navigation;
 14 using system.windows.shapes;
 15 
 16 namespace pupildistancedemo
 17 {
 18     /// <summary>
 19     /// mainwindow.xaml 的交互逻辑
 20     /// </summary>
 21     public partial class mainwindow : window
 22     {
 23         bool isleftbuttondown = false;
 24         image image;
 25 
 26         bool ispupildistance = false;
 27         size size;
 28 
 29         point currentpoint;
 30 
 31         public mainwindow()
 32         {
 33             initializecomponent();
 34 
 35             img1.mouseleftbuttondown += img_mouseleftbuttondown;
 36             img1.mousemove += img_mousemove;
 37             img1.mouseleftbuttonup += img_mouseleftbuttonup;
 38 
 39             img2.mouseleftbuttondown += img_mouseleftbuttondown;
 40             img2.mousemove += img_mousemove;
 41             img2.mouseleftbuttonup += img_mouseleftbuttonup;
 42 
 43             this.loaded += mainwindow_loaded;
 44         }
 45 
 46         private void mainwindow_loaded(object sender, routedeventargs e)
 47         {
 48             size = new size(img2.actualwidth, img2.actualheight);
 49         }
 50 
 51         private void img_mouseleftbuttonup(object sender, mousebuttoneventargs e)
 52         {
 53             isleftbuttondown = false;
 54             image = null;
 55         }
 56 
 57         private void img_mousemove(object sender, mouseeventargs e)
 58         {
 59             if (isleftbuttondown && sender is image imgc)
 60             {
 61                 var point = e.getposition(canvas);
 62                 if (ispupildistance && imgc.tag is line line)
 63                 {
 64                     if (image.equals(imgc))
 65                     {
 66                         var x = point.x;
 67                         var y = point.y;
 68                         if (x > line.x1) x -= 2;
 69                         else x += 2;
 70                         if (y > line.y1) y -= 2;
 71                         else y += 2;
 72                         line.x2 = x;
 73                         line.y2 = y;
 74                     }
 75                 }
 76                 else if (sender is image image)
 77                 {
 78                     image.setvalue(canvas.leftproperty, point.x - currentpoint.x);
 79                     image.setvalue(canvas.topproperty, point.y - currentpoint.y);
 80                 }
 81             }
 82         }
 83 
 84         private void img_mouseleftbuttondown(object sender, mousebuttoneventargs e)
 85         {
 86             image = sender as image;
 87             isleftbuttondown = true;
 88             if (sender is image imgc)
 89             {
 90                 currentpoint = e.getposition(imgc);
 91 
 92                 if (ispupildistance)
 93                 {
 94                     if (imgc.tag is line line)
 95                     {
 96                         canvas.children.remove(line);
 97                     }
 98 
 99                     line = new line();
100                     line.strokethickness = 2;
101                     line.stroke = new solidcolorbrush(colors.red);
102                     var point = e.getposition(canvas);
103                     line.x1 = point.x - 1;
104                     line.y1 = point.y - 1;
105                     line.x2 = line.x1;
106                     line.y2 = line.y1;
107                     canvas.children.add(line);
108                     imgc.tag = line;
109                 }
110             }
111         }
112 
113         private void button_click(object sender, routedeventargs e)
114         {
115             ispupildistance = true;
116         }
117 
118         private void button_click_1(object sender, routedeventargs e)
119         {
120             ispupildistance = false;
121         }
122 
123         /// <summary>
124         /// 计算瞳距
125         /// </summary>
126         /// <param name="sender"></param>
127         /// <param name="e"></param>
128         private void button_click_2(object sender, routedeventargs e)
129         {
130             var l1 = img1.tag as line;
131             var l2 = img2.tag as line;
132 
133             if (l1 == null || l2 == null)
134             {
135                 messagebox.show("请先 启用瞳距 ,再在图片上画线");
136                 return;
137             }
138 
139             //获取第一个图片的线
140             var length1 = distance(new point(l1.x1, l1.y1), new point(l1.x2, l1.y2));
141 
142             //获取第二个图片的线
143             var length2 = distance(new point(l2.x1, l2.y1), new point(l2.x2, l2.y2));
144 
145             //利用三角函数计算出以第一个图的线为基准,延长第二个图的线
146             var ac = math.abs(l2.x2 - l2.x1);
147             var bc = math.abs(l2.y2 - l2.y1);
148 
149             var jiaodu = math.atan(bc / ac);
150             var sinval = math.sin(jiaodu);
151             var cosval = math.cos(jiaodu);
152             var ac = cosval * length1;
153             var bc = sinval * length1;
154 
155             double xnew = 0, ynew = 0;
156             if (l2.x2 > l2.x1) xnew = ac + l2.x1;
157             else xnew = l2.x1 - ac;
158 
159             if (l2.y2 > l2.y1) ynew = l2.y1 + bc;
160             else ynew = l2.y1 - bc;
161 
162             l2.x2 = xnew;
163             l2.y2 = ynew;
164 
165             var wnew = length1 / (length2 / img2.actualwidth);
166             var hnew = length1 / (length2 / img2.actualheight);
167 
168             //以用户画的起点作为缩放中心
169             var x = (double)img2.getvalue(canvas.leftproperty);
170             var y = (double)img2.getvalue(canvas.topproperty);
171 
172             //起始点相对于图片的位置
173             var l2xtoimg = l2.x1 - x;
174             var l2ytoimg = l2.y1 - y;
175 
176             //获取起始点相对于图片的新位置,缩放后
177             var l2xtoimgnew = l2xtoimg / img2.actualwidth * wnew;
178             var l2ytoimgnew = l2ytoimg / img2.actualheight * hnew;
179 
180             img2.setvalue(canvas.leftproperty, l2.x1 - l2xtoimgnew);
181             img2.setvalue(canvas.topproperty, l2.y1 - l2ytoimgnew);
182 
183             //缩放
184             img2.width = wnew;
185             img2.height = hnew;
186         }
187 
188         /// <summary>
189         /// 计算点位之间的距离
190         /// </summary>
191         /// <param name="p1"></param>
192         /// <param name="p2"></param>
193         /// <returns></returns>
194         private double distance(point p1, point p2)
195         {
196             double result = 0;
197             result = math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
198             return result;
199         }
200 
201         /// <summary>
202         /// 重置
203         /// </summary>
204         /// <param name="sender"></param>
205         /// <param name="e"></param>
206         private void button_click_3(object sender, routedeventargs e)
207         {
208             list<line> l = new list<line>();
209             foreach (var item in canvas.children)
210             {
211                 if (item is line line)
212                 {
213                     l.add(line);
214                 }
215             }
216 
217             l.foreach(c => canvas.children.remove(c));
218 
219             img2.width = size.width;
220             img2.height = size.height;
221 
222             img2.setvalue(canvas.leftproperty, 380.0);
223             img2.setvalue(canvas.topproperty, 100.0);
224         }
225     }
226 }

 

看到这里,可以先揉揉眼睛,放松下...

全部代码已经贴上,下面是下载链接,有需要的朋友可以移步下载,欢迎点评,谢谢~