如何将向量的元素设置为指向数组数组中的第一个元素?
How do I set a vector's elements to point to the first element in an array of arrays?
我一直在通过尝试编写一个简单的刚性 body 模拟来学习 Julia,但我对变量的赋值和变异仍然有些困惑。
我将构成 body 形状的点存储到一个数组数组中,其中一个向量包含一个点的 x、y、z 坐标。为了使用 PyPlot 绘制 body,首先将点从本地坐标转换为世界坐标,然后分配给三个数组,分别保存这些点的 x、y 和 z 坐标。我想让这三个数组只引用数组值的数组而不是值的副本。
我的代码的相关部分如下所示
type Rigidbody
n::Integer
k::Integer
bodyXYZ::Array{Array{Float64,1},2}
worldXYZ::Array{Array{Float64,1},2}
worldX::Array{Float64,2}
worldY::Array{Float64,2}
worldZ::Array{Float64,2}
Rotmat::Array{Float64,2}
x::Array{Float64,1}
end
# body.worldXYZ[1,1] = [x; y; z]
# and body.worldX[1,1] should be body.worldXYZ[1,1][1]
function body_to_world(body::Rigidbody)
for j in range(1, body.k)
for i in range(1, body.n)
body.worldXYZ[i,j] = body.x + body.Rotmat*body.bodyXYZ[i,j]
body.worldX[i,j] = body.worldXYZ[i,j][1]
body.worldY[i,j] = body.worldXYZ[i,j][2]
body.worldZ[i,j] = body.worldXYZ[i,j][3]
end
end
return nothing
end
在调用 body_to_world() 并使用 === 检查元素后,它们的计算结果为 true 但是如果我然后例如设置
body.worldXYZ[1,1][1] = 99.999
更改未反映在 body.worldX 中。问题可能是微不足道的,但从我的代码可以看出,我是初学者,需要一些帮助。
body.worldX[i,j] = body.worldXYZ[i,j][1]
您在此处将一个数字设置为一个数字。数字是不可变的,所以 body.worldX[i,j]
不会引用回 body.worldXYZ[i,j][1]
。你在想的是数组的值将是一个引用,但数字没有引用,只有值本身。
但是,我敢说,如果您这样做,那您就错了。您可能应该在某处使用类型。请记住,Julia 中的类型具有良好的性能,所以不要害怕它们(不可变类型在 carneval 的 PR 之后应该几乎完美优化,所以真的没有必要害怕)。相反,我会让 world::Array{Point,2}
where
immutable Point{T}
x::T
y::T
z::T
end
然后你可以获得 body.world[i,j].x
作为 x
坐标等。然后你可以免费使用 map((i,j)->Ref(body.world[i,j].x),size(body.world)...)
来获取对 x
的引用数组的。
或者,您应该为您的类型添加调度。例如
import Base: size
size(RigidBody) = (n,k)
现在 size(body)
输出 (n,k)
,就像它是一个数组一样。用getindex
和setindex!
即可完成数组接口。这种向您的类型添加分派将极大地帮助清理代码。
我一直在通过尝试编写一个简单的刚性 body 模拟来学习 Julia,但我对变量的赋值和变异仍然有些困惑。
我将构成 body 形状的点存储到一个数组数组中,其中一个向量包含一个点的 x、y、z 坐标。为了使用 PyPlot 绘制 body,首先将点从本地坐标转换为世界坐标,然后分配给三个数组,分别保存这些点的 x、y 和 z 坐标。我想让这三个数组只引用数组值的数组而不是值的副本。
我的代码的相关部分如下所示
type Rigidbody
n::Integer
k::Integer
bodyXYZ::Array{Array{Float64,1},2}
worldXYZ::Array{Array{Float64,1},2}
worldX::Array{Float64,2}
worldY::Array{Float64,2}
worldZ::Array{Float64,2}
Rotmat::Array{Float64,2}
x::Array{Float64,1}
end
# body.worldXYZ[1,1] = [x; y; z]
# and body.worldX[1,1] should be body.worldXYZ[1,1][1]
function body_to_world(body::Rigidbody)
for j in range(1, body.k)
for i in range(1, body.n)
body.worldXYZ[i,j] = body.x + body.Rotmat*body.bodyXYZ[i,j]
body.worldX[i,j] = body.worldXYZ[i,j][1]
body.worldY[i,j] = body.worldXYZ[i,j][2]
body.worldZ[i,j] = body.worldXYZ[i,j][3]
end
end
return nothing
end
在调用 body_to_world() 并使用 === 检查元素后,它们的计算结果为 true 但是如果我然后例如设置
body.worldXYZ[1,1][1] = 99.999
更改未反映在 body.worldX 中。问题可能是微不足道的,但从我的代码可以看出,我是初学者,需要一些帮助。
body.worldX[i,j] = body.worldXYZ[i,j][1]
您在此处将一个数字设置为一个数字。数字是不可变的,所以 body.worldX[i,j]
不会引用回 body.worldXYZ[i,j][1]
。你在想的是数组的值将是一个引用,但数字没有引用,只有值本身。
但是,我敢说,如果您这样做,那您就错了。您可能应该在某处使用类型。请记住,Julia 中的类型具有良好的性能,所以不要害怕它们(不可变类型在 carneval 的 PR 之后应该几乎完美优化,所以真的没有必要害怕)。相反,我会让 world::Array{Point,2}
where
immutable Point{T}
x::T
y::T
z::T
end
然后你可以获得 body.world[i,j].x
作为 x
坐标等。然后你可以免费使用 map((i,j)->Ref(body.world[i,j].x),size(body.world)...)
来获取对 x
的引用数组的。
或者,您应该为您的类型添加调度。例如
import Base: size
size(RigidBody) = (n,k)
现在 size(body)
输出 (n,k)
,就像它是一个数组一样。用getindex
和setindex!
即可完成数组接口。这种向您的类型添加分派将极大地帮助清理代码。