Sanjoy Nath's AABB Qhenomenology physics process to analyse waves and signals in non fourier style no trigonometry used


Sanjoy Nath's AABB Qhenomenology physics process to analyse waves and signals in non fourier style no trigonometry used 



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


Comments

Popular posts from this blog

SANJOYNATHSMANIMMOVIES___SCENE.PY

GTTERMS_FORMALIZATION_GEOMETRIFYING_TRIGONOMETRY

why_set_theory_needed