/// <summary> /// method to determine if photon ray (or track) will intersect boundary of cylinder /// equations to determine intersection are derived by parameterizing ray from p1 to p2 /// as p2=p1+[dx dy dz]t t in [0,1] where dx=p2.x-p1.x dy=p2.y-p1.y dz=p2.z-p2.z /// and substituting into ellipsoid equations and solving quadratic in t, i.e. t1, t2 /// t1,t2 less than 0 or t1,t2 greater than 1 => no intersection /// 0 less than t1 less than 1 => one intersection /// 0 less than t2 less than 1 => one intersections, if above line true too => two intersections /// </summary> /// <param name="photon">photon position, direction, etc.</param> /// <param name="distanceToBoundary">return: distance to boundary</param> /// <returns>boolean</returns> public bool RayIntersectBoundary(Photon photon, out double distanceToBoundary) { distanceToBoundary = double.PositiveInfinity; _onBoundary = false; // reset _onBoundary double root = 0; var dp = photon.DP; var p1 = dp.Position; var d1 = dp.Direction; // determine location of end of ray var p2 = new Position(p1.X + d1.Ux * photon.S, p1.Y + d1.Uy * photon.S, p1.Z + d1.Uz * photon.S); bool oneIn = this.ContainsPosition(p1); bool twoIn = this.ContainsPosition(p2); //if ((Math.Abs(p1.X)<2)&& one_in) //{ // Console.WriteLine(String.Format("p1.x,y,z={0:F}, {1:F}, {2:F}, in={3}",p1.X,p1.Y,p1.Z,one_in)); // Console.WriteLine("****"); //} // check if ray within cylinder if ((oneIn || _onBoundary) && twoIn) { return(false); } _onBoundary = false; // reset flag return(CylinderTissueRegionToolbox.RayIntersectInfiniteCylinder(p1, p2, oneIn, CylinderTissueRegionAxisType.Y, Center, Radius, out distanceToBoundary)); }
/// <summary> /// method to determine if photon ray (or track) will intersect boundary of cylinder /// without caps /// </summary> /// <param name="photon">photon position, direction, etc.</param> /// <param name="distanceToBoundary">distance to boundary</param> /// <returns>boolean</returns> public bool RayIntersectBoundary(Photon photon, out double distanceToBoundary) { distanceToBoundary = double.PositiveInfinity; _onBoundary = false; // reset _onBoundary double root = 0; var dp = photon.DP; var p1 = dp.Position; var d1 = dp.Direction; // determine location of end of ray var p2 = new Position(p1.X + d1.Ux * photon.S, p1.Y + d1.Uy * photon.S, p1.Z + d1.Uz * photon.S); bool oneIn = this.ContainsPosition(p1); bool twoIn = this.ContainsPosition(p2); // check if ray within cylinder if ((oneIn || _onBoundary) && twoIn) { return(false); } _onBoundary = false; // reset flag double distanceToSides = double.PositiveInfinity; // first check if intersect with infinite cylinder var intersectSides = (CylinderTissueRegionToolbox.RayIntersectInfiniteCylinder( p1, p2, oneIn, CylinderTissueRegionAxisType.Z, Center, Radius, out distanceToSides)); if (intersectSides) { distanceToBoundary = distanceToSides; return(true); } //distanceToBottomLayer = double.PositiveInfinity; return(false); }
/// <summary> /// Method to determine if photon ray (or track) will intersect boundary of cylinder /// equations to determine intersection are derived by parameterizing ray from p1 to p2 /// as p2=p1+[dx dy dz]t t in [0,1] where dx=p2.x-p1.x dy=p2.y-p1.y dz=p2.z-p2.z /// and substituting into ellipsoid equations and solving quadratic in t, i.e. t1, t2 /// t1,t2<0 or t1,t2>1 => no intersection /// 0<t1<1 => one intersection /// 0<t2<1 => one intersections, if above line true too => two intersections /// Equations obtained from pdf at https://mrl.nyu.edu/~dzorin/rendering/lectures/lecture3/lecture3-6pp.pdf /// and modified to assume cylinder finite along z-axis with caps in x-y planes. /// Note: can't vouch for this code yet, especially if photon intersects sides AND cap /// </summary> /// <param name="photon">photon position, direction, etc.</param> /// <param name="distanceToBoundary">distance to boundary</param> /// <returns>boolean</returns> public bool RayIntersectBoundary(Photon photon, out double distanceToBoundary) { distanceToBoundary = double.PositiveInfinity; _onBoundary = false; // reset _onBoundary double root = 0; var dp = photon.DP; var p1 = dp.Position; var d1 = dp.Direction; // determine location of end of ray var p2 = new Position(p1.X + d1.Ux * photon.S, p1.Y + d1.Uy * photon.S, p1.Z + d1.Uz * photon.S); bool oneIn = this.ContainsPosition(p1); bool twoIn = this.ContainsPosition(p2); // check if ray within cylinder if ((oneIn || _onBoundary) && twoIn) { return(false); } _onBoundary = false; // reset flag double distanceToSides = double.PositiveInfinity; // first check if intersect with infinite cylinder var intersectSides = (CylinderTissueRegionToolbox.RayIntersectInfiniteCylinder(p1, p2, oneIn, CylinderTissueRegionAxisType.Z, Center, Radius, out distanceToSides)); // then check if intersect caps, create three tissue layers 1) above cylinder, 2) cylinder, 3) below double distanceToTopLayer = double.PositiveInfinity; var topLayer = new LayerTissueRegion( new DoubleRange(0, Center.Z - (Height / 2)), new OpticalProperties()); // doesn't matter what OPs are var intersectTopLayer = topLayer.RayIntersectBoundary(photon, out distanceToTopLayer); double distanceToCapLayer = double.PositiveInfinity; var enclosingLayer = new LayerTissueRegion( new DoubleRange(Center.Z - (Height / 2), Center.Z + (Height / 2)), new OpticalProperties()); var intersectCapLayer = enclosingLayer.RayIntersectBoundary(photon, out distanceToCapLayer); double distanceToBottomLayer = double.PositiveInfinity; var bottomLayer = new LayerTissueRegion( new DoubleRange(Center.Z + (Height / 2), double.PositiveInfinity), new OpticalProperties()); // doesn't matter what OPs are var intersectBottomLayer = bottomLayer.RayIntersectBoundary(photon, out distanceToBottomLayer); var hitCaps = false; double distanceToCap = double.PositiveInfinity; if (intersectTopLayer || intersectCapLayer || intersectBottomLayer) { distanceToCap = Math.Min(distanceToTopLayer, Math.Min(distanceToCapLayer, distanceToBottomLayer)); double xto = p1.X + distanceToCap * d1.Ux; double yto = p1.Y + distanceToCap * d1.Uy; double zto = p1.Z + distanceToCap * d1.Uz; if ((Math.Abs(zto - (Center.Z + (Height / 2))) < 1e-10 || Math.Abs(zto - (Center.Z - (Height / 2))) < 1e-10) && Math.Sqrt(xto * xto + yto * yto) < Radius) { hitCaps = true; } } if (hitCaps && distanceToCap < distanceToSides) { distanceToBoundary = distanceToCap; return(true); } if (intersectSides && distanceToSides < distanceToCapLayer) { distanceToBoundary = distanceToSides; return(true); } distanceToBottomLayer = double.PositiveInfinity; return(false); }