You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell Diagrams如何实现固定四向出入的节点连接箭头

问题原因

你当前的shaft函数硬编码了贝塞尔曲线终点为水平方向的r2 (3, 0),而connect'默认会自动对shaft做缩放、旋转以匹配两个节点中心的连线方向,因此节点垂直排列时整个箭头被旋转90度,进出方向不符合要求。

解决方法

优先使用diagrams内置的connectPerim'接口,它原生支持指定两个节点的连接进出方向,不需要手动适配节点排列方式:

完整实现代码

import Diagrams.Prelude
import Diagrams.Backend.SVG.CmdLine

data Dir = N | S | E | W
     deriving (Eq, Ord, Show)

cir, circlesH, circlesV :: Diagram B
cir  = circle 0.3 # showOrigin # lw thick
-- 水平排列节点
circlesH = (cir # named "1") ||| strutX 3 ||| (cir # named "2")
-- 垂直排列节点
circlesV = (cir # named "1") === strutY 3 === (cir # named "2")

-- 方向对应的圆周角度
dirAngle :: Dir -> Angle Double
dirAngle N = 90 @@ deg
dirAngle S = 270 @@ deg
dirAngle E = 0 @@ deg
dirAngle W = 180 @@ deg

-- 自定义箭头杆:贝塞尔曲线弯曲样式
bentShaft :: Trail V2 Double
bentShaft = trailFromSegments [bézier3 (r2 (0, 1)) (r2 (0, -1)) (r2 (1, 0))] # scaleUToX 1

-- 按指定进出方向连接两个节点
connectDir :: Dir -> Dir -> String -> String -> Diagram B -> Diagram B
connectDir outDir inDir n1 n2 = connectPerim' opts n1 n2 (dirAngle outDir) (dirAngle inDir)
  where opts = with & arrowShaft .~ bentShaft & lw thick

-- 水平排列测试
exampleH :: Diagram B
exampleH = circlesH # connectDir N S "1" "2"

-- 垂直排列测试
exampleV :: Diagram B
exampleV = circlesV # connectDir N S "1" "2"

上述实现不管节点是水平、垂直还是任意位置摆放,都可以保证箭头严格从指定的N/S/E/W四个正方向进出节点,不需要修改箭头杆的逻辑。

内容的提问来源于stack exchange,提问作者cdupont

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:15:03