OpenSCAD:如何从矢量到矢量绘制圆柱体?

时间:2018-06-15 04:24:34

标签: math 3d openscad

我在任意位置有两个物体,我想在一个和另一个之间画一个圆柱体。搜索数学解决方案告诉我,我需要分别使用点积和十字积作为角度和轴,但是我在生成四元数或将结果转换为const search = { multiple: function (query, projection, callback) { console.log('multiple was called'); client.connect(url, function (err, client ) { if (err) throw err; console.log('Connected to db'); const db = client.db(currentdb); const collection = db.collection(currentcollection); collection.find(query).project(projection) .toArray(function (err, result) { console.log('Result on the way'); if (err) throw err; callback(result) client.close() }); }); } }; 的参数时丢失了。

这是我到目前为止所做的:

rotate

function dot (v1, v2) = [v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]]; function normalize (v) = v / norm(v); function distance (v1, v2) = sqrt( pow(v2[0] - v1[0], 2) + pow(v2[1] - v1[1], 2) + pow(v2[2] - v1[2], 2) ); function lookAt(v1, v2) = let(n1 = normalize(v1)) let(n2 = normalize(v2)) let(v = dot(n1, n2)) let(angle = [acos(v[0]), acos(v[1]), acos(v[2])]) let(axis = normalize(cross(n1, n2))) [0, 0, 0]; // I don't know what to return here module cylTo(v1, v2) { translate(v1) rotate(lookAt(v1, v2)) cylinder(distance(v1, v2), 2); } v1 = [-33, -20, 22]; v2 = [20, 20, -20]; // Draw sphere 1 translate(v1) sphere(10); // Draw sphere 2 translate(v2) sphere(10); // Draw cylinder between the two cylTo(v1, v2); 需要什么,rotate()指向另一个对象?

4 个答案:

答案 0 :(得分:2)

我找到了一个简单的解决方案,它近似于两个点之间的圆柱体,但它并不精确,因为它产生了一个药丸(带有圆形末端),而不是一个平端的圆柱体。

// Draw cylinder between the two
hull() {
    translate(v1)
    sphere(2);

    translate(v2)
    sphere(2);
}

答案 1 :(得分:1)

以下是在OpenSCAD中用最小的算术和三角函数在两点之间构造圆柱体的方法。这是对以上问题的确切答案。

我们通过直接计算转换矩阵来做到这一点:

function transpose(A) = [for (j = [0:len(A[0])-1]) [for(i = [0:len(A)-1]) 

module cyl_between(P, Q, r){
    v = Q - P;    
    L = norm(v);  
    c = v / L;    
    is_c_vertical = ( 1 - abs(c * [0, 0, 1]) < 1e-6); 
    u = is_c_vertical ? [1, 0, 0] : cross([0, 0, 1], c); 
    a = u / norm(u); 
    b = cross(c, a);     
    MT = [a, b, c, P]; 
    M = transpose(MT); 
    multmatrix(M) cylinder(h=L, r=r, $fn=30);
}

以下是上面的注释很好的版本,它解释了数学原理:

// Transpose of matrix A (swap rows and columns)
function transpose(A) = [for (j = [0:len(A[0])-1]) [for(i = [0:len(A)-1]) A[i][j]]];

//  Cylinder of radius r from P to Q
module cyl_between(P, Q, r){
    v = Q - P;    // vector from P to Q
    L = norm(v);  // height of the cylnder = dist(P, Q) 
    c = v / L;    // unit vector: direction from P to Q    
    is_c_vertical = ( 1 - abs(c * [0, 0, 1]) < 1e-6); //is c parallel to z axis?
    u = is_c_vertical ? [1, 0, 0] : cross([0, 0, 1], c); // normal to c and Z axis
    a = u / norm(u); // unit vector normal to c and the Z axis
    b = cross(c, a); // unit vector normal to a and b
    // [a, b, c] is an orthonormal basis, i.e. the rotation matrix; P is the translation
    MT = [a, b, c, P]; // the transformation matrix
    M = transpose(MT); // OpenSCAD wants vectors in columns, so we need to transpose
    multmatrix(M)
        cylinder(h=L, r=r, $fn=30);
}

用法:

cyl_between([1,2,3], [4,5,6], 1);

答案 2 :(得分:0)

这是您要查找的功能,manual page上有一个非常相似的示例,我认为棘手的部分是按Z,Y,X顺序应用旋转:

function lookAt(v1, v2) =
    let(v = v2-v1)
    [
       0,
       acos(v[2]/distance(v1,v2)),
       atan2(v[1], v[0])
    ];

答案 3 :(得分:0)

尝试一下。它应该可以满足您的需求。

$fn=40;

function vectorLength(v1,v2) = sqrt(
    (v2[0]-v1[0])*(v2[0]-v1[0])+
    (v2[1]-v1[1])*(v2[1]-v1[1])+
    (v2[2]-v1[2])*(v2[2]-v1[2]));

function lookAt(v1, v2) =
    let(v = v2-v1)
    [
       0,
       acos(v[2]/vectorLength(v1,v2)),
       atan2(v[1], v[0])
    ];

module cylinderBetween(p1,p2,radius)
{
    translate(p1)
    rotate(lookAt(p1,p2))
    cylinder(vectorLength(p1,p2),radius,radius);
}

P1=[2,-7,2];
P2=[4,0,6];

// Draw the cylinder between
cylinderBetween(P1,P2,.25);

// Draw the ends
translate(P1)
rotate(lookAt(P1,P2))
cylinder(.01,1,1);

translate(P2)
rotate(lookAt(P1,P2))
cylinder(.01,1,1);