asypicture 动画

asypicture 动画

我正在尝试制作渐近线图片的动画。不幸的是,我遇到了一些困难。每当我尝试直接在渐近线中制作它们时,我的内存就会耗尽,以至于我的浏览器崩溃,我再也无法看到聊天网站上的精彩帖子。所以这是不可接受的。;-) 消化后这个答案这个答案,我找到了一个解决方法。我编写了一个 asy 代码,其中包含一个文件,我在循环中写入该文件。(真是一团糟!)然后,当用编译时-shell-escape,此代码片段会产生一个动画,可以将其转换为如这里所述

convert -density 200 -delay 24 -loop 0 -alpha remove <file>.pdf <outfile>.gif

这是代码:

\documentclass[border=3pt]{standalone}
\usepackage{filecontents}
\begin{filecontents*}{asyduck.asf}
\begin{asypicture}{name=AsyDuck}
import graph3;
import solids;

size(6cm,6cm);
settings.render = 4;

include anglefile;
real viewangle = 4.5 - 3*beakangle*2*pi/360;

//currentprojection = perspective((0.6,0.3,1), up=Z,autoadjust=true);
currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1.5));
currentlight=(-3,-5,5);

// from https://tex.stackexchange.com/a/227192/121799
draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);

//draw(2X+2Y+2Z -- 2X-2Y+2Z -- -2X-2Y-2Z,white);

//limits((-1,-1,0),(1,1,1),Crop);

//limits((-2,-2,-2),(3,2,3));

// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// if I comment these two draw commands out, I get a completely different perspective
draw(O -- 2X,white, L=Label("$x$",position=EndPoint));
draw(O -- 2Y,white, L=Label("$y$", position=EndPoint));
//draw(O -- 2Z,white, L=Label("$z$", position=EndPoint));

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple c1=S2((6pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c2=S2((4pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c3=S2((6pi/5,pi/4+0.45))+(0.5,0,1.5);
triple c4=S2((4pi/5,pi/4+0.45))+(0.5,0,1.5);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }

surface s1 = shift(1.1,0,0.7) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(0.5,0,1.5) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s3 = shift(0.3,0,1.6) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);
surface s4 = shift(0.3,0,1.6) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);


draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

draw(s5, surfacepen=m_eyeW);
draw(s6, surfacepen=m_eyeW);


real R=0.1, r=0.04;
draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
draw(surface(sphere(c4,r)),surfacepen=m_eyeB);
\end{asypicture}
\end{filecontents*}
\usepackage{asypictureB}
\standaloneenv{asypicture}
\usepackage{pgffor}


\begin{document}
\def\myangle{45}
\foreach \X [evaluate={\myangle=int(abs(20-\X))}] in {0,2,...,40}
{
\RequireAsyRecompile
\immediate\write18{echo "int beakangle = \myangle;" > anglefile.asy}
\input{asyduck.asf}
}
\end{document}

在此处输入图片描述

(我也不知道鸭子是如何进入我的 asy 代码的,它一定是一种非常鬼祟的动物。;-)

我的问题:有没有一种简单的方法可以实现同样的目的而不使用上述技巧?

编辑:我得到了一个非常Marcel Krüger 的回答很不错,但我最初的问题已由 Charles Staats 在评论中回答,我想在此向他表示感谢。事实证明,他已经为此准备了他的 asypictureB 包,我只是没有仔细阅读手册。结果是,人们可以将宏传递给 s asypicture,只需将 替换为\@这样,人们就可以直接将渐近线动画包含在 LaTeX 文档中:

\documentclass{standalone}
\standaloneconfig{border=-1.5cm -1.5cm -3cm 0.1cm} % see https://tex.stackexchange.com/q/422165/121799
\usepackage{filecontents}
\begin{filecontents*}{asyduck.asf}
\begin{asypicture}{name=AsyDuck}
import graph3;
import solids;

size(8cm,6cm);
settings.render = 4;

//include anglefile;
real beakangle = @myangle; // Big thanks to Charles Staats !!

real viewangle = 4.2 - 0*beakangle*2*pi/360;

//currentprojection = perspective((0.6,0.3,1), up=Z,autoadjust=true);
//currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1));
currentprojection=perspective(camera=scale3(4)*(2*cos(viewangle),2*sin(viewangle),1));

currentlight=(-3,-5,5);

// from https://tex.stackexchange.com/a/227192/121799
draw(scale(1.6,1.6,1.6)*unitsphere,lightgray+opacity(0));

// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// if I comment these two draw commands out, I get a completely different perspective
draw(O -- 2X,invisible, L=Label("$x$",position=EndPoint));
draw(O -- 2Y,invisible, L=Label("$y$", position=EndPoint));
draw(O -- 2Z,invisible, L=Label("$z$", position=EndPoint));

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple Water(pair uv) {
  real x = uv.x;
  real y = uv.y;
  real z = -0.2+0.1*cos(180*uv.x+18*beakangle) ;
  return (x, y, z);
}

//
//(0.5,0,1.5)
triple c1=S2((6pi/5,pi/4+0.3))+(-0.6,0,0.6);
triple c2=S2((4pi/5,pi/4+0.3))+(-0.6,0,0.6);
triple c3=S2((6pi/5,pi/4+0.5))+(-0.6,0,0.6);
triple c4=S2((4pi/5,pi/4+0.5))+(-0.6,0,0.6);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }
//shift(1.1,0,0.7)
surface s1 = shift(0,0,-0.2) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(-0.6,0,0.6) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s3 = shift(-0.8,0,0.7) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);
surface s4 = shift(-0.8,0,0.7) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(35, Z) * rotate(25, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-35, Z) * rotate(25, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s7 = surface(Water, (-3,-3), (5,3));


draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

draw(s5, surfacepen=m_eyeW);
draw(s6, surfacepen=m_eyeW);

draw(s7, surfacepen=blue+opacity(0.3));


real R=0.1, r=0.04;
draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
draw(surface(sphere(c4,r)),surfacepen=m_eyeB);
\end{asypicture}
\end{filecontents*}
\usepackage{asypictureB}
\standaloneenv{asypicture}
\usepackage{pgffor}
\begin{document}
\def\myangle{45}
\foreach \X [count=\n,evaluate={\myangle=int(abs(20-\X))}] in {0,2,...,40}
{
\RequireAsyRecompile
\input{asyduck.asf}
}
\end{document}

在此处输入图片描述

(如果有人看到这个并且知道如何让水更真实、鸭子更稳定,如果他/她能与我分享这些知识就太好了。)

答案1

您可以使用animate模块进行动画。使用默认设置,这需要大量内存,但您可以将选项添加global=falseanimation构造函数:使用此选项,在生成下一帧之前,每一帧都会从内存中删除,因此内存要求与您的解决方法类似。我还添加了另一个不可见的球体来阻止鸭子跳来跳去:asy使用以下源代码运行,这将直接生成 gif:

import animate;
import graph3;
import solids;

settings.render = 4;

currentlight=(-3,-5,5);


// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple c1=S2((6pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c2=S2((4pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c3=S2((6pi/5,pi/4+0.45))+(0.5,0,1.5);
triple c4=S2((4pi/5,pi/4+0.45))+(0.5,0,1.5);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }

surface s1 = shift(1.1,0,0.7) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(0.5,0,1.5) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s4 = shift(0.3,0,1.6) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);

animation A=animation(global=false);
for(int i=20; i != -20; i -= 2) {
  int beakangle = abs(i);
  real viewangle = 4.5 - 3*beakangle*2*pi/360;

  currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1.5));
  surface s3 = shift(0.3,0,1.6) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);

  erase();

  size(10cm, 10cm);

  // from https://tex.stackexchange.com/a/227192/121799
  // draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(shift(1,1,1)*scale(2,2,2)*unitsphere,invisible);
  draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

  draw(s5, surfacepen=m_eyeW);
  draw(s6, surfacepen=m_eyeW);


  real R=0.1, r=0.04;
  draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
  draw(surface(sphere(c4,r)),surfacepen=m_eyeB);

  // Thanks to O.G.
  A.add(BBox(1cm, nullpen));
}
erase();
A.movie(delay=240);

在此处输入图片描述

由于某种原因,这会增加很多空间并使鸭子变小,所以我们有一只动画小鸭子。已修复 OG 评论。

要将其集成到 LaTeX 文件中,您可以使用包。在我的实验中,由于缺少支持asymptote,它无法使用。您必须替换为以生成 PDF 动画而不是 gif 文件。注意:您的 PDF 阅读器需要 JavaScript 支持才能显示此文件。asypictureBinlineA.movieA.pdf

\documentclass[border=3pt]{standalone}
\usepackage[inline]{asymptote}
\usepackage{animate}
\standaloneenv{asypicture}
\begin{document}
\begin{asy}
import animate;
import graph3;
import solids;

settings.render = 4;

currentlight=(-3,-5,5);


// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple c1=S2((6pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c2=S2((4pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c3=S2((6pi/5,pi/4+0.45))+(0.5,0,1.5);
triple c4=S2((4pi/5,pi/4+0.45))+(0.5,0,1.5);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }

surface s1 = shift(1.1,0,0.7) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(0.5,0,1.5) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s4 = shift(0.3,0,1.6) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);

animation A=animation(global=false);
settings.inlinetex=false;
for(int i=20; i != -20; i -= 2) {
  int beakangle = abs(i);
  real viewangle = 4.5 - 3*beakangle*2*pi/360;

  currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1.5));
  surface s3 = shift(0.3,0,1.6) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);

  erase();

  size(10cm, 10cm);

  // from https://tex.stackexchange.com/a/227192/121799
  // draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(shift(1,1,1)*scale(2,2,2)*unitsphere,invisible);
  draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

  draw(s5, surfacepen=m_eyeW);
  draw(s6, surfacepen=m_eyeW);


  real R=0.1, r=0.04;
  draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
  draw(surface(sphere(c4,r)),surfacepen=m_eyeB);

  A.add(BBox(1cm,nullpen));
}
erase();
settings.inlinetex=true;
label(A.pdf("autoplay,loop",delay=240,keep=!settings.inlinetex));
\end{asy}
\end{document}

如果已保存,则可以使用或asyduck.tex构建它latexmk

pdflatex asyduck
asy asyduck-*.asy
pdflatex asyduck
pdflatex asyduck

相关内容