다음을 사용하여 안장 표면을 그리는 간단한 그림을 살펴보세요.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);
}
결과가 있음
저는 일반적으로 훨씬 얇은 눈금선을 선호하지만 실제로 문제가 나타나는지 확인할 수 있도록 눈금선을 두껍게 만들었습니다.
반면에 실제로 눈금선을 두껍고 튜브처럼 음영 처리하려는 경우 솔루션은 꽤 좋은 솔루션입니다. 기본적으로 선에 둥근 캡을 추가합니다(튜브 음영 없이 격자선을 그릴 때 자동으로 수행됨). 튜브형 경로를 손으로 그리려면 모듈의 매뉴얼 섹션(Asymptote 2.23 매뉴얼의 p. 134) tube
에 설명된 방법을 확인해야 합니다. three
이 접근 방식을 사용하는 대안은 그리드 가장자리에 격자선을 그리는 대신 그래프 가장자리에 순환 경로를 그리는 것(튜브)입니다.
업데이트: 메쉬를 손으로 그리는 방법은 다음과 같습니다(튜브와 별도의 윤곽선 포함). 혼란을 피하기 위해 펜 이름을 변경했습니다. 연산자는 &
끝점을 공유하는 두 경로를 연결하기 위한 것입니다.
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));
올바른 위치에 구를 그리는 데 도움이 될 수 있는 몇 가지 추가 매개변수와 함수를 정의했습니다.