前言

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

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

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

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

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

三角函数必要知识点温习

tan:对边 / 临边      tanA = BC / AC

sin:对边 / 斜边    sinA = BC / AB

cos:临边 / 斜边     cosA = AC / AB

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

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

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

请看图

已知了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了

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

 <Window x:Class="PupilDistanceDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PupilDistanceDemo"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="瞳距缩放" Height="" Width="">
<Grid>
<Canvas Background="#0D1728" x:Name="canvas">
<Image Source="2.jpg" x:Name="img1" Stretch="Fill" Width="" Canvas.Top="" Canvas.Left="" />
<Image Source="1.jpg" x:Name="img2" Stretch="Fill" Width="" Canvas.Top="" Canvas.Left="" />
</Canvas>
<StackPanel Orientation="Horizontal">
<Button Margin="" VerticalAlignment="Top" Click="Button_Click">启动瞳距</Button>
<Button Margin="" VerticalAlignment="Top" Click="Button_Click_1">关闭瞳距</Button>
<Button Margin="" VerticalAlignment="Top" Click="Button_Click_2">瞳距计算</Button>
<Button Margin="" VerticalAlignment="Top" Click="Button_Click_3">重置</Button>
<StackPanel VerticalAlignment="Top">
<TextBlock Text="{Binding ElementName=img2,Path=ActualWidth}" Foreground="Red" />
<TextBlock Text="{Binding ElementName=img2,Path=ActualHeight}" Foreground="Red" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace PupilDistanceDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
bool isLeftButtonDown = false;
Image image; bool isPupilDistance = false;
Size size; Point currentPoint; public MainWindow()
{
InitializeComponent(); img1.MouseLeftButtonDown += Img_MouseLeftButtonDown;
img1.MouseMove += Img_MouseMove;
img1.MouseLeftButtonUp += Img_MouseLeftButtonUp; img2.MouseLeftButtonDown += Img_MouseLeftButtonDown;
img2.MouseMove += Img_MouseMove;
img2.MouseLeftButtonUp += Img_MouseLeftButtonUp; this.Loaded += MainWindow_Loaded;
} private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
size = new Size(img2.ActualWidth, img2.ActualHeight);
} private void Img_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isLeftButtonDown = false;
image = null;
} private void Img_MouseMove(object sender, MouseEventArgs e)
{
if (isLeftButtonDown && sender is Image imgc)
{
var point = e.GetPosition(canvas);
if (isPupilDistance && imgc.Tag is Line line)
{
if (image.Equals(imgc))
{
var x = point.X;
var y = point.Y;
if (x > line.X1) x -= ;
else x += ;
if (y > line.Y1) y -= ;
else y += ;
line.X2 = x;
line.Y2 = y;
}
}
else if (sender is Image image)
{
image.SetValue(Canvas.LeftProperty, point.X - currentPoint.X);
image.SetValue(Canvas.TopProperty, point.Y - currentPoint.Y);
}
}
} private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
image = sender as Image;
isLeftButtonDown = true;
if (sender is Image imgc)
{
currentPoint = e.GetPosition(imgc); if (isPupilDistance)
{
if (imgc.Tag is Line line)
{
canvas.Children.Remove(line);
} line = new Line();
line.StrokeThickness = ;
line.Stroke = new SolidColorBrush(Colors.Red);
var point = e.GetPosition(canvas);
line.X1 = point.X - ;
line.Y1 = point.Y - ;
line.X2 = line.X1;
line.Y2 = line.Y1;
canvas.Children.Add(line);
imgc.Tag = line;
}
}
} private void Button_Click(object sender, RoutedEventArgs e)
{
isPupilDistance = true;
} private void Button_Click_1(object sender, RoutedEventArgs e)
{
isPupilDistance = false;
} /// <summary>
/// 计算瞳距
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_2(object sender, RoutedEventArgs e)
{
var l1 = img1.Tag as Line;
var l2 = img2.Tag as Line; if (l1 == null || l2 == null)
{
MessageBox.Show("请先 启用瞳距 ,再在图片上画线");
return;
} //获取第一个图片的线
var length1 = Distance(new Point(l1.X1, l1.Y1), new Point(l1.X2, l1.Y2)); //获取第二个图片的线
var length2 = Distance(new Point(l2.X1, l2.Y1), new Point(l2.X2, l2.Y2)); //利用三角函数计算出以第一个图的线为基准,延长第二个图的线
var AC = Math.Abs(l2.X2 - l2.X1);
var BC = Math.Abs(l2.Y2 - l2.Y1); var jiaodu = Math.Atan(BC / AC);
var sinVal = Math.Sin(jiaodu);
var cosVal = Math.Cos(jiaodu);
var ac = cosVal * length1;
var bc = sinVal * length1; double xnew = , ynew = ;
if (l2.X2 > l2.X1) xnew = ac + l2.X1;
else xnew = l2.X1 - ac; if (l2.Y2 > l2.Y1) ynew = l2.Y1 + bc;
else ynew = l2.Y1 - bc; l2.X2 = xnew;
l2.Y2 = ynew; var wnew = length1 / (length2 / img2.ActualWidth);
var hnew = length1 / (length2 / img2.ActualHeight); //以用户画的起点作为缩放中心
var x = (double)img2.GetValue(Canvas.LeftProperty);
var y = (double)img2.GetValue(Canvas.TopProperty); //起始点相对于图片的位置
var l2xToimg = l2.X1 - x;
var l2yToimg = l2.Y1 - y; //获取起始点相对于图片的新位置,缩放后
var l2xToimgnew = l2xToimg / img2.ActualWidth * wnew;
var l2yToimgnew = l2yToimg / img2.ActualHeight * hnew; img2.SetValue(Canvas.LeftProperty, l2.X1 - l2xToimgnew);
img2.SetValue(Canvas.TopProperty, l2.Y1 - l2yToimgnew); //缩放
img2.Width = wnew;
img2.Height = hnew;
} /// <summary>
/// 计算点位之间的距离
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
private double Distance(Point p1, Point p2)
{
double result = ;
result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
return result;
} /// <summary>
/// 重置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_3(object sender, RoutedEventArgs e)
{
List<Line> l = new List<Line>();
foreach (var item in canvas.Children)
{
if (item is Line line)
{
l.Add(line);
}
} l.ForEach(c => canvas.Children.Remove(c)); img2.Width = size.Width;
img2.Height = size.Height; img2.SetValue(Canvas.LeftProperty, 380.0);
img2.SetValue(Canvas.TopProperty, 100.0);
}
}
}

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

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

点击下载,资源下载

画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑的更多相关文章

  1. Unity5中的粒子缩放(附测试源码)

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/49363241 作者:car ...

  2. iOS小画板画线总结

    一:基本画线: 使用贝赛尔曲线画: //创建路径 UIBezierPath* aPath = [UIBezierPath bezierPath]; //设置线宽 aPath.lineWidth = 5 ...

  3. 用DirectX实现魔方(三)视角变换及缩放(附源码)

    在本系列第一篇介绍过鼠标按键的功能,如下. 左键拖拽 - 旋转魔方 右键拖拽 - 变换视角 滚轮 - 缩放魔方 今天研究一下如何实现后面两个功能,用到的技术主要是Arcball,Arcball是实现M ...

  4. [修复] Firemonkey 画线问题(Android & iOS 平台)

    问题:官方 QC 的一个 Firemonkey 移动平台画线问题: RSP-14309: [iOS & Android] Delphi 10.1 Berlin - drawing proble ...

  5. WPF画线问题,几千条以后就有明显的延迟了。

      我现在是这么画的,class A { private GeometryGroup _lines; private Path _path; public A() {    _path.Data = ...

  6. [stm32] 利用uc-gui封装画图和画线函数移植51上的模拟动画

    >_<:这里的动画是黄色矩形区域中一个模仿俯视图的起重机运作动画,一个是模仿主视图的吊钩的运动.通过改变初始Init函数中的数据b_x,b_y实现矩形区域的移动.当实时采集时要首先根据起重 ...

  7. win32画线考虑去锯齿

    整理日: 2015年2月16日 这几天一直在研究win32 SDk下画线去锯齿,之前一直用的QT的画线接口函数,里面有去锯齿的效果,可是突然项目要求不能用QT的只能用win32 SDK下的GDI画线接 ...

  8. Unity3D 画线插件 Vectrosity_Simple2DLine

    Vectrosity是一个很方便的画线插件,用它我们可以画出2D,3D,贝塞尔,圆,椭圆等各种线条图案. :链接: http://pan.baidu.com/s/1pJjTFjt 密码: uesn 首 ...

  9. Openlayer 3 的画线测量长度

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. k8s 获取 Pod ip 添加到环境变量

    0x00 事件 有一个需要将 Pod 自身的 ip 地址添加到环境变量的需求,可以在 yaml 文件的 env 中这样设置: env: - name: POD_OWN_IP_ADDRESS value ...

  2. Java基础面试题及答案(二)

    容器 18. java 容器都有哪些? 常用容器的图录: 19. Collection 和 Collections 有什么区别? java.util.Collection 是一个集合接口(集合类的一个 ...

  3. #在windows上使用ngix重定向目录访问远程服务器文件详细实例

    为了在开发环境保持于生产环境相同的访问远程服务器文件资源的目录配置,需要在开发环境(windows)在远程文件服务器使用nignx重定向文件目录,因为网上的资料大都是copy的,解释比较笼统,也没有具 ...

  4. 小白的springboot之路(六)、跨域解决方案CORS

    0-前言 前后端分离.分布式集群,经常都会涉及到跨域访问,而浏览器基于同源策略,正常情况下是不能跨域的,这就需要我们解决跨域访问问题:spring boot解决跨域也比较简单: 1-CORS跨域解决方 ...

  5. tp5实现支付宝电脑支付(详解)

    首先吐槽一下支付宝的官方文档,它只是简单介绍一下开发的流程和参数,而对于新人来说如果只看它的官方文档很多时候是看不懂的,我也是边看文档边网上查资料才把它弄懂.下面我详细介绍支付宝的电脑支付是如何实现 ...

  6. 思科CISCO ASA 5521 防火墙 Ipsec 配置详解

    版本信息: Cisco Adaptive Security Appliance Software Version 9.9(2) Firepower Extensible Operating Syste ...

  7. Redux和Context对比

    Redux和Context对比 如果项目体量较小,只是需要一个公共的store存储state,而不讲究使用action来管理state,那context完全可以胜任.反之,则是redux的优点. co ...

  8. 初步认知jQuery

    jQuery:是JavaScript的一个类库全写JavaScript query   write less do more JavaScript查询写的更少做的更多 第一步先导入js文件: < ...

  9. hdu4585Shaolin

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4585 题意: 第一个人ID为1,战斗力为1e9. 给定n,给出n个人的ID和战斗力. 每个人必须和战斗 ...

  10. cf1119d Frets On Fire 前缀和+二分

    题目:http://codeforces.com/problemset/problem/1119/D 题意:给一个数n,给出n个数组的第一个数(a[0]=m,a[1]=m+1,a[2]=m+2,... ...