Julia 如何将自定义数据类型转换为数组的数组
我是Julia的新手,在使用类型方法编程时遇到了一些困难 我想从一个文件中加载一个3D网格来练习,我制作了一些自定义类型来存储它 以下是我的类型:Julia 如何将自定义数据类型转换为数组的数组,julia,Julia,我是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]
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\u 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
Q:
- 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
[编辑] 顶点和法线(通常)是浮点数,面是整数 我使用的对象是 我在结构中加载对象的代码是:
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
)
现在,您可以定义打印功能,例如:
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来实现这一目标,但我希望您会同意,使用StructArrays会让您的代码更具可读性。谢谢,我正在努力让它发挥作用。但是,我的面是整数,顶点和法线通常是浮点数。我试着做一些类似的事情:
函数网格(t::Vector{t},f::Vector{U},n::Vector{t}),其中{在这种情况下,将所有内容转换为Float64
(您可以用不同的方式来做,但这应该足以满足您的需要)换言之,将面保持为浮点数可以简化代码,并且不会带来新的问题(除非您使用非常大的整数-超过52位,这是不可能的)。
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