/// <summary> /// Move (different than Photon.Move) checks if whether photon is going to first /// a) hit tissue boundary (BoundaryHitType.Tissue), and if so Photon.Move to /// intersection position, then /// b) Photon.CrossOrReflect checks if at border of system and sets /// appropriate photon state flag, e.g. PhotonStateType.PseudoBoundingVolumeTissueBoundary /// c) finally sets BoundaryHitType.Virtual and tallies in main MC loop /// </summary> /// <param name="photon"></param> /// <param name="closestVirtualBoundary"></param> /// <returns></returns> private BoundaryHitType Move(Photon photon, out IVirtualBoundary closestVirtualBoundary) { // get distance to any tissue boundary var tissueDistance = _tissue.GetDistanceToBoundary(photon); // get distance to any VB double vbDistance = double.PositiveInfinity; // find closest VB (will return null if no closest VB exists) closestVirtualBoundary = _virtualBoundaryController.GetClosestVirtualBoundary(photon.DP, out vbDistance); if (tissueDistance < vbDistance) // photon won't hit VB, but might not hit tissue boundary either { // no pseudo added here because set by tissue class var hitTissueBoundary = photon.Move(tissueDistance); return(hitTissueBoundary ? BoundaryHitType.Tissue : BoundaryHitType.None); } // otherwise, move to the closest virtual boundary // if both tissueDistance and vbDistance are both infinity, then photon dead if (vbDistance == double.PositiveInfinity) { photon.DP.StateFlag = photon.DP.StateFlag.Remove(PhotonStateType.Alive); return(BoundaryHitType.None); } var hitVirtualBoundary = photon.Move(vbDistance); // pseudo for tissue boundary set by tissue class photon.DP.StateFlag = photon.DP.StateFlag.Add(closestVirtualBoundary.PhotonStateType); // add pseudo-collision for vb // DC - also confusing that we'd add a pseudo for the vb if hitVirtualBoundary is false... return(hitVirtualBoundary ? BoundaryHitType.Virtual : BoundaryHitType.None); }
private BoundaryHitType Move(Photon photon, out IVirtualBoundary closestVirtualBoundary) { // get distance to any tissue boundary var tissueDistance = _tissue.GetDistanceToBoundary(photon); // get distance to any VB double vbDistance = double.PositiveInfinity; // find closest VB (will return null if no closest VB exists) closestVirtualBoundary = _virtualBoundaryController.GetClosestVirtualBoundary(photon.DP, out vbDistance); if (tissueDistance < vbDistance) // determine if will hit tissue boundary first { // DC - logic confusing; why no pseudo added here but added below for vb? var hitTissueBoundary = photon.Move(tissueDistance); return(hitTissueBoundary ? BoundaryHitType.Tissue : BoundaryHitType.None); } // otherwise, move to the closest virtual boundary // if both tissueDistance and vbDistance are both infinity, then photon dead if (vbDistance == double.PositiveInfinity) { photon.DP.StateFlag = photon.DP.StateFlag.Remove(PhotonStateType.Alive); return(BoundaryHitType.None); } var hitVirtualBoundary = photon.Move(vbDistance); // DC - logic confusing; why add pseudo here for vb, but no pseudo in this method for tissue boundary? photon.DP.StateFlag = photon.DP.StateFlag.Add(closestVirtualBoundary.PhotonStateType); // add pseudo-collision for vb // DC - also confusing that we'd add a pseudo for the vb if hitVirtualBoundary is false... return(hitVirtualBoundary ? BoundaryHitType.Virtual : BoundaryHitType.None); }
// /// <summary> // /// This static method instantiates a list of virtual boundaries // /// and the appropriate detectors are deposited into it. // /// </summary> // /// <param name="detectors"></param> // /// <returns></returns> // public static IList<IVirtualBoundary> GetVirtualBoundaries( // IList<IVirtualBoundaryInput> virtualBoundaryGroups, ITissue tissue, bool tallySecondMoment) // { // // this sql returns all VBs even when only RSpecularDetector in detectors // //var virtualBoundaries = // // from vb in EnumHelper.GetValues<VirtualBoundaryType>() // for each virtual boundary type // // where detectors.Select(d => d.TallyType.AppliesToBoundary(vb)).First() // where any detectors apply // // let vbDetectors = detectors.Where(d => d.TallyType.AppliesToBoundary(vb)).ToList() // gather the appropriate detectors // // select GetVirtualBoundary(vb, tissue, vbDetectors); // and instantiate the vb with the appropriate detectors // var virtualBoundaries = new List<IVirtualBoundary>(); // foreach (var vbg in virtualBoundaryGroups) // { // var detectors = DetectorFactory.GetDetectors( // vbg.DetectorInputs, tissue, tallySecondMoment); // var detectorController = DetectorControllerFactory.GetDetectorController( // vbg.VirtualBoundaryType, detectors); // if (detectors.Count > 0) // { // var vb = GetVirtualBoundary(vbg.VirtualBoundaryType, tissue, detectorController); // if (vb != null) // virtualBoundaries.Add(vb); // } // } // return virtualBoundaries.ToList(); // } /// <summary> /// method that gets appropriate VB /// </summary> /// <param name="vbType">VirtualBoundaryType</param> /// <param name="tissue">ITissue</param> /// <param name="detectorController">IDetectorController</param> /// <returns>IVirtualBoundary</returns> public static IVirtualBoundary GetVirtualBoundary( VirtualBoundaryType vbType, ITissue tissue, IDetectorController detectorController) { IVirtualBoundary vb = null; // todo: predicate defines switch (vbType) { case VirtualBoundaryType.DiffuseReflectance: vb = new DiffuseReflectanceVirtualBoundary( tissue, detectorController, VirtualBoundaryType.DiffuseReflectance.ToString()); break; case VirtualBoundaryType.DiffuseTransmittance: vb = new DiffuseTransmittanceVirtualBoundary( tissue, detectorController, VirtualBoundaryType.DiffuseTransmittance.ToString()); break; case VirtualBoundaryType.SpecularReflectance: // reflecting off first layer without transporting in medium vb = new SpecularReflectanceVirtualBoundary( tissue, detectorController, VirtualBoundaryType.SpecularReflectance.ToString()); break; case VirtualBoundaryType.SurfaceRadiance: vb = new RadianceVirtualBoundary( detectorController, VirtualBoundaryType.SurfaceRadiance.ToString()); break; case VirtualBoundaryType.GenericVolumeBoundary: vb = new GenericVolumeVirtualBoundary( tissue, detectorController, VirtualBoundaryType.GenericVolumeBoundary.ToString()); break; case VirtualBoundaryType.pMCDiffuseReflectance: vb = new pMCDiffuseReflectanceVirtualBoundary( tissue, detectorController, VirtualBoundaryType.DiffuseReflectance.ToString()); break; case VirtualBoundaryType.BoundingCylinderVolume: vb = new BoundingCylinderVirtualBoundary( tissue, detectorController, VirtualBoundaryType.BoundingCylinderVolume.ToString()); break; default: throw new ArgumentOutOfRangeException("Virtual boundary type not recognized: " + vbType); } return(vb); }
/// <summary> /// Method to determine the distance to the closest VB in VirtualBoundaries list. /// </summary> /// <param name="dp">current PhotonDataPoint</param> /// <param name="distance">return: distance to closest VB</param> /// <returns>closest VB</returns> public IVirtualBoundary GetClosestVirtualBoundary(PhotonDataPoint dp, out double distance) { IVirtualBoundary vb = null; distance = double.PositiveInfinity; if (_virtualBoundaries != null && _virtualBoundaries.Count > 0) { foreach (var virtualBoundary in _virtualBoundaries) { // each VB takes direction of VB into consideration when determining distance var distanceToVB = virtualBoundary.GetDistanceToVirtualBoundary(dp); if (distanceToVB < distance) { distance = distanceToVB; vb = virtualBoundary; } } } return(vb); }