private void Retrieve_Layer_Acoustics(object sender, EventArgs e)
            {
                int layer_index = Rhino.RhinoDoc.ActiveDoc.Layers.Find(LayerDisplay.Text, true);
                Rhino.DocObjects.Layer layer = Rhino.RhinoDoc.ActiveDoc.Layers[layer_index];
                string AC = layer.GetUserString("Acoustics");

                string M = layer.GetUserString("ABSType");
                if (M == "Buildup")
                {
                    Material_Mode(false);
                    string[] BU = layer.GetUserString("Buildup").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                    List<AbsorptionModels.ABS_Layer> Layers = new List<AbsorptionModels.ABS_Layer>();
                    for (int i = 0; i < BU.Length; i++) Layers.Add(AbsorptionModels.ABS_Layer.LayerFromCode(BU[i]));

                    Environment.Smart_Material sm = new Smart_Material(Layers, 44100, 1.2, 343, 2);
                    double[] AnglesDeg = new double[sm.Angles.Length];
                    for (int i = 0; i < sm.Angles.Length; i++) AnglesDeg[i] = sm.Angles[i].Real;
                    for (int i = 0; i < 8; i++) SmartMat_Display.Series[0].Points.DataBindXY(AnglesDeg, sm.Ang_Coef_Oct[i]);
                }
                else if(M == "Buildup_Finite")
                {
                    Material_Mode(false);
                    string[] BU = layer.GetUserString("Buildup").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                    List<AbsorptionModels.ABS_Layer> Layers = new List<AbsorptionModels.ABS_Layer>();
                    for (int i = 0; i < BU.Length; i++) Layers.Add(AbsorptionModels.ABS_Layer.LayerFromCode(BU[i]));

                    Environment.Smart_Material sm = new Smart_Material(Layers, 44100, 1.2, 343, 2);
                    double[] AnglesDeg = new double[sm.Angles.Length];
                    for (int i = 0; i < sm.Angles.Length; i++) AnglesDeg[i] = sm.Angles[i].Real;
                    for (int i = 0; i < 8; i++) SmartMat_Display.Series[0].Points.DataBindXY(AnglesDeg, sm.Ang_Coef_Oct[i]);
                }
                else
                {
                    Material_Mode(true);
                }

                if (!string.IsNullOrEmpty(AC))
                {
                    double[] Abs = new double[8];
                    double[] Sct = new double[8];
                    double[] Trn = new double[1];
                    PachydermAc_PlugIn.DecodeAcoustics(AC, ref Abs, ref Sct, ref Trn);
                    Abs63.Value = (int)(Abs[0] * 100);
                    Abs125.Value = (int)(Abs[1] * 100);
                    Abs250.Value = (int)(Abs[2] * 100);
                    Abs500.Value = (int)(Abs[3] * 100);
                    Abs1k.Value = (int)(Abs[4] * 100);
                    Abs2k.Value = (int)(Abs[5] * 100);
                    Abs4k.Value = (int)(Abs[6] * 100);
                    Abs8k.Value = (int)(Abs[7] * 100);
                    Scat63v.Value = (int)(Sct[0] * 100);
                    Scat125v.Value = (int)(Sct[1] * 100);
                    Scat250v.Value = (int)(Sct[2] * 100);
                    Scat500v.Value = (int)(Sct[3] * 100);
                    Scat1kv.Value = (int)(Sct[4] * 100);
                    Scat2kv.Value = (int)(Sct[5] * 100);
                    Scat4kv.Value = (int)(Sct[6] * 100);
                    Scat8kv.Value = (int)(Sct[7] * 100);
                    if (Trn != null && Trn.Length == 8 && Trn.Sum() > 0)
                    {
                        Trans_63v.Value = (int)(Trn[0] * 100);
                        Trans_125v.Value = (int)(Trn[1] * 100);
                        Trans_250v.Value = (int)(Trn[2] * 100);
                        Trans_500v.Value = (int)(Trn[3] * 100);
                        Trans_1kv.Value = (int)(Trn[4] * 100);
                        Trans_2kv.Value = (int)(Trn[5] * 100);
                        Trans_4kv.Value = (int)(Trn[6] * 100);
                        Trans_8kv.Value = (int)(Trn[7] * 100);
                        Trans_Check.Checked = true;
                    }
                    else { Trans_Check.Checked = false; }
                }
                else
                {
                    Abs63.Value = 1;
                    Abs125.Value = 1;
                    Abs250.Value = 1;
                    Abs500.Value = 1;
                    Abs1k.Value = 1;
                    Abs2k.Value = 1;
                    Abs4k.Value = 1;
                    Abs8k.Value = 1;
                    Scat63v.Value = 1;
                    Scat125v.Value = 1;
                    Scat250v.Value = 1;
                    Scat500v.Value = 1;
                    Scat1kv.Value = 1;
                    Scat2kv.Value = 1;
                    Scat4kv.Value = 1;
                    Scat8kv.Value = 1;
                    Trans_63v.Value = 0;
                    Trans_125v.Value = 0;
                    Trans_250v.Value = 0;
                    Trans_500v.Value = 0;
                    Trans_1kv.Value = 0;
                    Trans_2kv.Value = 0;
                    Trans_4kv.Value = 0;
                    Trans_8kv.Value = 0;
                }
            }
            public Finite_Material(Smart_Material Mat, Rhino.Geometry.Brep Br, Rhino.Geometry.Mesh M, int face_id, Medium_Properties med)
            {
                //Strictly for the flat X,Y case - oversimplified for now.
                Inf_Mat = Mat;
                Azimuth = new double[36];
                Altitude = new double[Mat.Angles.Length/2];
                alpha = new double[Altitude.Length][][];
                for(int i = 0; i < Altitude.Length; i++) Altitude[i] = Mat.Angles[i].Magnitude;
                for(int i = 0; i < Azimuth.Length; i++) Azimuth[i] = i * 360f / Azimuth.Length;

                    //Set up a frequency interpolated Zr for each direction individually.
                    Rhino.Geometry.Point3d pt = M.Faces.GetFaceCenter(face_id);

                    double[][][] ZrR = new double[Altitude.Length][][], ZrI = new double[Altitude.Length][][];
                    double[] fr = new double[9];
                    for (int k = 0; k < Altitude.Length; k++)
                    {
                        ZrR[k] = new double[Azimuth.Length][];
                        ZrI[k] = new double[Azimuth.Length][];
                        alpha[k] = new double[Azimuth.Length][];
                        for (int j = 0; j < Azimuth.Length; j++)
                        {
                            ZrR[k][j] = new double[9];
                            ZrI[k][j] = new double[9];
                            alpha[k][j] = new double[8];
                        }
                    }

                    for (int oct = 0; oct < 9; oct++)
                    {
                        fr[oct] = 62.5 * Math.Pow(2, oct) / Utilities.Numerics.rt2;
                        System.Numerics.Complex[][] Zr = AbsorptionModels.Operations.Finite_Radiation_Impedance_Rect_Longhand(pt.X, pt.Y, Br, fr[oct], Altitude, Azimuth, med.Sound_Speed(pt));

                        for (int k = 0; k < Zr.Length; k++)
                        {
                            for (int j = 0; j < Zr[k].Length; j++)
                            {
                                ZrR[k][j][oct] = Zr[k][j].Real;
                                ZrI[k][j][oct] = Zr[k][j].Imaginary;
                            }
                        }
                    }

                    MathNet.Numerics.Interpolation.CubicSpline[][] Zr_r = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];
                    MathNet.Numerics.Interpolation.CubicSpline[][] Zr_i = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];

                    for (int k = 0; k < Zr_r.Length; k++)
                    {
                        Zr_r[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                        Zr_i[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                        for (int j = 0; j < Zr_r[k].Length; j++)
                        {
                            //Interpolate over curve real and imaginary Zr here...
                            Zr_r[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrR[k][j]);
                            Zr_i[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrI[k][j]);
                        }
                    }

                    for (int k = 0; k < Zr_r.Length; k++)
                    {
                        for (int j = 0; j < Zr_r[k].Length; j++)
                        {
                            List<double> freq = new List<double>();
                            List<double> alpha_interp = new List<double>();
                            for (int l = 0; l < Mat.frequency.Length; l++)
                            {
                                if (Mat.frequency[l] > 10000) break;
                                freq.Add(Mat.frequency[l]);
                                alpha_interp.Add(AbsorptionModels.Operations.Finite_Unit_Absorption_Coefficient(Mat.Z[k][j], new System.Numerics.Complex(Zr_r[k][j].Interpolate(Mat.frequency[l]), Zr_i[k][j].Interpolate(Mat.frequency[l])), med.Rho(Utilities.PachTools.RPttoHPt(pt)), med.Sound_Speed(pt)));
                            }
                            MathNet.Numerics.Interpolation.CubicSpline a = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, alpha_interp);
                            for (int oct = 0; oct < 8; oct++)
                            {
                                alpha[k][j][oct] = 1 - a.Integrate(fr[oct], fr[oct + 1]) / (fr[oct + 1] - fr[oct]);
                            }
                        }
                    }
            }
            public Finite_Material(Smart_Material Mat, Rhino.Geometry.Brep Br, Rhino.Geometry.Mesh M, int face_id, Medium_Properties med)
            {
                //Strictly for the flat X,Y case - oversimplified for now.
                Inf_Mat  = Mat;
                Azimuth  = new double[36];
                Altitude = new double[Mat.Angles.Length / 2];
                alpha    = new double[Altitude.Length][][];
                for (int i = 0; i < Altitude.Length; i++)
                {
                    Altitude[i] = Mat.Angles[i].Magnitude;
                }
                for (int i = 0; i < Azimuth.Length; i++)
                {
                    Azimuth[i] = i * 360f / Azimuth.Length;
                }

                //Set up a frequency interpolated Zr for each direction individually.
                Rhino.Geometry.Point3d pt = M.Faces.GetFaceCenter(face_id);

                double[][][] ZrR = new double[Altitude.Length][][], ZrI = new double[Altitude.Length][][];
                double[]     fr  = new double[9];
                for (int k = 0; k < Altitude.Length; k++)
                {
                    ZrR[k]   = new double[Azimuth.Length][];
                    ZrI[k]   = new double[Azimuth.Length][];
                    alpha[k] = new double[Azimuth.Length][];
                    for (int j = 0; j < Azimuth.Length; j++)
                    {
                        ZrR[k][j]   = new double[9];
                        ZrI[k][j]   = new double[9];
                        alpha[k][j] = new double[8];
                    }
                }

                for (int oct = 0; oct < 9; oct++)
                {
                    fr[oct] = 62.5 * Math.Pow(2, oct) / Utilities.Numerics.rt2;
                    System.Numerics.Complex[][] Zr = AbsorptionModels.Operations.Finite_Radiation_Impedance_Rect_Longhand(pt.X, pt.Y, Br, fr[oct], Altitude, Azimuth, med.Sound_Speed(pt));

                    for (int k = 0; k < Zr.Length; k++)
                    {
                        for (int j = 0; j < Zr[k].Length; j++)
                        {
                            ZrR[k][j][oct] = Zr[k][j].Real;
                            ZrI[k][j][oct] = Zr[k][j].Imaginary;
                        }
                    }
                }

                MathNet.Numerics.Interpolation.CubicSpline[][] Zr_r = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];
                MathNet.Numerics.Interpolation.CubicSpline[][] Zr_i = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];

                for (int k = 0; k < Zr_r.Length; k++)
                {
                    Zr_r[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                    Zr_i[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                    for (int j = 0; j < Zr_r[k].Length; j++)
                    {
                        //Interpolate over curve real and imaginary Zr here...
                        Zr_r[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrR[k][j]);
                        Zr_i[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrI[k][j]);
                    }
                }

                for (int k = 0; k < Zr_r.Length; k++)
                {
                    for (int j = 0; j < Zr_r[k].Length; j++)
                    {
                        List <double> freq         = new List <double>();
                        List <double> alpha_interp = new List <double>();
                        for (int l = 0; l < Mat.frequency.Length; l++)
                        {
                            if (Mat.frequency[l] > 10000)
                            {
                                break;
                            }
                            freq.Add(Mat.frequency[l]);
                            alpha_interp.Add(AbsorptionModels.Operations.Finite_Unit_Absorption_Coefficient(Mat.Z[k][j], new System.Numerics.Complex(Zr_r[k][j].Interpolate(Mat.frequency[l]), Zr_i[k][j].Interpolate(Mat.frequency[l])), med.Rho(Utilities.PachTools.RPttoHPt(pt)), med.Sound_Speed(pt)));
                        }
                        MathNet.Numerics.Interpolation.CubicSpline a = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, alpha_interp);
                        for (int oct = 0; oct < 8; oct++)
                        {
                            alpha[k][j][oct] = 1 - a.Integrate(fr[oct], fr[oct + 1]) / (fr[oct + 1] - fr[oct]);
                        }
                    }
                }
            }