using System; using System.Globalization; using System.Text; namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Output.Visualization; /// 把共享图形模型的指标表写为带 BOM 的 UTF-8 CSV。 public sealed class SmoothingCsvWriter { private const string Header = "ScenarioId,Method,Status,PathLengthMeters,MaximumAbsoluteVehicleCurvaturePerMeter,RootMeanSquareVehicleCurvaturePerMeter,TotalAbsoluteCurvatureVariationPerMeter,CurvatureVariationEnergy,MinimumBodyClearanceMeters,MedianElapsedMilliseconds,TimingSampleCount,IsDeterministic"; public byte[] Write(SmoothingFigureModel model) { if (model == null) throw new ArgumentNullException(nameof(model)); var text = new StringBuilder(Header).Append("\r\n"); for (int index = 0; index < model.MetricRows.Count; index++) { SmoothingFigureMetricRow row = model.MetricRows[index]; PathQualityMetrics metrics = row.Metrics; text.Append(Field(model.ScenarioId)).Append(',').Append(Field(row.Method)).Append(',').Append(Field(row.Status.ToString())).Append(',') .Append(Number(metrics.PathLengthMeters)).Append(',').Append(Number(metrics.MaximumAbsoluteVehicleCurvaturePerMeter)).Append(',') .Append(Number(metrics.RootMeanSquareVehicleCurvaturePerMeter)).Append(',').Append(Number(metrics.TotalAbsoluteCurvatureVariationPerMeter)).Append(',') .Append(Number(metrics.CurvatureVariationEnergy)).Append(',').Append(Number(metrics.MinimumBodyClearanceMeters)).Append(',') .Append(Number(row.Timing == null ? 0d : row.Timing.MedianElapsedMilliseconds)).Append(',') .Append(row.Timing == null ? 0 : row.Timing.MeasuredElapsedMilliseconds.Count).Append(',') .Append(row.Timing != null && row.Timing.IsDeterministic ? "true" : "false").Append("\r\n"); } byte[] body = new UTF8Encoding(false).GetBytes(text.ToString()); byte[] preamble = new UTF8Encoding(true).GetPreamble(); var output = new byte[preamble.Length + body.Length]; Buffer.BlockCopy(preamble, 0, output, 0, preamble.Length); Buffer.BlockCopy(body, 0, output, preamble.Length, body.Length); return output; } private static string Number(double value) { return value.ToString("0.#################", CultureInfo.InvariantCulture); } private static string Field(string value) { string text = value ?? string.Empty; return text.IndexOfAny(new[] { ',', '\"', '\r', '\n' }) < 0 ? text : "\"" + text.Replace("\"", "\"\"") + "\""; } }