Saltar al contenido

Toro de hélice 3D con líneas ocultas

Solución:

Aquí hay un enfoque de Sketch / TikZ.

Corriendo sketch en este archivo:

def helix 
    def n_segs 600
  sweep [draw=orange]  n_segs, rotate(24*360 / n_segs, (1.5,0,0), [0,0,1]), rotate(1*360/n_segs, (0,0,0), [0,1,0])  (2.01,0,0)


def torus 
    def n_segs 60
    sweep [draw=none, fill=cyan, fill opacity=0.75] n_segs, rotate(360/n_segs, (0,0,0), [0,1,0])
        sweep n_segs, rotate(360/n_segs, (1.5,0,0), [0,0,1])
        (2,0,0)


put  view((10,4,2))  helix torus

global  language tikz 

genera un .tex archivo que se puede compilar usando pdflatex.

La hélice que gira alrededor de la hélice que gira alrededor de un toro.

se puede generar usando

def helix 
    def n_segs 10000
  sweep [draw=orange] 
    n_segs,
    rotate(1000*360 / n_segs, (2,0,0), [0,1,0]),
    rotate(24*360 / n_segs, (1.5,0,0), [0,0,1]),
    rotate(1*360/n_segs, (0,0,0), [0,1,0])
   (2.04,0,0)


def torus 
    def n_segs 50
    sweep [draw=none, fill=cyan, fill opacity=0.75] n_segs, rotate(360/n_segs, (0,0,0), [0,1,0])
        sweep n_segs, rotate(360/n_segs, (1.5,0,0), [0,0,1])
        (1.9,0,0)


put  view((10,4,2))  torus helix

global  language tikz 

El ejemplo muestra la función

 x(u,v)=(R1 + (R0 +RL*sin(u))*sin(k*v))*cos(v)-RL*cos(u)*sin(v)
 y(u,v)=(R1 + (R0 +RL*sin(u))*sin(k*v))*sin(v)+RL*cos(u)*cos(v)
 z(u,v)=(R0 + RL*sin(u))*cos(k*v)

con la configuración de parámetros que se muestra en el ejemplo. RL: radio de la línea de la bobina; R1: toro externo; R0: radio interior del toro; k: número de bobinas

ejecutarlo con xelatex o latex>dvips>ps2pdf (¡lleva algo de tiempo correr!)

documentclassminimal
usepackagepst-solides3d
pagestyleempty
begindocument

beginpspicture[solidmemory](-6,-4)(6,4)
pssetviewpoint=30 0 15 rtp2xyz,Decran=30,lightsrc=viewpoint
psSolid[object=tore,r1=5,r0=1,ngrid=36 36,
    fillcolor=blue!30,action=none,name=Torus]%
%axesIIID(4.5,4.5,0)(5,5,4)
codejps/R1 5 def /RL 0.05 def /R0 1.1 def /k 25 def%
defFunction[algebraic]helix(u,v)
    (R1 + (R0 +RL*sin(u))*sin(k*v))*cos(v)-RL*cos(u)*sin(v)
    (R1 + (R0 +RL*sin(u))*sin(k*v))*sin(v)+RL*cos(u)*cos(v)
    (R0 + RL*sin(u))*cos(k*v)
psSolid[object=surfaceparametree,
       base=0 6.2831853 0 6.2831853,
       linecolor=blue,linewidth=0.01,fillcolor=yellow,
       ngrid=0.8 0.01,function=helix,action=none,name=Helix]%
psSolid[object=fusion,base=Torus Helix,grid=false]
%gridIIID[Zmin=-3,Zmax=3,showAxes=false](-2,2)(-2,2)
endpspicture

beginpspicture[solidmemory](-6,-6)(6,6)
pssetviewpoint=30 0 90 rtp2xyz,Decran=30,lightsrc=viewpoint
psSolid[object=tore,r1=5,r0=1,ngrid=36 36,
    fillcolor=blue!30,action=none,name=Torus]%
%axesIIID(4.5,4.5,0)(5,5,4)
codejps/R1 5 def /RL 0.05 def /R0 1.1 def /k 25 def%
defFunction[algebraic]helix(u,v)
    (R1 + (R0 +RL*sin(u))*sin(k*v))*cos(v)-RL*cos(u)*sin(v)
    (R1 + (R0 +RL*sin(u))*sin(k*v))*sin(v)+RL*cos(u)*cos(v)
    (R0 + RL*sin(u))*cos(k*v)
psSolid[object=surfaceparametree,
       base=0 6.2831853 0 6.2831853,
       linecolor=blue,linewidth=0.01,fillcolor=yellow,
       ngrid=0.8 0.01,function=helix,action=none,name=Helix]%
psSolid[object=fusion,base=Torus Helix,grid=false]
%gridIIID[Zmin=-3,Zmax=3,showAxes=false](-2,2)(-2,2)
endpspicture

enddocument

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

una animación está aquí: http://tug.org/PSTricks/main.cgi?file=Animation/gif/gif

Con psSolid[object=fusion,base=Torus Helix,grid=false,opacity=0.5]
 (configuración de transparencia) y una hélice más delgada (disminución / RL) se obtiene

ingrese la descripción de la imagen aquí

y solo por diversión con

listfiles
documentclassminimal
usepackagepst-solides3d
begindocument
beginpspicture[solidmemory](-6.5,-3.5)(6.5,3)
pssetviewpoint=30 0 15 rtp2xyz,Decran=30,lightsrc=viewpoint
psSolid[object=tore,r1=5,r0=1,ngrid=36 36,tablez=0 0.05 1  for,
          zcolor= 1 .5 .5 .5 .5 1,action=none,name=Torus]
pstVerb/R1 5 def /R0 1.2 def /k 20 def /RL 0.15 def /kRL 40 def%
defFunction[algebraic]helix(t)
     (R1+R0*cos(k*t))*sin(t)+RL*sin(kRL*k*t)
     (R1+R0*cos(k*t))*cos(t)+RL*cos(kRL*k*t)
     R0*sin(k*t)+RL*sin(kRL*k*t)
psSolid[object=courbe,
        resolution=7800,
        fillcolor=black,incolor=black,
        r=0,
        range=0 6.2831853,
        function=helix,action=none,name=Helix]%
psSolid[object=fusion,base=Torus Helix,grid]
endpspicture
enddocument

ingrese la descripción de la imagen aquí

Actualizado: Incluye soluciones para dificultades anteriores con la compilación de rutas complejas.

Aquí hay un enfoque de asíntota que permite hélices de enésimo orden. Muestro ejemplos de una hélice de primer orden (que se envuelve una vez alrededor del toro, como en la pregunta original), una hélice de segundo orden y una hélice de tercer orden.

Aquí está el código (configurado para una hélice de primer orden):

settings.outformat = "png";
settings.render = 16;
settings.prc = false;
real unit = 2cm;
unitsize(unit);

import graph3;

void drawsafe(path3 longpath, pen p, int maxlength = 400) 
  int length = length(longpath);
  if (length <= maxlength) draw(longpath, p);
  else 
    int divider = floor(length/2);
    drawsafe(subpath(longpath, 0, divider), p=p, maxlength=maxlength);
    drawsafe(subpath(longpath, divider, length), p=p, maxlength=maxlength);
  


struct helix 
  path3 center;
  path3 helix;
  int numloops;
  int pointsperloop = 12;
  /* t should range from 0 to 1*/
  triple centerpoint(real t) 
    return point(center, t*length(center));
  
  triple helixpoint(real t) 
    return point(helix, t*length(helix));
  
  triple helixdirection(real t) 
    return dir(helix, t*length(helix));
  
  /* the vector from the center point to the point on the helix */
  triple displacement(real t) 
    return helixpoint(t) - centerpoint(t);
  
  bool iscyclic() 
    return cyclic(helix);
  


path3 operator cast(helix h) 
  return h.helix;


helix helixcircle(triple c = O, real r = 1, triple normal = Z) 
  helix toreturn;
  toreturn.center = c;
  toreturn.helix = Circle(c=O, r=r, normal=normal, n=toreturn.pointsperloop);
  toreturn.numloops = 1;
  return toreturn;


helix helixAbout(helix center, int numloops, real radius) 
  helix toreturn;
  toreturn.numloops = numloops;
  from toreturn unravel pointsperloop;
  toreturn.center = center.helix;
  int n = numloops * pointsperloop;
  triple[] newhelix;
  for (int i = 0; i <= n; ++i) 
    real theta = (i % pointsperloop) * 2pi / pointsperloop;
    real t = i / n;
    triple ihat = unit(center.displacement(t));
    triple khat = center.helixdirection(t);
    triple jhat = cross(khat, ihat);
    triple newpoint = center.helixpoint(t) + radius*(cos(theta)*ihat + sin(theta)*jhat);
    newhelix.push(newpoint);
  
  toreturn.helix = graph(newhelix, operator ..);
  return toreturn;


int loopfactor = 20;
real radiusfactor = 1/8;
helix wrap(helix input, int order, int initialloops = 10, real initialradius = 0.6, int loopfactor=loopfactor) 
  helix toreturn = input;
  int loops = initialloops;
  real radius = initialradius;
  for (int i = 1; i <= order; ++i) 
    toreturn = helixAbout(toreturn, loops, radius);
    loops *= loopfactor;
    radius *= radiusfactor;
  
  return toreturn;


currentprojection = perspective(12,0,6);

helix circle = helixcircle(r=2, c=O, normal=Z);

/* The variable part of the code starts here. */
int order = 1;    // This line varies.
real helixradius = 0.5;
real safefactor = 1;
for (int i = 1; i < order; ++i)
  safefactor -= radiusfactor^i;
real saferadius = helixradius * safefactor;

helix todraw = wrap(circle, order=order, initialradius = helixradius);    // This line varies (optional loopfactor parameter).

surface torus = surface(Circle(c=2X, r=0.99*saferadius, normal=-Y, n=32), c=O, axis=Z, n=32);
material toruspen = material(diffusepen=gray, ambientpen=white);
draw(torus, toruspen);

drawsafe(todraw, p=0.5purple+linewidth(1pt));  // This line varies (linewidth only).

La salida:

Para una hélice de segundo orden, cambie la última parte del código anterior a lo siguiente:

/* The variable part of the code starts here. */
int order = 2;    // This line varies.
real helixradius = 0.5;
real safefactor = 1;
for (int i = 1; i < order; ++i)
  safefactor -= radiusfactor^i;
real saferadius = helixradius * safefactor;

helix todraw = wrap(circle, order=order, initialradius = helixradius, loopfactor=40);    // This line varies (optional loopfactor parameter).

surface torus = surface(Circle(c=2X, r=0.99*saferadius, normal=-Y, n=32), c=O, axis=Z, n=32);
material toruspen = material(diffusepen=gray, ambientpen=white);
draw(torus, toruspen);

drawsafe(todraw, p=0.5purple+linewidth(0.6pt));  // This line varies (linewidth only).

La salida:

ingrese la descripción de la imagen aquí

Para una hélice de tercer orden, cambie la parte "variable" del código a lo siguiente:

/* The variable part of the code starts here. */
int order = 3;    // This line varies.
real helixradius = 0.5;
real safefactor = 1;
for (int i = 1; i < order; ++i)
  safefactor -= radiusfactor^i;
real saferadius = helixradius * safefactor;

helix todraw = wrap(circle, order=order, initialradius = helixradius);    // This line varies (optional loopfactor parameter).

surface torus = surface(Circle(c=2X, r=0.99*saferadius, normal=-Y, n=32), c=O, axis=Z, n=32);
material toruspen = material(diffusepen=gray, ambientpen=white);
draw(torus, toruspen);

drawsafe(todraw, p=0.5purple+linewidth(0.2pt));  // This line varies (linewidth only).

La salida:

ingrese la descripción de la imagen aquí

Un comentario final: el mecanismo de renderizado en Asymptote para superficies translúcidas no funciona bien con más de una capa de superficie translúcida (es decir, cuando una superficie translúcida está oscureciendo otra superficie translúcida (o parte de una)). Aquí tienes un ejemplo de la dificultad:

Esto es un poco menos notorio en la respuesta de mrc, pero sigue ahí, al menos por ahora.

Sin embargo, esta dificultad se puede mitigar (cuando solo está involucrada una superficie y no tiene autointersecciones) clasificando los parches constituyentes para que se dibujen en orden de distancia desde la cámara:

settings.outformat = "png";
settings.render = 16;
settings.prc = false;
real unit = 2cm;
unitsize(unit);

import graph3;

void drawsafe(path3 longpath, pen p, int maxlength = 400) 
  int length = length(longpath);
  if (length <= maxlength) draw(longpath, p);
  else 
    int divider = floor(length/2);
    drawsafe(subpath(longpath, 0, divider), p=p, maxlength=maxlength);
    drawsafe(subpath(longpath, divider, length), p=p, maxlength=maxlength);
  


void sort(surface s) 
  projection P = currentprojection;
  //The following code is copied from three_surface.asy
  // Sort patches by mean distance from camera
  triple camera=P.camera;
  if(P.infinity) 
    triple m=min(s);
    triple M=max(s);
    camera=P.target+camerafactor*(abs(M-m)+abs(m-P.target))*unit(P.vector());
  

  real[][] depth=new real[s.s.length][];
  for(int i=0; i < depth.length; ++i)
    depth[i]=new real[] abs(camera-s.s[i].cornermean()),i;

  depth=sort(depth);
  //end of copied code

  int[] permutation = sequence(new int(int i) return (int)depth[i][4];, depth.length);

  int[][] inversionTool = new int[permutation.length][5];
  for (int i = 0; i < permutation.length; ++i)
    inversionTool[i] = new int[] permutation[i], i;
  inversionTool = sort(inversionTool);
  int inverse(int i) return inversionTool[i][6];;

  patch[] sortedS = new patch[depth.length];
  for (int i = 0; i < sortedS.length; ++i) 
    sortedS[i] = s.s[permutation[i]];
  
  s.s = sortedS;

  for (int[] currentrow : s.index)
    for (int i = 0; i < currentrow.length; ++i)
      currentrow[i] = inverse(currentrow[i]);


struct helix 
  path3 center;
  path3 helix;
  int numloops;
  int pointsperloop = 12;
  /* t should range from 0 to 1*/
  triple centerpoint(real t) 
    return point(center, t*length(center));
  
  triple helixpoint(real t) 
    return point(helix, t*length(helix));
  
  triple helixdirection(real t) 
    return dir(helix, t*length(helix));
  
  /* the vector from the center point to the point on the helix */
  triple displacement(real t) 
    return helixpoint(t) - centerpoint(t);
  
  bool iscyclic() 
    return cyclic(helix);
  


path3 operator cast(helix h) 
  return h.helix;


helix helixcircle(triple c = O, real r = 1, triple normal = Z) 
  helix toreturn;
  toreturn.center = c;
  toreturn.helix = Circle(c=O, r=r, normal=normal, n=toreturn.pointsperloop);
  toreturn.numloops = 1;
  return toreturn;


helix helixAbout(helix center, int numloops, real radius) 
  helix toreturn;
  toreturn.numloops = numloops;
  from toreturn unravel pointsperloop;
  toreturn.center = center.helix;
  int n = numloops * pointsperloop;
  triple[] newhelix;
  for (int i = 0; i <= n; ++i) 
    real theta = (i % pointsperloop) * 2pi / pointsperloop;
    real t = i / n;
    triple ihat = unit(center.displacement(t));
    triple khat = center.helixdirection(t);
    triple jhat = cross(khat, ihat);
    triple newpoint = center.helixpoint(t) + radius*(cos(theta)*ihat + sin(theta)*jhat);
    newhelix.push(newpoint);
  
  toreturn.helix = graph(newhelix, operator ..);
  return toreturn;


int loopfactor = 20;
real radiusfactor = 1/8;
helix wrap(helix input, int order, int initialloops = 10, real initialradius = 0.6, int loopfactor=loopfactor) 
  helix toreturn = input;
  int loops = initialloops;
  real radius = initialradius;
  for (int i = 1; i <= order; ++i) 
    toreturn = helixAbout(toreturn, loops, radius);
    loops *= loopfactor;
    radius *= radiusfactor;
  
  return toreturn;


currentprojection = perspective(12,0,6);

helix circle = helixcircle(r=2, c=O, normal=Z);

/* The variable part of the code starts here. */
int order = 1;    // This line varies.
real helixradius = 0.5;
real safefactor = 1;
for (int i = 1; i < order; ++i)
  safefactor -= radiusfactor^i;
real saferadius = helixradius * safefactor;

helix todraw = wrap(circle, order=order, initialradius = helixradius);    // This line varies (optional loopfactor parameter).

surface torus = surface(Circle(c=2X, r=0.99*saferadius, normal=-Y, n=32), c=O, axis=Z, n=32);
sort(torus);
material toruspen = material(diffusepen=gray + opacity(0.5), ambientpen=white);
draw(torus, toruspen);

drawsafe(todraw, p=0.4magenta+linewidth(1pt));  // This line varies (linewidth only).

Recuerda que te concedemos agregar una reseña si te fue útil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *