0

我试图画一条从一个foreignObject到另一个的路径。

我希望根据每个对象的中心来定向/设置路径,但只能从距离对象一段距离开始。例如,这里是从一个对象到两个不同对象的直线路径:注意路径的起点不同;相反,它已被调整为位于连接两个对象的线上。

在此处输入图像描述

如果路径是一条直线,这很容易实现:只需沿着由对象中心点定义的直线在位移 Δr 处开始和结束路径。

但是,在贝塞尔曲线(二次或三次)的情况下,我不确定如何实现这一点。

在此处输入图像描述

如果可以使部分路径透明(即为路径的不同部分设置描边颜色),那么可以只使用中心点并将第一个 Δs px 设置为transparent; 但是,我不知道有任何方法可以做到这一点。

或者,如果可以独立于用于计算路径的点设置路径的起点和终点,这将解决所有情况(线性、贝塞尔二次或三次)。

另一种选择可能是使用该dash-array属性,但这需要知道路径的长度。例如,如果路径长度为S,则将 dash-array 设置为x-calc(S-2x)-x也可以达到预期的结果。

有没有办法以编程方式实现这一目标?

我不介意跑腿,所以即使只是指向正确方向的指针也会受到赞赏。

4

2 回答 2

1

使用层的基本解决方案:

  • 第 1 层:路径;
  • 第 2 层:与背景颜色相同的元素,比在它们上面分层的元素稍大(对于表情符号,我使用了圆圈,对于文本,我使用了相同的文本,具有更大的 pt-size);
  • 第 3 层:元素本身。

优点缺点

优点:

  • 快的;
  • 简单的;

缺点:

  • 不能使用markers(因为它们被背景色物体遮住了);
  • 可能需要一些修补才能找到最合适的背景元素类型;

这是示例输出的屏幕截图:

在此处输入图像描述

于 2021-05-25T17:01:04.220 回答
1

这是一个想法:使用de Casteljau 算法两次修剪曲线的开始和结束部分。

假设您被要求评估由控制点 C_{0,0}、C_{1,0}、C_{2,0} 和 C_{3,0} 定义的三次贝塞尔曲线,参数 t 介于 0 和1.(我假设曲线的参数区间是[0,1],我给控制点起这样奇怪的名字是为了期待下面的内容。如果你使用与以下不同的曲线度数,请查看维基百科文章3.)

您将按以下方式进行:

for j = 1, ..., 3
  for i = 0, ..., 3 - j
    C_{i, j} = (1 - t) * C_{i, j-1} + t * C_{i+1, j-1}

点 C_{0, 3} 是曲线在参数值 t 处的值。整件事用一张图就更容易理解了(我拍了 t=0.5):

三次曲线的 de Casteljau 算法

但是,该算法为您提供了更多信息。例如,控制点 C_{0,0}、C_{0,1}、C_{0,2} 和 C_{0,3} 是控制多边形一条曲线,它等于限制在区间 [ 0,吨];类似地,C_{0,3}、C_{1,2}、C_{2,1} 和 C_{3,0} 给你一个贝塞尔曲线,等于你的曲线限制为 [t, 1]。这意味着您可以使用 de Casteljau 算法以规定的间隔将曲线一分为二。

在你的情况下,你会:

  1. 从底部图片中显示的曲线开始。
  2. 使用 de Casteljau 算法在接近 0 的参数 t_0 处分割曲线(我将从 t_0 = 0.1 开始,看看会发生什么)。
  3. 丢弃在 [0, t_0] 上定义的部分,只保留在 [t_0, 1] 上定义的部分。
  4. 取一个接近 1 的参数 t_1 并将剩余部分从 3 中拆分出来。
  5. 保留开头并丢弃(短)结尾。

请注意,这样您将根据参数值而不是根据其长度来分割曲线。如果您的曲线形状相似,这不是问题,但如果它们会有显着差异,您可能需要花费一些精力以编程方式找到合适的 t_0 和 t_1 值。

另一个问题是 t_1 的选择。我想由于对称性,您可能希望将曲线拆分为 [0, t_0]、[t_0, 1 - t_0]、[1 - t_0, 1]。取 t_2 = 1 - t_1 是不行的,因为 t_2 指的是第 3 步结果的参数区间,也就是[0, 1]!相反,您需要类似 t_2 = (1 - t_1)^2 的东西。

于 2021-05-22T07:49:18.540 回答