public void Begin() { Random Rnd = new Random(); for (int q = 0; q < RayCount; q++) { Rhino.RhinoApp.SetCommandPrompt(string.Format("Finding Ray {0} of {1}", q, RayCount)); double SumLength = 0; Pachyderm_Acoustic.Environment.OctaveRay R = Source.Directions(q, 0, ref Rnd).SplitRay(5); double u = 0; double v = 0; int ChosenIndex = 0; Polyline Ray = new Polyline(); List <double> leg = new List <double> { 0 }; List <int> code = new List <int> { 0 }; List <Hare.Geometry.Point> Start; //List<int> IDs = new List<int>(); Ray.Add(PachTools.HPttoRPt(R.origin)); List <double> P = new List <double> { R.Intensity }; do { R.Ray_ID = Rnd.Next(); if (Room.shoot(R, out u, out v, out ChosenIndex, out Start, out leg, out code)) { double cos_theta; for (int i = 0; i < Start.Count; i++) { Ray.Add(PachTools.HPttoRPt(Start[i])); //IDs.Add(-1); R.Intensity *= Math.Pow(10, -.1 * Room.Attenuation(code[i])[5] * leg[i]); SumLength += leg[i]; } R.origin = Start[Start.Count - 1]; R.Surf_ID = ChosenIndex; bool trans = (Rnd.NextDouble() < Room.TransmissionValue[ChosenIndex][5]); Room.Absorb(ref R, out cos_theta, u, v); Room.Scatter_Simple(ref R, ref Rnd, cos_theta, u, v); if (trans) { R.direction *= -1; R.Intensity *= Room.TransmissionValue[ChosenIndex][5]; } else { R.Intensity *= (1 - Room.TransmissionValue[ChosenIndex][5]); } P.Add((double)R.Intensity); //if (Rnd.NextDouble() < Room.ScatteringValue[ChosenIndex].Coefficient(5)) //{ // Room.Scatter_Simple(ref R, ref Rnd); // //Utilities.PachTools.Ray_Acoustics.LambertianReflection_Stoch(ref R.direction, ref Rnd, Room.Normal(ChosenIndex, u, v)); // if (trans) // { // R.direction *= -1; // R.Intensity *= Room.TransmissionValue[ChosenIndex][5]; // } // else // { // R.Intensity *= Room.AbsorptionValue[ChosenIndex].Coefficient_A_Broad()[5]; // } //} //else //{ // if (!trans) // { // Utilities.PachTools.Ray_Acoustics.SpecularReflection(ref R.direction, ref Room, ref u, ref v, ref ChosenIndex); // R.Intensity *= Room.AbsorptionValue[ChosenIndex].Coefficient_A_Broad()[5]; // } // else // { // R.Intensity *= Room.TransmissionValue[ChosenIndex][5]; // } //} } else { //Rhino.RhinoDoc.ActiveDoc.Objects.AddLine(PachTools.HPttoRPt(R.origin), PachTools.HPttoRPt(R.origin + R.direction)); break; } }while (SumLength < CutoffLength); //Poly_ID.Add(IDs); if (SumLength > CutoffLength) { Ray.Add(PachTools.HPttoRPt(R.origin)); } RayList.Add(Ray); Power.Add(P); } }
/// <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) { ///Homogeneous media only... Calc_Params Params = (Calc_Params)i; Random Rnd = new Random(Params.RandomSeed); _st = DateTime.Now; Point Origin = Source.H_Origin(); int Dir_ID = Params.StartIndex; List <Point> Start; List <double> leg; List <int> code; Queue <OctaveRay> Rays = new Queue <OctaveRay>(); BroadRay R; int order; double Threshold_Power_1 = 0; double[] Threshold_Power_2 = new double[8]; double[] Threshold_Power_3 = new double[8]; for (_currentRay[Params.ThreadID] = 0; _currentRay[Params.ThreadID] < Params.EndIndex - Params.StartIndex; _currentRay[Params.ThreadID]++) { R = Source.Directions(_currentRay[Params.ThreadID] + Params.StartIndex, Params.ThreadID, ref Rnd, _octaves); for (int oct = 0; oct < 8; oct++) { R.Energy[oct] /= Raycount; } for (int j = 0; j < 8; j++) { _eInit[Params.ThreadID] += R.Energy[j]; } Threshold_Power_1 = R.Energy[h_oct] * 1E-2; foreach (int o in _octaves) { Threshold_Power_2[o] = R.Energy[o] * 1E-4; //Cease splitting at 0.0001 sound intensity, or 40 dB down. Threshold_Power_3[o] = R.Energy[o] * 1E-10; //Finish 16 digits (double Precision) under 60 dB of decay. } order = 0; double u = 0, v = 0; do { R.Ray_ID = Rnd.Next(); if (!Params.Room.shoot(R, out u, out v, out R.Surf_ID, out Start, out leg, out code)) { //Ray is lost... move on... for (int j = 0; j < 8; j++) { _lost[Params.ThreadID] += R.Energy[j]; } goto Do_Scattered; } if (order > IS_Order) { //Specular ray order exceeds order of image source calculation. Start logging specular part. RecMain.CheckBroadbandRay(R, Start[0]); } R.Energy[0] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[0] * leg[0]); R.Energy[1] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[1] * leg[0]); R.Energy[2] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[2] * leg[0]); R.Energy[3] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[3] * leg[0]); R.Energy[4] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[4] * leg[0]); R.Energy[5] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[5] * leg[0]); R.Energy[6] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[6] * leg[0]); R.Energy[7] *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[7] * leg[0]); R.AddLeg(leg[0] / Room.Sound_speed(code[0])); R.origin = Start[0]; order++; /////////////////////////////////////////////////////////////// //The Split Case : Specular and Diffuse Explicit ///Standard Energy Conservation Routine- // 1. Multiply by Reflection energy. (1 - Absorption) double cos_theta; Room.Absorb(ref R, out cos_theta, u, v); // 2. Apply Transmission (if any). //// a. Create new source for transmitted energy (E * Transmission). //// b. Modify E (E * 1 - Transmission). foreach (int oct in _octaves) { if (Params.Room.TransmissionValue[R.Surf_ID][oct] > 0.0) { Rays.Enqueue(R.SplitRay(oct, Params.Room.TransmissionValue[R.Surf_ID][oct])); } } //3. Apply Scattering Room.Scatter_Early(ref R, ref Rays, ref Rnd, cos_theta, u, v); /////////////////////////////////////////////////////////////// //Utilities.PachTools.Ray_Acoustics.SpecularReflection(ref R.direction, ref Room, ref _u[Params.ThreadID], ref _v[Params.ThreadID], ref R.Surf_ID); } while (R.Energy[h_oct] > Threshold_Power_1); foreach (int o in _octaves) { Rays.Enqueue(R.SplitRay(o)); //Split all rays into individual octaves. } Do_Scattered: if (Rays.Count > 0) { do { OctaveRay OR = Rays.Dequeue(); _rayTotal[Params.ThreadID]++; do { OR.Ray_ID = Rnd.Next(); if (!Params.Room.shoot(OR, out u, out v, out OR.Surf_ID, out Start, out leg, out code)) { _lost[Params.ThreadID] += OR.Intensity; goto Do_Scattered; } RecMain.CheckRay(OR, Start[0]); OR.Intensity *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[OR.Octave] * leg[0]); OR.AddLeg(leg[0] / Room.Sound_speed(code[0])); OR.origin = Start[0]; ///Standard Energy Conservation Routine- // 1. Multiply by Reflection energy. (1 - Absorption) double cos_theta; Room.Absorb(ref OR, out cos_theta, u, v); // 2. Apply Transmission (if any). if (Params.Room.TransmissionValue[OR.Surf_ID][OR.Octave] > 0.0) { //_rayTotal[Params.ThreadID]++; //// a. Create new source for transmitted energy (E * Transmission). //// b. Modify E (E * 1 - Transmission). if (Rnd.NextDouble() < Params.Room.TransmissionValue[OR.Surf_ID][OR.Octave]) { OR.direction *= -1; Utilities.PachTools.Ray_Acoustics.SpecularReflection(ref OR.direction, ref Room, ref _u[OR.ThreadID], ref _v[OR.ThreadID], ref OR.Surf_ID); } } // 3. Apply Scattering. Room.Scatter_Late(ref OR, ref Rays, ref Rnd, cos_theta, u, v); }while (OR.t_sum < COTime && OR.Intensity > Threshold_Power_2[OR.Octave]); do { OR.Ray_ID = Rnd.Next(); if (!Params.Room.shoot(OR, out u, out v, out OR.Surf_ID, out Start, out leg, out code)) { _lost[OR.ThreadID] += OR.Intensity; goto Do_Scattered; } RecMain.CheckRay(OR, Start[0]); //OctChecks.Enqueue(new object[] { OR.Clone(), new Hare.Geometry.Point(Start[0].x, Start[0].y, Start[0].z) }); OR.Intensity *= Math.Pow(10, -.1 * Room.Attenuation(code[0])[OR.Octave] * leg[0]); OR.AddLeg(leg[0] / Room.Sound_speed(code[0])); OR.origin = Start[0]; ///Standard Energy Conservation Routine- // 1. Multiply by Reflection energy. (1 - Absorption) double cos_theta; Room.Absorb(ref OR, out cos_theta, u, v); // 2. Apply Transmission (if any). if (Params.Room.TransmissionValue[OR.Surf_ID][OR.Octave] > 0.0) { //// a. Create new source for transmitted energy (E * Transmission). //// b. Modify E (E * 1 - Transmission). if (Rnd.NextDouble() < Params.Room.TransmissionValue[OR.Surf_ID][OR.Octave]) { OR.direction *= -1; Utilities.PachTools.Ray_Acoustics.SpecularReflection(ref OR.direction, ref Params.Room, ref _u[OR.ThreadID], ref _v[OR.ThreadID], ref OR.Surf_ID); } } // 3. Apply Scattering. Room.Scatter_Simple(ref OR, ref Rnd, cos_theta, u, v); }while (OR.t_sum < COTime && OR.Intensity > Threshold_Power_3[OR.Octave]); }while (Rays.Count > 0); } } _ts = DateTime.Now - _st; }