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);
                }
            }
Пример #2
0
        /// <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;
        }