This repository has been archived on 2026-08-05. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Course-Project-on-Surveying…/Services/InputParser.cs
T
biss f61e298871
Build and Release / Publish Windows, Linux and macOS (push) Successful in 3m7s
Migrate desktop app to Avalonia and publish cross-platform releases
2026-07-19 08:51:41 +08:00

151 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Globalization;
using System.Text;
using kcsj.Models;
namespace kcsj.Services;
public static class InputParser
{
private static readonly char[] Separators = [' ', '\t', ',', ''];
public static List<KnownPoint> ReadKnownPointsFile(string filePath) =>
ParseKnownPoints(File.ReadLines(filePath, Encoding.UTF8), Path.GetFileName(filePath));
public static List<Observation> ReadObservationsFile(string filePath) =>
ParseObservations(File.ReadLines(filePath, Encoding.UTF8), Path.GetFileName(filePath));
public static List<KnownPoint> ParseKnownPointsText(string text) =>
ParseKnownPoints(SplitText(text), "手动输入");
public static List<Observation> ParseObservationsText(string text) =>
ParseObservations(SplitText(text), "手动输入");
public static string BuildKnownPointsPreview(IEnumerable<KnownPoint> points)
{
StringBuilder text = new("点名\t高程(m)\n");
foreach (KnownPoint point in points)
{
text.AppendLine($"{point.Name}\t{point.Elevation:F4}");
}
return text.ToString();
}
public static string BuildObservationsPreview(IEnumerable<Observation> observations)
{
StringBuilder text = new("起点\t终点\t高差(m)\t距离(km)\n");
foreach (Observation observation in observations)
{
text.AppendLine(
$"{observation.FromPoint}\t{observation.ToPoint}\t" +
$"{observation.HeightDiff:F6}\t{observation.Distance:F4}");
}
return text.ToString();
}
private static List<KnownPoint> ParseKnownPoints(IEnumerable<string> lines, string sourceName)
{
List<KnownPoint> result = [];
HashSet<string> names = new(StringComparer.OrdinalIgnoreCase);
int lineNumber = 0;
foreach (string rawLine in lines)
{
lineNumber++;
string line = rawLine.Trim();
if (ShouldSkip(line))
{
continue;
}
string[] parts = SplitLine(line);
if (parts.Length != 2)
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行格式错误,应为:点名 高程");
}
string name = parts[0].Trim();
if (!names.Add(name))
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行点名重复:{name}");
}
if (!TryParseNumber(parts[1], out double elevation))
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行高程不是有效数字");
}
result.Add(new KnownPoint(name, elevation));
}
if (result.Count == 0)
{
throw new FormatException($"{sourceName} 中没有有效的已知点数据");
}
return result;
}
private static List<Observation> ParseObservations(IEnumerable<string> lines, string sourceName)
{
List<Observation> result = [];
int lineNumber = 0;
foreach (string rawLine in lines)
{
lineNumber++;
string line = rawLine.Trim();
if (ShouldSkip(line))
{
continue;
}
string[] parts = SplitLine(line);
if (parts.Length != 4)
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行格式错误,应为:起点 终点 高差 距离");
}
string from = parts[0].Trim();
string to = parts[1].Trim();
if (string.Equals(from, to, StringComparison.OrdinalIgnoreCase))
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行起点和终点不能相同");
}
if (!TryParseNumber(parts[2], out double heightDiff))
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行高差不是有效数字");
}
if (!TryParseNumber(parts[3], out double distance) || distance <= 0)
{
throw new FormatException($"{sourceName} 第 {lineNumber} 行距离必须是大于 0 的数字");
}
result.Add(new Observation(from, to, heightDiff, distance));
}
if (result.Count == 0)
{
throw new FormatException($"{sourceName} 中没有有效的观测数据");
}
return result;
}
private static string[] SplitText(string text) =>
text.Replace("\r\n", "\n", StringComparison.Ordinal).Replace('\r', '\n').Split('\n');
private static string[] SplitLine(string line) =>
line.Split(Separators, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
private static bool ShouldSkip(string line) =>
string.IsNullOrWhiteSpace(line) || line.StartsWith('#') || line.StartsWith("//", StringComparison.Ordinal);
private static bool TryParseNumber(string text, out double value) =>
double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value) ||
double.TryParse(text, NumberStyles.Float, CultureInfo.CurrentCulture, out value);
}