![Закройте углы сетки (трубок) на поверхности в асимптоте](https://rvso.com/image/281492/%D0%97%D0%B0%D0%BA%D1%80%D0%BE%D0%B9%D1%82%D0%B5%20%D1%83%D0%B3%D0%BB%D1%8B%20%D1%81%D0%B5%D1%82%D0%BA%D0%B8%20(%D1%82%D1%80%D1%83%D0%B1%D0%BE%D0%BA)%20%D0%BD%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D1%85%D0%BD%D0%BE%D1%81%D1%82%D0%B8%20%D0%B2%20%D0%B0%D1%81%D0%B8%D0%BC%D0%BF%D1%82%D0%BE%D1%82%D0%B5.png)
Рассмотрим следующий простой рисунок седловой поверхности с использованиемasymptote
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);
и взгляните на снимок вывода:
Вы, вероятно, видите неприятный способ, которым трубки, которые формируют линии сетки, соединяются в углах поверхности. Я, вероятно, мог бы вручную добавить шарики нужного радиуса в углах в качестве обходного пути. Например, добавьте следующую строку:
draw(shift(-2,-2,f((-2,-2)))*scale(0.05,0.05,0.05)*unitsphere,blue);
и получить следующее улучшение:
Интересно, есть ли способ получше? Как мне аккуратно закрыть соединения линий сетки (точнее трубок)?
решение1
Как правило, если вы не используете settings.render=0
, я не рекомендую использовать meshpen
опцию при рисовании поверхности. Рисование сетки самостоятельно имеет ряд преимуществ; решение вашей проблемы — одно из наименее значимых преимуществ.
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);
}
имеет результат
Обратите внимание, что я обычно предпочитаю более тонкие линии сетки, но эти сделал толстыми, чтобы вы могли увидеть, проявляется ли проблема.
С другой стороны, если вы действительно хотите, чтобы линии сетки были толстыми и затененными как трубки, то ваше решение довольно хорошее; по сути, вы добавляете круглые колпачки к линиям (что делается автоматически, когда вы рисуете линии сетки без затенения трубок). Если вы хотите рисовать трубчатые пути вручную, вам следует проверить метод tube
, который описан в разделе руководства по three
модулю (стр. 134 в руководстве для Asymptote 2.23). Альтернативой использования этого подхода было бы рисование (трубки для) циклического пути на краю графика вместо или в дополнение к рисованию линий сетки на краю сетки.
Обновление: Вот как нарисовать сетку вручную (с трубками и отдельным контуром). Я изменил название пера, чтобы избежать путаницы. Обратите внимание, что оператор &
предназначен для объединения двух путей, которые имеют общую конечную точку.
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);
Результат:
решение2
Вот обходной путь, о котором я упомянул в 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));
Я определил некоторые дополнительные параметры и функцию, которые могут помочь нарисовать сферу в нужных местах.