Files
2026-03-04 10:03:45 +08:00

475 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using TriangleNet.Geometry;
namespace TriangleNet.IO
{
public class TriangleReader
{
private static NumberFormatInfo nfi = NumberFormatInfo.InvariantInfo;
private int startIndex;
public static bool IsNullOrWhiteSpace(string value)
{
if (value == null)
{
return true;
}
return string.IsNullOrEmpty(value.Trim());
}
private bool TryReadLine(StreamReader reader, out string[] token)
{
token = null;
if (reader.EndOfStream)
{
return false;
}
string text = reader.ReadLine().Trim();
while (IsNullOrWhiteSpace(text) || text.StartsWith("#"))
{
if (reader.EndOfStream)
{
return false;
}
text = reader.ReadLine().Trim();
}
token = text.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
return true;
}
private void ReadVertex(List<Vertex> data, int index, string[] line, int attributes, int marks)
{
double x = double.Parse(line[1], nfi);
double y = double.Parse(line[2], nfi);
Vertex vertex = new Vertex(x, y);
if (marks > 0 && line.Length > 3 + attributes)
{
vertex.Label = int.Parse(line[3 + attributes]);
}
_ = 0;
data.Add(vertex);
}
public void Read(string filename, out Polygon polygon)
{
polygon = null;
string text = Path.ChangeExtension(filename, ".poly");
if (File.Exists(text))
{
polygon = ReadPolyFile(text);
return;
}
text = Path.ChangeExtension(filename, ".node");
polygon = ReadNodeFile(text);
}
public void Read(string filename, out Polygon geometry, out List<ITriangle> triangles)
{
triangles = null;
Read(filename, out geometry);
string text = Path.ChangeExtension(filename, ".ele");
if (File.Exists(text) && geometry != null)
{
triangles = ReadEleFile(text);
}
}
public IPolygon Read(string filename)
{
Polygon polygon = null;
Read(filename, out polygon);
return polygon;
}
public Polygon ReadNodeFile(string nodefilename)
{
return ReadNodeFile(nodefilename, readElements: false);
}
public Polygon ReadNodeFile(string nodefilename, bool readElements)
{
startIndex = 0;
int num = 0;
int attributes = 0;
int marks = 0;
Polygon polygon;
using (StreamReader reader = new StreamReader(nodefilename))
{
if (!TryReadLine(reader, out var token))
{
throw new Exception("Can't read input file.");
}
num = int.Parse(token[0]);
if (num < 3)
{
throw new Exception("Input must have at least three input vertices.");
}
if (token.Length > 1 && int.Parse(token[1]) != 2)
{
throw new Exception("Triangle only works with two-dimensional meshes.");
}
if (token.Length > 2)
{
attributes = int.Parse(token[2]);
}
if (token.Length > 3)
{
marks = int.Parse(token[3]);
}
polygon = new Polygon(num);
if (num > 0)
{
for (int i = 0; i < num; i++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (vertices).");
}
if (token.Length < 3)
{
throw new Exception("Invalid vertex.");
}
if (i == 0)
{
startIndex = int.Parse(token[0], nfi);
}
ReadVertex(polygon.Points, i, token, attributes, marks);
}
}
}
if (readElements)
{
string text = Path.ChangeExtension(nodefilename, ".ele");
if (File.Exists(text))
{
ReadEleFile(text, readArea: true);
}
}
return polygon;
}
public Polygon ReadPolyFile(string polyfilename)
{
return ReadPolyFile(polyfilename, readElements: false, readArea: false);
}
public Polygon ReadPolyFile(string polyfilename, bool readElements)
{
return ReadPolyFile(polyfilename, readElements, readArea: false);
}
public Polygon ReadPolyFile(string polyfilename, bool readElements, bool readArea)
{
startIndex = 0;
int num = 0;
int attributes = 0;
int marks = 0;
Polygon polygon;
using (StreamReader reader = new StreamReader(polyfilename))
{
if (!TryReadLine(reader, out var token))
{
throw new Exception("Can't read input file.");
}
num = int.Parse(token[0]);
if (token.Length > 1 && int.Parse(token[1]) != 2)
{
throw new Exception("Triangle only works with two-dimensional meshes.");
}
if (token.Length > 2)
{
attributes = int.Parse(token[2]);
}
if (token.Length > 3)
{
marks = int.Parse(token[3]);
}
if (num > 0)
{
polygon = new Polygon(num);
for (int i = 0; i < num; i++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (vertices).");
}
if (token.Length < 3)
{
throw new Exception("Invalid vertex.");
}
if (i == 0)
{
startIndex = int.Parse(token[0], nfi);
}
ReadVertex(polygon.Points, i, token, attributes, marks);
}
}
else
{
polygon = ReadNodeFile(Path.ChangeExtension(polyfilename, ".node"));
num = polygon.Points.Count;
}
List<Vertex> points = polygon.Points;
if (points.Count == 0)
{
throw new Exception("No nodes available.");
}
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (segments).");
}
int num2 = int.Parse(token[0]);
int num3 = 0;
if (token.Length > 1)
{
num3 = int.Parse(token[1]);
}
for (int j = 0; j < num2; j++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (segments).");
}
if (token.Length < 3)
{
throw new Exception("Segment has no endpoints.");
}
int num4 = int.Parse(token[1]) - startIndex;
int num5 = int.Parse(token[2]) - startIndex;
int label = 0;
if (num3 > 0 && token.Length > 3)
{
label = int.Parse(token[3]);
}
if (num4 < 0 || num4 >= num)
{
if (Log.Verbose)
{
Log.Instance.Warning("Invalid first endpoint of segment.", "MeshReader.ReadPolyfile()");
}
}
else if (num5 < 0 || num5 >= num)
{
if (Log.Verbose)
{
Log.Instance.Warning("Invalid second endpoint of segment.", "MeshReader.ReadPolyfile()");
}
}
else
{
polygon.Add(new Segment(points[num4], points[num5], label));
}
}
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (holes).");
}
int num6 = int.Parse(token[0]);
if (num6 > 0)
{
for (int k = 0; k < num6; k++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (holes).");
}
if (token.Length < 3)
{
throw new Exception("Invalid hole.");
}
polygon.Holes.Add(new Point(double.Parse(token[1], nfi), double.Parse(token[2], nfi)));
}
}
if (TryReadLine(reader, out token))
{
int num7 = int.Parse(token[0]);
if (num7 > 0)
{
for (int l = 0; l < num7; l++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (region).");
}
if (token.Length < 4)
{
throw new Exception("Invalid region attributes.");
}
if (!int.TryParse(token[3], out var result))
{
result = l;
}
double result2 = 0.0;
if (token.Length > 4)
{
double.TryParse(token[4], NumberStyles.Number, nfi, out result2);
}
polygon.Regions.Add(new RegionPointer(double.Parse(token[1], nfi), double.Parse(token[2], nfi), result, result2));
}
}
}
}
if (readElements)
{
string text = Path.ChangeExtension(polyfilename, ".ele");
if (File.Exists(text))
{
ReadEleFile(text, readArea);
}
}
return polygon;
}
public List<ITriangle> ReadEleFile(string elefilename)
{
return ReadEleFile(elefilename, readArea: false);
}
private List<ITriangle> ReadEleFile(string elefilename, bool readArea)
{
int num = 0;
int num2 = 0;
List<ITriangle> list;
using (StreamReader reader = new StreamReader(elefilename))
{
bool flag = false;
if (!TryReadLine(reader, out var token))
{
throw new Exception("Can't read input file (elements).");
}
num = int.Parse(token[0]);
num2 = 0;
if (token.Length > 2)
{
num2 = int.Parse(token[2]);
flag = true;
}
if (num2 > 1)
{
Log.Instance.Warning("Triangle attributes not supported.", "FileReader.Read");
}
list = new List<ITriangle>(num);
for (int i = 0; i < num; i++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (elements).");
}
if (token.Length < 4)
{
throw new Exception("Triangle has no nodes.");
}
InputTriangle inputTriangle = new InputTriangle(int.Parse(token[1]) - startIndex, int.Parse(token[2]) - startIndex, int.Parse(token[3]) - startIndex);
if (num2 > 0 && flag)
{
int result = 0;
flag = int.TryParse(token[4], out result);
inputTriangle.label = result;
}
list.Add(inputTriangle);
}
}
if (readArea)
{
string text = Path.ChangeExtension(elefilename, ".area");
if (File.Exists(text))
{
ReadAreaFile(text, num);
}
}
return list;
}
private double[] ReadAreaFile(string areafilename, int intriangles)
{
double[] array = null;
using StreamReader reader = new StreamReader(areafilename);
if (!TryReadLine(reader, out var token))
{
throw new Exception("Can't read input file (area).");
}
if (int.Parse(token[0]) != intriangles)
{
Log.Instance.Warning("Number of area constraints doesn't match number of triangles.", "ReadAreaFile()");
return null;
}
array = new double[intriangles];
for (int i = 0; i < intriangles; i++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (area).");
}
if (token.Length != 2)
{
throw new Exception("Triangle has no nodes.");
}
array[i] = double.Parse(token[1], nfi);
}
return array;
}
public List<Edge> ReadEdgeFile(string edgeFile, int invertices)
{
List<Edge> list = null;
startIndex = 0;
using StreamReader reader = new StreamReader(edgeFile);
if (!TryReadLine(reader, out var token))
{
throw new Exception("Can't read input file (segments).");
}
int num = int.Parse(token[0]);
int num2 = 0;
if (token.Length > 1)
{
num2 = int.Parse(token[1]);
}
if (num > 0)
{
list = new List<Edge>(num);
}
for (int i = 0; i < num; i++)
{
if (!TryReadLine(reader, out token))
{
throw new Exception("Can't read input file (segments).");
}
if (token.Length < 3)
{
throw new Exception("Segment has no endpoints.");
}
int num3 = int.Parse(token[1]) - startIndex;
int num4 = int.Parse(token[2]) - startIndex;
int label = 0;
if (num2 > 0 && token.Length > 3)
{
label = int.Parse(token[3]);
}
if (num3 < 0 || num3 >= invertices)
{
if (Log.Verbose)
{
Log.Instance.Warning("Invalid first endpoint of segment.", "MeshReader.ReadPolyfile()");
}
}
else if (num4 < 0 || num4 >= invertices)
{
if (Log.Verbose)
{
Log.Instance.Warning("Invalid second endpoint of segment.", "MeshReader.ReadPolyfile()");
}
}
else
{
list.Add(new Edge(num3, num4, label));
}
}
return list;
}
}
}