在线流程图和思维导图开发技术详解(三)

一、项目概述

二、项目架构

三、几何计算难点

四、鼠标事件处理

五、数据保存与导出

六、文本处理

三、几何计算难点

3.1 矩形变换

我们先来看没有旋转的情况。不旋转的情况是比较简单的,只是情况比较多,代码难以做到优雅。看下图:

矩形有8个方位可以进行拖动,还要分是否保持比例。如果用16个if/else来写,代码冗长而不易修改。事实上,很多情况是可以合并的。例如在不保持比例的情况下,只要拖动位置跟“左”有关的,矩形的x坐标和宽度都要修改,而跟“右”有关的,只要修改宽度即可。这里无法列出整个算法过程,实现的时候慢慢总结归并即可。

对于旋转的情况,先看下图:

旋转矩形的描述是rect(x,y,width,height,angle),直接给定一个鼠标点P(x,y),无法判断这个点跟旋转矩形的关系。一个可行的解决方案是:

  1. 鼠标点绕旧旋转点“逆旋转”,也就是按负角度进行旋转,得到点P'。这个点就是在无旋转矩形坐标系下的相对点。

  2. 计算矩形(x,y,width,height)在P'点作用下的新矩形rect'(x',y',width',height')。这时的width'和height'就是最终结果的矩形宽高,但x'和y'不是。因为矩形的旋转中心已经变了,x'和y'是相对于旧旋转中心的。

  3. rect'绕旧旋转点“正旋转”,计算出四个角的坐标(其中左上角坐标为(x'',y''))。由此计算出新旋转点。

  4. 把上述的左上角坐标绕新旋转点“逆旋转”,即是最终结果的左上角坐标了。至此,新的矩形坐标求出(angle不变的)。

3.2 组内变换

当多个图元合并成一个组之后,当组发生变换时,内部的图元也要跟随变换。如下图所示:

这实际上是一个坐标系转换的问题。组相对于画布坐标系变换,而组内的图元则相对于组坐标系进行变换。要算一个矩形的变换会比较困难,我们可以用两个点(左上角、右下角)来描述矩形,变换之后,这两个点再转换为矩形即可。

在一个组的变换过程中,里面的点相对于组唯一不变的就是相对于两垂直轴的原点偏移率,如下图所示:

以内部矩形的左上角为例,L1、L2为组矩形的长和宽,l1、l2是左上角点在两条边上的投影点距离组矩形原点的距离。在变换前后,保持不变的只的r1=l1/L2和r2=l2/L2。那么,组变换的算法流程可以这样:

  1. 求出内部点在组矩形两条边上的投影点,并算出距离原点的距离。

  2. 求出上述距离和组矩形两条边的比例r1、r2。

  3. 组矩形按上一节的方法进行变换。

  4. 利用r1、r2,反推出两个点的坐标。

  5. 利用两个点的坐标,反推出矩形的x,y,width,height。

3.3 连接线生成

连接线有三种类型,分别是直线、折线和曲线(bezier)。直线过于简单不需讨论。Bezier曲线事实上也不困难,要确定一条Bezier曲线,只要四个点,两个端点和两个辅助点。辅助点沿着端点的反方向移动一段距离即可。

关于折线类型的连接线生成,在我的另一篇博文里已经有介绍。流程图连接线生成算法

3.4 思维导图节点位置

思维导图就是一棵树,每个节点都有width和height属性(在本项目中,每个节点的大小是可以不一样的)。思维导图有几个方向,在计算位置的时候会有所差异。但这个差异并不大,可以通过旋转完成。所以下面我们讨论思维导图在下方的这种情况。

我们先看下面的两张图:

两棵树都是合理的,而左树能够更省空间,而右树的计算会简单很多。我们将使用右树这种方式。

第一步,计算每个节点在横向所占的位置。这需要把树遍历一次,每个节点所占的位置是其所有子的总和(还要加上间隙)。

第二步,计算每个节点的纵向位置。由于所有节点在横向都是不会相交的(因为我们选择了右树这种方式),所以纵向的计算就会很简单的。一层一层累加就可以。每个父节点把自己所在的位置传给子节点,子节点在父节点位置的基础上累加高度。

第三步,计算每个节点的坐标。由于在第一步已经计算出节点在横向所占位置,节点的x坐标就是在父节点的中间减去这一长度的一半。而y坐标在第二步其实已经算出来了。

第四步,整体进行平移。在计算之前,整棵树的大小是未知的,树摆放在哪里不好把握。我们一开始计算的时候,会假定根节点的坐标是(0,0),然后计算出每个节点的相对坐标。最后,把确定的根节点坐标作为一个偏移量,叠加在每个节点的坐标之上。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值