我是Julia的新手,使用类型方法进行编程时遇到一些困难。

我想从文件中加载3D网格进行练习,并做了一些自定义类型来存储它。

这是我的类型:

struct Vertex
    x::Number
    y::Number
    z::Number
    Vertex(x::Number, y::Number, z::Number) = new(x, y, z)
    Vertex(t::Tuple{Number, Number, Number}) = new(t[1], t[2], t[3])

    Vertex(x::Number, y::Number) = new(x, y, 0)
    Vertex(t::Tuple{Number, Number}) = new(t[1], t[2], 0)

    Vertex(x::Number) = new(x, 0, 0)
    Vertex(t::Tuple{Number}) = new(t[1], 0, 0)

    Vertex() = new(0, 0, 0)
    Vertex(t::Tuple{}) = new(0, 0, 0)
end

struct Mesh
    t::Vector{Vertex} # List of triangles
    f::Vector{Vertex} # List of faces
    n::Vector{Vertex} # List of normals
    Mesh(t::Vertex, f::Vertex) = new([t], [f], [])
    Mesh(t::Vector{Vertex}, f::Vector{Vertex}, n::Vector{Vertex}) = new(t, f, n)
    Mesh(t::Vector{Vertex}, f::Vector{Vertex}, n::Vector) = new(t, f, n)

    Mesh(t::Vector, f::Vector, n::Vector) = new(t, f, n)

    #Mesh(t::Triangle) = new([t], [])
    #Mesh(t::Vector{Triangle}) = new(t, [])
end

我可以有效地以网格类型加载网格。

现在,我想使用 PyPlot 中的 plot_trisurf 方法来绘制它。但是,此方法需要一个数组数组,我不确定我的处理方法是否正确:
function plotMesh(M)
    Xv = map(e -> e.x, M.t[:])
    Yv = map(e -> e.x, M.t[:])
    Zv = map(e -> e.x, M.t[:])
    Fv = map(e -> (e.x, e.y, e.z), M.f[:])

    plot_trisurf(Xv, Yv, Zv, triangles=Fv, alpha=1)
    gca()[:projection] = "3d"
end

:

Xv,Yv,Zv目前感觉不正确
  • 和Fv根本不起作用。 [已更正->请参阅编辑]
  • 这是什么最好的方法?
  • 我的字体设计正确吗?还是应该将其更改为更合适的名称?

  • 谢谢

    [编辑]
    经过更多测试之后,我终于设法使它工作了,但是我仍然不确定这是否是在Julia中做事的最佳方法,还是我的类型系统是否是一个好的系统。
    function plotMesh(M::Mesh)
        Xv = map(e -> e.x, M.t[:])
        Yv = map(e -> e.y, M.t[:])
        Zv = map(e -> e.z, M.t[:])
        Fv = map(e -> [Int(e.x)-1, Int(e.y)-1, Int(e.z)-1], M.f[:])
        print(size(Xv))
        print(size(Fv))
    
        plot_trisurf(Xv, Yv, Zv, triangles=Fv)
        gca()[:projection] = "3d"
    end
    

    First 3D plot in Julia

    [编辑]
    顶点和法线通常是浮点数,而面是整数。

    我正在使用的对象是bunny.obj
    我在结构中加载对象的代码是:
    function read_obj(filename::String)
        v = []
        f = []
        n = []
    
        tof(x) = parse(Float64, x)
    
        open(filename) do file
           for line in eachline(file)
                l = split(line, ' ')
                if l[1] ∈ ["v", "f", "n"]
                    values = (tof(l[2]), tof(l[3]), tof(l[4]))
                    if l[1] == "v"
                        push!(v, Vertex(values))
                    elseif l[1] == "f"
                        faces = (Int(values[1]), Int(values[2]), Int(values[3]))
                        push!(f, Vertex(faces))
                    elseif l[1] == "n"
                        push!(n, Vertex(values))
                    end
                end
            end
        end
    
        return Mesh(v, f, n)
    end
    

    我加载对象的方式肯定不是最好的方式。如果您有任何提高我的技能的材料,请随时分享:)

    最佳答案

    首先,我将像这样更改Vertex的定义(似乎在下面,您要求条目为整数,如果不是,则可以将Integer更改为Number)

    struct Vertex{T<:Integer}
        x::T
        y::T
        z::T
    end
    
    Vertex(x::T=0, y::T=zero(T)) where {T<:Integer} = Vertex(x,y,zero(T))
    Vertex(t::Tuple) = Vertex(t...)
    

    接下来在Mesh中,您可以像这样使用StructArrays.jl包(通过这种方式,您可以轻松地将Vertex的字段作为矢量进行访问):
    using StructArrays
    
    struct Mesh{S<:StructArray, T}
        t::S
        f::S
        n::S
        function Mesh(t::Vector{T}, f::Vector{T}, n::Vector{T}) where {T<:Vertex}
            st, sf, sn = StructArray(t), StructArray(f), StructArray(n)
            new{typeof(st), T}(st, sf, sn)
        end
    end
    
    Mesh(t::T, f::T) where {T<:Vertex} = Mesh([t], [f], T[])
    

    现在您可以将绘图功能定义为:
    function plotMesh(M::Mesh{S, T}) where {S,T}
        Fv = eachrow([M.f.x M.f.y M.f.z] .- one(T))
        print(size(M.t.x))
        print(size(Fv))
        plot_trisurf(M.t.x, M.t.y, M.t.z, triangles=Fv)
        gca()[:projection] = "3d"
    end
    

    注1:所有代码均确保所有结构都对具体类型进行操作,因此该代码将比使用抽象类型(如Number)更快。我还要确保所有条目都具有相同的类型。

    注意2:由于您没有提供用于测试代码的数据(因此请告诉我该代码中是否有任何失败),是我写的。严格来说,您不必使用StructArrays.jl即可达到目标,但我希望您同意使用它们可以使您的代码更具可读性。

    关于julia - 如何将自定义数据类型转换为数组数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57349738/

    10-11 22:54
    查看更多