using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using QuantumConcepts.Formats.StereoLithography;
namespace QuantumConcepts.Formats.StereoLithography
{
/// A simple XYZ representation of a vertex.
public class Vertex : IEquatable
{
/// The X coordinate of this .
public float X { get; set; }
/// The Y coordinate of this .
public float Y { get; set; }
/// The Z coordinate of this .
public float Z { get; set; }
/// Creates a new, empty .
public Vertex() { }
/// Creates a new using the provided coordinates.
///
///
///
public Vertex(float x, float y, float z)
: this()
{
this.X = x;
this.Y = y;
this.Z = z;
}
/// Shifts the by the X, Y and Z values in the parameter.
/// The amount to shift the vertex.
public void Shift(Vertex shift)
{
this.X += shift.X;
this.Y += shift.Y;
this.Z += shift.Z;
}
/// Writes the as text to the .
/// The writer to which the will be written at the current position.
public void Write(StreamWriter writer)
{
writer.WriteLine("\t\t\t{0}".Interpolate(this.ToString()));
}
/// Writes the as binary to the .
/// The writer to which the will be written at the current position.
public void Write(BinaryWriter writer)
{
writer.Write(this.X);
writer.Write(this.Y);
writer.Write(this.Z);
}
/// Returns the string representation of this .
public override string ToString()
{
//return "vertex {0} {1} {2}".FormatString(this.X, this.Y, this.Z);
return String.Format(CultureInfo.InvariantCulture, "vertex {0} {1} {2}", this.X, this.Y, this.Z);
}
/// Determines whether or not this instance is the same as the instance.
/// The to which to compare.
public bool Equals(Vertex other)
{
return (this.X.Equals(other.X)
&& this.Y.Equals(other.Y)
&& this.Z.Equals(other.Z));
}
/// Reads a single from the .
/// The reader which contains a to be read at the current position
public static Vertex ReadRegex(StreamReader reader)
{
// vertex 5.417830e-001 2.674600e-001 -4.180212e+000
const string regex = @"\s*(facet normal|vertex)\s+(?[^\s]+)\s+(?[^\s]+)\s+(?[^\s]+)";
const NumberStyles numberStyle = (NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign);
string data = null;
float x, y, z;
Match match = null;
if (reader == null)
return null;
//Read the next line of data.
data = reader.ReadLine();
if (data == null)
return null;
//Ensure that the data is formatted correctly.
match = Regex.Match(data, regex, RegexOptions.IgnoreCase);
if (!match.Success)
return null;
//Parse the three coordinates.
if (!float.TryParse(match.Groups["X"].Value, numberStyle, CultureInfo.InvariantCulture, out x))
throw new FormatException("Could not parse X coordinate \"{0}\" as a decimal.".Interpolate(match.Groups["X"]));
if (!float.TryParse(match.Groups["Y"].Value, numberStyle, CultureInfo.InvariantCulture, out y))
throw new FormatException("Could not parse Y coordinate \"{0}\" as a decimal.".Interpolate(match.Groups["Y"]));
if (!float.TryParse(match.Groups["Z"].Value, numberStyle, CultureInfo.InvariantCulture, out z))
throw new FormatException("Could not parse Z coordinate \"{0}\" as a decimal.".Interpolate(match.Groups["Z"]));
return new Vertex()
{
X = x,
Y = y,
Z = z
};
}
/// Reads a single from the .
/// The reader which contains a to be read at the current position
public static Vertex Read(StreamReader reader)
{
// facet normal -1.732201e-002 1.019131e-001 -9.946425e-001
// vertex 5.417830e-001 2.674600e-001 -4.180212e+000
const NumberStyles numberStyle = (NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign);
string data = null;
float x, y, z;
Match match = null;
if (reader == null)
return null;
//Read the next line of data.
data = reader.ReadLine();
if (data == null)
return null;
string[] tmp = data.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
if (tmp.Length > 0 && tmp[0].Length == 8 && tmp[0].ToLower() == "endsolid")
return null;
int start;
if (tmp.Length == 4) start = 1;
else if (tmp.Length == 5) start = 2;
else return null;
//Parse the three coordinates.
if (!float.TryParse(tmp[start + 0], numberStyle, CultureInfo.InvariantCulture, out x))
throw new FormatException("Could not parse X coordinate \"{0}\" as a decimal.".Interpolate(match.Groups["X"]));
if (!float.TryParse(tmp[start + 1], numberStyle, CultureInfo.InvariantCulture, out y))
throw new FormatException("Could not parse Y coordinate \"{0}\" as a decimal.".Interpolate(match.Groups["Y"]));
if (!float.TryParse(tmp[start + 2], numberStyle, CultureInfo.InvariantCulture, out z))
throw new FormatException("Could not parse Z coordinate \"{0}\" as a decimal.".Interpolate(match.Groups["Z"]));
return new Vertex()
{
X = x,
Y = y,
Z = z
};
}
/// Reads a single from the .
/// The reader which contains a to be read at the current position
public static Vertex Read(BinaryReader reader)
{
const int floatSize = sizeof(float);
const int vertexSize = (floatSize * 3);
if (reader == null)
return null;
//Read 3 floats.
byte[] data = new byte[vertexSize];
int bytesRead = reader.Read(data, 0, data.Length);
//If no bytes are read then we're at the end of the stream.
if (bytesRead == 0)
return null;
else if (bytesRead != data.Length)
throw new FormatException("Could not convert the binary data to a vertex. Expected {0} bytes but found {1}.".Interpolate(vertexSize, bytesRead));
//Convert the read bytes to their numeric representation.
return new Vertex()
{
X = BitConverter.ToSingle(data, 0),
Y = BitConverter.ToSingle(data, floatSize),
Z = BitConverter.ToSingle(data, (floatSize * 2))
};
}
}
}