4

我在任意位置有两个对象,我想在一个和另一个之间画一个圆柱体。搜索数学解决方案告诉我我需要点积和叉积分别作为角度和轴,但是我在生成四元数或将结果转换为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()在另一个对象上这么一个cylinder()点需要什么?

4

4 回答 4

3

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

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

    translate(v2)
    sphere(2);
}
于 2018-06-15T05:09:16.607 回答
2

以下是如何在 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);
于 2020-09-20T09:18:20.307 回答
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);
于 2018-07-21T04:28:44.000 回答
0

这是您正在寻找的功能,手册页上有一个非常相似的示例,我认为棘手的部分是旋转是按 Z、Y、X 顺序应用的:

function lookAt(v1, v2) =
    let(v = v2-v1)
    [
       0,
       acos(v[2]/distance(v1,v2)),
       atan2(v[1], v[0])
    ];
于 2018-06-22T18:34:45.443 回答