2010-12-04 56 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,根據你的區域檢查方法的返回值,它應該很容易,以確定哪些值需要是真的或者是真的。

以這種方式分開代碼 - 或者其他方式 - 將使測試變得更容易。