/// <summary>
 /// Constructor prepares image source calculation to run.
 /// </summary>
 /// <param name="Source"></param>
 /// <param name="Receiver"></param>
 /// <param name="Direct"></param>
 /// <param name="Rm"></param>
 /// <param name="MaxOrder_in">The maximum order to be calculated for.</param>
 public ImageSourceData(Source Source, Receiver_Bank Receiver, Direct_Sound Direct, Polygon_Scene Rm, int[] Octaves, int MaxOrder_in, bool Edge_Diffraction, int SourceID_in)
 {
     IncludeEdges = Edge_Diffraction;
     Diffraction = Edge_Diffraction;
     Oct_choice = new int[Octaves[1] - Octaves[0] + 1];
     for (int i = 0; i < Octaves.Length; i++) Oct_choice[i] = i + Octaves[0];
     SrcNo = SourceID_in;
     ValidPaths = new List<Deterministic_Reflection>[Receiver.Count];
     Speed_of_Sound = Rm.Sound_speed(0);
     MaxOrder = MaxOrder_in;
     Src = Source;
     Rec = new Hare.Geometry.Point[Receiver.Count];
     SampleCT = Receiver.SampleCT;
     SampleRate = Receiver.SampleRate;
     for(int i = 0; i < Receiver.Count; i++)
     {
         Rec[i] = Receiver.H_Origin(i);
     }
     Room = Rm;
     Direct_Time = new double[Receiver.Count];
     for (int q = 0; q < Receiver.Count; q++)
     {
         Direct_Time[q] = Direct.Min_Time(q);
     }
 }
 public static Rhino.Geometry.Point3d[] Origins(Direct_Sound[] D)
 {
     System.Collections.Generic.List<Rhino.Geometry.Point3d> Orig = new System.Collections.Generic.List<Rhino.Geometry.Point3d>();
     foreach (Direct_Sound Dir in D)
     {
         Orig.Add(Dir.Src_Origin);
     }
     return Orig.ToArray();
 }
        /// <summary>
        /// This method fills out a direct sound object with the minimum information from a .pac1 file. The Binary Reader must be set to a point where the method can read the direct sound data without any adjustment.
        /// </summary>
        /// <param name="BR">The open BinaryReader object</param>
        /// <param name="Rec_CT">The number of receivers the direct sound was calculated for.</param>
        /// <returns>The completed direct sound simulation type.</returns>
        public static Direct_Sound Read_Data(ref System.IO.BinaryReader BR, IEnumerable<Hare.Geometry.Point> RecPts, Hare.Geometry.Point SrcPt, double[] Rho_C, string Version)
        {
            Direct_Sound D = new Direct_Sound();

            D.Receiver = RecPts.ToList<Hare.Geometry.Point>(); //new Receiver_Bank(RecPts, SrcPt, 343, new double[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 1000, 0, Receiver_Bank.Type.Stationary);
            int Rec_Ct = D.Receiver.Count;//RecPts.Count<Rhino.Geometry.Point3d>();
            D.Rho_C = Rho_C;
            //2. Write strength reference data
            //Pre 2.0, 8 doubles.
            if (double.Parse(Version.Substring(0, 3)) < 2.0)
            {
                for(int i = 0; i < 8; i++) BR.ReadDouble();
            }
            ////Duration_ms = 1;
            //TODO Add version 1.5 and greater Source direction. (oops)
            if (double.Parse(Version.Substring(0, 3)) >= 1.1)
            {
                //2.1 Write source data - type and SWL
                string[] typestring = BR.ReadString().Split(':'); //string
                D.type = typestring[0];
                //if (typestring.Length > 1 && typestring[1] == "Histogram") 
                //{
                    //2.2 Write number of samples
                    ////Duration_ms = BR.ReadInt32();
                //}
                D.SWL = new double[8];
                for (int o = 0; o < 8; o++)
                {
                    D.SWL[o] = BR.ReadDouble(); //double
                }
                if (double.Parse(Version.Substring(0, 3)) >= 2.0)
                {
                    D.Delay_ms = BR.ReadDouble();
                }
                else
                {
                    D.Delay_ms = 0;
                }
            }
            else 
            {
                D.type = "Geodesic Source";
                    D.SWL = new double[]{120, 120, 120, 120, 120, 120, 120, 120};
                    D.Delay_ms = 0;
            }

            D.Src = new GeodesicSource(D.SWL, new double[8]{0,0,0,0,0,0,0,0}, new Rhino.Geometry.Point3d(SrcPt.x, SrcPt.y, SrcPt.z), 0, 0);
            D.Validity = new Boolean[RecPts.Count<Hare.Geometry.Point>()];
            D.Time_Pt = new double[RecPts.Count<Hare.Geometry.Point>()];
            D.Io = new double[RecPts.Count<Hare.Geometry.Point>()][][];
            D.Dir_Rec_Pos = new float[RecPts.Count<Hare.Geometry.Point>()][][][];
            D.Dir_Rec_Neg = new float[RecPts.Count<Hare.Geometry.Point>()][][][];

            double v = double.Parse(Version.Substring(0, 3));

            for (int q = 0; q < RecPts.Count<Hare.Geometry.Point>(); q++)
            {
                //2.2 Write number of samples
                int no_of_samples = BR.ReadInt32();
                //3. Write the validity of the direct sound
                D.Validity[q] = BR.ReadBoolean();
                //4. Write the Time point
                D.Time_Pt[q] = BR.ReadDouble();
                D.Io[q] = new double[9][];
                D.Dir_Rec_Pos[q] = new float[8][][];
                D.Dir_Rec_Neg[q] = new float[8][][];

                for (int oct = 0; oct < 8; oct++)
                {
                    D.Io[q][oct] = new double[no_of_samples];
                    D.Dir_Rec_Pos[q][oct] = new float[no_of_samples][];
                    D.Dir_Rec_Neg[q][oct] = new float[no_of_samples][];
                    for (int t = 0; t < no_of_samples; t++)
                    {
                        D.Dir_Rec_Pos[q][oct][t] = new float[3];
                        D.Dir_Rec_Neg[q][oct][t] = new float[3];
                    }
                }

                D.Io[q][8] = new double[no_of_samples];

                for (int s = 0; s < no_of_samples; s++)
                {
                    //5a. Write all Energy data
                    D.Io[q][0][s] = BR.ReadDouble();
                    D.Io[q][1][s] = BR.ReadDouble();
                    D.Io[q][2][s] = BR.ReadDouble();
                    D.Io[q][3][s] = BR.ReadDouble();
                    D.Io[q][4][s] = BR.ReadDouble();
                    D.Io[q][5][s] = BR.ReadDouble();
                    D.Io[q][6][s] = BR.ReadDouble();
                    D.Io[q][7][s] = BR.ReadDouble();
                    D.Io[q][8][s] = D.Io[q][0][s] + D.Io[q][1][s] + D.Io[q][2][s] + D.Io[q][3][s] + D.Io[q][4][s] + D.Io[q][5][s] + D.Io[q][6][s] + D.Io[q][7][s];

                    if (v == 1.7)
                    {
                        //5b. Write all Pressure Data
                        //Real
                        //Imag
                        for(int i = 0; i < 16; i++) BR.ReadSingle();    
                    }
                    //5c. Write all directional data
                    for (int oct = 0; oct < 8; oct++) for (int dir = 0; dir < 3; dir++)
                        {
                            D.Dir_Rec_Pos[q][oct][s][dir] = BR.ReadSingle();
                            D.Dir_Rec_Neg[q][oct][s][dir] = BR.ReadSingle();
                        }
                }
            }

            D.Create_Pressure();

            return D;
        }
 public ImageSourceData(Source Source, Receiver_Bank Receiver, Direct_Sound Direct, Polygon_Scene Rm, int MaxOrder_in, bool ED, int SourceID_in)
     : this(Source, Receiver, Direct, Rm, new int[2] { 0, 7 }, MaxOrder_in, ED, SourceID_in)
 { }
        /// <summary>
        /// Constructor which takes a Binary Reader at the appropriate point, from which calculated data will be extracted.
        /// </summary>
        /// <param name="BR"></param>
        /// <param name="Rec_CT"></param>
        /// <param name="Direct"></param>
        /// <returns></returns>
        public static ImageSourceData Read_Data(ref System.IO.BinaryReader BR, int Rec_CT, Direct_Sound Direct, bool Edges, int Src_ID, string version)
        {
            ImageSourceData IS = new ImageSourceData();
            IS.ValidPaths = new List<Deterministic_Reflection>[Rec_CT];
            IS.Direct_Time = new double[Rec_CT];
            double v = double.Parse(version.Substring(0, 3));

            for (int q = 0; q < Rec_CT; q++)
            {
                IS.ValidPaths[q] = new List<Deterministic_Reflection>();
                //2. Write the receiver number:int
                BR.ReadInt32();
                //3. Write number of paths:int
                int PathCt = BR.ReadInt32();
                for (int i = 0; i < PathCt; i++)
                {
                    int ReflectionType = BR.ReadInt16();
                    if (ReflectionType == 0)
                    {
                        //Speculare Reflection
                        //4. Write the number of reflection path points
                        Hare.Geometry.Point[] PTS = new Hare.Geometry.Point[BR.ReadInt32()];

                        //5. Write the reflection path:double
                        for (int r = 0; r < PTS.Length; r++)
                        {
                            PTS[r] = new Hare.Geometry.Point(BR.ReadDouble(), BR.ReadDouble(), BR.ReadDouble());
                        }

                        //Previously, Pachyderm performed the deterministic part in intensity only...                    
                        //6a. Write the energy values
                        double[] Energy = new double[8];
                        Energy[0] = BR.ReadDouble();
                        Energy[1] = BR.ReadDouble();
                        Energy[2] = BR.ReadDouble();
                        Energy[3] = BR.ReadDouble();
                        Energy[4] = BR.ReadDouble();
                        Energy[5] = BR.ReadDouble();
                        Energy[6] = BR.ReadDouble();
                        Energy[7] = BR.ReadDouble();

                        bool Special_Filter = BR.ReadBoolean();
                        System.Numerics.Complex[] Filter = null;
                   
                        if (Special_Filter)
                        {
                            //6aa1. Write length of filter...
                            int Filter_Length = BR.ReadInt32();
                            Filter = new System.Numerics.Complex[Filter_Length];
                            //6aa2. Write filter...
                            for(int j = 0; j < Filter.Length; j++)
                            {
                                Filter[j] = new System.Numerics.Complex(BR.ReadDouble(), BR.ReadDouble());
                            }
                            //6aa3. Write octave band root mean square pressure...
                        }

                        double[] prms = new double[8];
                        for (int j = 0; j < prms.Length; j++) prms[j] = BR.ReadDouble();

                        //7. Write the arrival time:double
                        double Time = BR.ReadDouble();

                        //8. Write the Reflection Sequence:int
                        int[] Sequence = new int[PTS.Length - 2];
                        for (int r = 0; r < Sequence.Length; r++)
                        {
                            Sequence[r] = BR.ReadInt32();
                        }

                        IS.ValidPaths[q].Add(new Specular_Path(PTS, Energy, prms, Filter, Time, Sequence, Direct.Min_Time(q), Src_ID));
                    }
                    else if (ReflectionType == 1)
                    {
                        //TODO: Find a robust format for compound reflection paths...
                        ///Specular Path:
                        //BW.Write((short)1);
                        //Write the number of samples and the pressure signal down:
                        //Write the number of samples and the pressure signal down:

                        //6a.2. Write the number of samples in the pressure signal.(int)
                        //6b. Write the pressure values
                    }

                }
            }
            return IS;
        }