渐近线路径的变换/映射

渐近线路径的变换/映射

我最近开始使用 asymptote 进行一些绘图和绘画,用于我的研究。然而,我偶然发现了一些我想做的事情 - 但我不知道是否有可能。

我有这样的身材,

在此处输入图片描述

我想将其映射到圆的周长,像这样

在此处输入图片描述

如果我能像第一个图形那样在常规笛卡尔坐标系(x,y)中绘制该图形,然后将其映射到极坐标系(r,\theta),再返回到笛卡尔坐标系(\tilde x,\tilde y'),那么绘制该图形就会简单得多。映射到极坐标系中将是,

r = y, \theta = \frac{x}{r} = \frac{x}{y}

映射回新的笛卡尔系统将是

\tilde x (r,\theta) = r \cos (\theta) = y \cos (\frac{x}{y}),
\tilde y (r,\theta) = r \csin (\theta) = y \sin (\frac{x}{y}).

我已经研究过可能的变换,但它们似乎都不允许这种变换。我是否可以自己制作一个允许使用非仿射变换的程序?

如果这可以在 TikZ 中实现,我也会对此非常感兴趣。

谢谢,克里斯蒂安

附言:如果有人能告诉我如何使我的数学看起来正确,那也将不胜感激。

答案1

尝试这个:

\documentclass[margin=10pt]{standalone}
\usepackage{asymptote}

\begin{asydef}
struct planeTransformation {
  int nInterpolate = 4;
  pair apply(real, real);
  pair apply(pair uv) { return apply(uv.x, uv.y); }
  transform derivative(real, real);
  transform derivative(pair uv) { return derivative(uv.x, uv.y); }
  transform linearization(real u, real v) {
    return shift(apply(u,v)) * derivative(u,v) * shift(-(u,v));
  }
  transform linearization(pair uv) {
    return linearization(uv.x, uv.y);
  }
  /* Apply to a single Bezier spline. */
  guide _apply(pair p1, pair c1, pair c2, pair p2) {
    return apply(p1) .. controls linearization(p1)*c1 and linearization(p2)*c2 .. apply(p2);
  }
  guide _apply(path g) {
    assert((length(g)) == 1);
    return _apply(point(g,0), postcontrol(g,0), precontrol(g,1), point(g,1));
  }
  path apply(path g, int nInterpolate = nInterpolate) {
    guide toreturn;
    for (int i = 0; i < nInterpolate*length(g); ++i) {
      real currentpos = i / nInterpolate;
      real nextpos = (i+1) / nInterpolate;
      toreturn = toreturn & _apply(subpath(g, currentpos, nextpos));
    }
    if (cyclic(g)) toreturn = toreturn & cycle;
    return toreturn;
  }
}

planeTransformation polar;

polar.apply = new pair(real r, real theta) {
  return r * expi(theta);
};

polar.derivative = new transform(real r, real theta) {
  transform t = (0, 0, cos(theta), -r*sin(theta), sin(theta), r*cos(theta));
  return t;
};
\end{asydef}

\begin{document}
\begin{asy}
size(5cm);
path curvedbox = polar.apply(box((1, -pi), (2, pi)));
draw(curvedbox);
\end{asy}
\end{document}

结果:

请注意,这只是一个近似变换。为了使其更精确,请调用该函数,例如,polar.apply(g, nInterpolate=16);其中g是应应用变换的路径。默认值为nInterpolate = 4;不同的路径将需要不同级别的插值。路径越复杂,所需的插值点可能就越少。

结果如下

path curvedbox = polar.apply(box((1, -pi), (2, pi)), nInterpolate=16);


补充说明:上面的代码将y-value 映射到角度,而 OP 最初要求将 -value 映射y到半径。以下函数应切换到最初请求的顺序:

path switchedPolar(path g) {
    return polar.apply(reflect((0,0),(1,1)) * g);
}

polar.apply或者,在和的定义中,和polar.derivative的顺序可以互换:rtheta

polar.apply = new pair(real theta, real r) {

ETC。

相关内容