Skip to content

[0911] 绘图模式线段中点绿色吸附点 - #4345

Closed
PinkMagicFly wants to merge 8 commits into
MoganLab:mainfrom
PinkMagicFly:pigmagicfly/0911/segment-midpoint-snap
Closed

[0911] 绘图模式线段中点绿色吸附点#4345
PinkMagicFly wants to merge 8 commits into
MoganLab:mainfrom
PinkMagicFly:pigmagicfly/0911/segment-midpoint-snap

Conversation

@PinkMagicFly

@PinkMagicFly PinkMagicFly commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

任务

0911(非 issue):绘图模式中,鼠标贴近线段(吸附距离的一半以内,不要求完全压线)时,在该线段中点显示一个绿色的可吸附点。

改动内容

吸附候选(C++)

  • src/Edit/Interface/edit_graphics.cpp 新增 snap_curve_midpoint():鼠标贴近曲线对象(curve-point / curve-handle 命中)时,对折线/多边形逐边处理——get_control_points 取控制点(闭合曲线补首尾相连边,与 curve_box_rep::graphical_select 的区间划分一致),每边先用点到线段距离判定鼠标确实贴近该边,再判定该边是直边,取区间中点作为该边中点。
  • 鼠标与中点距离小于吸附距离时,追加 curve-mid-point 类型的吸附候选;can_snap 中该类型复用 "curve point" 吸附开关(关闭曲线点吸附时中点同步失效)。
  • src/Graphics/Types/curve.cpp/.hppis_straight_line 新增参数区间重载(原单参版本转调区间版本,行为不变),供逐边直边判定复用,消除逻辑重复。

绿色圆点渲染(Scheme)

  • TeXmacs/progs/graphics/graphics-ghost.scm:新增中点状态与 graphics-set-midpoints(变更检测,集合变化才刷新装饰)、graphics-clear-midpointsgraphics-get-decorations-midpointgraphics-midpoints-active?graphics-render-midpoints;中点渲染为 (with "color" "green" "point-style" "disk" (point x y)) 绿色圆点,复用标尺(ghost line)的注册/刷新/清空链路。
  • graphics-object.scmgraphics-extra-decorations 追加中点装饰;create-graphical-object 的 group 分支(绘制完成后自动进入的 group-edit edit-props 选择态)追加渲染中点绿点;空对象分支在中点仍激活时保留绿点预览。
  • graphics-single.scmedit_move 非绘制态改为鼠标仍贴近线段时仅渲染绿点预览,避免预览被整体清空。

折线绘制中的中点

  • 绘制中的折线只存在于绘制覆盖层(sketch),尚未进入文档树,
    graphical_select 选不到;graphics-ghost.scm 新增
    graphics-get-previous-midpoints,按与角度标尺相同的「已落固定点」
    语义提供各线段中点(仅 line/cline,spline 控制点连线不是线段),
    C++ 侧注册显示并在鼠标靠近时追加吸附候选。

设计要点

  • 显示条件是「鼠标贴近该线段本身」(点到线段距离 ≤ 吸附距离的一半,
    两条路径统一按边过滤),而非落入整个吸附距离即可;吸附候选额外要求
    鼠标与中点本身的距离小于吸附距离,避免长边远端被强行拉到中点。
  • C++ 每次鼠标移动上报当前中点集合,变更检测与刷新放在 scheme 侧,保证 scheme 状态被 graphics-decorations-reset 清空后仍能重新注册。
  • 坐标经 f2 逆变换转回文档坐标系后传给 scheme,与标尺坐标约定一致。

验证

单元测试

  • xmake b stem && xmake r graphics-ghost-test(新增纯逻辑测试,覆盖 midpoint-decorations 空集/单点/多点输出形状):3 correct, 0 failed。

GUI 端到端验证(已自行执行)

方法:X11 XTest 合成真实鼠标/键盘事件 + 截图像素分析 + 状态栏坐标读取。测试文档含三角形 <cline>(3 边含闭合边)、独立两点、独立 <line>

  1. 悬停三角形任意一边及独立线段:各边中点出现绿点,绿点像素位置与中点理论屏幕坐标一致;
  2. 非绘制态悬停(未落任何点)、绘制中(line 工具落第一个点后)、group-edit edit-props 选择态(绘制完成后自动进入)三种状态绿点均正常显示;
  3. 状态栏坐标吸附:悬停斜边中点读出精确 (2,1.5);在中点附近 3px 处点击,新插入的点精确落在 (2,0);偏移 6px 以上不吸附(与既有吸附距离行为一致);
  4. 远离线段、移出绘图区后绿点消失,无残留。

手工验收步骤

  1. 启动 Mogan STEM,绘制一个三角形(cline)和一条独立线段;
  2. 鼠标贴近任一边(约吸附距离一半以内):该边中点出现绿色圆点,稍远即不显示;
  3. 鼠标移近绿点:状态栏坐标吸附为精确中点值,点击落点即中点;
  4. 用折线工具落下两个点(不结束绘制),鼠标靠近已落的边重复第 2 步;
  5. 分别在「未开始绘制」「绘制中」「绘制完成后的选择态」重复第 2 步;
  6. 鼠标远离线段:绿点消失。

Comment thread src/Edit/Interface/edit_graphics.cpp Outdated
/** 鼠标到线段 (a, b) 的距离(投影限制在线段内) */
static double
dist_to_segment (point p, point a, point b) {
point v = b - a;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

推测已经有了

如果没有,应该放在相应的位置

- 折线/多边形逐边识别直边并取每边中点,注册为 curve-mid-point 吸附候选
- 悬停(含非绘制态与 group-edit 选择态)渲染绿色中点圆点,远离自动消失
- is_straight_line 新增参数区间重载供逐边判定复用
- graphics-ghost.scm 新增 graphics-get-previous-midpoints:绘制
  line/cline 时提供已落固定点连成的各线段中点
- edit_graphics.cpp 消费该结果注册绿点显示与 curve-mid-point
  吸附候选;两处注册代码合并为 register_midpoint 辅助函数;
  is_straight_edge 保持为本文件内静态函数,还原共享 curve.cpp 的
  is_straight_line 区间重载改动
- 修复 graphics-ghost-test.scm 的 gf fmt 格式(CI clang-format-check 失败项)
- snap_curve_midpoint 以 on_line_tol = snap_distance/2 门控绿点注册,
  两条路径(文档对象边 / 折线绘制中已落边)统一按点到线段距离过滤
- graphics-get-previous-midpoints 改为 graphics-get-previous-line-points
  (返回已落固定点,line/cline 限定,复用 graphics-get-all-previous-points),
  C++ 侧逐边过滤后取中点,绘制中路径不再无条件显示全部边中点
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants