Friday, June 20, 2025

GREAT CREST TROUGH INFOS VERTICAL SPECTRUMS

 namespace ENHANCING___SAANS_WAVEFILES_CREST_TROUGHS_ANALYSISWaveform___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

{

    public class WavMetadata

    {

        public int SampleRate;

        public int BitsPerSample;

        public int Channels;

    }//public class WavMetadata

    public class CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

    {

        //CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS.

        public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_CRESTS = +600000000;

        public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_CRESTS = -600000000;

        public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_TROUGHS = +600000000;

        public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_TROUGHS = -600000000;

        public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS = +600000000;

        public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS = -600000000;

        public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUND_IN_CRESTS = -600000000;

        public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUND_IN_TROUGHS = -600000000;

        public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUNDOVERALL_IN_CRESTS_AND_TROUGHS = -600000000;

        public static WavMetadata ReadMetadata(string path)

        {

            WavMetadata meta = new WavMetadata();

            using (BinaryReader br = new BinaryReader(File.OpenRead(path)))

            {

                br.ReadBytes(12); // RIFF header

                while (br.BaseStream.Position < br.BaseStream.Length)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();

                    if (chunkID == "fmt ")

                    {

                        br.ReadInt16(); // audio format

                        meta.Channels = br.ReadInt16();

                        meta.SampleRate = br.ReadInt32();

                        br.ReadInt32(); // byte rate

                        br.ReadInt16(); // block align

                        meta.BitsPerSample = br.ReadInt16();

                        if (chunkSize > 16)

                            br.ReadBytes(chunkSize - 16); // skip extra

                        break;

                    }

                    else

                    {

                        br.BaseStream.Seek(chunkSize, SeekOrigin.Current);

                    }

                }

            }

            return meta;

        }//public static WavMetadata ReadMetadata(string path)

        public static void ExportDxfWithBoxesAndCenterlines(List<CrestTroughObject> crestTroughs, string wavPath)

        {

            string path = Path.ChangeExtension(wavPath, "_GRAPH_CG_BOXES_AXES.dxf");

            using (StreamWriter sw = new StreamWriter(path))

            {

                sw.WriteLine("0\nSECTION\n2\nENTITIES");

                foreach (var ct in crestTroughs)

                {

                    float cx = ct.CG.X;

                    float cy = ct.IsCrest ? ct.CG.Y : -Math.Abs(ct.CG.Y);

                    float radius = Math.Max(1f, (ct.EndSampleIndex - ct.StartSampleIndex) / 10f);

                    int color = ct.IsCrest ? 5 : 1;

                    sw.WriteLine($"0\nCIRCLE\n8\n0\n62\n{color}\n10\n{cx.ToString("F3", CultureInfo.InvariantCulture)}\n20\n{cy.ToString("F3", CultureInfo.InvariantCulture)}\n30\n0\n40\n{radius.ToString("F3", CultureInfo.InvariantCulture)}");

                    float x1 = cx - ct.BoundingBox.Width / 2;

                    float x2 = cx + ct.BoundingBox.Width / 2;

                    float y1 = ct.IsCrest ? 0 : -ct.BoundingBox.Height;

                    float y2 = ct.IsCrest ? ct.BoundingBox.Height : 0;

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{x1.ToString("F3", CultureInfo.InvariantCulture)}\n20\n{y1.ToString("F3", CultureInfo.InvariantCulture)}\n30\n0\n11\n{x2.ToString("F3", CultureInfo.InvariantCulture)}\n21\n{y2.ToString("F3", CultureInfo.InvariantCulture)}\n31\n0");

                }

                sw.WriteLine("0\nENDSEC\n0\nEOF");

            }

        }//public static void ExportDxfWithBoxesAndCenterlines(List<CrestTroughObject> crestTroughs, string wavPath)

        public static void ExportCrestTroughGroupingPivot(List<CrestTroughObject> crestTroughs, string wavPath)

        {

            string path = Path.ChangeExtension(wavPath, "_GROUP_PIVOT.csv");

            using (StreamWriter sw = new StreamWriter(path))

            {

                sw.WriteLine("Type,GroupKey,Count");

                var crestGroups = crestTroughs.Where(c => c.IsCrest).GroupBy(c => $"{(int)(c.WidthMicroseconds / 1000)}ms_{(int)(c.HeightAmplitude * 1000)}amp_{(int)(c.AreaProportion * 1000)}aprop");

                var troughGroups = crestTroughs.Where(c => !c.IsCrest).GroupBy(c => $"{(int)(c.WidthMicroseconds / 1000)}ms_{(int)(c.HeightAmplitude * 1000)}amp_{(int)(c.AreaProportion * 1000)}aprop");

                foreach (var g in crestGroups)

                    sw.WriteLine($"CREST,{g.Key},{g.Count()}");

                foreach (var g in troughGroups)

                    sw.WriteLine($"TROUGH,{g.Key},{g.Count()}");

            }

        }// public static void ExportCrestTroughGroupingPivot(List<CrestTroughObject> crestTroughs, string wavPath)

        public static void ExportBitmapWithBoxesAndAxes(List<CrestTroughObject> crestTroughs, string wavPath, float widthScale, float heightScale, float maxWidth, float maxHeight, int bmpWidth, int bmpHeight)

        {

            //////float maxWidth = Math.Max(1f, filtered.Max(ct => ct.WidthMicroseconds));

            //////float maxHeight = Math.Max(1f, filtered.Max(ct => Math.Abs(ct.CG.Y)));

            //////float widthScale = maxWidth > 1000f ? 1000f / maxWidth : 1f;

            //////float heightScale = maxHeight > 1f ? 100f / maxHeight : 1f;

            //////int bmpWidth = Math.Max(64, (int)(maxWidth * widthScale) + 10);

            //////int bmpHeight = Math.Max(64, (int)(filtered.Count * maxHeight * heightScale) + 10);

            using (Bitmap bmp = new Bitmap(bmpWidth, bmpHeight))

            {

                Graphics g = Graphics.FromImage(bmp);

                g.Clear(Color.White);

                g.DrawLine(Pens.Black, 0, bmpHeight / 2, bmpWidth, bmpHeight / 2);

                Font font = new Font("Arial", 7);

                g.DrawString(Path.GetFileName(wavPath), font, Brushes.Black, 2, bmpHeight / 2);

                int offsetY = 0;

                foreach (var ct in crestTroughs)

                {

                    PointF cg = ct.CG;

                    int x = (int)((cg.X / ct.WidthMicroseconds) * maxWidth * widthScale);

                    int y = ct.IsCrest

                        ? (int)(bmpHeight / 2 - ((cg.Y / ct.HeightAmplitude) * maxHeight * heightScale))

                        : (int)(bmpHeight / 2 + ((Math.Abs(cg.Y) / ct.HeightAmplitude) * maxHeight * heightScale));

                    int radius = Math.Max(2, (ct.EndSampleIndex - ct.StartSampleIndex) / 128);

                    for (int dx = -radius; dx <= radius; dx++)

                        for (int dy = -radius; dy <= radius; dy++)

                            if (x + dx >= 0 && x + dx < bmp.Width && y + dy >= 0 && y + dy < bmp.Height)

                                bmp.SetPixel(x + dx, y + dy, ct.IsCrest ? Color.Blue : Color.Red);

                    Rectangle box = new Rectangle(

                        (int)(x - (ct.BoundingBox.Width * widthScale / 2)),

                        ct.IsCrest

                            ? (int)(bmpHeight / 2 - ct.BoundingBox.Height * heightScale)

                            : (int)(bmpHeight / 2),

                        (int)(ct.BoundingBox.Width * widthScale),

                        (int)(ct.BoundingBox.Height * heightScale));

                    g.DrawRectangle(ct.IsCrest ? Pens.Blue : Pens.Red, box);

                }

                if (bmpWidth <= 0 || bmpHeight <= 0)

                {

                    MessageBox.Show("Invalid bitmap dimensions. Aborting image save.");

                    return;

                }//if (bmpWidth <= 0 || bmpHeight <= 0)

                bmp.Save(Path.ChangeExtension(wavPath, "_GRAPH_CG_BOXES_AXES.bmp"));

            }

        }//public static void ExportBitmapWithBoxesAndAxes(List<CrestTroughObject> crestTroughs, string wavPath, float widthScale, float heightScale, float maxWidth, float maxHeight, int bmpWidth, int bmpHeight)

        public class CrestTroughObject

        {

            public int StartSampleIndex;

            public int EndSampleIndex;

            public float MaxAmplitude;

            public float MinAmplitude;

            public bool IsCrest;

            public List<PointF> TipPointsMicrosecondsVsAmplitude = new List<PointF>();

            public RectangleF BoundingBox;

            public PointF CG;

            public float WidthMicroseconds;

            public float HeightAmplitude;

            public float AreaUnderCurve;

            public float AreaBoundingBox;

            public float AreaProportion;

            public List<float> LocalAnglesMilliDegrees = new List<float>();

            public int LocalMaximaCount = 0;

            public int LocalMinimaCount = 0;

            public void ComputeGeometry(int sampleRate)

            {

                int sampleCount = EndSampleIndex - StartSampleIndex + 1;

                WidthMicroseconds = (sampleCount * 1000000f) / sampleRate;

                ///  HeightAmplitude = Math.Max(0.001f, Math.Abs(IsCrest ? MaxAmplitude : MinAmplitude));

                ///  

                 HeightAmplitude = Math.Max(0.000001f, Math.Abs(IsCrest ? MaxAmplitude : MinAmplitude));

              //  HeightAmplitude = Math.Max(0.000001f, Math.Abs(IsCrest ? (MaxAmplitude*10000f) : (MinAmplitude*1000f)));

                BoundingBox = new RectangleF(0, 0, WidthMicroseconds, HeightAmplitude);

                float sumX = 0f, sumY = 0f;

                AreaUnderCurve = 0f;

                for (int i = 0; i < TipPointsMicrosecondsVsAmplitude.Count; i++)

                {

                    PointF p = TipPointsMicrosecondsVsAmplitude[i];

                    sumX += p.X;

                    sumY += p.Y;

                    if (i > 0)

                    {

                        float dx = TipPointsMicrosecondsVsAmplitude[i].X - TipPointsMicrosecondsVsAmplitude[i - 1].X;

                        float avgY = (TipPointsMicrosecondsVsAmplitude[i].Y + TipPointsMicrosecondsVsAmplitude[i - 1].Y) / 2f;

                        AreaUnderCurve += Math.Abs(avgY * dx);

                    }//if (i > 0)

                    if (i > 0 && i < TipPointsMicrosecondsVsAmplitude.Count - 1)

                    {

                        PointF p1 = TipPointsMicrosecondsVsAmplitude[i - 1];

                        PointF p2 = TipPointsMicrosecondsVsAmplitude[i];

                        PointF p3 = TipPointsMicrosecondsVsAmplitude[i + 1];

                        float dx1 = p2.X - p1.X;

                        float dy1 = (p2.Y - p1.Y);

                        float dx2 = p3.X - p2.X;

                        float dy2 = (p3.Y - p2.Y);

                        float angle1 = (float)Math.Atan2(dy1, dx1);

                        float angle2 = (float)Math.Atan2(dy2, dx2);

                        float diff = angle2 - angle1;

                        float degrees = diff * (180000f / (float)Math.PI);

                        if (degrees < 0) degrees += 360000f;

                        LocalAnglesMilliDegrees.Add(degrees);

                    }//if (i > 0 && i < TipPointsMicrosecondsVsAmplitude.Count - 1)

                }//for (int i = 0; i < TipPointsMicrosecondsVsAmplitude.Count; i++)

                for (int i = 1; i < TipPointsMicrosecondsVsAmplitude.Count - 1; i++)

                {

                    float prev = TipPointsMicrosecondsVsAmplitude[i - 1].Y;

                    float curr = TipPointsMicrosecondsVsAmplitude[i].Y;

                    float next = TipPointsMicrosecondsVsAmplitude[i + 1].Y;

                    if (curr > prev && curr > next) LocalMaximaCount++;

                    if (curr < prev && curr < next) LocalMinimaCount++;

                }

                AreaBoundingBox = WidthMicroseconds * HeightAmplitude;

                AreaProportion = AreaBoundingBox == 0f ? 0f : AreaUnderCurve / AreaBoundingBox;

                if (TipPointsMicrosecondsVsAmplitude.Count > 0)

                {

                    CG = new PointF(sumX / TipPointsMicrosecondsVsAmplitude.Count, sumY / TipPointsMicrosecondsVsAmplitude.Count);

                }//if (TipPointsMicrosecondsVsAmplitude.Count > 0)

            }//public void ComputeGeometry(int sampleRate)

        }//public class CrestTroughObject

        // TRIED TO MULTIPLY Y WITH 1000 AND THAT CAUSED THE PROBLEMS IN THE BITMAPS

        //////public class CrestTroughObject

        //////{

        //////    public int StartSampleIndex;

        //////    public int EndSampleIndex;

        //////    public float MaxAmplitude;

        //////    public float MinAmplitude;

        //////    public bool IsCrest;

        //////    public List<PointF> TipPointsMicrosecondsVsAmplitude = new List<PointF>();

        //////    public RectangleF BoundingBox;

        //////    public PointF CG;

        //////    public float WidthMicroseconds;

        //////    public float HeightAmplitude;

        //////    public float AreaUnderCurve;

        //////    public float AreaBoundingBox;

        //////    public float AreaProportion;

        //////    public List<float> LocalAnglesMilliDegrees = new List<float>();

        //////    public int LocalMaximaCount = 0;

        //////    public int LocalMinimaCount = 0;

        //////    public void ComputeGeometry(int sampleRate)

        //////    {

        //////        int sampleCount = EndSampleIndex - StartSampleIndex + 1;

        //////        WidthMicroseconds = (sampleCount * 1000000f) / sampleRate;

        //////        MaxAmplitude *= 1000f;

        //////        MinAmplitude *= 1000f;

        //////        HeightAmplitude = Math.Max(0.001f, Math.Abs(IsCrest ? MaxAmplitude : MinAmplitude));

        //////        BoundingBox = new RectangleF(0, 0, WidthMicroseconds, HeightAmplitude);

        //////        float sumX = 0f, sumY = 0f;

        //////        AreaUnderCurve = 0f;

        //////        for (int i = 0; i < TipPointsMicrosecondsVsAmplitude.Count; i++)

        //////        {

        //////            PointF p = TipPointsMicrosecondsVsAmplitude[i];

        //////            float ampY = p.Y * 1000f;

        //////            sumX += p.X;

        //////            sumY += ampY;

        //////            if (i > 0)

        //////            {

        //////                float dx = p.X - TipPointsMicrosecondsVsAmplitude[i - 1].X;

        //////                float y1 = TipPointsMicrosecondsVsAmplitude[i - 1].Y * 1000f;

        //////                float avgY = (ampY + y1) / 2f;

        //////                AreaUnderCurve += Math.Abs(avgY * dx);

        //////            }// if (i > 0)

        //////            if (i > 0 && i < TipPointsMicrosecondsVsAmplitude.Count - 1)

        //////            {

        //////                float x1 = TipPointsMicrosecondsVsAmplitude[i - 1].X;

        //////                float y1 = TipPointsMicrosecondsVsAmplitude[i - 1].Y * 1000f;

        //////                float x2 = p.X;

        //////                float y2 = ampY;

        //////                float x3 = TipPointsMicrosecondsVsAmplitude[i + 1].X;

        //////                float y3 = TipPointsMicrosecondsVsAmplitude[i + 1].Y * 1000f;

        //////                float dx1 = x2 - x1;

        //////                float dy1 = y2 - y1;

        //////                float dx2 = x3 - x2;

        //////                float dy2 = y3 - y2;

        //////                float angle1 = (float)Math.Atan2(dy1, dx1);

        //////                float angle2 = (float)Math.Atan2(dy2, dx2);

        //////                float diff = angle2 - angle1;

        //////                float degrees = diff * (180000f / (float)Math.PI);

        //////                if (degrees < 0) degrees += 360000f;

        //////                LocalAnglesMilliDegrees.Add(degrees);

        //////            }//if (i > 0 && i < TipPointsMicrosecondsVsAmplitude.Count - 1)

        //////        }//for (int i = 0; i < TipPointsMicrosecondsVsAmplitude.Count; i++)

        //////        for (int i = 1; i < TipPointsMicrosecondsVsAmplitude.Count - 1; i++)

        //////        {

        //////            float prev = TipPointsMicrosecondsVsAmplitude[i - 1].Y * 1000f;

        //////            float curr = TipPointsMicrosecondsVsAmplitude[i].Y * 1000f;

        //////            float next = TipPointsMicrosecondsVsAmplitude[i + 1].Y * 1000f;

        //////            if (curr > prev && curr > next) LocalMaximaCount++;

        //////            if (curr < prev && curr < next) LocalMinimaCount++;

        //////        }//for (int i = 1; i < TipPointsMicrosecondsVsAmplitude.Count - 1; i++)

        //////        AreaBoundingBox = WidthMicroseconds * HeightAmplitude;

        //////        AreaProportion = AreaBoundingBox == 0f ? 0f : AreaUnderCurve / AreaBoundingBox;

        //////        if (TipPointsMicrosecondsVsAmplitude.Count > 0)

        //////            CG = new PointF(sumX / TipPointsMicrosecondsVsAmplitude.Count, sumY / TipPointsMicrosecondsVsAmplitude.Count);

        //////    }

        //////}//public class CrestTroughObject

        //////public static void OpenAndScanWavFile___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS(ref ProgressBar progressBarFOR_ANALYSIS)

        //////{

        //////    OpenFileDialog ofd = new OpenFileDialog();

        //////    ofd.Filter = "WAV files (*.wav)|*.wav";

        //////    if (ofd.ShowDialog() != DialogResult.OK) return;

        //////    string wavPath = ofd.FileName;

        //////    WavMetadata meta = ReadMetadata(wavPath);

        //////    if (meta.Channels != 1)

        //////    {

        //////        MessageBox.Show("Only mono WAV files are supported.");

        //////        return;

        //////    }

        //////    List<CrestTroughObject> crestTroughs = new List<CrestTroughObject>();

        //////    int chunkSize = 8192;

        //////    float maxWidth = 1f, maxHeight = 1f;

        //////    using (FileStream fs = new FileStream(wavPath, FileMode.Open, FileAccess.Read))

        //////    using (BinaryReader br = new BinaryReader(fs))

        //////    {

        //////        br.ReadBytes(12);

        //////        while (br.BaseStream.Position < br.BaseStream.Length)

        //////        {

        //////            string chunkID = new string(br.ReadChars(4));

        //////            int chunkSizeBytes = br.ReadInt32();

        //////            if (chunkID != "data")

        //////            {

        //////                br.BaseStream.Position += chunkSizeBytes;

        //////                continue;

        //////            }

        //////            int bytesPerSample = meta.BitsPerSample / 8;

        //////            int totalSamples = chunkSizeBytes / bytesPerSample;

        //////            float[] buffer = new float[chunkSize];

        //////            int samplesRead = 0;

        //////            CrestTroughObject current = null;

        //////            bool positive = true;

        //////            progressBarFOR_ANALYSIS.Minimum = 0;

        //////            progressBarFOR_ANALYSIS.Maximum = totalSamples;

        //////            while (samplesRead < totalSamples)

        //////            {

        //////                int blockSamples = Math.Min(chunkSize, totalSamples - samplesRead);

        //////                for (int i = 0; i < blockSamples; i++)

        //////                {

        //////                    switch (meta.BitsPerSample)

        //////                    {

        //////                        case 8: buffer[i] = (br.ReadByte() - 128) / 128f; break;

        //////                        case 16: buffer[i] = br.ReadInt16() / 32768f; break;

        //////                        case 24:

        //////                            byte[] b = br.ReadBytes(3);

        //////                            int val = (b[2] << 16) | (b[1] << 8) | b[0];

        //////                            if ((val & 0x800000) != 0) val |= unchecked((int)0xFF000000);

        //////                            buffer[i] = val / 8388608f; break;

        //////                        case 32: buffer[i] = br.ReadInt32() / (float)Int32.MaxValue; break;

        //////                        default: MessageBox.Show("Unsupported bit depth."); return;

        //////                    }

        //////                }

        //////                for (int i = 0; i < blockSamples; i++)

        //////                {

        //////                    bool currentSign = buffer[i] >= 0;

        //////                    int globalIndex = samplesRead + i;

        //////                    if (current == null)

        //////                    {

        //////                        current = new CrestTroughObject { StartSampleIndex = globalIndex, IsCrest = currentSign };

        //////                        positive = currentSign;

        //////                    }

        //////                    else if (currentSign != positive)

        //////                    {

        //////                        current.EndSampleIndex = globalIndex - 1;

        //////                        int segLen = current.EndSampleIndex - current.StartSampleIndex + 1;

        //////                        if (segLen < 2)

        //////                        {

        //////                            current = new CrestTroughObject { StartSampleIndex = globalIndex, IsCrest = currentSign };

        //////                            positive = currentSign;

        //////                            continue;

        //////                        }

        //////                        float[] seg = new float[segLen];

        //////                        for (int j = 0; j < segLen; j++)

        //////                        {

        //////                            int idx = i - segLen + j;

        //////                            seg[j] = (idx < 0 || idx >= blockSamples) ? 0f : buffer[idx];

        //////                        }

        //////                        current.MaxAmplitude = seg.Max();

        //////                        current.MinAmplitude = seg.Min();

        //////                        float peak = current.IsCrest ? current.MaxAmplitude : current.MinAmplitude;

        //////                        int peakIndex = Array.IndexOf(seg, peak);

        //////                        float xMicro = (peakIndex * 1000000f) / meta.SampleRate;

        //////                        current.TipPointsMicrosecondsVsAmplitude.Add(new PointF(xMicro, peak));

        //////                        current.ComputeGeometry(meta.SampleRate);

        //////                        maxWidth = Math.Max(maxWidth, current.WidthMicroseconds);

        //////                        maxHeight = Math.Max(maxHeight, current.HeightAmplitude);

        //////                        crestTroughs.Add(current);

        //////                        current = new CrestTroughObject { StartSampleIndex = globalIndex, IsCrest = currentSign };

        //////                        positive = currentSign;

        //////                    }

        //////                }

        //////                samplesRead += blockSamples;

        //////                progressBarFOR_ANALYSIS.Value = Math.Min(progressBarFOR_ANALYSIS.Maximum, samplesRead);

        //////                progressBarFOR_ANALYSIS.Refresh();

        //////            }

        //////        }

        //////    }

        //////    int MAX_BMP_WIDTH = 10000;

        //////    int MAX_BMP_HEIGHT = 30000;

        //////    float widthScale = maxWidth > MAX_BMP_WIDTH ? MAX_BMP_WIDTH / maxWidth : 1f;

        //////    float heightScale = (crestTroughs.Count * maxHeight) > MAX_BMP_HEIGHT ? MAX_BMP_HEIGHT / (crestTroughs.Count * maxHeight) : 1f;

        //////    int bmpWidth = Math.Max(32, (int)(maxWidth * widthScale) + 10);

        //////    int bmpHeight = Math.Max(32, (int)(crestTroughs.Count * maxHeight * heightScale) + 10);

        //////    try

        //////    {

        //////        ExportBitmapWithBoxesAndAxes(crestTroughs, wavPath, widthScale, heightScale, maxWidth, maxHeight, bmpWidth, bmpHeight);

        //////        ExportDetailedCSV(crestTroughs, wavPath, meta);

        //////        ExportDxfWithBoxesAndText(crestTroughs, wavPath);

        //////        ExportCrestTroughGroupingPivot(crestTroughs, wavPath);

        //////        MessageBox.Show("Complete. Bitmap, CSV, DXF, and pivot reports saved.");

        //////    }

        //////    catch (Exception ex)

        //////    {

        //////        MessageBox.Show("Report generation failed: " + ex.Message);

        //////    }

        //////}//public static void OpenAndScanWavFile___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS(ref ProgressBar progressBarFOR_ANALYSIS)

        // RRR

        /// <summary>

        /// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// </summary>

        //////public class DISCARDING_SINCE_WE_NEED_1000_TIMES_AMPLITUDES___CrestTroughObject

        //////{

        //////    public int StartSampleIndex;

        //////    public int EndSampleIndex;

        //////    public float MaxAmplitude;

        //////    public float MinAmplitude;

        //////    public bool IsCrest;

        //////    public List<PointF> TipPointsMicrosecondsVsAmplitude = new List<PointF>();

        //////    public RectangleF BoundingBox;

        //////    public PointF CG;

        //////    public float WidthMicroseconds;

        //////    public float HeightAmplitude;

        //////    public float AreaUnderCurve;

        //////    public float AreaBoundingBox;

        //////    public float AreaProportion;

        //////    public List<float> LocalAnglesMilliDegrees = new List<float>();

        //////    public int LocalMaximaCount = 0;

        //////    public int LocalMinimaCount = 0;

        //////    public void ComputeGeometry(int sampleRate)

        //////    {

        //////        int sampleCount = EndSampleIndex - StartSampleIndex + 1;

        //////        WidthMicroseconds = (sampleCount * 1000000f) / sampleRate;

        //////        HeightAmplitude = Math.Max(0.001f, Math.Abs(IsCrest ? MaxAmplitude : MinAmplitude));

        //////        BoundingBox = new RectangleF(0, 0, WidthMicroseconds, HeightAmplitude);

        //////        float sumX = 0f, sumY = 0f;

        //////        AreaUnderCurve = 0f;

        //////        for (int i = 0; i < TipPointsMicrosecondsVsAmplitude.Count; i++)

        //////        {

        //////            PointF p = TipPointsMicrosecondsVsAmplitude[i];

        //////            sumX += p.X;

        //////            sumY += p.Y;

        //////            if (i > 0)

        //////            {

        //////                float dx = TipPointsMicrosecondsVsAmplitude[i].X - TipPointsMicrosecondsVsAmplitude[i - 1].X;

        //////                float avgY = (TipPointsMicrosecondsVsAmplitude[i].Y + TipPointsMicrosecondsVsAmplitude[i - 1].Y) / 2f;

        //////                AreaUnderCurve += Math.Abs(avgY * dx);

        //////            }

        //////            if (i > 0 && i < TipPointsMicrosecondsVsAmplitude.Count - 1)

        //////            {

        //////                PointF p1 = TipPointsMicrosecondsVsAmplitude[i - 1];

        //////                PointF p2 = TipPointsMicrosecondsVsAmplitude[i];

        //////                PointF p3 = TipPointsMicrosecondsVsAmplitude[i + 1];

        //////                float dx1 = p2.X - p1.X;

        //////                float dy1 = (p2.Y - p1.Y) * 1000f;

        //////                float dx2 = p3.X - p2.X;

        //////                float dy2 = (p3.Y - p2.Y) * 1000f;

        //////                float angle1 = (float)Math.Atan2(dy1, dx1);

        //////                float angle2 = (float)Math.Atan2(dy2, dx2);

        //////                float diff = angle2 - angle1;

        //////                float degrees = diff * (180000f / (float)Math.PI);

        //////                if (degrees < 0) degrees += 360000f;

        //////                LocalAnglesMilliDegrees.Add(degrees);

        //////            }

        //////        }

        //////        for (int i = 1; i < TipPointsMicrosecondsVsAmplitude.Count - 1; i++)

        //////        {

        //////            float prev = TipPointsMicrosecondsVsAmplitude[i - 1].Y;

        //////            float curr = TipPointsMicrosecondsVsAmplitude[i].Y;

        //////            float next = TipPointsMicrosecondsVsAmplitude[i + 1].Y;

        //////            if (curr > prev && curr > next) LocalMaximaCount++;

        //////            if (curr < prev && curr < next) LocalMinimaCount++;

        //////        }

        //////        AreaBoundingBox = WidthMicroseconds * HeightAmplitude;

        //////        AreaProportion = AreaBoundingBox == 0f ? 0f : AreaUnderCurve / AreaBoundingBox;

        //////        if (TipPointsMicrosecondsVsAmplitude.Count > 0)

        //////            CG = new PointF(sumX / TipPointsMicrosecondsVsAmplitude.Count, sumY / TipPointsMicrosecondsVsAmplitude.Count);

        //////    }// public void ComputeGeometry(int sampleRate)

        //////}// public class CrestTroughObject

        public static void ExportStatisticsSummary(List<CrestTroughObject> crestTroughs, string wavPath)

        {

            var groups = new[] {

                new { Label = "CREST", Items = crestTroughs.Where(x => x.IsCrest).ToList() },

                new { Label = "TROUGH", Items = crestTroughs.Where(x => !x.IsCrest).ToList() }

            };

            string path = Path.ChangeExtension(wavPath, "_CHARACTERISTICS_STATS.csv");

            using (StreamWriter sw = new StreamWriter(path))

            {

                sw.WriteLine("Group,Feature,Mean,StdDev,Skewness,Kurtosis,Count");

                foreach (var grp in groups)

                {

                    string[] features = new[] { "AreaProportion", "HeightAmplitude", "WidthMicroseconds" };

                    foreach (var feat in features)

                    {

                        var values = grp.Items.Select(x =>

                            feat == "AreaProportion" ? x.AreaProportion :

                            feat == "HeightAmplitude" ? x.HeightAmplitude :

                            x.WidthMicroseconds).ToList();

                        int n = values.Count;

                        if (n < 2) continue;

                        float mean = values.Average();

                        float std = (float)Math.Sqrt(values.Sum(v => (v - mean) * (v - mean)) / (n - 1));

                        float skew = values.Sum(v => (float)Math.Pow((v - mean) / std, 3)) / n;

                        float kurt = values.Sum(v => (float)Math.Pow((v - mean) / std, 4)) / n - 3;

                        sw.WriteLine($"{grp.Label},{feat},{mean:F4},{std:F4},{skew:F4},{kurt:F4},{n}");

                    }

                }

            }

        }// public static void ExportStatisticsSummary(List<CrestTroughObject> crestTroughs, string wavPath)

        public static void ExportShortDurationFiltered(List<CrestTroughObject> crestTroughs, string wavPath, int sampleRate)

        {

            int thresholdSamples = (sampleRate / 1000) * 20;

            var filtered = crestTroughs.Where(ct => (ct.EndSampleIndex - ct.StartSampleIndex + 1) < thresholdSamples).ToList();

            if (filtered.Count == 0)

            {

                MessageBox.Show("No short duration crests/troughs (<20ms) found.");

                return;

            }

            string baseName = Path.GetFileNameWithoutExtension(wavPath);

            string folder = Path.GetDirectoryName(wavPath);

            using (StreamWriter sw = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.csv")))

            {

                sw.WriteLine("Index,StartSample,EndSample,NumSamples,WidthMicroSec,Height,AreaUnderCurve,AreaProp,IsCrest");

                for (int i = 0; i < filtered.Count; i++)

                {

                    var ct = filtered[i];

                    sw.WriteLine(string.Join(",",

                        i,

                        ct.StartSampleIndex,

                        ct.EndSampleIndex,

                        ct.EndSampleIndex - ct.StartSampleIndex + 1,

                        ct.WidthMicroseconds.ToString("F2", CultureInfo.InvariantCulture),

                        ct.HeightAmplitude.ToString("F4", CultureInfo.InvariantCulture),

                        ct.AreaUnderCurve.ToString("F2", CultureInfo.InvariantCulture),

                        ct.AreaProportion.ToString("F4", CultureInfo.InvariantCulture),

                        ct.IsCrest ? "CREST" : "TROUGH"));

                }//for (int i = 0; i < filtered.Count; i++)

            }//using (StreamWriter sw = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.csv")))

            using (StreamWriter dxf = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.dxf")))

            {

                CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS.ExportDxfWithBoxesAndText_UNSCALED_CG_LEFTSALIGNED_AABB_GRAPH_CG_SHOWS_VERTS_SPECTRAS(filtered, wavPath);

            }//using (StreamWriter dxf = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.dxf")))

            float maxWidth = filtered.Max(ct => ct.WidthMicroseconds);

          //  float maxHeight = filtered.Max(ct => Math.Abs(ct.CG.Y));

            float maxHeight = filtered.Max(ct => Math.Abs(ct.CG.Y/10f));// i have accumulated the data 10000f times while populating the amplitudes

            float widthScale = maxWidth > 1000 ? 1000f / maxWidth : 1f;

            float heightScale = maxHeight > 1f ? 100f / maxHeight : 1f;

            int bmpWidth = Math.Max(64, (int)(maxWidth * widthScale) + 10);

            int bmpHeight = Math.Max(64, (int)(filtered.Count * maxHeight * heightScale) + 10);

            //////float maxWidth = Math.Max(1f, filtered.Max(ct => ct.WidthMicroseconds));

            //////float maxHeight = Math.Max(1f, filtered.Max(ct => Math.Abs(ct.CG.Y)));

            //////float widthScale = maxWidth > 1000f ? 1000f / maxWidth : 1f;

            //////float heightScale = maxHeight > 1f ? 100f / maxHeight : 1f;

            //////int bmpWidth = Math.Max(64, (int)(maxWidth * widthScale) + 10);

            //////int bmpHeight = Math.Max(64, (int)(filtered.Count * maxHeight * heightScale) + 10);

            try

            {

            using (Bitmap bmp = new Bitmap(bmpWidth, bmpHeight))

            {

                using (Graphics g = Graphics.FromImage(bmp))

                {

                    g.Clear(Color.White);

                    for (int i = 0; i < filtered.Count; i++)

                    {

                        var ct = filtered[i];

                        float cx = ct.CG.X * widthScale;

                        float cy = ct.IsCrest

                            ? (i * maxHeight * heightScale + (maxHeight * heightScale - ct.CG.Y * heightScale))

                            : (i * maxHeight * heightScale + (maxHeight * heightScale + Math.Abs(ct.CG.Y) * heightScale));

                        int radius = Math.Max(2, (ct.EndSampleIndex - ct.StartSampleIndex) / 128);

                        Brush b = ct.IsCrest ? Brushes.Blue : Brushes.Red;

                        g.FillEllipse(b, cx - radius, cy - radius, radius * 2, radius * 2);

                        g.DrawString($"#{i}", SystemFonts.DefaultFont, Brushes.Black, cx + 4, cy + 4);

                    }

                }

                if (bmpWidth <= 0 || bmpHeight <= 0)

                {

                    MessageBox.Show("Invalid bitmap dimensions. Aborting image save.");

                    return;

                }//if (bmpWidth <= 0 || bmpHeight <= 0)

                bmp.Save(Path.Combine(folder, baseName + "_SHORT_FILTERED.bmp"));

            }// using (Bitmap bmp = new Bitmap(bmpWidth, bmpHeight))

            }

            catch (Exception ___excp_to_save_bitmaps_short_filtered)

            {

                System.Windows.Forms.MessageBox.Show("___excp_to_save_bitmaps_short_filtered =  " + ___excp_to_save_bitmaps_short_filtered.Message + "   " + ___excp_to_save_bitmaps_short_filtered.StackTrace.ToString() + " bmpWidth = " + bmpWidth + " bmpHeight = " + bmpHeight);

                Console.WriteLine("___excp_to_save_bitmaps_short_filtered =  " + ___excp_to_save_bitmaps_short_filtered.Message + "   " + ___excp_to_save_bitmaps_short_filtered.StackTrace.ToString() + " bmpWidth = " + bmpWidth + " bmpHeight = " + bmpHeight);

            }//catch(Exception ___excp_to_save_bitmaps_short_filtered)

        }//public static void ExportShortDurationFiltered(List<CrestTroughObject> crestTroughs, string wavPath, int sampleRate)

        //////public static void ExportShortDurationFiltered(List<CrestTroughObject> crestTroughs, string wavPath, int sampleRate)

        //////{

        //////    int thresholdSamples = (sampleRate / 1000) * 20;

        //////    var filtered = crestTroughs.Where(ct => (ct.EndSampleIndex - ct.StartSampleIndex + 1) < thresholdSamples).ToList();

        //////    if (filtered.Count == 0)

        //////    {

        //////        MessageBox.Show("No short duration crests/troughs (<20ms) found.");

        //////        return;

        //////    }

        //////    string baseName = Path.GetFileNameWithoutExtension(wavPath);

        //////    string folder = Path.GetDirectoryName(wavPath);

        //////    using (StreamWriter sw = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.csv")))

        //////    {

        //////        sw.WriteLine("Index,StartSample,EndSample,NumSamples,WidthMicroSec,Height,AreaUnderCurve,AreaProp,IsCrest");

        //////        for (int i = 0; i < filtered.Count; i++)

        //////        {

        //////            var ct = filtered[i];

        //////            sw.WriteLine(string.Join(",",

        //////                i,

        //////                ct.StartSampleIndex,

        //////                ct.EndSampleIndex,

        //////                ct.EndSampleIndex - ct.StartSampleIndex + 1,

        //////                ct.WidthMicroseconds.ToString("F2", CultureInfo.InvariantCulture),

        //////                ct.HeightAmplitude.ToString("F4", CultureInfo.InvariantCulture),

        //////                ct.AreaUnderCurve.ToString("F2", CultureInfo.InvariantCulture),

        //////                ct.AreaProportion.ToString("F4", CultureInfo.InvariantCulture),

        //////                ct.IsCrest ? "CREST" : "TROUGH"));

        //////        }

        //////    }

        //////    using (StreamWriter dxf = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.dxf")))

        //////    {

        //////        CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS.ExportDxfWithBoxesAndText(filtered, wavPath);

        //////    }

        //////    int bmpWidth = 1000;

        //////    int bmpHeight = Math.Max(64, 200 + 30 * filtered.Count);

        //////    using (Bitmap bmp = new Bitmap(bmpWidth, bmpHeight))

        //////    {

        //////        using (Graphics g = Graphics.FromImage(bmp))

        //////        {

        //////            g.Clear(Color.White);

        //////            for (int i = 0; i < filtered.Count; i++)

        //////            {

        //////                var ct = filtered[i];

        //////                float cx = ct.CG.X / 100f;

        //////                float cy = ct.IsCrest ? 100 - (ct.CG.Y) : 100 + (Math.Abs(ct.CG.Y));

        //////                int radius = Math.Max(2, (ct.EndSampleIndex - ct.StartSampleIndex) / 128);

        //////                Brush b = ct.IsCrest ? Brushes.Blue : Brushes.Red;

        //////                g.FillEllipse(b, cx - radius, cy - radius, radius * 2, radius * 2);

        //////                g.DrawString($"#{i}", SystemFonts.DefaultFont, Brushes.Black, cx + 4, cy + 4);

        //////            }

        //////        }

        //////        bmp.Save(Path.Combine(folder, baseName + "_SHORT_FILTERED.bmp"));

        //////    }

        //////}//public static void ExportShortDurationFiltered(List<CrestTroughObject> crestTroughs, string wavPath, int sampleRate)

        //////public static void ExportShortDurationFiltered(List<CrestTroughObject> crestTroughs, string wavPath, int sampleRate)

        //////{

        //////    int thresholdSamples = (sampleRate / 1000) * 20;

        //////    var filtered = crestTroughs.Where(ct => (ct.EndSampleIndex - ct.StartSampleIndex + 1) < thresholdSamples).ToList();

        //////    string baseName = Path.GetFileNameWithoutExtension(wavPath);

        //////    string folder = Path.GetDirectoryName(wavPath);

        //////    using (StreamWriter sw = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.csv")))

        //////    {

        //////        sw.WriteLine("Index,StartSample,EndSample,NumSamples,WidthMicroSec,Height,AreaUnderCurve,AreaProp,IsCrest");

        //////        for (int i = 0; i < filtered.Count; i++)

        //////        {

        //////            var ct = filtered[i];

        //////            sw.WriteLine(string.Join(",",

        //////                i,

        //////                ct.StartSampleIndex,

        //////                ct.EndSampleIndex,

        //////                ct.EndSampleIndex - ct.StartSampleIndex + 1,

        //////                ct.WidthMicroseconds.ToString("F2", CultureInfo.InvariantCulture),

        //////                ct.HeightAmplitude.ToString("F4", CultureInfo.InvariantCulture),

        //////                ct.AreaUnderCurve.ToString("F2", CultureInfo.InvariantCulture),

        //////                ct.AreaProportion.ToString("F4", CultureInfo.InvariantCulture),

        //////                ct.IsCrest ? "CREST" : "TROUGH"));

        //////        }

        //////    }

        //////    using (StreamWriter dxf = new StreamWriter(Path.Combine(folder, baseName + "_SHORT_FILTERED.dxf")))

        //////    {

        //////        AddDxfDecorations(dxf, filtered, wavPath);

        //////    }

        //////    using (Bitmap bmp = new Bitmap(1000, 200 + 30 * filtered.Count))

        //////    {

        //////        using (Graphics g = Graphics.FromImage(bmp))

        //////        {

        //////            g.Clear(Color.White);

        //////            for (int i = 0; i < filtered.Count; i++)

        //////            {

        //////                var ct = filtered[i];

        //////                float cx = ct.CG.X / 100f;

        //////                float cy = ct.IsCrest ? 100 - (ct.CG.Y * 1000) : 100 + (Math.Abs(ct.CG.Y) * 1000);

        //////                int radius = Math.Max(2, (ct.EndSampleIndex - ct.StartSampleIndex) / 128);

        //////                Brush b = ct.IsCrest ? Brushes.Blue : Brushes.Red;

        //////                g.FillEllipse(b, cx - radius, cy - radius, radius * 2, radius * 2);

        //////                g.DrawString($"#{i}", SystemFonts.DefaultFont, Brushes.Black, cx + 4, cy + 4);

        //////            }

        //////        }

        //////        bmp.Save(Path.Combine(folder, baseName + "_SHORT_FILTERED.bmp"));

        //////    }

        //////}//public static void ExportShortDurationFiltered(List<CrestTroughObject> crestTroughs, string wavPath, int sampleRate)

        // Full method: OpenAndScanWavFile___WITH_TRANSPARENT_RECTANGLES_...

        // Including WAV reading, crest/trough extraction, geometry calculation, bitmap + CSV + DXF export

        // Enhancements: zero-line alignment, bounding boxes, CG markers, filename labels, area proportions, local angles, statistical grouping

        // This is a full replacement of the method and related helpers for direct copy-paste

        // === DECLARATION START ===

        public static void OpenAndScanWavFile___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS(ref ProgressBar progressBarFOR_ANALYSIS)

        {

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "WAV files (*.wav)|*.wav";

            if (ofd.ShowDialog() != DialogResult.OK) return;

            string wavPath = ofd.FileName;

            WavMetadata meta = ReadMetadata(wavPath);

            if (meta.Channels != 1) { MessageBox.Show("Only mono WAV files are supported."); return; }

            List<CrestTroughObject> crestTroughs = new List<CrestTroughObject>();

            int chunkSize = 8192;

            float maxWidth = 1f, maxHeight = 1f;

            using (FileStream fs = new FileStream(wavPath, FileMode.Open, FileAccess.Read))

            {

            using (BinaryReader br = new BinaryReader(fs))

            {

                br.ReadBytes(12);

                while (br.BaseStream.Position < br.BaseStream.Length)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSizeBytes = br.ReadInt32();

                    if (chunkID != "data")

                        {

                            br.BaseStream.Position += chunkSizeBytes; continue;

                        }// if (chunkID != "data")

                        int bytesPerSample = meta.BitsPerSample / 8;

                    int totalSamples = chunkSizeBytes / bytesPerSample;

                    float[] buffer = new float[chunkSize];

                    int samplesRead = 0;

                    CrestTroughObject current = null;

                    bool positive = true;

                    progressBarFOR_ANALYSIS.Minimum = 0;

                    progressBarFOR_ANALYSIS.Maximum = totalSamples;

                    while (samplesRead < totalSamples)

                    {

                        int blockSamples = Math.Min(chunkSize, totalSamples - samplesRead);

                        for (int i = 0; i < blockSamples; i++)

                        {

                            switch (meta.BitsPerSample)

                            {

                                case 8: buffer[i] = (br.ReadByte() - 128) / 128f; break;

                                case 16: buffer[i] = br.ReadInt16() / 32768f; break;

                                case 24:

                                    byte[] b = br.ReadBytes(3);

                                    int val = (b[2] << 16) | (b[1] << 8) | b[0];

                                    if ((val & 0x800000) != 0) val |= unchecked((int)0xFF000000);

                                    buffer[i] = val / 8388608f; break;

                                case 32: buffer[i] = br.ReadInt32() / (float)Int32.MaxValue; break;

                                default: MessageBox.Show("Unsupported bit depth."); return;

                            }//switch (meta.BitsPerSample)

                        }//for (int i = 0; i < blockSamples; i++)

                        for (int i = 0; i < blockSamples; i++)

                        {

                            bool currentSign = buffer[i] >= 0;

                            int globalIndex = samplesRead + i;

                            if (current == null)

                            {

                                current = new CrestTroughObject { StartSampleIndex = globalIndex, IsCrest = currentSign };

                                positive = currentSign;

                            }

                            else if (currentSign != positive)

                            {

                                current.EndSampleIndex = globalIndex - 1;

                                int segLen = current.EndSampleIndex - current.StartSampleIndex + 1;

                                if (segLen < 2)

                                    {

                                        current = new CrestTroughObject { StartSampleIndex = globalIndex, IsCrest = currentSign }; positive = currentSign; continue;

                                    }//if (segLen < 2)

                                float[] seg = new float[segLen];

                                for (int j = 0; j < segLen; j++)

                                {

                                    int idx = i - segLen + j;

                                    //seg[j] = (idx < 0 || idx >= blockSamples) ? 0f : buffer[idx];

                                    seg[j] = (idx < 0 || idx >= blockSamples) ? 0f : buffer[idx];

                                }//for (int j = 0; j < segLen; j++)

                                    //saan stopped it here       current.MaxAmplitude = seg.Max();

                                    //saan stopped it here       current.MinAmplitude = seg.Min();

                                    //all segment data populated

                                    current.MaxAmplitude = seg.Max();//saan brought it here

                                    current.MinAmplitude = seg.Min();//saan brought it here

                               for (int j = 0; j < segLen; j++)

                                {

                                    //  RRR

                                    float timeMicro = (j * 1000000f) / meta.SampleRate;

                                    // current.TipPointsMicrosecondsVsAmplitude.Add(new PointF(timeMicro, seg[j]));

                                    current.TipPointsMicrosecondsVsAmplitude.Add(new PointF(timeMicro, seg[j] * 10000f));//saan did * 10000f to get better angles calcs

                                }//for (int j = 0; j < segLen; j++)

                                //////current.MaxAmplitude = seg.Max();//saan brought it here

                                //////current.MinAmplitude = seg.Min();//saan brought it here

                                current.ComputeGeometry(meta.SampleRate);

                                maxWidth = Math.Max(maxWidth, current.WidthMicroseconds);

                                maxHeight = Math.Max(maxHeight, current.HeightAmplitude);

                                crestTroughs.Add(current);

                                current = new CrestTroughObject { StartSampleIndex = globalIndex, IsCrest = currentSign };

                                positive = currentSign;

                                    //done in open and scan wav files

                                    ////////CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS.

                                    //////public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_CRESTS = +600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_CRESTS = -600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_TROUGHS = +600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_TROUGHS = -600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS = +600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS = -600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUND_IN_CRESTS = -600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUND_IN_TROUGHS = -600000000;

                                    //////public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUNDOVERALL_IN_CRESTS_AND_TROUGHS = -600000000;

                                                            CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                                                            .PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                                                            =

                                                            Math.Min

                                                            (

                                                            CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                                                            .PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                                                            ,

                                                            (double) maxWidth

                                                            );

                                                        CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                                                        .PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                                                        =

                                                        Math.Max

                                                        (

                                                        CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                                                        .PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                                                        ,

                                                        (double)maxWidth

                                                        );

                                }

                        }//for (int i = 0; i < blockSamples; i++)

                        samplesRead += blockSamples;

                        progressBarFOR_ANALYSIS.Value = Math.Min(progressBarFOR_ANALYSIS.Maximum, samplesRead);

                        progressBarFOR_ANALYSIS.Refresh();

                    }

                }

            }

            }//using (FileStream fs = new FileStream(wavPath, FileMode.Open, FileAccess.Read))

            int MAX_BMP_WIDTH = 10000;

            int MAX_BMP_HEIGHT = 30000;

            float widthScale = maxWidth > MAX_BMP_WIDTH ? MAX_BMP_WIDTH / maxWidth : 1f;

            float heightScale = (crestTroughs.Count * maxHeight) > MAX_BMP_HEIGHT ? MAX_BMP_HEIGHT / (crestTroughs.Count * maxHeight) : 1f;

          //  float heightScale = ( maxHeight) > MAX_BMP_HEIGHT ? MAX_BMP_HEIGHT / ( maxHeight) : 1f;

              int bmpWidth = Math.Max(32, (int)(maxWidth * widthScale) + 10);

              int bmpHeight = Math.Max(32, (int)(crestTroughs.Count * maxHeight * heightScale) + 10);

           // int bmpHeight = Math.Max(32, (int)((1+1)*10000f * maxHeight * heightScale) + 10);

            ExportBitmapWithBoxesAndAxes(crestTroughs, wavPath, widthScale, heightScale, maxWidth, maxHeight, bmpWidth, bmpHeight);

            ExportCrestTroughGroupingPivot(crestTroughs, wavPath);

            ExportDetailedCSV(crestTroughs, wavPath, meta);

            // THIS HAS THE  ExportDxfWithBoxesAndText_UNSCALED_CG_LEFTSALIGNED_AABB_GRAPH_CG_SHOWS_VERTS_SPECTRAS

            ExportDxfWithBoxesAndText_UNSCALED_CG_LEFTSALIGNED_AABB_GRAPH_CG_SHOWS_VERTS_SPECTRAS(crestTroughs, wavPath);

            /////////SPECIAL DXF

            ExportDxf_With_SAAN_STYLES_SINGLE_OUTER_GRAPH_SAANS_NORMALIZED_SCALED_TO_MAX_WIDTH_CG_X_DATABoxesAndText(crestTroughs, wavPath);

            //  ExportDetailedCSV(crestTroughs, wavPath, meta);

            //   ExportBitmapWithBoxesAndAxes(crestTroughs, wavPath, widthScale, heightScale, maxWidth, maxHeight, bmpWidth, bmpHeight);

            //  ExportCrestTroughGroupingPivot(crestTroughs, wavPath);

            //     ExportShortDurationFiltered(crestTroughs, wavPath, meta);

            ExportShortDurationFiltered(crestTroughs, wavPath, meta.SampleRate);

            ExportStatisticsSummary(crestTroughs, wavPath);

           // ExportDxfWithBoxesAndCenterlines(crestTroughs, wavPath, meta);

          //  ExportStatisticsSummary(crestTroughs, wavPath);

          //  ExportShortDurationFiltered(crestTroughs, wavPath, meta);

            MessageBox.Show("Complete. Bitmap, CSV, DXF, and pivot reports saved.");

        }//public static void OpenAndScanWavFile___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS(ref ProgressBar progressBarFOR_ANALYSIS)

        //ExportDxfWithBoxesAndText

        // ExportDetailedCSV

        public static void ExportDetailedCSV(List<CrestTroughObject> crestTroughs, string wavPath, WavMetadata meta)

        {

            using (StreamWriter sw = new StreamWriter(Path.ChangeExtension(wavPath, "_DETAILED_STATS.csv")))

            {

                sw.WriteLine("Index,StartSample,EndSample,NumSamples,WidthMicroSec,Height,CG_X,CG_Y,AreaUnderCurve,AreaBox,AreaRatio,MaximaCount,MinimaCount,IsCrest,Angles");

                for (int i = 0; i < crestTroughs.Count; i++)

                {

                    var ct = crestTroughs[i];

                    string angles = string.Join("|", ct.LocalAnglesMilliDegrees.Select(a => a.ToString("F1", CultureInfo.InvariantCulture)));

                    sw.WriteLine(string.Join(",",

                        i,

                        ct.StartSampleIndex,

                        ct.EndSampleIndex,

                        (ct.EndSampleIndex - ct.StartSampleIndex + 1),

                        ct.WidthMicroseconds.ToString("F1", CultureInfo.InvariantCulture),

                        ct.HeightAmplitude.ToString("F6", CultureInfo.InvariantCulture),

                        ct.CG.X.ToString("F1", CultureInfo.InvariantCulture),

                        ct.CG.Y.ToString("F6", CultureInfo.InvariantCulture),

                        ct.AreaUnderCurve.ToString("F1", CultureInfo.InvariantCulture),

                        ct.AreaBoundingBox.ToString("F1", CultureInfo.InvariantCulture),

                        ct.AreaProportion.ToString("F3", CultureInfo.InvariantCulture),

                        ct.LocalMaximaCount,

                        ct.LocalMinimaCount,

                        ct.IsCrest ? "CREST" : "TROUGH",

                        angles));

                }

            }

        }//public static void ExportDetailedCSV(List<CrestTroughObject> crestTroughs, string wavPath, WavMetadata meta)

        //////public static void ExportDxfWithBoxesAndText(List<CrestTroughObject> crestTroughs, string wavPath)

        //////{

        //////    string path = Path.ChangeExtension(wavPath, "_GRAPH_CG_BOXES_AXES.dxf");

        //////    using (StreamWriter sw = new StreamWriter(path))

        //////    {

        //////        sw.WriteLine("0\nSECTION\n2\nENTITIES");

        //////        foreach (var ct in crestTroughs)

        //////        {

        //////            float cx = ct.CG.X;

        //////            float cy = ct.IsCrest ? ct.CG.Y : -Math.Abs(ct.CG.Y);

        //////            float radius = Math.Max(1f, (ct.EndSampleIndex - ct.StartSampleIndex) / 10f);

        //////            int color = ct.IsCrest ? 5 : 1;

        //////            sw.WriteLine($"0\nCIRCLE\n8\n0\n62\n{color}\n10\n{cx.ToString("F3", CultureInfo.InvariantCulture)}\n20\n{cy.ToString("F3", CultureInfo.InvariantCulture)}\n30\n0\n40\n{radius.ToString("F3", CultureInfo.InvariantCulture)}");

        //////            float x1 = cx - ct.BoundingBox.Width / 2;

        //////            float x2 = cx + ct.BoundingBox.Width / 2;

        //////            float y1 = ct.IsCrest ? 0 : -ct.BoundingBox.Height;

        //////            float y2 = ct.IsCrest ? ct.BoundingBox.Height : 0;

        //////            sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{x1.ToString("F3", CultureInfo.InvariantCulture)}\n20\n{y1.ToString("F3", CultureInfo.InvariantCulture)}\n30\n0\n11\n{x2.ToString("F3", CultureInfo.InvariantCulture)}\n21\n{y2.ToString("F3", CultureInfo.InvariantCulture)}\n31\n0");

        //////        }// foreach (var ct in crestTroughs)

        //////        sw.WriteLine("0\nENDSEC\n0\nEOF");

        //////    }// using (StreamWriter sw = new StreamWriter(path))

        //////}//public static void ExportDxfWithBoxesAndText(List<CrestTroughObject> crestTroughs, string wavPath)

      public static void ExportDxf_With_SAAN_STYLES_SINGLE_OUTER_GRAPH_SAANS_NORMALIZED_SCALED_TO_MAX_WIDTH_CG_X_DATABoxesAndText(List<CrestTroughObject> crestTroughs, string wavPath)

        {

            string path = Path.ChangeExtension(wavPath, "_GRAPH_SAANS_NORMALIZED_SCALED_TO_MAX_WIDTH_CG_X_DATA.dxf");

            using (StreamWriter sw = new StreamWriter(path))

            {

                sw.WriteLine("0\nSECTION\n2\nENTITIES");

                float w =

                   (float)CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                        .PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS;

                    //ct.BoundingBox.Width;

                float h =

                    10000f;

                //  ct.BoundingBox.Height;

                float left = 0f;// cx - w / 2;

                float right = w;//  cx + w / 2;

                float top = h;// ct.IsCrest ? 0 + h : 0;

                float bottom = -h;// ct.IsCrest ? 0 : 0 - h;

                int color = 6;// ct.IsCrest ? 5 : 1;

                float center_x = w / 2;// 0;

                //////// Bounding box edges (4 lines)

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{top:F3}\n31\n0");     // top

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{bottom:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0"); // bottom

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{left:F3}\n21\n{bottom:F3}\n31\n0");     // left

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{right:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0");   // right

                //////// Axes lines

                color = 1;//

                sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{left:F3}\n20\n0.000\n30\n0\n11\n{right:F3}\n21\n0.000\n31\n0");   // X axis

                                                                                                                            //  sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{cx:F3}\n20\n{bottom:F3}\n30\n0\n11\n{cx:F3}\n21\n{top:F3}\n31\n0"); // Y axis

                sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{center_x:F3}\n20\n{bottom:F3}\n30\n0\n11\n{center_x:F3}\n21\n{top:F3}\n31\n0"); // Y axis

                /// crestTroughs.ToArray<CrestTroughObject>().

                /// 

                //done in open and scan wav files

                ////////CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS.

                //////public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_CRESTS = +600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_CRESTS = -600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_TROUGHS = +600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_TROUGHS = -600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS = +600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS = -600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUND_IN_CRESTS = -600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUND_IN_TROUGHS = -600000000;

                //////public static double PUBLIC_STATIC_DOUBLE_MAX_ABS_AMPLITUDES_FOUND_10000_TIMES_FOUNDOVERALL_IN_CRESTS_AND_TROUGHS = -600000000;

                //////CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                //////.PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                //////=

                //////Math.Min

                //////(

                //////CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                //////.PUBLIC_STATIC_DOUBLE_MIN_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                //////,

                //////(double)current.WidthMicroseconds

                //////);

                //////CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                //////.PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                //////=

                //////Math.Max

                //////(

                //////CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                //////.PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                //////,

                //////(double)current.WidthMicroseconds

                //////);

                for (int i = 0; i < crestTroughs.Count; i++)

                {

                    float _saans_x_width_scales_factor = 1.0f;

                    // var ct = crestTroughs[i];

                    CrestTroughObject ct = crestTroughs[i];

                    _saans_x_width_scales_factor

                        =

                        (float)

                     ( (float)CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                        .PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS

                        /

                        (ct.WidthMicroseconds));

                 //   Console.WriteLine("to calculate cx  data  ======  max mikros found = " + CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS.PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS + " ct.WidthMicroseconds = " + ct.WidthMicroseconds + " _saans_x_width_scales_factor= " + _saans_x_width_scales_factor);

                    float cx = ct.CG.X;

                    cx

                   = (float)((_saans_x_width_scales_factor) * cx);

                    float cy = ct.IsCrest ? ct.CG.Y : -Math.Abs(ct.CG.Y);

                    //////float w = ct.BoundingBox.Width;

                    //////float h = ct.BoundingBox.Height;

                    //////float left = cx - w / 2;

                    //////float right = cx + w / 2;

                    //////float top = ct.IsCrest ? 0 + h : 0;

                    //////float bottom = ct.IsCrest ? 0 : 0 - h;

                    //////int color = ct.IsCrest ? 5 : 1;

                     color = ct.IsCrest ? 5 : 1;

                    // CG circle

                    float radius = Math.Max(1f, (ct.EndSampleIndex - ct.StartSampleIndex) / 10f);

                    sw.WriteLine($"0\nCIRCLE\n8\n0\n62\n{color}\n10\n{cx:F3}\n20\n{cy:F3}\n30\n0\n40\n{radius:F3}");

                    // Label text

                    sw.WriteLine($"0\nTEXT\n8\n0\n62\n{color}\n10\n{cx:F3}\n20\n{cy:F3}\n30\n0\n40\n{radius:F3}\n1\n#{i}");

                }

                sw.WriteLine("0\nENDSEC\n0\nEOF");

            }

        }//public static void ExportDxf_With_SAAN_STYLES_SINGLE_OUTER_GRAPH_SAANS_NORMALIZED_SCALED_TO_MAX_WIDTH_CG_X_DATABoxesAndText(List<CrestTroughObject> crestTroughs, string wavPath)

        public static void ExportDxfWithBoxesAndText_UNSCALED_CG_LEFTSALIGNED_AABB_GRAPH_CG_SHOWS_VERTS_SPECTRAS(List<CrestTroughObject> crestTroughs, string wavPath)

        {

            string path = Path.ChangeExtension(wavPath, "_UNSCALED_CG_LEFTSALIGNED_AABB_GRAPH_CG_SHOWS_VERTS_SPECTRAS.dxf");

            using (StreamWriter sw = new StreamWriter(path))

            {

                sw.WriteLine("0\nSECTION\n2\nENTITIES");

                float w =

                   (float)CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

                        .PUBLIC_STATIC_DOUBLE_MAX_WIDTH_MIKROSEC_FOUND_IN_OVERALL_IN_CRESTS_AND_TROUGHS;

                //ct.BoundingBox.Width;

                float h =

                    10000f;

                //  ct.BoundingBox.Height;

                float left = 0f;// cx - w / 2;

                float right = w;//  cx + w / 2;

                float top = h;// ct.IsCrest ? 0 + h : 0;

                float bottom = -h;// ct.IsCrest ? 0 : 0 - h;

                int color = 6;// ct.IsCrest ? 5 : 1;

                float center_x = w / 2;// 0;

                //////// Bounding box edges (4 lines)

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{top:F3}\n31\n0");     // top

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{bottom:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0"); // bottom

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{left:F3}\n21\n{bottom:F3}\n31\n0");     // left

                sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{right:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0");   // right

                //////// Axes lines

                color = 1;//

                sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{left:F3}\n20\n0.000\n30\n0\n11\n{right:F3}\n21\n0.000\n31\n0");   // X axis

                                                                                                                            //  sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{cx:F3}\n20\n{bottom:F3}\n30\n0\n11\n{cx:F3}\n21\n{top:F3}\n31\n0"); // Y axis

                sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{center_x:F3}\n20\n{bottom:F3}\n30\n0\n11\n{center_x:F3}\n21\n{top:F3}\n31\n0"); // Y axis

                for (int i = 0; i < crestTroughs.Count; i++)

                {

                    var ct = crestTroughs[i];

                    float cx = ct.CG.X;

                    float cy = ct.IsCrest ? ct.CG.Y : -Math.Abs(ct.CG.Y);

                   // float

                        w = ct.BoundingBox.Width;

                  //  float

                        h = ct.BoundingBox.Height;

                   // float 

                        left = cx - w / 2;

                  //  float

                        right = cx + w / 2;

                   // float

                        top = ct.IsCrest ? 0 + h : 0;

                   // float

                        bottom = ct.IsCrest ? 0 : 0 - h;

                    top = top * (10000f);

                    bottom = bottom * (10000f);

                  //  int 

                        color = ct.IsCrest ? 5 : 1;

                    // Bounding box edges (4 lines)

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{top:F3}\n31\n0");     // top

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{bottom:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0"); // bottom

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{left:F3}\n21\n{bottom:F3}\n31\n0");     // left

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{right:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0");   // right

                    // Axes lines

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{left:F3}\n20\n0.000\n30\n0\n11\n{right:F3}\n21\n0.000\n31\n0");   // X axis

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{cx:F3}\n20\n{bottom:F3}\n30\n0\n11\n{cx:F3}\n21\n{top:F3}\n31\n0"); // Y axis

                    // CG circle

                    float radius = Math.Max(1f, (ct.EndSampleIndex - ct.StartSampleIndex) / 10f);

                    sw.WriteLine($"0\nCIRCLE\n8\n0\n62\n{color}\n10\n{cx:F3}\n20\n{cy:F3}\n30\n0\n40\n{radius:F3}");

                    // Label text

                    sw.WriteLine($"0\nTEXT\n8\n0\n62\n{color}\n10\n{cx:F3}\n20\n{cy:F3}\n30\n0\n40\n{radius:F3}\n1\n#{i}");

                }

                sw.WriteLine("0\nENDSEC\n0\nEOF");

            }

        }//public static void ExportDxfWithBoxesAndText_UNSCALED_CG_LEFTSALIGNED_AABB_GRAPH_CG_SHOWS_VERTS_SPECTRAS(List<CrestTroughObject> crestTroughs, string wavPath)

        public static void ExportDxfWithBoxesAndText___WITH_4_BOUNDARY_LINES_2_AXES_LINES_FOR_ALL_AABB_CREST_TROUGHT(List<CrestTroughObject> crestTroughs, string wavPath)

        {

            string path = Path.ChangeExtension(wavPath, "_GRAPH_CG_BOXES_AXES.dxf");

            using (StreamWriter sw = new StreamWriter(path))

            {

                sw.WriteLine("0\nSECTION\n2\nENTITIES");

                for (int i = 0; i < crestTroughs.Count; i++)

                {

                    var ct = crestTroughs[i];

                    float cx = ct.CG.X;

                    float cy = ct.IsCrest ? ct.CG.Y : -Math.Abs(ct.CG.Y);

                    float w = ct.BoundingBox.Width;

                    float h = ct.BoundingBox.Height;

                    float left = cx - w / 2;

                    float right = cx + w / 2;

                    float top = ct.IsCrest ? 0 + h : 0;

                    float bottom = ct.IsCrest ? 0 : 0 - h;

                    int color = ct.IsCrest ? 5 : 1;

                    // Bounding box edges (4 lines)

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{top:F3}\n31\n0");     // top

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{bottom:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0"); // bottom

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{left:F3}\n20\n{top:F3}\n30\n0\n11\n{left:F3}\n21\n{bottom:F3}\n31\n0");     // left

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n{color}\n10\n{right:F3}\n20\n{top:F3}\n30\n0\n11\n{right:F3}\n21\n{bottom:F3}\n31\n0");   // right

                    // Axes lines

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{left:F3}\n20\n0.000\n30\n0\n11\n{right:F3}\n21\n0.000\n31\n0");   // X axis

                    sw.WriteLine($"0\nLINE\n8\n0\n62\n8\n10\n{cx:F3}\n20\n{bottom:F3}\n30\n0\n11\n{cx:F3}\n21\n{top:F3}\n31\n0"); // Y axis

                    // CG circle

                    float radius = Math.Max(1f, (ct.EndSampleIndex - ct.StartSampleIndex) / 10f);

                    sw.WriteLine($"0\nCIRCLE\n8\n0\n62\n{color}\n10\n{cx:F3}\n20\n{cy:F3}\n30\n0\n40\n{radius:F3}");

                    // Label text

                    sw.WriteLine($"0\nTEXT\n8\n0\n62\n{color}\n10\n{cx:F3}\n20\n{cy:F3}\n30\n0\n40\n{radius:F3}\n1\n#{i}");

                }

                sw.WriteLine("0\nENDSEC\n0\nEOF");

            }

        }//public static void ExportDxfWithBoxesAndText(List<CrestTroughObject> crestTroughs, string wavPath)

        public static void AddDxfDecorations(StreamWriter dxf, List<CrestTroughObject> objects, string wavPath)

        {

            dxf.WriteLine("0\nSECTION\n2\nENTITIES");

            foreach (var ct in objects)

            {

                float cx = ct.CG.X;

                float cy = ct.CG.Y;

                float radius = Math.Max(0.001f, (ct.EndSampleIndex - ct.StartSampleIndex) / 10f);

                string color = ct.IsCrest ? "5" : "1";

                dxf.WriteLine($"0\nCIRCLE\n8\n0\n62\n{color}\n10\n{cx:F2}\n20\n{cy:F6}\n30\n0\n40\n{radius:F2}");

            }

            dxf.WriteLine("0\nENDSEC\n0\nEOF");

        }//public static void AddDxfDecorations(StreamWriter dxf, List<CrestTroughObject> objects, string wavPath)

    }//public class CrestTroughAnalyzer___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

}//namespace ENHANCING___SAANS_WAVEFILES_CREST_TROUGHS_ANALYSISWaveform___WITH_TRANSPARENT_RECTANGLES_OF_TRACING_PAPER_STACKS_BITMAPS_CSV_REPORTS

No comments:

Post a Comment