using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
namespace AIStudio.Wpf.DiagramDesigner.Geometrys
{
[Serializable]
public struct PointBase : IFormattable
{
public static PointBase Zero { get; } = new PointBase(0, 0);
public PointBase(double x, double y)
{
_x = x;
_y = y;
}
///
/// 中间X
///
internal double _x;
public double X
{
get
{
return _x;
}
set
{
_x = value;
}
}
///
/// 中间Y
///
internal double _y;
public double Y
{
get
{
return _y;
}
set
{
_y = value;
}
}
public double Dot(PointBase other) => X * other.X + Y * other.Y;
public PointBase Lerp(PointBase other, double t)
=> new PointBase(X * (1.0 - t) + other.X * t, Y * (1.0 - t) + other.Y * t);
// Maybe just make Points mutable?
public PointBase Add(double value) => new PointBase(X + value, Y + value);
public PointBase Add(double x, double y) => new PointBase(X + x, Y + y);
public PointBase Substract(double value) => new PointBase(X - value, Y - value);
public PointBase Substract(double x, double y) => new PointBase(X - x, Y - y);
public double DistanceTo(PointBase other)
=> Math.Sqrt(Math.Pow(X - other.X, 2) + Math.Pow(Y - other.Y, 2));
public void Deconstruct(out double x, out double y)
{
x = X;
y = Y;
}
//public static PointBase operator -(PointBase a, PointBase b)
//{
// return new PointBase(a.X - b.X, a.Y - b.Y);
//}
//public static PointBase operator +(PointBase a, PointBase b)
//{
// return new PointBase(a.X + b.X, a.Y + b.Y);
//}
public static implicit operator PointBase(Point point)
{
return new PointBase(point.X, point.Y);
}
public static implicit operator Point(PointBase pointInfoBase)
{
return new Point(pointInfoBase.X, pointInfoBase.Y);
}
//public override string ToString() => $"PointBase(x={X}, y={Y})";
#region Statics
///
/// Empty - a static property which provides an Empty rectangle. X and Y are positive-infinity
/// and Width and Height are negative infinity. This is the only situation where Width or
/// Height can be negative.
///
public static PointBase Empty
{
get
{
return s_empty;
}
}
#endregion Statics
#region Private Methods
static private PointBase CreateEmptyRect()
{
PointBase point = new PointBase();
// We can't set these via the property setters because negatives widths
// are rejected in those APIs.
point._x = Double.PositiveInfinity;
point._y = Double.PositiveInfinity;
return point;
}
#endregion Private Methods
#region Private Fields
private readonly static PointBase s_empty = CreateEmptyRect();
#endregion Private Fields
#region Public Methods
///
/// Compares two PointBase instances for exact equality.
/// Note that double values can acquire error when operated upon, such that
/// an exact comparison between two values which are logically equal may fail.
/// Furthermore, using this equality operator, Double.NaN is not equal to itself.
///
///
/// bool - true if the two PointBase instances are exactly equal, false otherwise
///
/// The first PointBase to compare
/// The second PointBase to compare
public static bool operator ==(PointBase point1, PointBase point2)
{
return point1.X == point2.X &&
point1.Y == point2.Y;
}
///
/// Compares two PointBase instances for exact inequality.
/// Note that double values can acquire error when operated upon, such that
/// an exact comparison between two values which are logically equal may fail.
/// Furthermore, using this equality operator, Double.NaN is not equal to itself.
///
///
/// bool - true if the two PointBase instances are exactly unequal, false otherwise
///
/// The first PointBase to compare
/// The second PointBase to compare
public static bool operator !=(PointBase point1, PointBase point2)
{
return !(point1 == point2);
}
///
/// Compares two PointBase instances for object equality. In this equality
/// Double.NaN is equal to itself, unlike in numeric equality.
/// Note that double values can acquire error when operated upon, such that
/// an exact comparison between two values which
/// are logically equal may fail.
///
///
/// bool - true if the two PointBase instances are exactly equal, false otherwise
///
/// The first PointBase to compare
/// The second PointBase to compare
public static bool Equals(PointBase point1, PointBase point2)
{
return point1.X.Equals(point2.X) &&
point1.Y.Equals(point2.Y);
}
///
/// Equals - compares this PointBase with the passed in object. In this equality
/// Double.NaN is equal to itself, unlike in numeric equality.
/// Note that double values can acquire error when operated upon, such that
/// an exact comparison between two values which
/// are logically equal may fail.
///
///
/// bool - true if the object is an instance of PointBase and if it's equal to "this".
///
/// The object to compare to "this"
public override bool Equals(object o)
{
if ((null == o) || !(o is PointBase))
{
return false;
}
PointBase value = (PointBase)o;
return PointBase.Equals(this, value);
}
///
/// Equals - compares this PointBase with the passed in object. In this equality
/// Double.NaN is equal to itself, unlike in numeric equality.
/// Note that double values can acquire error when operated upon, such that
/// an exact comparison between two values which
/// are logically equal may fail.
///
///
/// bool - true if "value" is equal to "this".
///
/// The PointBase to compare to "this"
public bool Equals(PointBase value)
{
return PointBase.Equals(this, value);
}
///
/// Returns the HashCode for this PointBase
///
///
/// int - the HashCode for this PointBase
///
public override int GetHashCode()
{
// Perform field-by-field XOR of HashCodes
return X.GetHashCode() ^
Y.GetHashCode();
}
/////
///// Parse - returns an instance converted from the provided string using
///// the culture "en-US"
///// string with PointBase data
/////
//public static PointBase Parse(string source)
//{
// IFormatProvider formatProvider = System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS;
// TokenizerHelper th = new TokenizerHelper(source, formatProvider);
// PointBase value;
// String firstToken = th.NextTokenRequired();
// value = new PointBase(
// Convert.ToDouble(firstToken, formatProvider),
// Convert.ToDouble(th.NextTokenRequired(), formatProvider));
// // There should be no more tokens in this string.
// th.LastTokenRequired();
// return value;
//}
#endregion Public Methods
#region Internal Properties
///
/// Creates a string representation of this object based on the current culture.
///
///
/// A string representation of this object.
///
public override string ToString()
{
// Delegate to the internal method which implements all ToString calls.
return ConvertToString(null /* format string */, null /* format provider */);
}
///
/// Creates a string representation of this object based on the IFormatProvider
/// passed in. If the provider is null, the CurrentCulture is used.
///
///
/// A string representation of this object.
///
public string ToString(IFormatProvider provider)
{
// Delegate to the internal method which implements all ToString calls.
return ConvertToString(null /* format string */, provider);
}
///
/// Creates a string representation of this object based on the format string
/// and IFormatProvider passed in.
/// If the provider is null, the CurrentCulture is used.
/// See the documentation for IFormattable for more information.
///
///
/// A string representation of this object.
///
string IFormattable.ToString(string format, IFormatProvider provider)
{
// Delegate to the internal method which implements all ToString calls.
return ConvertToString(format, provider);
}
///
/// Creates a string representation of this object based on the format string
/// and IFormatProvider passed in.
/// If the provider is null, the CurrentCulture is used.
/// See the documentation for IFormattable for more information.
///
///
/// A string representation of this object.
///
internal string ConvertToString(string format, IFormatProvider provider)
{
// Helper to get the numeric list separator for a given culture.
char separator = ',';
return String.Format(provider,
"{1:" + format + "}{0}{2:" + format + "}",
separator,
_x,
_y);
}
#endregion Internal Properties
#region Public Methods
///
/// Offset - update the location by adding offsetX to X and offsetY to Y
///
/// The offset in the x dimension
/// The offset in the y dimension
public void Offset(double offsetX, double offsetY)
{
_x += offsetX;
_y += offsetY;
}
///
/// Operator PointBase + Vector
///
///
/// PointBase - The result of the addition
///
/// The PointBase to be added to the Vector
/// The Vectr to be added to the PointBase
public static PointBase operator +(PointBase point, VectorBase vector)
{
return new PointBase(point._x + vector._x, point._y + vector._y);
}
///
/// Add: PointBase + Vector
///
///
/// PointBase - The result of the addition
///
/// The PointBase to be added to the Vector
/// The Vector to be added to the PointBase
public static PointBase Add(PointBase point, VectorBase vector)
{
return new PointBase(point._x + vector._x, point._y + vector._y);
}
///
/// Operator PointBase - Vector
///
///
/// PointBase - The result of the subtraction
///
/// The PointBase from which the Vector is subtracted
/// The Vector which is subtracted from the PointBase
public static PointBase operator -(PointBase point, VectorBase vector)
{
return new PointBase(point._x - vector._x, point._y - vector._y);
}
///
/// Subtract: PointBase - Vector
///
///
/// PointBase - The result of the subtraction
///
/// The PointBase from which the Vector is subtracted
/// The Vector which is subtracted from the PointBase
public static PointBase Subtract(PointBase point, VectorBase vector)
{
return new PointBase(point._x - vector._x, point._y - vector._y);
}
///
/// Operator PointBase - PointBase
///
///
/// Vector - The result of the subtraction
///
/// The PointBase from which point2 is subtracted
/// The PointBase subtracted from point1
public static VectorBase operator -(PointBase point1, PointBase point2)
{
return new VectorBase(point1._x - point2._x, point1._y - point2._y);
}
///
/// Subtract: PointBase - PointBase
///
///
/// Vector - The result of the subtraction
///
/// The PointBase from which point2 is subtracted
/// The PointBase subtracted from point1
public static VectorBase Subtract(PointBase point1, PointBase point2)
{
return new VectorBase(point1._x - point2._x, point1._y - point2._y);
}
///
/// Operator PointBase * Matrix
///
//public static PointBase operator *(PointBase point, Matrix matrix)
//{
// return matrix.Transform(point);
//}
///
/// Multiply: PointBase * Matrix
///
//public static PointBase Multiply(PointBase point, Matrix matrix)
//{
// return matrix.Transform(point);
//}
///
/// Explicit conversion to Size. Note that since Size cannot contain negative values,
/// the resulting size will contains the absolute values of X and Y
///
///
/// Size - A Size equal to this PointBase
///
/// PointBase - the PointBase to convert to a Size
public static explicit operator SizeBase(PointBase point)
{
return new SizeBase(Math.Abs(point._x), Math.Abs(point._y));
}
///
/// Explicit conversion to Vector
///
///
/// Vector - A Vector equal to this PointBase
///
/// PointBase - the PointBase to convert to a Vector
public static explicit operator VectorBase(PointBase point)
{
return new VectorBase(point._x, point._y);
}
#endregion Public Methods
}
}