Cerrar las esquinas de una rejilla (de tubos) sobre una superficie en asíntota

Cerrar las esquinas de una rejilla (de tubos) sobre una superficie en asíntota

Considere el siguiente dibujo simple de la superficie de una silla de montar usandoasymptote

import graph3;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

surface saddle=surface(f,(-2,-2),(2,2),nx=5,Spline);

draw(saddle,gray,0.1+blue);

y eche un vistazo a la instantánea del resultado:

instantánea de la salida

Probablemente puedas ver la forma desagradable en que los tubos, que forman las líneas de la rejilla, se unen en las esquinas de la superficie. Probablemente podría agregar, manualmente, bolas del radio correcto en las esquinas como solución alternativa. Por ejemplo, agregue la siguiente línea:

draw(shift(-2,-2,f((-2,-2)))*scale(0.05,0.05,0.05)*unitsphere,blue);

y obtener la siguiente mejora: ingrese la descripción de la imagen aquí

Me pregunto ¿hay una mejor manera? ¿Cómo debo cerrar bien las conexiones de las líneas de la rejilla (tubos para ser más precisos)?

Respuesta1

Como regla general, a menos que use settings.render=0, recomiendo no usar la meshpenopción al dibujar una superficie. Dibujar la malla usted mismo tiene una serie de ventajas; Resolver su problema es una de las ventajas menos importantes.

settings.outformat="png";
settings.render=8;
unitsize(1cm);

import graph3;

currentprojection=perspective(5,5,5);

pen meshpen = 2pt + 0.7blue + 0.1green;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

surface saddle=surface(f,(-2,-2),(2,2),nx=5,Spline);

draw(saddle, surfacepen=gray);

for(int x = -2; x <= 2; ++x) {
  draw(graph(new triple(real y) {return (x,y,f((x,y)) );}, -2, 2), meshpen);
}
for (int y = -2; y <= 2; ++y) {
  draw(graph(new triple(real x) {return (x,y,f((x,y)) );}, -2, 2), meshpen);
}

tiene resultado

ingrese la descripción de la imagen aquí

Tenga en cuenta que generalmente prefiero líneas de cuadrícula mucho más delgadas, pero las he hecho gruesas para que pueda ver si su problema aparece.

Por otro lado, si realmente quieres que las líneas de la cuadrícula sean gruesas y sombreadas como tubos, entonces tu solución es bastante buena; Básicamente, estás agregando tapas redondas a las líneas (lo cual se hace automáticamente cuando dibujas las líneas de la cuadrícula sin sombreado de tubo). Si desea dibujar caminos tubulares a mano, debe consultar el tubemétodo, que se describe en la sección del manual del threemódulo (p. 134 en el manual de la asíntota 2.23). Una alternativa al uso de este enfoque sería dibujar (un tubo para) la ruta cíclica en el borde del gráfico, en lugar de dibujar las líneas de la cuadrícula en el borde de la cuadrícula o además de dibujarlas.


Actualización: Aquí se explica cómo dibujar la malla a mano (con tubos y un contorno separado). Cambié el nombre del bolígrafo para evitar confusiones. Tenga en cuenta que el operador &sirve para concatenar dos rutas que comparten un punto final.

settings.outformat="png";
settings.render=8;
unitsize(1cm);

import graph3;

surface operator cast(tube t) {
  return t.s;
}

currentprojection=perspective(5,5,5);

pen gridpen = blue;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

int xmin = -2, xmax=2, ymin=-2, ymax=2;

surface saddle=surface(f,(xmin,ymin),(xmax,ymax),nx=5,Spline);

draw(saddle, surfacepen=gray);

int nx=5, ny=5;

path3 x_equals(real x) {
  return graph(new triple(real y) {return (x,y,f((x,y)));}, ymin, ymax);
}
path3 y_equals(real y) {
  return graph(new triple(real x) {return (x,y,f((x,y)));}, xmin, xmax);
}

real tubewidth = 0.1;

for(int i = 1; i < nx; ++i) {
  real x = (xmax-xmin)*(i/nx) + xmin;
  surface todraw = tube(x_equals(x), width=tubewidth);
  draw(todraw, gridpen);
}
for (int i = 1; i < ny; ++i) {
  real y = (ymax-ymin)*(i/ny) + ymin;
  surface todraw = tube(y_equals(y), width=tubewidth);
  draw(todraw, gridpen);
}

path3 outline = x_equals(xmin) & y_equals(ymax) & reverse(x_equals(xmax)) & reverse(y_equals(ymin)) & cycle;
draw(tube(outline,width=tubewidth), gridpen);

El resultado:

ingrese la descripción de la imagen aquí

Respuesta2

Aquí está la solución que mencioné en el OP.

import graph3;

real gridWidth=0.05;
pen  gridPen=blue;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

void fillGap (pair p) {
  real width=0.5*gridWidth;
  draw(shift(p.x,p.y,f(p))*scale(width,width,width)*unitsphere,gridPen);
}

real minVal = -2;
real maxVal = -minVal;

surface saddle=surface(f,(minVal,minVal),(maxVal,maxVal),nx=5,Spline);

draw(saddle,gray+opacity(0.95),gridWidth+gridPen);

fillGap((minVal,minVal));
fillGap((minVal,maxVal));
fillGap((maxVal,minVal));
fillGap((maxVal,maxVal));

Definí algunos parámetros adicionales y una función que puede ayudar a dibujar la esfera en los lugares correctos.

información relacionada