mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-03 00:00:57 +08:00
466 lines
16 KiB
C#
466 lines
16 KiB
C#
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 中间X
|
|
/// </summary>
|
|
internal double _x;
|
|
public double X
|
|
{
|
|
get
|
|
{
|
|
return _x;
|
|
}
|
|
|
|
set
|
|
{
|
|
_x = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 中间Y
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the two PointBase instances are exactly equal, false otherwise
|
|
/// </returns>
|
|
/// <param name='point1'>The first PointBase to compare</param>
|
|
/// <param name='point2'>The second PointBase to compare</param>
|
|
public static bool operator ==(PointBase point1, PointBase point2)
|
|
{
|
|
return point1.X == point2.X &&
|
|
point1.Y == point2.Y;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the two PointBase instances are exactly unequal, false otherwise
|
|
/// </returns>
|
|
/// <param name='point1'>The first PointBase to compare</param>
|
|
/// <param name='point2'>The second PointBase to compare</param>
|
|
public static bool operator !=(PointBase point1, PointBase point2)
|
|
{
|
|
return !(point1 == point2);
|
|
}
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the two PointBase instances are exactly equal, false otherwise
|
|
/// </returns>
|
|
/// <param name='point1'>The first PointBase to compare</param>
|
|
/// <param name='point2'>The second PointBase to compare</param>
|
|
public static bool Equals(PointBase point1, PointBase point2)
|
|
{
|
|
return point1.X.Equals(point2.X) &&
|
|
point1.Y.Equals(point2.Y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the object is an instance of PointBase and if it's equal to "this".
|
|
/// </returns>
|
|
/// <param name='o'>The object to compare to "this"</param>
|
|
public override bool Equals(object o)
|
|
{
|
|
if ((null == o) || !(o is PointBase))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
PointBase value = (PointBase)o;
|
|
return PointBase.Equals(this, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if "value" is equal to "this".
|
|
/// </returns>
|
|
/// <param name='value'>The PointBase to compare to "this"</param>
|
|
public bool Equals(PointBase value)
|
|
{
|
|
return PointBase.Equals(this, value);
|
|
}
|
|
/// <summary>
|
|
/// Returns the HashCode for this PointBase
|
|
/// </summary>
|
|
/// <returns>
|
|
/// int - the HashCode for this PointBase
|
|
/// </returns>
|
|
public override int GetHashCode()
|
|
{
|
|
// Perform field-by-field XOR of HashCodes
|
|
return X.GetHashCode() ^
|
|
Y.GetHashCode();
|
|
}
|
|
|
|
///// <summary>
|
|
///// Parse - returns an instance converted from the provided string using
|
|
///// the culture "en-US"
|
|
///// <param name="source"> string with PointBase data </param>
|
|
///// </summary>
|
|
//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
|
|
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of this object based on the current culture.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
public override string ToString()
|
|
{
|
|
// Delegate to the internal method which implements all ToString calls.
|
|
return ConvertToString(null /* format string */, null /* format provider */);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of this object based on the IFormatProvider
|
|
/// passed in. If the provider is null, the CurrentCulture is used.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
public string ToString(IFormatProvider provider)
|
|
{
|
|
// Delegate to the internal method which implements all ToString calls.
|
|
return ConvertToString(null /* format string */, provider);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
string IFormattable.ToString(string format, IFormatProvider provider)
|
|
{
|
|
// Delegate to the internal method which implements all ToString calls.
|
|
return ConvertToString(format, provider);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Offset - update the location by adding offsetX to X and offsetY to Y
|
|
/// </summary>
|
|
/// <param name="offsetX"> The offset in the x dimension </param>
|
|
/// <param name="offsetY"> The offset in the y dimension </param>
|
|
public void Offset(double offsetX, double offsetY)
|
|
{
|
|
_x += offsetX;
|
|
_y += offsetY;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Operator PointBase + Vector
|
|
/// </summary>
|
|
/// <returns>
|
|
/// PointBase - The result of the addition
|
|
/// </returns>
|
|
/// <param name="point"> The PointBase to be added to the Vector </param>
|
|
/// <param name="vector"> The Vectr to be added to the PointBase </param>
|
|
public static PointBase operator +(PointBase point, VectorBase vector)
|
|
{
|
|
return new PointBase(point._x + vector._x, point._y + vector._y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add: PointBase + Vector
|
|
/// </summary>
|
|
/// <returns>
|
|
/// PointBase - The result of the addition
|
|
/// </returns>
|
|
/// <param name="point"> The PointBase to be added to the Vector </param>
|
|
/// <param name="vector"> The Vector to be added to the PointBase </param>
|
|
public static PointBase Add(PointBase point, VectorBase vector)
|
|
{
|
|
return new PointBase(point._x + vector._x, point._y + vector._y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Operator PointBase - Vector
|
|
/// </summary>
|
|
/// <returns>
|
|
/// PointBase - The result of the subtraction
|
|
/// </returns>
|
|
/// <param name="point"> The PointBase from which the Vector is subtracted </param>
|
|
/// <param name="vector"> The Vector which is subtracted from the PointBase </param>
|
|
public static PointBase operator -(PointBase point, VectorBase vector)
|
|
{
|
|
return new PointBase(point._x - vector._x, point._y - vector._y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Subtract: PointBase - Vector
|
|
/// </summary>
|
|
/// <returns>
|
|
/// PointBase - The result of the subtraction
|
|
/// </returns>
|
|
/// <param name="point"> The PointBase from which the Vector is subtracted </param>
|
|
/// <param name="vector"> The Vector which is subtracted from the PointBase </param>
|
|
public static PointBase Subtract(PointBase point, VectorBase vector)
|
|
{
|
|
return new PointBase(point._x - vector._x, point._y - vector._y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Operator PointBase - PointBase
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Vector - The result of the subtraction
|
|
/// </returns>
|
|
/// <param name="point1"> The PointBase from which point2 is subtracted </param>
|
|
/// <param name="point2"> The PointBase subtracted from point1 </param>
|
|
public static VectorBase operator -(PointBase point1, PointBase point2)
|
|
{
|
|
return new VectorBase(point1._x - point2._x, point1._y - point2._y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Subtract: PointBase - PointBase
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Vector - The result of the subtraction
|
|
/// </returns>
|
|
/// <param name="point1"> The PointBase from which point2 is subtracted </param>
|
|
/// <param name="point2"> The PointBase subtracted from point1 </param>
|
|
public static VectorBase Subtract(PointBase point1, PointBase point2)
|
|
{
|
|
return new VectorBase(point1._x - point2._x, point1._y - point2._y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Operator PointBase * Matrix
|
|
/// </summary>
|
|
//public static PointBase operator *(PointBase point, Matrix matrix)
|
|
//{
|
|
// return matrix.Transform(point);
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Multiply: PointBase * Matrix
|
|
/// </summary>
|
|
//public static PointBase Multiply(PointBase point, Matrix matrix)
|
|
//{
|
|
// return matrix.Transform(point);
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Explicit conversion to Size. Note that since Size cannot contain negative values,
|
|
/// the resulting size will contains the absolute values of X and Y
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Size - A Size equal to this PointBase
|
|
/// </returns>
|
|
/// <param name="point"> PointBase - the PointBase to convert to a Size </param>
|
|
public static explicit operator SizeBase(PointBase point)
|
|
{
|
|
return new SizeBase(Math.Abs(point._x), Math.Abs(point._y));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Explicit conversion to Vector
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Vector - A Vector equal to this PointBase
|
|
/// </returns>
|
|
/// <param name="point"> PointBase - the PointBase to convert to a Vector </param>
|
|
public static explicit operator VectorBase(PointBase point)
|
|
{
|
|
return new VectorBase(point._x, point._y);
|
|
}
|
|
|
|
#endregion Public Methods
|
|
}
|
|
} |