2010-12-04 58 views
0

此代码需要3阵列(位置)并测试以确定它是否位于模型的某个区域中。问题出在PbSheild方法中,但我无法解释为什么。此代码将按原样工作(当然,它不会工作,这就是要点)。如何包含所有可能性?

class Geometry      

$polyCylRad = 2.5      
$polyCylFr = 15       
$polyCylB = -2.0       
$borPolyBoxL = 9.0/2 
$pbCylRad = 3.0 
$pbBoxL = 10.0/2 
$cdBoxL = 9.5/2 
$xSquared = Float 
$ySquared = Float 
$zSquared = Float 
$modX = Float 
$modY = Float 
$modZ =Float 
$position = Array.new 


def checkMaterial(params) 

    $position = params 
    $xSquared = $position[0] ** 2 
    $ySquared = $position[1] ** 2 
    $zSquared = $position[2] ** 2 
    $modX = Math.sqrt($xSquared) 
    $modY = Math.sqrt($ySquared) 
    $modZ = Math.sqrt($zSquared) 

    puts "polyCyl: " + self.polyCylinder.to_s 
    puts "borpoly: " + self.borPolyBox.to_s 
    puts "Cd: " + self.CdShield.to_s 
    puts "Pb Cylinder: " + self.PbCylinder.to_s 
    puts "Pb: " + self.PbShield.to_s 
    puts "FreeSpace: " + self.FreeSpace.to_s 

    material 
end 

def polyCylinder 
    Math.sqrt($ySquared + $zSquared) <= $polyCylRad && $position[0] >= $polyCylB && $position[0] <= $polyCylFr 
end 

def borPolyBox 
    !polyCylinder && ($modX <= $borPolyBoxL || $modY <= $borPolyBoxL || $modZ <= borPolyBoxL) && !($modX > $borPolyBoxL || $modY > $borPolyBoxL || $modZ > borPolyBoxL) 
end 

def CdShield 
    !polyCylinder && !borPolyBox && ($modX <= $cdBoxL || $modY <= $cdBoxL || $modZ <= $cdBoxL) && !($modX > $cdBoxL || $modY > $cdBoxL || $modZ > $cdBoxL) 
end 

def PbCylinder 
    !polyCylinder && $position[0] >= $cdBoxL && $position[0] <= $polyCylFr && Math.sqrt($ySquared + zSquared) <= $pbCylRad 
end 

def PbShield 
    !polyCylinder && !borPolyBox && !CdShield && !PbCylinder && ($modX <= $pbBoxL || $modY <= $pbBoxL || $modZ <= $pbBoxL) && !($modX > $pbBoxL || $modY > $pbBoxL || $modZ > $pbBoxL)             
end 

def FreeSpace 
    !polyCylinder && !borPolyBox && !CdShield && !PbShield && !PbCylinder 
end 

def material 
    [ 
    [:polyCylinder, 'poly'], 
    [:borPolyBox, 'borPoly'], 
    [:CdShield, 'Cd'], 
    [:PbCylinder, 'Pb'], 
    [:PbShield, 'Pb'], 
    [:FreeSpace, 'air'] 
    ].each do |method, name| 
    return name if send(method) 
       end 
    false 
end 

end 

$bob = Geometry.new 
posVect = Array.new 
posVect << 0 << 0 << 0 
$bob.checkMaterial(posVect) 

while posVect[0] < 25 do 

$bob.checkMaterial(posVect) 
puts "Xpos: " + posVect[0].to_s 
puts "Ypos: " + posVect[1].to_s 
puts "Zpos: " + posVect[2].to_s 
puts "polyCyl: " + $bob.polyCylinder.to_s 
puts "borpoly: " + $bob.borPolyBox.to_s 
puts "Cd: " + $bob.CdShield.to_s 
puts "Pb: " + $bob.PbShield.to_s 
puts "FreeSpace: " + $bob.FreeSpace.to_s 
puts "" 

posVect[0] += 1 

end 

如果你认为这看起来很像是涉及到我的C++代码,你是正确的,我写两种结构不同的蒙特卡洛在Ruby和C++(学习Ruby,并在同一时间将深化C++知识)。

谢谢!

+0

马上跳出来的一件事就是你正在使用很多全局变量,你不需要。我不知道这是否会给你带来任何问题,但这绝对不是一种好的风格。如果你想要一个只能在类中访问的变量(这似乎是你想要的)使用一个实例变量:@var而不是$ var。没有什么特别的理由让$ bob在这里只是本地的。 – philosodad 2010-12-04 20:54:36

+0

$ bob的原因是我在类之外的定义中使用了它,但它们是全局变量的主要原因是用于测试,尽管感谢实例建议。 :) – morb 2010-12-05 12:53:48

回答

0

我会完全重写。你有一些你想解决的问题。首先,你要定义一个区域,看看一个点是否在该区域内。这应该可能是一个模块,它具有定义区域的方法和将点放置在定义区域内的方法。如果您愿意,您可以在模块本身中定义区域,或者在运行中定义它们,无论哪个。这将使你能够传递一个区域名称或定义,并指向一个单一的方法,并返回该点是否在该区域内。这将更容易测试。

其次,您要确定每种材质的材质值:true或false。你可以考虑使用一个case语句。你写你的区域测试返回值的方法(如:聚,:箱,等等),然后用其作为测试你的case语句:

case whatever(point) 
    when (:foo) 
    set some values 
    when (:bar) 
    set some other values 
    end 

如果您设置默认为每个材料的价值假(一个好的计划),那么你只需要更新trues,根据你的区域检查方法的返回值,它应该很容易,以确定哪些值需要是真的或者是真的。

以这种方式分开代码 - 或者其他方式 - 将使测试变得更容易。