在 Asymptote 中是否存在fill
适用于平面 3D 路径的命令等效项?
我以为surface
这样做了:我期望命令
fill(project(p))
和
draw(surface(p))
对于任何平面路径 3 ,始终产生相同的结果p
。但是,这对于我正在处理的路径(在下面的代码中调用)不起作用tile(identity4)
:基本上它是一些非凸形状,并且 3D 表面包含其凸包未被路径包围的部分。
我没能写出一个简单的 MWE。不管怎样,这是我的代码;恐怕理解起来有点复杂!我删除了与问题无关的所有定义;但当我试图进一步简化它时,它突然在合理的时间内停止编译,所以我放弃了这件事。
你可能会问为什么我不直接使用前一个命令。问题是我的图片中还有其他数据,而且当我绘制 2D 图片时,似乎所有之前绘制的 3D 对象都会被删除。
unitsize(100);
import three;
import graph3;
import solids;
real tmax = 1.15; //contraction strength
real translation_speed = 0.2; //ratio of translation part over contraction part of an infinitesimal generator
real height = 1; //height of the cutting plane
real radius = 5; //radius of the "projective sphere
real width = 2; //how far do the "infinite" surfaces actually go
int subdiv = 1; //how much we subdivide curves when projecting to the sphere
transform3 squish(real t) {
return scale(exp(-t), 1, exp(t)) * shift(t*translation_speed*Y);
}
transform3 halfgplus = squish(tmax);
transform3 halfgminus = squish(-tmax);
transform3 gplus = squish(2*tmax);
transform3 gminus = squish(-2*tmax);
transform3 conj = rotate(90,X+Z);
transform3 halfhplus = conj * halfgplus * inverse(conj);
transform3 halfhminus = conj * halfgminus * inverse(conj);
transform3 hplus = conj * gplus * inverse(conj);
transform3 hminus = conj * gminus * inverse(conj);
triple c1 = (1,0,1);
triple c3 = (1,0,-1);
triple c5 = (-1,0,-1);
triple c7 = (-1,0,1);
path3 tennisball = scale3(width) *
(arc((1,0,0),c1,c3,-X) &
arc((0,0,-1),c3,c5,-Z) &
arc((-1,0,0),c5,c7,X) &
arc((0,0,1),c7,c1,Z));
path3[] cut(path3 p, triple center) {
//Cuts the path p by the plane x+z = height, then projects the upper part onto the plane.
//Returns {flattened upper part, lower part}.
//Assumes exactly 2 intersections.
path p_projected = project(p, orthographic(1,0,-1));
real [] cuttimes = times(p_projected, (0, height));
real t1 = cuttimes[0];
real t2 = cuttimes[1];
pair test_point = point(p_projected, (t1+t2)/2);
path3 upper_part = (test_point.y >= height) ? subpath(p, t1, t2) :
subpath(p, t2, length(p)) & subpath(p, 0, t1);
path3 lower_part = (test_point.y >= height) ? subpath(p, t2, length(p)) & subpath(p, 0, t1) :
subpath(p, t1, t2);
triple projection_target = planeproject(X+Z, sqrt(2)*height*Z) * center;
path plane_upper_part = project(upper_part, perspective(center, target=projection_target));
path3 flat_upper_part = invert(plane_upper_part, X+Z, sqrt(2)*height*Z, perspective(center, target=projection_target));
return new path3[] {flat_upper_part, lower_part};
}
triple sph_proj(triple x, triple proj_cen) {
//Projects a point from some center (assumed to be inside the sphere) onto the sphere of center O and given radius.
triple v = unit(x - proj_cen); //Unit vector generating the half-line.
triple q = proj_cen - dot(v, proj_cen) * v; //Point of the line closest to O.
return q + (radius +-+ abs(q)) * v;
}
path3 sph_proj_path(path3 p, triple proj_cen) {
//Projects a smooth, cyclic, non null path from some center (assumed to be inside the sphere) onto the sphere of center O and given radius.
int n=length(p);
guide3 g=sph_proj(point(p,0), proj_cen);
for(int i=1; i < n*subdiv; ++i)
g=g..sph_proj(point(p,i/subdiv), proj_cen);
return g..cycle;
}
path3 side(transform3 gamma) {
triple cen = gamma * O;
return cut(sph_proj_path((gamma * tennisball), cen), cen)[0];
}
path3 tile(transform3 gamma) {
path3 side_gplus = side(gamma * halfgplus);
path3 side_gminus = side(gamma * halfgminus);
path3 side_hplus = side(gamma * halfhplus * conj);
path3 side_hminus = side(gamma * halfhminus * conj);
path3 tile_contour = reverse(side_gplus) -- reverse(side_hplus) -- side_gminus -- side_hminus -- cycle;
return planeproject(X+Z, sqrt(2)*height*Z) * tile_contour;
}
draw(surface(tile(identity4)), gray+opacity(0.8));
更新:我也试过了
draw(surface(project(p, orthographic(n)), plane=myplane))
myplane
我想要绘制表面的平面在哪里n
,它的法线在哪里。这会产生不同的结果,但仍然不是我期望的结果。
答案1
使用 Asymptore,3D 曲面是贝塞尔曲面片。平面路径 3 不定义这样的曲面。我知道的唯一解决方案是使用 bezulate 例程,将 2D 路径(循环路径或循环路径的并集)转换为贝塞尔三角剖分(2D)。然后,您可以使用表面(bezulate(您的 2D 路径)))绘制它。它被开发为具有 3D 标签。
我对您的代码(投影选择)有些疑问,特别是对于 halfgminus 和 halfhminus,bezulate 例程会返回错误消息。以下是您的图片的一部分
path[] aa= project(side(identity4*halfgplus)--cycle ^^reverse(side(identity4*halfhplus*conj)--cycle),
orthographic(X+Z));
path[] gg=bezulate(aa);
draw(planeproject(X+Z)*surface(gg),opacity(0.4));