目录

图形自由变换

图形的存储方式

鼠标交互

图形拓扑算法

总结


常见的二维几何图形包括点、线、面三种类型,而某些的地图标准规范中还区分多点、多线、多面、环等。本文,主要讲述简单的几何图形的自由变换(平移、缩放、旋转)的核心思路。至于复杂的几何图形则可以通过简单的几何图形组装变换得到。后面的文章会讲述如何拖拽增加修改顶点和编写辅助线的核心思路。

图形自由变换

图形自由变换是指可以通过自由旋转、比例、倾斜、扭曲、透视和变形来变换对象。例如在photoshop和illustrator中的自由变换功能。

             

图形的存储方式

在计算机中几何图形的点的存储方式以x,y坐标的形式存储,坐标系统可以是屏幕的像素坐标系统,可以是地理坐标系统,也可以是自定义的单位的坐标系统。但存储方式必须能够表示二维两个方向的值。例如:point: Array<2>或者point:Object<x, y>

而比点图形稍微复杂的线图形和面图形,则是以点为单位存储的集合图形,line: Array<point> 和 polygon: Array<point>

     

鼠标交互

自由变换涉及的鼠标交互比较简单,大致为如下:

  1. 鼠标点击图形,标记开始;
  2. 鼠标拖拽,记录偏移量
  3. 鼠标松开,标记结束

我们知道,鼠标的每一个动作,都能记录当前的鼠标在屏幕上的一个状态,包括屏幕像素坐标和鼠标操作事件。在鼠标与图形的交互中,所使用的东西,莫非是 鼠标的左右键点击和松开,以及一个 delta值

delta = f(deltaX, deltaY)。可以理解为delta是与屏幕的横轴X和纵轴Y的差值有F的关联关系。

图形拓扑算法

  • 图形的平移

图形的平移比较简单,就是给每一个点加上delta。公式如下: 新的坐标 += delta

const newCoordinate = event.coordinate;
const deltaX = newCoordinate[0] - this.lastCoordinate_[0];
const deltaY = newCoordinate[1] - this.lastCoordinate_[1];const graphics = this.graphics_ // 图形对象graphics.forEach(function(graphic) {const geom = graphic.getGeometry(); // 图形的坐标数据const coordinates = geom.getCoordinates()translate(coordinates , 0, coordinates.length, 2, deltaX, deltaY, coordinates);graphic.setGeometry(geom);}); function translate(coordinates, offset, end, stride, deltaX, deltaY, opt_dest) {const dest = opt_dest ? opt_dest : [];let i = 0;for (let j = offset; j < end; j += stride) {dest[i++] = coordinates[j] + deltaX;dest[i++] = coordinates[j + 1] + deltaY;for (let k = j + 2; k < j + stride; ++k) {dest[i++] = coordinates[k];}}if (opt_dest && dest.length != i) {dest.length = i;}return dest;
}
  • 图形的缩放

图形的缩放比图形的平移稍微复杂一点点,需要先定义如下两个参数:

1. 根据鼠标交互得到delta,定义缩放的比例与delta的关系;

2. 定义图形比例缩放的anchor(锚点),通常取图形的几何中心点,锚点不同会影响缩放后的坐标的结果。比如有等比例缩放,向上向下缩放等。


/*** 缩放坐标* @param {Array<number>} coordinates 坐标信息.* @param {number} offset 坐标数组的起点索引,默认是0.* @param {number} end 坐标数组的起点索引的终点索引.* @param {number} stride 坐标的维度,二维图形是2.* @param {number} sx 相对于x轴的缩放比例.* @param {number} sy 相对于y轴的缩放比例.* @param {Array<number>} anchor 缩放的锚点.* @param {Array<number>=} opt_dest 目标数组中.* @return {Array<number>} 经过变形的坐标.*/
function scale(coordinates, offset, end, stride, sx, sy, anchor, opt_dest) {const dest = opt_dest ? opt_dest : [];const anchorX = anchor[0];const anchorY = anchor[1];let i = 0;for (let j = offset; j < end; j += stride) {const deltaX = coordinates[j] - anchorX;const deltaY = coordinates[j + 1] - anchorY;dest[i++] = anchorX + sx * deltaX;dest[i++] = anchorY + sy * deltaY;for (let k = j + 2; k < j + stride; ++k) {dest[i++] = coordinates[k];}}if (opt_dest && dest.length != i) {dest.length = i;}return dest;
}/** example **/
const coordinates= this.coordinates_;
let anchor = getCenter(coordinates); // 获取几何中心点const stride = 2;
const sx = 2;
const sy = 2;scale(coordinates, 0, coordinates.length,stride, sx, sy, anchor, coordinates);
  • 图形的旋转

几何图形的旋转又比图形的缩放复杂那么一丢丢,仍然需要先定义如下两个参数:

1. 根据鼠标交互得到delta,定义旋转角度的比例与delta的关系;

2. 定义图形比例缩放的anchor(锚点),通常取图形的几何中心点,锚点不同会影响旋转后的坐标的结果。

经过旋转后,新的坐标与旧坐标的关系的公式如下:

/*** @param {Array<number>} coordinates 坐标数组.* @param {number} offset 坐标数组起始的坐标的偏移.* @param {number} end 标数组终点的坐标的索引.* @param {number} stride 坐标的维度,二维的为2.* @param {number} angle 旋转角度.* @param {Array<number>} anchor 旋转的锚点.* @param {Array<number>=} opt_dest 目标数组.* @return {Array<number>} 已经转换的坐标.*/
export function rotate(coordinates, offset, end, stride, angle, anchor, opt_dest) {const dest = opt_dest ? opt_dest : [];const cos = Math.cos(angle);const sin = Math.sin(angle);const anchorX = anchor[0];const anchorY = anchor[1];let i = 0;for (let j = offset; j < end; j += stride) {const deltaX = coordinates[j] - anchorX;const deltaY = coordinates[j + 1] - anchorY;dest[i++] = anchorX + deltaX * cos - deltaY * sin;dest[i++] = anchorY + deltaX * sin + deltaY * cos;for (let k = j + 2; k < j + stride; ++k) {dest[i++] = coordinates[k];}}if (opt_dest && dest.length != i) {dest.length = i;}return dest;
}/**example**/
const coordinates = this.coordinates_
const stride =2
const angle = 45 * Math.PI / 180
const anchor = getCenter(coordinates)
rotate(coordinates, 0, coordinates.length,stride, angle, anchor, coordinates);

总结

几何图形的自由变换的核心思路比较简单,上述描述的情况都是基于二维几何图形的,但是也适合三维几何图形的情况。后面的文章会讲述几何图形的修改,变形以及贝塞尔曲线实现。

二维几何图形自由变换的思路(平移、缩放、旋转)相关推荐

  1. 二维几何图形创作方法(Geometry2D)

    本文所讲的内容已经开源,你可以在 这里 找到源代码. 这里我们介绍一下在场景中构建二维几何图形,计算图形的顶点.边的方法.创作几何图形主要依靠鼠标(或者触摸屏.手写笔之类的点输入设备),输入几个点,快 ...

  2. BUUCTF misc 二维码1解题思路

    BUUCTF misc 二维码1解题思路 1题目 2打开后发现是一个二维码,首先我们将它放到010中分析发现藏有pk开头的压缩包,然后我们使用kali把压缩包分离出来 dd if=QR_code.pn ...

  3. [Python从零到壹] 三十八.图像处理基础篇之图像几何变换(平移缩放旋转)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  4. 线性代数:矩阵变换图形(三维平移缩放旋转)

    紧接上一篇:http://blog.csdn.net/yinhun2012/article/details/79544205 这篇博文我只是准备对上一篇博文的内容进行扩展,因为上一篇我写完二维xy仿射 ...

  5. qgraphicsview鼠标移动图片_交互式QGraphicsView(平移/缩放/旋转)-阿里云开发者社区...

    简述 Graphics View提供了一个平台用于大量自定义 2D 图元的管理与交互框架包括一个事件传播架构支持场景 Scene 中的图元 Item 进行精确的双精度交互功能.Item 可以处理键盘事 ...

  6. 圆柱曲面二维码扫描识别思路

    偶然发现,二维码贴在圆柱面或其他曲面时,扫描不上,扫描不出来的原因跟曲面二维码扭曲,导致定位点距离偏差有关. 解决思路: 方法一: 扫描的时候,二维码截图以纵向中心线为基准向两侧,越远越密集(大概是这 ...

  7. 微信二维码登录实现思路

    在电脑上使用微信时,你可能已经发现微信不提供传统的账号密码登陆,取而代之的是通过扫描二维码进行登陆.今天就要研究下次登陆方式微信时如何实现的? 1.每次用户打开PC端登陆请求,系统返回一个唯一的uid ...

  8. opengl矩阵变换与平移缩放旋转

    2019独角兽企业重金招聘Python工程师标准>>> 坐标系: 1.右手坐标系 2.左手坐标系 左手坐标系是X轴向右,Y轴向上,Z轴向前,右手坐标系的Z轴正好相反,是指向" ...

  9. [Python图像处理] 三十六.OpenCV图像几何变换万字详解(平移缩放旋转、镜像仿射透视)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

最新文章

  1. 我的csdnmark
  2. linux学习总结之基本命令
  3. 游戏设计亦或课件设计
  4. linux批量分区,Linux磁盘批量分区格式化和挂载脚本
  5. Redis与Redisson的分布式锁
  6. 20220626-JAVA高德地图天气API调用总结
  7. 多渠道下门店如何进行会员管理和会员营销
  8. 概率论的学习和整理--番外5:等差数列求和公式,等比数列求和公式,以及比较 数列,函数,级数等相似概念
  9. vue验证码图片显示不出来,将图片转换为base64格式显示
  10. 海外服务器配置多少带宽比较合适?
  11. 携程去哪儿合并可行性研究报告
  12. 街头篮球服务器ip地域位置图,浅谈《街头篮球》韩服与国服六个位置的不同之处...
  13. 色彩构成与搭配——人对色彩的感觉
  14. 苹果app商品定价_苹果将调整应用商店定价:中国区应用最低价涨至8元
  15. 计算机游戏开发职业生涯规划,计算机动漫设计与制作专业职业生涯规划书
  16. 冷门但实用的Word技巧
  17. python命令行调试_Linux 黑乎乎的命令行下,如何调试 Python?
  18. 【react】react18的学习(三)--hooks组件
  19. 我在校园自动打卡autojs脚本
  20. Linux学习日记1——Ubuntu

热门文章

  1. .net项目与下载包之间不兼容时,如何下载NuGet之前版本的包
  2. 时隔多年,腾讯再次上线 Linux 版 QQ !
  3. 猴子吃桃问题 php,趣味算法:猴子吃桃问题
  4. ROS kinetic VREP3.6.2 配合使用在Unbuntu 16.04中
  5. windows无法连接linux共享文件夹
  6. logstash处理snmptrap消息问题
  7. [中国评书论坛] 社区登陆
  8. java 注解与反射
  9. 理论力学知识要点(六)
  10. 如何将Word文件批量转换成PDF