【问题标题】:OpenSCAD: How to draw a cylinder from vector to vector?OpenSCAD:如何从向量到向量绘制圆柱体?
【发布时间】:2018-06-15 04:24:33
【问题描述】:

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

【问题讨论】:

  • @TorstenPaul 这个问题是关于旋转,而不是线条。
  • 也许可以通过仔细查看 rotate_from_to() 再次阅读该代码?
  • 认为你不必担心归一化和点积,只需用三角函数从距离计算角度

标签: math 3d openscad


【解决方案1】:

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

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

    translate(v2)
    sphere(2);
}

【讨论】:

  • 这也是 1) 昂贵,2) 结果因角度而异。 PS:尽管如此,我也用过这个。
【解决方案2】:

这里是如何在 OpenSCAD 中用最少的算术和 no 三角函数在两点之间构建圆柱体。这是对上述问题的准确答案。

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

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);

【讨论】:

    【解决方案3】:

    这是您要查找的函数,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])
        ];
    

    【讨论】:

      【解决方案4】:

      试试这个。它应该满足您的需求。

      $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);
      

      【讨论】:

        猜你喜欢
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-20
        • 1970-01-01
        • 2021-06-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多