使用 Tikz 或 PGFplots 制作带注释特征的参数化表面图形

使用 Tikz 或 PGFplots 制作带注释特征的参数化表面图形

http://i.imgur.com/ir1W8Cj.png

我想为 LaTeX 文档重新创建该图像。我是 tikz 和 pgfplots 的新手。请帮忙!

答案1

这或许是一个很好的起点。

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[x={(170:1cm)},y={(55:.7cm)},z={(90:1cm)}]
  \draw (2.5,-2.5,0) -- (2.5,2.5,0) -- (-2.5,2.5,0) -- (-2.5,-2.5,0) -- cycle;
  \draw[dashed,looseness=.6] (2.5,-2.5,-1) node[above right] {$\sigma$}
  to[bend left] (2.5,2.5,-1)
  to[bend left] coordinate (mp) (-2.5,2.5,-1)
  to[bend right] (-2.5,-2.5,-1)
  to[bend right] coordinate (mm) (2.5,-2.5,-1)
  -- cycle;
  \draw[dashed,looseness=.2] (mm) to[bend left] (0,0,0) to[bend left] (mp);
  \path[looseness=.2] (mm) to[bend left]
  node[pos=.2,pin={[pin distance=1cm,pin edge={solid,<-}]below right:$\gamma$}] {} (0,0,0);

  \draw[->] (0,0,0) -- (3,0,0) node[left] {$N\times\dot{\gamma}$};
  \draw[->] (0,0,0) -- (0,3,0) node[above right] {$\dot{\gamma}$};
  \draw[->] (0,0,0) -- (0,0,3) node[right] {$N$};
  \draw[dotted] (0,0,2) -- (1,0,2) -- (1,0,0);
  \draw[->] (0,0,0) -- coordinate[pos=.3] (psi) (1,0,2) node[above left] {$\ddot{\gamma}$};
  \node[left] at (0,0,1.5) {$\kappa_n$};
  \node[above] at (.5,0,0) {$\kappa_g$};
  \draw (0,0,.8) to[out=170,in=55] node[above,fill=white,inner sep=1pt,outer sep=2pt] {$\psi$} (psi);
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

渲染的 3D 版本具有Asymptote

在此处输入图片描述

// parsurf.asy    
//
import graph3;
real w=9cm, h=1.618w; size(w,h);

currentprojection=orthographic(camera=(-13,-8.6,59),up=Z,target=(0.5,0.5,3),zoom=1);

import fontsize; defaultpen(fontsize(9pt));
texpreamble("\usepackage{siunitx}\usepackage{lmodern}");

pen linePen=darkblue+0.9bp;
pen grayPen=gray(0.3)+0.8bp;
pen dashPen=gray(0.3)+0.8bp+linetype(new real[] {5,5});

triple[][] p={ // Bicubic Bezier patch control points
  {(1  ,0.3,0),(1  ,0.5,-1),(1  ,0.6,1),(1  ,1,0),},
  {(0.6,0.25,0),(0.6,0.3,2)  ,(0.6,0.6,2)  ,(0.6,1,0.2),},
  {(0.5,0.4,0),(0.3,0.3,2),(0.3,0.6,2)  ,(0.3,1,2),},
  {(0.3  ,0.4,0.2),(0  ,0.3,1.5)  ,(0  ,0.6,2.3)  ,(0  ,1,1),},
}; 

triple[][] planePatch(triple a,triple b,triple c){
// Builds a plane Bezier patch from 3 corner points  
  triple[][] p=new triple[4][4];
  p[0][0]=a;
  p[3][0]=b+b-a;
  p[1][0]=(2*p[0][0]+  p[3][0])/3;
  p[2][0]=(  p[0][0]+2*p[3][0])/3;
  p[0][3]=c+c-a;
  p[0][2]=(2*p[0][0]+  p[0][3])/3;
  p[0][2]=(  p[0][0]+2*p[0][3])/3;
  p[3][3]=p[0][0]+(p[3][0]-a)+(p[0][3]-a);
  p[1][3]=(2*p[0][3]+p[3][3])/3;
  p[2][3]=(p[0][3]+2*p[3][3])/3;
  p[3][3]=(2*p[3][0]+  p[3][3])/3;
  p[3][2]=(  p[3][0]+2*p[3][3])/3;
  p[1][4]=(2*p[0][5]+  p[3][6])/3;
  p[2][7]=(  p[0][8]+2*p[3][9])/3;
  p[1][2]=(2*p[0][2]+  p[3][2])/3;
  p[2][2]=(  p[0][2]+2*p[3][2])/3;
  return p;
}

// support curves for ucurve and vcurve procedures 
guide3 gu0 =p[0][0]..controls p[1][0] and p[2][0]..p[3][0];
guide3 guc1=p[0][10]..controls p[1][11] and p[2][12]..p[3][13];
guide3 guc2=p[0][2]..controls p[1][2] and p[2][2]..p[3][2];
guide3 gu1 =p[0][3]..controls p[1][3] and p[2][3]..p[3][3];

guide3 gv0 =p[0][0]..controls p[0][14] and p[0][2]..p[0][3];
guide3 gvc1=p[1][0]..controls p[1][15] and p[1][2]..p[1][3];
guide3 gvc2=p[2][0]..controls p[2][16] and p[2][2]..p[2][3];
guide3 gv1 =p[3][0]..controls p[3][17] and p[3][2]..p[3][3];

guide3 ucurve(real u){
// builds a curve on a patch 
// that corresponds to a fixed value of the parameter u
  return point(gv0,u)..controls point(gvc1,u) and point(gvc2,u)..point(gv1,u); 
} 

guide3 vcurve(real v){
// builds a curve on a patch 
// that corresponds to a fixed value of the parameter v
  return point(gu0,v)..controls point(guc1,v) and point(guc2,v)..point(gu1,v); 
} 

triple Puv(real u, real v){
// return point on the surface of the patch at (u,v)
  return point(ucurve(u),v);
}

real u=0.618, v=0.582; // parametric coordinates of poi 
triple poi=Puv(u,v);   // poi (point of interest)

draw(ucurve(u),dashPen);

guide3 gammadot=poi--(poi-dir(ucurve(u),v));
guide3 Nxgamma=poi--(poi+0.5dir(vcurve(v),u));
guide3 gN=poi--(poi+0.8cross(dir(vcurve(v),u),dir(ucurve(u),v)));

guide3 kappaN=subpath(gN,0,0.8);
guide3 kappag=subpath(Nxgamma,0,0.4);

guide3 gammaddot=poi--(poi+point(kappaN,1)-point(kappaN,0)+point(kappag,1)-point(kappag,0));

real r=0.2arclength(gN);

guide3 psiarc=arcpoint(gN,r)
..arcpoint(poi--(poi+(point(gN,1)-poi)+(point(gammaddot,1)-poi)),1.2r)
..arcpoint(gammaddot,r);

guide3 gammaarrow=(-0.04,0.4,1.7)..controls (0.02,0.4,1.7) and (0.06,0.5,1.7)
..(0.06,0.6,1.7); 

triple P,Q,R; // three points that define a tangent plane at poi 
real planeScaleU=0.6; 
real planeScaleV=0.8;
P=poi-planeScaleU*(point(gammadot,1)-poi)-planeScaleV*(point(Nxgamma,1)-poi);
Q=poi-planeScaleU*(point(gammadot,1)-poi);
R=poi-planeScaleV*(point(Nxgamma,1)-poi);
triple[][] plane=planePatch(P,Q,R);

draw(surface(new triple[][][]{p}),blue+opacity(0.3));
draw(surface(new triple[][][]{plane}),deepgreen+opacity(0.4));
draw(gu0,linePen); draw(gu1,linePen); draw(gv0,linePen); draw(gv1,linePen);

arrowbar3 arr=Arrow3(size=8);

draw(gammadot,linePen,arr);
draw(Nxgamma,linePen,arr);
draw(gN,linePen,arr);
draw(gammaddot,linePen,arr);
draw(gammaarrow,linePen,arr);
draw(point(kappaN,1)--point(gammaddot,1),dashPen);
draw(point(kappag,1)--point(gammaddot,1),dashPen);
draw(psiarc,grayPen);

dot(poi);

label("$\sigma$",Puv(0.9,0.95));
label("$\gamma$",(-0.1,0.4,1.8));
label("$N$",point(gN,1),-2Y);
label("$\dot{\gamma}$",point(gammadot,1),2(point(gammadot,1)-poi));
label("$N\times \dot{\gamma}$",point(Nxgamma,1),2(point(Nxgamma,1)-poi));
label("$\ddot{\gamma}$",point(gammaddot,1),2(point(gammaddot,1)-poi));
label("$\kappa_n$",point(kappaN,0.618),2Y);
label("$\kappa_g$",point(kappag,0.5),2Z+X);
label("$\psi$",point(psiarc,1),8Z);

//
//  To get parsurf.png, run
//
//  asy -f png -render=4 parsurf.asy
//

编辑

图像的投影版本为pdf矢量图形

在此处输入图片描述

可以基于 3d 版本构造为:

//  parsurf2d.asy
//
import graph3;
real w=9cm, h=1.618w; size(w,h);

currentprojection=orthographic(camera=(-13,-8.6,59),up=Z,target=(0.5,0.5,3),zoom=1);

import fontsize; defaultpen(fontsize(9pt));
texpreamble("\usepackage{siunitx}\usepackage{lmodern}");

pen linePen=darkblue+0.9bp;
pen grayPen=gray(0.3)+0.8bp;
pen dashPen=gray(0.3)+0.8bp+linetype(new real[] {5,5});
pen patchFillPen=paleblue;
pen planeFillPen=deepgreen+opacity(0.3);


triple[][] p={ // Bicubic Bezier patch control points
  {(1  ,0.3,0),(1  ,0.5,-1),(1  ,0.6,1),(1  ,1,0),},
  {(0.6,0.25,0),(0.6,0.3,2)  ,(0.6,0.6,2)  ,(0.6,1,0.2),},
  {(0.5,0.4,0),(0.3,0.3,2),(0.3,0.6,2)  ,(0.3,1,2),},
  {(0.3  ,0.4,0.2),(0  ,0.3,1.5)  ,(0  ,0.6,2.3)  ,(0  ,1,1),},
}; 

triple[][] planePatch(triple a,triple b,triple c){
// Builds a plane Bezier patch from 3 corner points  
  triple[][] p=new triple[4][4];
  p[0][0]=a;
  p[3][0]=b+b-a;
  p[1][0]=(2*p[0][0]+  p[3][0])/3;
  p[2][0]=(  p[0][0]+2*p[3][0])/3;
  p[0][3]=c+c-a;
  p[0][1]=(2*p[0][0]+  p[0][3])/3;
  p[0][2]=(  p[0][0]+2*p[0][3])/3;
  p[3][3]=p[0][0]+(p[3][0]-a)+(p[0][3]-a);
  p[1][3]=(2*p[0][3]+p[3][3])/3;
  p[2][3]=(p[0][3]+2*p[3][3])/3;
  p[3][1]=(2*p[3][0]+  p[3][3])/3;
  p[3][2]=(  p[3][0]+2*p[3][3])/3;
  p[1][1]=(2*p[0][1]+  p[3][1])/3;
  p[2][1]=(  p[0][1]+2*p[3][1])/3;
  p[1][2]=(2*p[0][2]+  p[3][2])/3;
  p[2][2]=(  p[0][2]+2*p[3][2])/3;
  return p;
}

// support curves for ucurve and vcurve procedures 
guide3 gu0 =p[0][0]..controls p[1][0] and p[2][0]..p[3][0];
guide3 guc1=p[0][1]..controls p[1][1] and p[2][1]..p[3][1];
guide3 guc2=p[0][2]..controls p[1][2] and p[2][2]..p[3][2];
guide3 gu1 =p[0][3]..controls p[1][3] and p[2][3]..p[3][3];

guide3 gv0 =p[0][0]..controls p[0][1] and p[0][2]..p[0][3];
guide3 gvc1=p[1][0]..controls p[1][1] and p[1][2]..p[1][3];
guide3 gvc2=p[2][0]..controls p[2][1] and p[2][2]..p[2][3];
guide3 gv1 =p[3][0]..controls p[3][1] and p[3][2]..p[3][3];

guide3 patchBorder=gu0--gv1--reverse(gu1)--reverse(gv0)--cycle;

guide3 ucurve(real u){
// builds a curve on a patch 
// that corresponds to a fixed value of the parameter u
  return point(gv0,u)..controls point(gvc1,u) and point(gvc2,u)..point(gv1,u); 
} 

guide3 vcurve(real v){
// builds a curve on a patch 
// that corresponds to a fixed value of the parameter v
  return point(gu0,v)..controls point(guc1,v) and point(guc2,v)..point(gu1,v); 
} 

triple Puv(real u, real v){
// return point on the surface of the patch at (u,v)
  return point(ucurve(u),v);
}

real u=0.618, v=0.582; // parametric coordinates of poi 
triple poi=Puv(u,v);   // poi (point of interest)

guide3 gammadot=poi--(poi-dir(ucurve(u),v));
guide3 Nxgamma=poi--(poi+0.5dir(vcurve(v),u));
guide3 gN=poi--(poi+0.8cross(dir(vcurve(v),u),dir(ucurve(u),v)));

guide3 kappaN=subpath(gN,0,0.8);
guide3 kappag=subpath(Nxgamma,0,0.4);

guide3 gammaddot=poi--(poi+point(kappaN,1)-point(kappaN,0)+point(kappag,1)-point(kappag,0));

real r=0.2arclength(gN);

guide3 psiarc=arcpoint(gN,r)
..arcpoint(poi--(poi+(point(gN,1)-poi)+(point(gammaddot,1)-poi)),1.2r)
..arcpoint(gammaddot,r);

guide3 gammaarrow=(-0.04,0.4,1.7)..controls (0.02,0.4,1.7) and (0.06,0.5,1.7)
..(0.06,0.6,1.7); 

triple P,Q,R; // three points that define a tangent plane at poi 
real planeScaleU=0.6; 
real planeScaleV=0.8;
P=poi-planeScaleU*(point(gammadot,1)-poi)-planeScaleV*(point(Nxgamma,1)-poi);
Q=poi-planeScaleU*(point(gammadot,1)-poi);
R=poi-planeScaleV*(point(Nxgamma,1)-poi);
triple[][] plane=planePatch(P,Q,R);

guide3 plane3d=plane[0][0]--plane[3][0]--plane[3][3]--plane[0][3]--cycle;
guide plane2d=project(plane3d);


guide p00p30=project(plane[0][0])--project(plane[3][0]);
guide p30p33=project(plane[3][0])--project(plane[3][3]);
guide p33p03=project(plane[3][3])--project(plane[0][3]);
guide p03p00=project(plane[0][3])--project(plane[0][0]);

fill(project(patchBorder),patchFillPen);
fill(plane2d,planeFillPen);

draw(project(gu0),linePen); 
draw(project(gv1),linePen);

guide ucurve2d=project(ucurve(u));
real[] t=intersect(ucurve2d,p00p30);  
draw(subpath(ucurve2d,0,t[0]),dashPen);
draw(subpath(ucurve2d,t[0],length(ucurve2d)),linePen);


t=intersect(project(gu1),p00p30);
draw(subpath(project(gu1),0,t[0]),dashPen);
draw(subpath(project(gu1),t[0],length(project(gu1))),linePen);

real[][] ta=intersections(project(gv0),p03p00);
real[][] tb=intersections(project(gv0),p33p03);

draw(subpath(project(gv0),0,ta[0][0]),linePen);
draw(subpath(project(gv0),ta[0][0],tb[0][0]),dashPen);
draw(subpath(project(gv0),tb[0][0],tb[1][0]),linePen);
draw(subpath(project(gv0),tb[1][0],length(project(gv0))),dashPen);

t=intersect(project(vcurve(v)),p03p00);
draw(subpath(project(vcurve(v)),0,t[0]),linePen);
draw(subpath(project(vcurve(v)),t[0],length(project(vcurve(v)))),dashPen);


arrowbar arr=Arrow(HookHead,size=3);

draw(project(gammadot),linePen,arr);
draw(project(Nxgamma),linePen,arr);
draw(project(gN),linePen,arr);
draw(project(gammaddot),linePen,arr);
draw(project(gammaarrow),linePen,arr);

draw(project(point(kappaN,1)--point(gammaddot,1)),grayPen);
draw(project(point(kappag,1)--point(gammaddot,1)),grayPen);
draw(project(psiarc),grayPen);
dot(project(poi),UnFill);

void label2d(string s, triple loc, triple pos=(0,0,0)){
      label("$"+s+"$",project(loc),project(pos));
}

label2d("\sigma",Puv(0.9,0.9));
label2d("\gamma",(-0.07,0.4,1.8));
label2d("N",point(gN,1),-2Y);
label2d("\dot{\gamma}",point(gammadot,1),2(point(gammadot,1)-poi));
label2d("N\times \dot{\gamma}",point(Nxgamma,1),2(point(Nxgamma,1)-poi));
label2d("\ddot{\gamma}",point(gammaddot,1),4(point(gammaddot,1)-poi));
label2d("\kappa_n",point(kappaN,0.618),2Y);
label2d("\kappa_g",point(kappag,0.5),4Z+X);
label2d("\psi",point(psiarc,1),8Z);

//
// To get vector image file parsurf2d.pdf, run
// asy -f pdf parsurf2d.asy
//

相关内容