Пример #1
0
            public override BroadRay Directions(int index, int thread, ref Random random, int[] Octaves)
            {
                BroadRay Ray = Directions(index, thread, ref random);

                Ray.Octaves = Octaves;
                return(Ray);
            }
            public override void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal)
            {
                cos_theta = Hare.Geometry.Hare_math.Dot(Ray.direction, Normal);
                int index = 18 - (int)Math.Round(Math.Acos(Math.Abs(cos_theta)) / angle_incr);

                for (int oct = 0; oct < 8; oct++)
                {
                    Ray.Energy[oct] *= (1 - Ang_Coef_Oct[oct][index]);
                }
            }
Пример #3
0
            public override BroadRay Directions(int index, int thread, ref Random random, int[] Octaves)
            {
                double Theta     = random.NextDouble() * 2 * System.Math.PI;
                double Phi       = random.NextDouble() * 2 * System.Math.PI;
                Vector Direction = new Vector(Math.Sin(Theta) * Math.Cos(Phi), Math.Sin(Theta) * Math.Sin(Phi), Math.Cos(Theta));

                BroadRay B = new BroadRay(H_Center, Direction, random.Next(), thread, DirPower(thread, random.Next(), Direction), 0, Source_ID(), Octaves);

                return(B);
            }
Пример #4
0
            public override BroadRay Directions(int index, int thread, ref Random random, int[] Octaves)
            {
                double Theta     = random.NextDouble() * 2 * System.Math.PI;
                double Phi       = random.NextDouble() * 2 * System.Math.PI;
                Vector Direction = new Vector(Math.Sin(Theta) * Math.Cos(Phi), Math.Sin(Theta) * Math.Sin(Phi), Math.Cos(Theta));

                BroadRay B = new BroadRay(H_Center, Direction, random.Next(), thread, SourcePower, phase, delay, Source_ID(), Octaves); //Provides divided Power[stochastic]

                return(B);
            }
 public override void Absorb(ref BroadRay Ray, Hare.Geometry.Vector Normal)
 {
     Ray.Energy[0] *= (Ref[0]);
     Ray.phase[0]  += PD[0];
     Ray.Energy[1] *= (Ref[1]);
     Ray.phase[1]  += PD[1];
     Ray.Energy[2] *= (Ref[2]);
     Ray.phase[2]  += PD[2];
     Ray.Energy[3] *= (Ref[3]);
     Ray.phase[3]  += PD[3];
     Ray.Energy[4] *= (Ref[4]);
     Ray.phase[4]  += PD[4];
     Ray.Energy[5] *= (Ref[5]);
     Ray.phase[5]  += PD[5];
     Ray.Energy[6] *= (Ref[6]);
     Ray.phase[6]  += PD[6];
     Ray.Energy[7] *= (Ref[7]);
     Ray.phase[7]  += PD[7];
 }
            public override void Absorb(ref BroadRay Ray, Hare.Geometry.Vector Normal)
            {
                //Simplified for sample laid on floor...
                Ray.direction.Normalize();
                int Alt = (int)Math.Floor((Math.Acos(Hare.Geometry.Hare_math.Dot(Ray.direction, new Hare.Geometry.Vector(0, 0, -1))) * Altitude.Length) / (Math.PI / 2));

                if (Alt >= Altitude.Length / 2)
                {
                    Alt = Altitude.Length - 1;
                }
                int Azi = (int)Math.Round((Math.Atan2(Ray.direction.y, Ray.direction.x) * Azimuth.Length) / Math.PI);

                if (Ray.direction.y < 0 && Azi < Azimuth.Length / 2)
                {
                    Azi = Azimuth.Length - Math.Abs(Azi);
                }
                for (int oct = 0; oct < 8; oct++)
                {
                    Ray.Energy[oct] *= alpha[Alt][Azi][oct];
                }
            }
            public override void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal)
            {
                cos_theta = Hare.Geometry.Hare_math.Dot(Normal, Ray.direction);

                Ray.Energy[0] *= (Ref[0]);
                Ray.phase[0]  += PD[0];
                Ray.Energy[1] *= (Ref[1]);
                Ray.phase[1]  += PD[1];
                Ray.Energy[2] *= (Ref[2]);
                Ray.phase[2]  += PD[2];
                Ray.Energy[3] *= (Ref[3]);
                Ray.phase[3]  += PD[3];
                Ray.Energy[4] *= (Ref[4]);
                Ray.phase[4]  += PD[4];
                Ray.Energy[5] *= (Ref[5]);
                Ray.phase[5]  += PD[5];
                Ray.Energy[6] *= (Ref[6]);
                Ray.phase[6]  += PD[6];
                Ray.Energy[7] *= (Ref[7]);
                Ray.phase[7]  += PD[7];
            }
 /// <summary>
 /// Checks receivers for intersections with a Broadband Ray (specular only). Records detections. Use after shooting a ray, but before adding the distance of ray travel to the total of distance traveled.
 /// </summary>
 /// <param name="R">a broadband ray.</param>
 /// <param name="Sumlength">the length of the ray before detection. Adds on the distance from the last reflection to the receiver.</param>
 /// <param name="EndPt">The point of the d</param>
 /// <param name="X">The current voxel index 'X'</param>
 /// <param name="Y">The current voxel index 'Y'</param>
 /// <param name="Z">The current voxel index 'Z'</param>
 private void CheckReceivers_Broadband(BroadRay R, Hare.Geometry.Point EndPt, int X, int Y, int Z)
 {
     //PachTools.AddBox(Voxels[X, Y, 0].Min(), Voxels[X, Y, 0].Max());//Debug tool...
     for (int i = 0; i < Voxel_Inv[X, Y, Z].Count; i++)
     {
         if (!(Rec_List[Voxel_Inv[X, Y, Z][i]].Ray_ID[R.ThreadID] == R.Ray_ID))
         {
             Rec_List[Voxel_Inv[X, Y, Z][i]].CheckBroadbandRay(R, EndPt);
             //    //Debug Code
             //    ///////////////////////////////////////////////////////////////////
             //    //OnSphere sphere = new OnSphere(Rec_List[Voxel_Inv[X, Y, Z][i]].Origin,Rec_List[Voxel_Inv[X, Y, Z][i]].Radius);
             //    //OnRevSurface sphere_srf = sphere.RevSurfaceForm();
             //    //MRhinoSurfaceObject sphere_obj = new MRhinoSurfaceObject();
             //    //sphere_obj.SetSurface(sphere_srf);
             //    //RhUtil.RhinoApp().ActiveDoc().AddObject(sphere_obj);
             //    ///////////////////////////////////////////////////////////////////
             //}
             Rec_List[Voxel_Inv[X, Y, Z][i]].Ray_ID[R.ThreadID] = R.Ray_ID;
         }
     }
 }
            public override void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal)
            {
                cos_theta = Hare.Geometry.Hare_math.Dot(Ray.direction, Normal);
                int index = 18 - (int)Math.Round(Math.Acos(Math.Abs(cos_theta)) / angle_incr);

                for (int oct = 0; oct < 8; oct++) Ray.Energy[oct] *= (1 - Ang_Coef_Oct[oct][index]);
            }
 public abstract void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal);
            public override void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal)
            {
                Ray.direction.Normalize();
                cos_theta = Math.Acos(Hare.Geometry.Hare_math.Dot(Ray.direction, new Hare.Geometry.Vector(0, 0, -1)));
                int Alt = (int)Math.Floor((cos_theta * Altitude.Length) / (Math.PI / 2));
                if (Alt >= Altitude.Length / 2) Alt = Altitude.Length - 1;
                int Azi = (int)Math.Round((Math.Atan2(Ray.direction.y, Ray.direction.x) * Azimuth.Length) / Math.PI);
                if (Ray.direction.y < 0 && Azi < Azimuth.Length / 2) Azi = Azimuth.Length - Math.Abs(Azi);

                for (int oct = 0; oct < 8; oct++) Ray.Energy[oct] *= alpha[Alt][Azi][oct];
            }
            public override void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal)
            {
                cos_theta = Hare.Geometry.Hare_math.Dot(Normal, Ray.direction);

                Ray.Energy[0] *= (Ref[0]);
                Ray.phase[0] += PD[0];
                Ray.Energy[1] *= (Ref[1]);
                Ray.phase[1] += PD[1];
                Ray.Energy[2] *= (Ref[2]);
                Ray.phase[2] += PD[2];
                Ray.Energy[3] *= (Ref[3]);
                Ray.phase[3] += PD[3];
                Ray.Energy[4] *= (Ref[4]);
                Ray.phase[4] += PD[4];
                Ray.Energy[5] *= (Ref[5]);
                Ray.phase[5] += PD[5];
                Ray.Energy[6] *= (Ref[6]);
                Ray.phase[6] += PD[6];
                Ray.Energy[7] *= (Ref[7]);
                Ray.phase[7] += PD[7];
            }
 public abstract void Absorb(ref BroadRay Ray, out double cos_theta, double u, double v);
 public override void Absorb(ref BroadRay Ray, out double cos_theta, double u, double v)
 {
     AbsorptionData[Ray.Surf_ID].Absorb(ref Ray, out cos_theta, Normal(Ray.Surf_ID, u, v));                
 }
 public abstract void Scatter_Early(ref BroadRay Ray, ref Queue <OctaveRay> Rays, ref Random rand, double cos_theta, double u, double v);
 public abstract void Absorb(ref BroadRay Ray, out double cos_theta, double u, double v);
 public override void Scatter_Early(ref BroadRay Ray, ref Queue <OctaveRay> Rays, ref Random rand, double cos_theta, double u, double v)
 {
     return;
 }
 public override void Absorb(ref BroadRay Ray, out double cos_theta, double u, double v)
 {
     cos_theta = 0;
 }
 /// <summary>
 /// this method checks all receivers in the bank for intersections with a broadband ray.
 /// </summary>
 /// <param name="Length">the distance traveled by the ray up to the reflection prior to potential receiver intersection</param>
 /// <param name="R">the broadband ray</param>
 /// <param name="EndPt">the point of intersection with the room after the potential receiver intersection</param>
 public virtual void CheckBroadbandRay(BroadRay R, Hare.Geometry.Point EndPt)
 {
     foreach (Spherical_Receiver S in Rec_List) {S.CheckBroadbandRay(R,EndPt);};
 }
 /// <summary>
 /// This method checks a receiver for an intersection with a ray.
 /// </summary>
 /// <param name="R">the ray.</param>
 /// <param name="EndPt">The point at which the ray intersects the model after potential receiver intersection.</param>
 /// <param name="Length">The length of the ray at the reflection point before potential intersection</param>
 /// <returns>true if intersects, false if not.</returns>
 public virtual bool SimpleCheck(BroadRay R, Hare.Geometry.Point EndPt)
 {
     Vector m = R.origin - H_Origin;
     double b = Hare_math.Dot(m, R.direction);
     double c = Hare_math.Dot(m, m) - Radius2;
     if (c > 0 && b > 0) return false;
     double discr = b * b - c;
     if (discr < 0) return false;
     double t1 = -b - Math.Sqrt(discr);
     double t2 = -b + Math.Sqrt(discr);
     double t = (t1 + t2) * .5;
     if (t > 0 && t * t < SqDistance(EndPt, R.origin)) return true;
     return false;
 }
 /// <summary>
 /// This method checks a receiver for a ray using a Broadband Ray (these typically occur before rays are split in the Raytracing simulation.
 /// </summary>
 /// <param name="Length">The length of the ray at the reflection point before potential intersection</param>
 /// <param name="R">the ray.</param>
 /// <param name="EndPt">The point at which the ray intersects the model after potential receiver intersection.</param>
 public virtual void CheckBroadbandRay(BroadRay R, Hare.Geometry.Point EndPt)
 {
     Vector m = R.origin - H_Origin;
     double b = Hare_math.Dot(m, R.direction);
     double c = Hare_math.Dot(m, m)  - Radius2;
     if (c > 0 && b > 0) return;
     double discr = b * b - c;
     if (discr < 0) return;
     double t1 = -b - Math.Sqrt(discr);
     double t2 = -b + Math.Sqrt(discr);
     double tsphere = (t2 - t1) * 0.5;
     double t = (t1 + t2) * .5;
     if (t > 0 && t * t < SqDistance(EndPt, R.origin))
     {
         double RayTime = t*Inv_C_Sound + R.t_sum;
         Vector Dir = R.direction * -1;
         Dir.Normalize();
         Recs.Add(RayTime, R.Energy[0] * Math.Pow(10,-.1 * Atten[0] * t) * SizeMod * tsphere, Dir, R.phase[0], Rho_C, 0);
         Recs.Add(RayTime, R.Energy[1] * Math.Pow(10,-.1 * Atten[1] * t) * SizeMod * tsphere, Dir, R.phase[1], Rho_C, 1);
         Recs.Add(RayTime, R.Energy[2] * Math.Pow(10,-.1 * Atten[2] * t) * SizeMod * tsphere, Dir, R.phase[2], Rho_C, 2);
         Recs.Add(RayTime, R.Energy[3] * Math.Pow(10,-.1 * Atten[3] * t) * SizeMod * tsphere, Dir, R.phase[3], Rho_C, 3);
         Recs.Add(RayTime, R.Energy[4] * Math.Pow(10,-.1 * Atten[4] * t) * SizeMod * tsphere, Dir, R.phase[4], Rho_C, 4);
         Recs.Add(RayTime, R.Energy[5] * Math.Pow(10,-.1 * Atten[5] * t) * SizeMod * tsphere, Dir, R.phase[5], Rho_C, 5);
         Recs.Add(RayTime, R.Energy[6] * Math.Pow(10,-.1 * Atten[6] * t) * SizeMod * tsphere, Dir, R.phase[6], Rho_C, 6);
         Recs.Add(RayTime, R.Energy[7] * Math.Pow(10,-.1 * Atten[7] * t) * SizeMod * tsphere, Dir, R.phase[7], Rho_C, 7);
     }
 }
 /// <summary>
 /// Checks all receivers for intersections with a ray. This method does not record energy.
 /// </summary>
 /// <param name="R">the single octave band ray</param>
 /// <param name="EndPt">the point of intersection with the room after the potential receiver intersection</param>
 /// <param name="Length">the distance traveled by the ray up to the reflection prior to potential receiver intersection</param>
 /// <returns> an array of boolean values, indexed by receiver number</returns>
 public virtual bool[] SimpleCheck(BroadRay R, Hare.Geometry.Point EndPt, double Length)
 {
     bool[] B = new bool[Rec_List.Length];
     for (int i = 0; i < Rec_List.Length; i++) { B[i] = Rec_List[i].SimpleCheck(R, EndPt);};
     return B;
 }
            public override void Scatter_Early(ref BroadRay Ray, ref Queue <OctaveRay> Rays, ref Random rand, Hare.Geometry.Vector Normal, double Cos_Theta)
            {
                double roughness_chance = rand.NextDouble();

                if (Cos_Theta > 0)
                {
                    Normal    *= -1;
                    Cos_Theta *= -1;
                }

                foreach (int oct in Ray.Octaves)
                {
                    // 3. Apply Scattering.
                    //// a. Create new source for scattered energy (E * Scattering).
                    //// b. Modify E (E * 1 - Scattering).
                    OctaveRay R = Ray.SplitRay(oct, Scattering_Coefficient[oct, 1]);

                    Hare.Geometry.Vector diffx;
                    Hare.Geometry.Vector diffy;
                    Hare.Geometry.Vector diffz;
                    double proj;
                    //Check that the ray and the normal are both on the same side...
                    diffz = Normal;
                    diffx = new Hare.Geometry.Vector(0, 0, 1);
                    proj  = Math.Abs(Hare.Geometry.Hare_math.Dot(diffz, diffx));

                    if (0.99 < proj && 1.01 > proj)
                    {
                        diffx = new Hare.Geometry.Vector(1, 0, 0);
                    }
                    diffy = Hare.Geometry.Hare_math.Cross(diffz, diffx);
                    diffx = Hare.Geometry.Hare_math.Cross(diffy, diffz);
                    diffx.Normalize();
                    diffy.Normalize();
                    diffz.Normalize();

                    double u1;
                    double u2;
                    double x;
                    double y;
                    double z;
                    Hare.Geometry.Vector vect;
                    u1 = 2.0 * Math.PI * rand.NextDouble();
                    // random azimuth
                    double Scat_Mod = rand.NextDouble();
                    u2 = Math.Acos(Scat_Mod);
                    // random zenith (elevation)
                    x = Math.Cos(u1) * Math.Sin(u2);
                    y = Math.Sin(u1) * Math.Sin(u2);
                    z = Math.Cos(u2);

                    vect = (diffx * x) + (diffy * y) + (diffz * z);
                    vect.Normalize();

                    //Return the new direction
                    R.direction = vect;

                    if (R.t_sum == 0)
                    {
                        Rhino.RhinoApp.Write("Something's up!");
                    }

                    Rays.Enqueue(R);
                }
                Ray.direction -= Normal * Cos_Theta * 2;
            }
 /// <summary>
 /// Calculates the direction of a specular reflection.
 /// </summary>
 /// <param name="RayDirect"></param>
 /// <param name="u"></param>
 /// <param name="v"></param>
 /// <param name="x"></param>
 protected virtual void ReflectRay(ref BroadRay RayDirect, ref double u, ref double v, ref int x)
 {
     Vector local_N = Room.Normal(x, u, v);
     RayDirect.direction -= local_N * Hare_math.Dot(RayDirect.direction, local_N) * 2;
 }
 public override void Scatter_Early(ref BroadRay Ray, ref Queue<OctaveRay> Rays, ref Random rand, double cos_theta, double u, double v)
 {
     ScatteringData[Ray.Surf_ID].Scatter_Early(ref Ray, ref Rays, ref rand, Normal(Ray.Surf_ID, u, v), cos_theta);
 }
            /// <summary>
            /// This method checks a receiver for a ray using a Broadband Ray (these typically occur before rays are split in the Raytracing simulation.
            /// </summary>
            /// <param name="Length">The length of the ray at the reflection point before potential intersection</param>
            /// <param name="R">the ray.</param>
            /// <param name="EndPt">The point at which the ray intersects the model after potential receiver intersection.</param>
            public override void CheckBroadbandRay(BroadRay R, Hare.Geometry.Point EndPt)
            {
                double Radius = (R.t_sum * C_Sound) * Math.Sqrt(6.28 / (RayCount));
                double Radius2 = Radius * Radius;
                Vector m = R.origin - H_Origin;
                double RayLength = (EndPt - R.origin).Length();
                Vector d = (EndPt - R.origin) / RayLength;
                double b = Hare_math.Dot(m, d);
                double c = Hare_math.Dot(m, m) - (Radius2);
                if (c > 0 && b > 0) return;
                double discr = b * b - c;
                if (discr < 0) return;
                double t1 = -b - Math.Sqrt(discr);
                double t2 = -b + Math.Sqrt(discr);
                double t = (t1 + t2) * .5;
                if (t > 0 && t * t < SqDistance(EndPt, R.origin))
                {
                    double t_ACC = Math.Abs(t1 - t2);
                    double RayTime = t * Inv_C_Sound + R.t_sum;
                    Vector Dir = R.direction * -1;
                    double Area = Math.PI * Radius2;

                    Recs.Add(RayTime, (R.Energy[0] * Math.Pow(10,-.1 * Atten[0] * t) / Area), Dir, R.phase[0], Rho_C, 0);
                    Recs.Add(RayTime, (R.Energy[1] * Math.Pow(10,-.1 * Atten[1] * t) / Area), Dir, R.phase[1], Rho_C, 1);
                    Recs.Add(RayTime, (R.Energy[2] * Math.Pow(10,-.1 * Atten[2] * t) / Area), Dir, R.phase[2], Rho_C, 2);
                    Recs.Add(RayTime, (R.Energy[3] * Math.Pow(10,-.1 * Atten[3] * t) / Area), Dir, R.phase[3], Rho_C, 3);
                    Recs.Add(RayTime, (R.Energy[4] * Math.Pow(10,-.1 * Atten[4] * t) / Area), Dir, R.phase[4], Rho_C, 4);
                    Recs.Add(RayTime, (R.Energy[5] * Math.Pow(10,-.1 * Atten[5] * t) / Area), Dir, R.phase[5], Rho_C, 5);
                    Recs.Add(RayTime, (R.Energy[6] * Math.Pow(10,-.1 * Atten[6] * t) / Area), Dir, R.phase[6], Rho_C, 6);
                    Recs.Add(RayTime, (R.Energy[7] * Math.Pow(10,-.1 * Atten[7] * t) / Area), Dir, R.phase[7], Rho_C, 7);
                }
                return;
            }
 public abstract void Scatter_Early(ref BroadRay Ray, ref Queue<OctaveRay> Rays, ref Random rand, double cos_theta, double u, double v);
 public abstract void Absorb(ref BroadRay Ray, Hare.Geometry.Vector Normal);
 public override void Absorb(ref BroadRay Ray, Hare.Geometry.Vector Normal)
 {
     Ray.Energy[0] *= (Ref[0]);
     Ray.phase[0] += PD[0];
     Ray.Energy[1] *= (Ref[1]);
     Ray.phase[1] += PD[1];
     Ray.Energy[2] *= (Ref[2]);
     Ray.phase[2] += PD[2];
     Ray.Energy[3] *= (Ref[3]);
     Ray.phase[3] += PD[3];
     Ray.Energy[4] *= (Ref[4]);
     Ray.phase[4] += PD[4];
     Ray.Energy[5] *= (Ref[5]);
     Ray.phase[5] += PD[5];
     Ray.Energy[6] *= (Ref[6]);
     Ray.phase[6] += PD[6];
     Ray.Energy[7] *= (Ref[7]);
     Ray.phase[7] += PD[7];
 }
 public override void Scatter_Early(ref BroadRay Ray, ref Queue <OctaveRay> Rays, ref Random rand, double cos_theta, double u, double v)
 {
     ScatteringData[Ray.Surf_ID].Scatter_Early(ref Ray, ref Rays, ref rand, Normal(Ray.Surf_ID, u, v), cos_theta);
 }
 public abstract void Absorb(ref BroadRay Ray, Hare.Geometry.Vector Normal);
        /// <summary>
        /// Called by each thread from the begin method.
        /// </summary>
        /// <param name="i">the object is type "Calc_Params" which holds all the necessary information to run a portion of the simulation.</param>
        public void Calculate(object i)
        {
            Calc_Params Params = (Calc_Params)i;
            Random      RND    = new Random(Params.RandomSeed);

            ST = DateTime.Now;
            Hare.Geometry.Point Origin = Source.H_Origin();
            ///'''''''''''''Renewable Variables''''''''''''''''''
            double SumLength;
            double u = 0;
            double v = 0;

            Hare.Geometry.Point Point = new Hare.Geometry.Point();
            int ChosenIndex           = 0;
            List <Hare.Geometry.Point> Start;
            int        Reflections;
            List <int> Sequence = new List <int>();

            ///''''''''''''''''''''''''''''''''''''''''''''''''''

            for (Current_Ray[Params.ThreadID] = 0; Current_Ray[Params.ThreadID] < Params.EndIndex - Params.StartIndex; Current_Ray[Params.ThreadID]++)
            {
                BroadRay R = Source.Directions(Current_Ray[Params.ThreadID] + Params.StartIndex, Params.ThreadID, ref RND);
                SumLength   = 0;
                Reflections = 0;
                Sequence.Clear();
                List <int> code = new List <int> {
                    0
                };
                List <double> leg = new List <double> {
                    0
                };
                do
                {
                    ///Only useable with homogeneous media///
                    SumLength += leg[0];
                    R.Ray_ID   = RND.Next();
                    if (Room.shoot(R, out u, out v, out ChosenIndex, out Start, out leg, out code))
                    {
                        if (!Room.IsPlanar(ChosenIndex))
                        {
                            break;
                        }
                        Reflections++;
                        ReflectRay(ref R, ref u, ref v, ref ChosenIndex);
                        if (Reflections > ImageOrder + 1)
                        {
                            bool[] B = Receiver.SimpleCheck(R, Start[0], SumLength);
                            for (int q = 0; q < B.Length; q++)
                            {
                                if (B[q])
                                {
                                    Detections[q, Params.ThreadID].Add(Sequence.ToArray());
                                }
                            }
                        }
                    }
                    else
                    {
                        //Rhino.RhinoDoc.ActiveDoc.Objects.AddCurve(new LineCurve(Pachyderm_Acoustic.Utilities.PachTools.HPttoRPt(R.origin), Pachyderm_Acoustic.Utilities.PachTools.HPttoRPt(R.origin + R.direction) * 5));
                        break;
                    }
                    Sequence.Add(Room.PlaneID(ChosenIndex));
                    R.origin = Start[0];
                }while (SumLength < CutoffLength);
            }
        }
 public abstract void Scatter_Early(ref BroadRay Ray, ref Queue<OctaveRay> Rays, ref Random rand, Hare.Geometry.Vector Normal, double Cos_Theta);
 /// <summary>
 /// This method checks a receiver for a ray using a Broadband Ray (these typically occur before rays are split in the Raytracing simulation.
 /// </summary>
 /// <param name="r">the ray.</param>
 /// <param name="endPt">The point at which the ray intersects the model after potential receiver intersection.</param>
 public override void CheckBroadbandRay(BroadRay r, Hare.Geometry.Point endPt)
 {
     Vector m = r.origin - H_Origin;
     double b = Hare_math.Dot(m, r.direction);
     double c = Hare_math.Dot(m, m) - Radius2;
     if (c > 0 && b > 0) return;
     double discr = b * b - c;
     if (discr < 0) return;
     double t1 = -b - Math.Sqrt(discr);
     double t2 = -b + Math.Sqrt(discr);
     double t = (t1 + t2) / 2;
     if (t > 0 && t * t < SqDistance(endPt, r.origin))
     {
         double raydist = t/C_Sound + r.t_sum - Direct_Time;
         Vector dir = r.direction * -1;
         Recs.Add(raydist, r.Energy[0] * Math.Pow(10,-.1 * Atten[0] * raydist) * SizeMod, dir, r.phase[0], Rho_C, 0);
         Recs.Add(raydist, r.Energy[1] * Math.Pow(10,-.1 * Atten[1] * raydist) * SizeMod, dir, r.phase[1], Rho_C, 1);
         Recs.Add(raydist, r.Energy[2] * Math.Pow(10,-.1 * Atten[2] * raydist) * SizeMod, dir, r.phase[2], Rho_C, 2);
         Recs.Add(raydist, r.Energy[3] * Math.Pow(10,-.1 * Atten[3] * raydist) * SizeMod, dir, r.phase[3], Rho_C, 3);
         Recs.Add(raydist, r.Energy[4] * Math.Pow(10,-.1 * Atten[4] * raydist) * SizeMod, dir, r.phase[4], Rho_C, 4);
         Recs.Add(raydist, r.Energy[5] * Math.Pow(10,-.1 * Atten[5] * raydist) * SizeMod, dir, r.phase[5], Rho_C, 5);
         Recs.Add(raydist, r.Energy[6] * Math.Pow(10,-.1 * Atten[6] * raydist) * SizeMod, dir, r.phase[6], Rho_C, 6);
         Recs.Add(raydist, r.Energy[7] * Math.Pow(10,-.1 * Atten[7] * raydist) * SizeMod, dir, r.phase[7], Rho_C, 7);
     }
 }
            public override void Scatter_Early(ref BroadRay Ray, ref Queue<OctaveRay> Rays, ref Random rand, Hare.Geometry.Vector Normal, double Cos_Theta)
            {
                double roughness_chance = rand.NextDouble();
                if (Cos_Theta > 0)
                {
                    Normal *= -1;
                    Cos_Theta *= -1;
                }

                foreach (int oct in Ray.Octaves)
                {
                    // 3. Apply Scattering.
                    //// a. Create new source for scattered energy (E * Scattering).
                    //// b. Modify E (E * 1 - Scattering).
                    OctaveRay R = Ray.SplitRay(oct, Scattering_Coefficient[oct, 1]);

                    Hare.Geometry.Vector diffx;
                    Hare.Geometry.Vector diffy;
                    Hare.Geometry.Vector diffz;
                    double proj;
                    //Check that the ray and the normal are both on the same side...
                    diffz = Normal;
                    diffx = new Hare.Geometry.Vector(0, 0, 1);
                    proj = Math.Abs(Hare.Geometry.Hare_math.Dot(diffz, diffx));

                    if (0.99 < proj && 1.01 > proj) diffx = new Hare.Geometry.Vector(1, 0, 0);
                    diffy = Hare.Geometry.Hare_math.Cross(diffz, diffx);
                    diffx = Hare.Geometry.Hare_math.Cross(diffy, diffz);
                    diffx.Normalize();
                    diffy.Normalize();
                    diffz.Normalize();

                    double u1;
                    double u2;
                    double x;
                    double y;
                    double z;
                    Hare.Geometry.Vector vect;
                    u1 = 2.0 * Math.PI * rand.NextDouble();
                    // random azimuth
                    double Scat_Mod = rand.NextDouble();
                    u2 = Math.Acos(Scat_Mod);
                    // random zenith (elevation)
                    x = Math.Cos(u1) * Math.Sin(u2);
                    y = Math.Sin(u1) * Math.Sin(u2);
                    z = Math.Cos(u2);

                    vect = (diffx * x) + (diffy * y) + (diffz * z);
                    vect.Normalize();

                    //Return the new direction
                    R.direction = vect;

                    if (R.t_sum == 0)
                    {
                        Rhino.RhinoApp.Write("Something's up!");
                    }

                    Rays.Enqueue(R);

                }
                Ray.direction -= Normal * Cos_Theta * 2;
            }
 public override BroadRay Directions(int index, int thread, ref Random random, int[] Octaves)
 {
     double Theta = random.NextDouble() * 2 * System.Math.PI;
     double Phi = random.NextDouble() * 2 * System.Math.PI;
     Vector Direction = new Vector(Math.Sin(Theta) * Math.Cos(Phi), Math.Sin(Theta) * Math.Sin(Phi), Math.Cos(Theta));
     
     BroadRay B = new BroadRay(H_Center, Direction, random.Next(), thread, SourcePower, phase, delay, Source_ID(), Octaves); //Provides divided Power[stochastic]
     return B;
 }
 public override void Absorb(ref BroadRay Ray, out double cos_theta, double u, double v)
 {
     AbsorptionData[Ray.Surf_ID].Absorb(ref Ray, out cos_theta, Normal(Ray.Surf_ID, u, v));
 }
 /// <summary>
 /// This method checks a receiver for an intersection with a ray.
 /// </summary>
 /// <param name="R">the ray.</param>
 /// <param name="EndPt">The point at which the ray intersects the model after potential receiver intersection.</param>
 /// <param name="Length">The length of the ray at the reflection point before potential intersection</param>
 /// <returns>true if intersects, false if not.</returns>
 public override bool SimpleCheck(BroadRay R, Hare.Geometry.Point EndPt)
 {
     double Radius = R.t_sum * Math.Sqrt(6.28 / RayCount);
     Vector m = R.origin - H_Origin;
     double b = Hare_math.Dot(m, R.direction);
     double c = Hare_math.Dot(m, m) - (Radius * Radius);
     if (c > 0 && b > 0) return false;
     double discr = b * b - c;
     if (discr < 0) return false;
     double t = (-b - Math.Sqrt(discr)) + (-b + Math.Sqrt(discr)) / 2;
     if (t * t < SqDistance(EndPt, R.origin)) return true;
     return false;
 }
 public abstract void Absorb(ref BroadRay Ray, out double cos_theta, Hare.Geometry.Vector Normal);
 public abstract void Scatter_Early(ref BroadRay Ray, ref Queue <OctaveRay> Rays, ref Random rand, Hare.Geometry.Vector Normal, double Cos_Theta);
        /// <summary>
        /// Calculates the direction of a specular reflection.
        /// </summary>
        /// <param name="RayDirect"></param>
        /// <param name="u"></param>
        /// <param name="v"></param>
        /// <param name="x"></param>
        protected virtual void ReflectRay(ref BroadRay RayDirect, ref double u, ref double v, ref int x)
        {
            Vector local_N = Room.Normal(x, u, v);

            RayDirect.direction -= local_N * Hare_math.Dot(RayDirect.direction, local_N) * 2;
        }
            /// <summary>
            /// Checks receivers for intersections with a broadband ray (specular only). Records detections. Use after shooting a ray, but before adding the distance of ray travel to the total of distance traveled.
            /// </summary>
            /// <param name="R">a broadband ray.</param>
            /// <param name="Sumlength">the length of the ray before detection. Adds on the distance from the last reflection to the receiver.</param>
            /// <param name="EndPt">The point of the d</param>
            public override void CheckBroadbandRay(BroadRay R, Hare.Geometry.Point EndPt)
            {
               // R.ThreadID = this.Get_shotID();
                int X, Y, Z, Xend, Yend, Zend;
                //Identify whether the Origin is inside the voxel grid...
                double Sumlength = R.t_sum;

                if (!OBox.IsPointInBox(R.origin))
                {
                    double t0 = 0;
                    if (!OBox.Intersect(R, ref t0, ref R.origin)) return;
                    Sumlength += t0;
                }

                //Identify where the ray enters the voxel grid...
                X = (int)Math.Floor((R.origin.x - OBox.Min_PT.x) / VoxelDims.x);
                Y = (int)Math.Floor((R.origin.y - OBox.Min_PT.y) / VoxelDims.y);
                Z = (int)Math.Floor((R.origin.z - OBox.Min_PT.z) / VoxelDims.z);

                Xend = (int)Math.Floor((EndPt.x - OBox.Min_PT.x) / VoxelDims.x);
                Yend = (int)Math.Floor((EndPt.y - OBox.Min_PT.y) / VoxelDims.y);
                Zend = (int)Math.Floor((EndPt.z - OBox.Min_PT.z) / VoxelDims.z);

                double tDeltaX, tDeltaY, tDeltaZ;
                double tMaxX = 0, tMaxY = 0, tMaxZ = 0;

                int stepX, stepY, stepZ, OutX, OutY, OutZ;

                if (X < 0) X = 0;
                if (X >= VoxelCtX) X = VoxelCtX - 1;
                if (Y < 0) Y = 0;
                if (Y >= VoxelCtY) Y = VoxelCtY - 1;
                if (Z < 0) Z = 0;
                if (Z >= VoxelCtZ) Z = VoxelCtZ - 1;

                if (R.direction.x < 0)
                {
                    OutX = -1;
                    stepX = -1;
                    tMaxX = (Voxels[X, Y, Z].Min_PT.x - R.origin.x) / R.direction.x;
                    tDeltaX = VoxelDims.x / R.direction.x * stepX;
                }
                else
                {
                    OutX = VoxelCtX;
                    stepX = 1;
                    tMaxX = (Voxels[X, Y, Z].Max_PT.x - R.origin.x) / R.direction.x;
                    tDeltaX = VoxelDims.x / R.direction.x * stepX;
                }

                if (R.direction.y < 0)
                {
                    OutY = -1;
                    stepY = -1;
                    tMaxY = (Voxels[X, Y, Z].Min_PT.y - R.origin.y) / R.direction.y;
                    tDeltaY = VoxelDims.y / R.direction.y * stepY;
                }
                else
                {
                    OutY = VoxelCtY;
                    stepY = 1;
                    tMaxY = (Voxels[X, Y, Z].Max_PT.y - R.origin.y) / R.direction.y;
                    tDeltaY = VoxelDims.y / R.direction.y * stepY;
                }

                if (R.direction.z < 0)
                {
                    OutZ = -1;
                    stepZ = -1;
                    tMaxZ = (Voxels[X, Y, Z].Min_PT.z - R.origin.z) / R.direction.z;
                    tDeltaZ = VoxelDims.z / R.direction.z * stepZ;
                }
                else
                {
                    OutZ = VoxelCtZ;
                    stepZ = 1;
                    tMaxZ = (Voxels[X, Y, Z].Max_PT.z - R.origin.z) / R.direction.z;
                    tDeltaZ = VoxelDims.z / R.direction.z * stepZ;
                }

                do
                {
                    CheckReceivers_Broadband(R, EndPt, X, Y, Z);

                    if (tMaxX < tMaxY)
                    {
                        if (tMaxX < tMaxZ)
                        {
                            X += stepX;
                            if (X < 0 || X >= VoxelCtX)
                                return; /* outside grid */
                            tMaxX = tMaxX + tDeltaX;
                        }
                        else
                        {
                            Z += stepZ;
                            if (Z < 0 || Z >= VoxelCtZ)
                                return; /* outside grid */
                            tMaxZ = tMaxZ + tDeltaZ;
                        }
                    }

                    else
                    {
                        if (tMaxY < tMaxZ)
                        {
                            Y += stepY;
                            if (Y < 0 || Y >= VoxelCtY)
                                return; /* outside grid */
                            tMaxY = tMaxY + tDeltaY;
                        }
                        else
                        {
                            Z += stepZ;
                            if (Z < 0 || Z >= VoxelCtZ)
                                return; /* outside grid */
                            tMaxZ = tMaxZ + tDeltaZ;
                        }
                    }
                } while (X != Xend && Y != Yend && Z != Zend);
            }