![如何移动循环路径中的第一个点?](https://linux22.com/image/368531/%E5%A6%82%E4%BD%95%E7%A7%BB%E5%8A%A8%E5%BE%AA%E7%8E%AF%E8%B7%AF%E5%BE%84%E4%B8%AD%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%82%B9%EF%BC%9F.png)
给定一个循环的指南(或路径)g,我想构造一个相同的指南,但所有控制点的n
位置都发生了偏移。结果是第一个节点和最后一个节点发生了偏移,例如,如果 a、b、c 和 d 是从 a 开始的循环路径的节点,则偏移后n=2
得到的路径应为 c、d、a、b,从 c 开始。
我尝试从指南中提取控制点和张力参数,但似乎无法在我构建的指南中设置这些字段。这是我尝试过的:
guide rotate_seam(guide g, int n)
{
guide res;
tensionSpecifier T[], t;
pair[] P;
T.cyclic = true;
P.cyclic = true;
for (int i = 0; i < length(g); ++i)
{
t = tensionSpecifier(g, i);
P.push(point(g, i));
T.push(t);
}
T = T[n:n+T.length];
P = P[n:n+P.length];
for (pair i : P) { res = res..i; }
res = res..cycle;
for (int i = 0; i < T.length; ++i)
{
t = tensionSpecifier(res, i);
t.in = T[i].in;
t.out = T[i].out;
t.atLeast = T[i].atLeast;
}
return res;
}
答案1
这是一个相当简短的解决方案:
path rotate_seam(path g, int n) {
// Ensure path is cyclic so that `subpath` can extend past the end of the path.
if (!cyclic(g)) g = g & cycle;
return subpath(g, n, length(g) + n) & cycle;
}
请注意,& cycle
丢弃路径中的最后一个节点,并将第一个节点放置在其位置,如果最后一个节点实际上与第一个节点是同一点,那么这是正确的做法。
答案2
我找到了解决方案。新指南是使用控制点信息逐段构建的。据我所知,没有办法传递任何包含控制点的结构并让 Asymptote 按照规范构建指南。
struct CPoint
{
pair ctrl;
pair pre_ctrl;
pair post_ctrl;
}
guide rotate_seam(path p, int n)
{
CPoint P[];
P.cyclic = true;
for (int i = 0; i < length(p); ++i)
{
CPoint tmp;
tmp.ctrl = point(p, i);
tmp.pre_ctrl = precontrol(p, i);
tmp.post_ctrl = postcontrol(p, i);
P.push(tmp);
}
P = P[n:n+P.length];
guide res, seg;
for (int i = 0; i < P.length - 1; ++i)
{
seg = P[i].ctrl..controls P[i].post_ctrl and P[i + 1].pre_ctrl..P[i + 1].ctrl;
res = res & seg;
}
seg = P[P.length - 1].ctrl..controls P[P.length - 1].post_ctrl and P[0].pre_ctrl..P[0].ctrl;
res = res & seg;
return res & cycle;
}