我怎样才能包括所有可能性?

时间:2010-12-04 16:08:39

标签: ruby

此代码接受3array(位置)并测试它是否位于模型的某个区域。问题出在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 ++中编写两个结构上不同的monte carlo(同时学习Ruby和深化的c ++知识)。

谢谢!

1 个答案:

答案 0 :(得分:0)

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

其次,您要为每种材料确定材料值:true或false。您可以考虑使用case语句。您编写了一个返回区域测试值的方法(如:poly,:box,whatever),然后将其用作case语句的测试:

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

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

以这种方式打破代码 - 或者其他方式 - 将使测试更加容易。