利用svg.js结合向量法实现多边形新增点与剪裁功能

一、多边形后续增加点

ocr标注中,在绘制完一个多边形后,想要继续新增点的操作是一项具有重要意义的任务。常规的方法是删除当前多边形并重新绘制,然而这种做法会导致额外的工作量,尤其是对于复杂的多边形而言,耗时更长。因此,我们需要找到一种在绘制完多边形后能够继续新增点的有效方法。 在探讨如何增加点之前,首先需要对多边形的组成进行简单的分析。在SVG中,一个多边形可以简单地理解为由多个点组成的形状。然而,这些点的顺序会影响多边形的形状,如下图所示。

此时只需要改变一下点2 点3得顺序就会得到一个完全不一样的图形。

为了正确插入新增的点到多边形中,我们可以采取以下两步策略。

第一步,找到新增点的坐标。根据多边形的特性,我们可以通过计算新增点与已知2点之间的距离,来确定新增点的坐标。具体而言,我们可以使用向量运算来计算。首先,我们需要通过遍历多边形点来组成若干线段,然后计算鼠标点与这些线段之间的距离。接下来,找到最短距离的那个映射点作为新增点坐标。

第二步,将新增点的坐标插入到多边形中。根据多边形的定义,我们知道多边形是由一系列有序的点组成的。因此,我们需要确定新增点在多边形中的插入位置。一种常用的方法是通过遍历多边形的边,找到新增点应该插入的边。具体而言,我们可以计算新增点与多边形中每条边的距离,并找到距离最短的边。然后,我们可以将新增点插入到该边的前一个或后一个顶点之间,以保持多边形的有序性。

通过以上两步策略,我们可以正确地将新增点插入到多边形中,确保生成的多边形形状符合预期。

1、如何找到新增坐标点

方案:鼠标在移动时,可以获取当前鼠标位置(A),我们只需要求出 p点,到多边形的最短距离即可。那么该如何理解这个最短距离呢?

我们可以将一个由n个点组成的多边形,拆分为 n - 1个线段。将问题简化为,一个点p到 n - 1个线段的最短距离。

该如何计算一个点到线段的距离呢?假设线段的2个点为 B,C。由于我们可以同时知道3个点的坐标 A,B,C。利用向量法来计算点到线段的距离。

在计算前,先了解几个公式。

  1. 向量的点积

    向量A(x,y)向量B (x1, y1),那么向量AB的点积为 xx1 + yy1

  2. 向量的模

    向量 A(x,y), 其模为 √ xx + yy

  3. 向量A在向量B的投影长度

    AB的点积 / B的模

知道上面的公式后,再简单的手绘一下,如下

A点为鼠标点 B,C点为线段的开始结束点。所以共有 3种场景,如下图

通过上述分析,可利用向量法求出最短距离。如下图

上述代码,我们共返回了2个参数 一个是最短距离,第二个是当前映射的点坐标。

  1. 最短距离的作用在于确定当前鼠标点与多边形中的哪一条线段之间的距离最短。由于多边形被拆分成多个线段,因此我们需要进行比较,以获取点坐标A到不同线段的最短距离的最小值。这样,我们就能够确定目标线段的索引,并将新增点添加到该线段上,以解决新增点位置不准确导致多边形图形错误的问题。
  2. 点坐标是指我们需要添加的新点的具体位置。

2、时时绘制新增点

当我们获取到鼠标点距离最近点的坐标时,我们可以实时绘制新增点的图形,从而帮助使用者更好地使用。这一功能能够提高用户的操作体验,并使用户能够更加方便地进行相关操作。通过实时绘制新增点的图形,用户可以清晰地观察到点的位置和形状,从而更准确地进行后续操作。这种实时绘制的效果能够有效提升用户的工作效率和操作准确性。其效果如下

黄色点为新增点时时的展示效果:

具体代码如下:

上述代码主要用于鼠标移动时,获取鼠标到矩形最短距离,所对应的线段索引,并将映射在该线段的新增点时时绘制出来。

3.将新增点添加到多边形上

由于已经拿到了点坐标以及线段的索引.只需要将点插入多边形的指定位置即可,代码如下:

上述代码的主要逻辑:拿到新增点的坐标[cx,cy],多边形点的坐标points,通过插入线段的索引 insertIndex, 将cx,cy插入points中,并重新绘制多边形。

二、多边形剪切功能

多边形的剪切功能是一种用于处理两个多边形相交情况的方法,它通过使用一个多边形来分割另一个多边形。在执行剪切操作时,需要确保所有相交的交点都能正确还原到两个多边形上。此外,被裁剪的图形中被覆盖的部分需要被删除。这里我们借助 polybooljs 库来实现该功能。

1、使用 polybooljs

经过分析 polybooljs 中 提供的2个方法 difference(求不同) 以及 intersect(求交集),可以很好的辅助我们来完成该功能的开发。

difference方法:

difference 方法是一种用于计算两个多边形之间差异的函数。它接受两个多边形作为输入,并返回一个新的多边形作为输出。这个新的多边形包含了第一个多边形中存在,但在第二个多边形中不存在的部分。换句话说,它从第一个多边形中减去了与第二个多边形重叠的部分,从而得到了被剪裁的图形的所有坐标。

效果如下:

intersect方法:

intersect 方法用于计算两个多边形的交集,并返回交集部分的几何形状。

当拿到所以交集后,如何将所有交点插入图形中,就成为了主要的难点。

那么接下来,先来看该方法返回的数据是什么样的?

可以看出返回的结果是个数组,数组的每一项,由多个点组成,而这些点就是所有的相交点。

到此为止,可以获得 相交点 intersect 的坐标数据,以及剪切图形 clipPolygon的坐标数据,接下来。就是需要将这两组数据合并在一起。

在合并数据前,先看一个场景(同一个线段上出现2个以及2个以上的点):

假设相交点中,有点A,B两个点,都在线段 L 上,那么该如何拼接这3个点,成为一个新的线段呢。和多边形加点存在同样的问题,加点的顺序不同,线段的最终形状也不相同。 我们假设一种场景:

共有4个点,相交点A,B。线段的起始点C,D。

线段的走向为:由C到D。

为了保障新插入P,P1点后,整个线段的走向不发生变化。就需要求出 PC P1C的距离并排序。

那么整体的逻辑如下:

对多边形(polygon)进行遍历,遍历的同时生成 n-1个线段,每次遍历时,再对所有相交点(intersect)进行遍历,利用上述获取最短距离的方法,得到所有在线段上的点。并在此基础上,对所有点进行排序。由于线段本身就按照顺序排序的,因此排序后的点,可以按顺序依次添加到新的数组中。最终这个数组就是新多边形的所有点的集合。

具体代码如下:

拿到多边形点坐标点后,重新绘制即可!

相关推荐
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐4 小时前
前端图像处理(一)
前端