网页版几何画板开发笔记(十三) 对象移动算法

问题: 当选中多个几何对象, 使用鼠标移动, 则如何移动, 以保证正确的几何约束关系, 以及
   使人"看起来"此移动比较"正常,合理"?

设被选中的对象的集合为S, 先构造一个集合M, 移动S被转换为等价于移动集合M, 且集合M
中的对象都是自由度非0(可自主=2或半自主=1移动的)的对象.

当前有完全移动自由度的对象主要是自由点. 也有FixedText,Button的特殊对象, 但它们通常不
具有几何约束关系, 故而在研究移动的时候可以略. 自由点对象可以在 x,y 两个方向任意移动,
其影响别的几何对象, 且不被别的任何几何对象影响.

有半移动自由度的对象是对象上的点(Point On Object). 它们有在对象路径(path)上的 t 方向
的一个自由度. 如果此次移动操作不影响该类点的父对象, 则该点可以看做是自由点移动.

从 S 构造 M 的算法如下:
1. 设置 M 的初值 = S (复制一份); 在实际中, S 是数组, M 是以对象 id 为 key 的 map.
2. 构造 M 的所有子孙节点的集合 C, C 包含 M 及 M 的所有子孙对象.
3. 扫描 M 集合的每个对象 obj, 如果该对象的自由度 = 0, 则从 M 中移除该 obj, 加入 该
  obj 的移动控制对象 (move_ctrl()), 其一般是但不绝对是父对象集合. 同时更新 C.
4. 重复步骤 3, 直到集合 M 不再发生变化. 此时 M 是最终的移动控制集合.

通过移动集合 M 中的对象, 这些对象相互之间的移动是独立的, 可以"分别"移动. 移动发生之后
更新集合 C 中所有受影响对象, 即可完成移动操作.

为实现移动操作的 Undo/Redo , 需要给对象的位置信息(可能在移动的每一个时刻)都建立
一个快照(snapshot), 一个 undo 操作等价于将位置信息恢复到开始点的位置快照, 一个 redo
操作等价于将位置信息设置到结束点的位置快照.

位置快照使用的数据的逻辑结构是 M: { id: pos-snapshot }, 其中每个 pos-snapshot 可约定简化
为一个数字的 array, 如 [x, y], 或 [t]. 可以使用压缩的表示方法, 如 3,x,y|4,t|9,x,y ...
由于集合 C 可以通过 M 构造出来, 所以可不被保存到快照中, 而是每次 undo/redo 操作时构造.


你可能感兴趣的:(网页版几何画板开发笔记(十三) 对象移动算法)