This code takes in a 3array (position) and tests to see whether it sits in some region of the model or not. The problem is in the PbSheild method, I can't work out why though. This code will work as is (well it will not work as is, that's the point).
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 <=开发者_如何学JAVA $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
If you think this looks suspiciously like it is related to my c++ code you are correct, am writing two structurally different monte carlo's in Ruby and c++ (learning Ruby and the deepening c++ knowledge at the same time).
Thanks!
I would rewrite this entirely. You have a couple of problems that you want to solve. First, you want to define a region and see if a point is within that region. That should probably be one module with a method for defining regions and a method for placing a point within a defined region. You could, if you wished, define the regions in the module itself, or define them on the fly, whichever. That would give you the ability to pass a region name or definition and a point to a single method and get back whether the point is within that region. That would be much easier to test.
Second, you want to determine the material value: true or false, for every material. You might consider using a case statement for this. You write a method that returns values for your region test (like :poly, :box, whatever) and then use that as the test for your case statement:
case whatever(point)
when (:foo)
set some values
when (:bar)
set some other values
end
If you set the default for every material value to false (a good plan) then you'll only have to update the trues, and it should be easy, based on the return value of your region check method, to decide what values need to be true or can be true.
Breaking the code apart this way--or some other way--will make it much easier to test.
精彩评论