答案1
我想我明白了(编辑: 不,请参阅下面的编辑), 使用革命,正如@Schrodinger's cat 所建议的(谢谢!)。
(0,0,0)
其思想是,先从到构建一个旋转曲面(1,0,0)
,然后在方向上缩放该曲面X
,length(B-A)
然后通过一个将单位向量发送(1,0,0)
到单位向量的旋转来映射该曲面(B-A)/length(B-A)
,并进行平移A
。
settings.render = 4;
settings.outformat = "pdf";
import solids;
size(5cm,0);
currentprojection = orthographic(1,2,4);
path3 pathAB(triple A, triple B, int n){
path3 out;
for(int i = 0; i <= n; ++i){
real t = i/n;
triple M = A + t*(B-A);
real r = length(M);
out = out -- (t, r, 0);
}
return out;
}
triple A = (2,1,0);
triple B = (-10,2,1);
path3 p3 = pathAB(A, B, 100);
revolution a = scale(length(B-A),1,1)*revolution(p3,X,0,360);
struct quaternion {
real w;
real x;
real y;
real z;
}
// unit quaternion to rotation matrix
transform3 quat2rot(quaternion q){
transform3 T = identity4;
real a = q.w;
real b = q.x;
real c = q.y;
real d = q.z;
T[0][0] = a*a+b*b-c*c-d*d; T[0][1] = 2*b*c-2*a*d; T[0][2] = 2*a*c+2*b*d;
T[1][0] = 2*a*d+2*b*c; T[1][1] = a*a-b*b+c*c-d*d; T[1][2] = 2*c*d-2*a*b;
T[2][0] = 2*b*d-2*a*c; T[2][1] = 2*a*b+2*c*d; T[2][2] = a*a-b*b-c*c+d*d;
return T;
}
// quaternion sending u to v
quaternion from2vectors(triple u, triple v){
real norm_u_norm_v = length(u) * length(v);
real cos_theta = dot(u, v) / norm_u_norm_v;
real half_cos = sqrt(0.5 * (1 + cos_theta));
triple w = cross(u, v) / (norm_u_norm_v * 2 * half_cos);
quaternion q;
q.w = half_cos; q.x = w.x; q.y = w.y; q.z = w.z;
return q;
}
//
quaternion q = from2vectors((1,0,0), (B-A)/length(B-A));
transform3 T = quat2rot(q);
draw(shift(A)*T*surface(a), red+opacity(0.5), render(compression=Low,merge=true));
draw(shift(A)*scale3(0.1)*unitsphere, black);
draw(shift(B)*scale3(0.1)*unitsphere, black);
编辑
以上都不是我想要的(我不会删除它,因为它有自己的利益)。
我写错了“我知道管道包,但据我所知,它只允许恒定部分。”。确实,tube
有一个变换参数允许对路径上每个点的管段应用变换。以下是示例:
settings.render = 4;
settings.outformat = "pdf";
import tube;
import graph3;
size(5cm,0);
currentprojection = orthographic(0,0,4);
// define a path
triple f(real x){
return (x, x*x*x, 1);
}
int n = 200;
path3 p = graph(f, -1, 1, n=n, operator ..);
// transformation to apply to the section of the tube
// t varies from 0 to n/4
transform T(real t){
triple M = relpoint(p, t/(n/4));
return scale(length(M)/10);
}
// draw tube
draw(tube(p, unitcircle, T), purple);
draw(shift(relpoint(p,0))*scale3(0.1)*unitsphere, green);
draw(shift(relpoint(p,1))*scale3(0.1)*unitsphere, red);
这就是我要找的东西。这就是我想要做的,立体双棱镜: