• 数学图形之将曲线(curve)转化成曲面管


    在我关于数学图形的博客中,一开始讲曲线的生成算法.然后在最近的章节中介绍了圆环,还介绍了螺旋管以及海螺的生成算法.一类是曲线,一类是环面,为什么不将曲线变成环的图形,毕竟曲线看上去太单薄了,这一节我将介绍如何依照曲线(Curve)生成其相应的曲面管.

    相关软件参见:数学图形可视化工具,使用自己定义语法的脚本代码生成数学图形.

    圆柱面这一节的最后,我提供了两种算法,以生成朝向任意方向的圆柱面,一种是极坐标原理,另一种是矩阵原理.这一节也是采用这两个原理生成曲面管,因为由曲线生成的曲面管就是若干个有朝向的圆柱面组成.

    先看个三维曲线的代码:

    圆环面螺线:

    #http://xuxzmail.blog.163.com/blog/static/25131916200976114621705/
    #Toroidal spiral
    
    vertices = 1000
    
    t = from 0 to (2*PI)
    
    r = 5
    n = 20
    
    x = (r+sin(20*t))*cos(t)
    y = (r+sin(20*t))*sin(t)
    z = cos(n*t)
    
    r = 10;
    x = x*r
    y = y*r
    z = z*r

    圆环面螺线管(极坐标原理):

    #http://xuxzmail.blog.163.com/blog/static/25131916200976114621705/
    #Toroidal spiral
    
    vertices = D1:36 D2:720
    
    u = from 0 to (2*PI) D1
    v = from 0 to (2*PI) D2
    
    r = 5
    n = 20
    
    xq = (r+sin(20*v))*cos(v)
    yq = (r+sin(20*v))*sin(v)
    zq = cos(n*v)
    
    #由线变管
    
    xd = array_difference(xq, 36)
    yd = array_difference(yq, 36)
    zd = array_difference(zq, 36)
    
    len = sqrt(xd*xd + yd*yd + zd*zd)
    a = xd/len
    b = yd/len
    c = zd/len
    
    radius =0.2
    
    ac = sqrt(a*a + c*c)
    angleY = atan2(ac, b)
    angleXZ = atan2(a,c)
    
    m = cos(u) * radius
    n = sin(u) * radius
    
    e = sin(angleY)
    f = cos(angleY)
    
    g = sin(angleXZ)
    h = cos(angleXZ)
    
    x0 = m
    y0 = -n*e
    z0 = n*f
    
    x1 = x0*h + z0*g
    y1 = y0
    z1 = -x0*g + z0*h
    
    x = x1 + xq
    y = y1 + yq
    z = z1 + zq

    圆环面螺线管(矩阵原理):

    #http://xuxzmail.blog.163.com/blog/static/25131916200976114621705/
    #Toroidal spiral
    
    vertices = D1:36 D2:720
    
    u = from 0 to (2*PI) D1
    v = from 0 to (2*PI) D2
    
    r = 5
    n = 20
    
    xq = (r+sin(20*v))*cos(v)
    yq = (r+sin(20*v))*sin(v)
    zq = cos(n*v)
    
    #由线变管
    
    xd = array_difference(xq, 36)
    yd = array_difference(yq, 36)
    zd = array_difference(zq, 36)
    
    len = sqrt(xd*xd + yd*yd + zd*zd)
    len = max(len, 0.00001)
    a = xd/len
    b = yd/len
    c = zd/len
    
    len = sqrt(b*b + c*c)
    len = max(len, 0.00001)
    m = c/len
    n = -b/len
    
    i = b*n - c*m
    j = - a*n
    k = a*m
    
    radius = 0.2
    
    x0 = cos(u) * radius
    z0 = sin(u) * radius
    
    x = x0*i + xq
    y = x0*j + z0*m + yq
    z = x0*k + z0*n + zq

    这是我所写的最复杂的脚本代码了,为了写这种脚本,我不惜将脚本解析器实现对自定义变量的支持.

    不过这两种写法都会有点瑕疵,因为在某个情况下拐点时,会出现扭曲,这种瑕疵似乎很难解决.

    再举个节的例子:

    line_torus_knot(37)

    vertices = 10000
    t = from 0 to (6*PI)
    
    p = 3
    q = 7
    
    r = 2 + cos(q/p*t)
    
    x = r*sin(t)
    y = sin(q/p*t)
    z = r*cos(t)
    
    r = 0.5 + 0.5*sin(t)
    g = 0.5 + 0.5*y
    b = 0.5 + 0.5*cos(t)

    pipe_torus_knot(37)极坐标原理

    vertices = D1:36 D2:360
    
    u = from 0 to (2*PI) D1
    v = from 0 to (6*PI) D2
    
    p = 3
    q = 7
    
    r = 2 + cos(q/p*v)
    
    xq = r*sin(v)
    yq = sin(q/p*v)
    zq = r*cos(v)
    
    r = 0.5 + 0.5*sin(v)
    g = 0.5 + 0.5*yq
    b = 0.5 + 0.5*cos(v)
    
    #由线变管
    
    xd = array_difference(xq, 36)
    yd = array_difference(yq, 36)
    zd = array_difference(zq, 36)
    
    len = sqrt(xd*xd + yd*yd + zd*zd)
    a = xd/len
    b = yd/len
    c = zd/len
    
    radius = 0.2
    
    ac = sqrt(a*a + c*c)
    angleY = atan2(ac, b)
    angleXZ = atan2(a,c)
    
    m = cos(u) * radius
    n = sin(u) * radius
    
    e = sin(angleY)
    f = cos(angleY)
    
    g = sin(angleXZ)
    h = cos(angleXZ)
    
    x0 = m
    y0 = -n*e
    z0 = n*f
    
    x1 = x0*h + z0*g
    y1 = y0
    z1 = -x0*g + z0*h
    
    x = x1 + xq
    y = y1 + yq
    z = z1 + zq

    pipe_torus_knot(37)矩阵原理

    vertices = D1:36 D2:360
    
    u = from 0 to (2*PI) D1
    v = from 0 to (6*PI) D2
    
    p = 3
    q = 7
    
    r = 2 + cos(q/p*v)
    
    xq = r*sin(v)
    yq = sin(q/p*v)
    zq = r*cos(v)
    
    r = 0.5 + 0.5*sin(v)
    g = 0.5 + 0.5*yq
    b = 0.5 + 0.5*cos(v)
    
    #由线变管
    
    xd = array_difference(xq, 36)
    yd = array_difference(yq, 36)
    zd = array_difference(zq, 36)
    
    len = sqrt(xd*xd + yd*yd + zd*zd)
    px = xd/len
    py = yd/len
    pz = zd/len
    
    len = sqrt(py*py + pz*pz)
    len = max(len, 0.00001)
    m = pz/len
    n = -py/len
    
    i = py*n - pz*m
    j = - px*n
    k = px*m
    
    radius = 0.2
    
    x0 = cos(u) * radius
    z0 = sin(u) * radius
    
    x = x0*i + xq
    y = x0*j + z0*m + yq
    z = x0*k + z0*n + zq

  • 相关阅读:
    Python—模块
    Python之路_Day5
    Python之路_Day4
    Py获取本机指定网卡的ip地址
    Python之路_Day3
    Python之路—Day2作业
    Python之路—Day2
    Python之路—Day1作业
    Python之路—Day1
    Python数据类型
  • 原文地址:https://www.cnblogs.com/WhyEngine/p/3887039.html
Copyright © 2020-2023  润新知