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
Post a Comment