before candybox editor update

This commit is contained in:
meelstorm
2025-09-16 10:42:43 +02:00
parent e5746ef766
commit dc12b3e51a
103 changed files with 96379 additions and 343 deletions

View File

@@ -0,0 +1,120 @@
namespace CandyboxPlugin.Geometry
{
public class DefaultRectangle2Algorithm
{
public List<IntPoint> FindRectangle2(List<IntPoint> hullPoints)
{
//check if no bounding box available
if (hullPoints.Count <= 1)
return hullPoints;
Rectangle2d minBox = null;
var minAngle = 0d;
//foreach edge of the convex hull
for (var i = 0; i < hullPoints.Count; i++)
{
var nextIndex = i + 1;
var current = hullPoints[i];
var next = hullPoints[nextIndex % hullPoints.Count];
//min / max points
var top = double.MinValue;
var bottom = double.MaxValue;
var left = double.MaxValue;
var right = double.MinValue;
//get angle of segment to x axis
var angle = AngleToXAxis(current,next);
//rotate every point and get min and max values for each direction
foreach (var p in hullPoints)
{
var rotatedPoint = RotateToXAxis(p, angle);
top = Math.Max(top, rotatedPoint.Y);
bottom = Math.Min(bottom, rotatedPoint.Y);
left = Math.Min(left, rotatedPoint.X);
right = Math.Max(right, rotatedPoint.X);
}
//create axis aligned bounding box
var box = new Rectangle2d(new IntPoint((int)left, (int)bottom), new IntPoint((int)right, (int)top));
if (minBox == null || minBox.Area() > box.Area())
{
minBox = box;
minAngle = angle;
}
}
//rotate axis algined box back
var minimalBoundingBox = minBox.Points.Select(p => RotateToXAxis(p, -minAngle)).ToList();
return minimalBoundingBox;
}
/// <summary>
/// Calculates the angle to the X axis.
/// </summary>
/// <returns>The angle to the X axis.</returns>
/// <param name="s">The segment to get the angle from.</param>
static double AngleToXAxis(IntPoint a, IntPoint b)
{
var delta = a-b;
return -Math.Atan((float)delta.Y / (float)delta.X);
}
/// <summary>
/// Rotates vector by an angle to the x-Axis
/// </summary>
/// <returns>Rotated vector.</returns>
/// <param name="v">Vector to rotate.</param>
/// <param name="angle">Angle to trun by.</param>
static IntPoint RotateToXAxis(IntPoint v, double angle)
{
var newX = v.X * Math.Cos(angle) - v.Y * Math.Sin(angle);
var newY = v.X * Math.Sin(angle) + v.Y * Math.Cos(angle);
return new IntPoint((int)newX, (int)newY);
}
}
public class Rectangle2d
{
public IntPoint Location { get; set; }
public IntPoint Size { get; set; }
public Rectangle2d()
{
}
public Rectangle2d(IntPoint a, IntPoint c) : this()
{
Location = a;
Size = c - a;
}
public double Area()
{
return Size.X * Size.Y;
}
public IntPoint[] Points
{
get
{
return new[] {
new IntPoint (Location.X, Location.Y),
new IntPoint (Location.X + Size.X, Location.Y),
new IntPoint (Location.X + Size.X, Location.Y + Size.Y),
new IntPoint (Location.X, Location.Y + Size.Y)
};
}
}
}
}

View File

@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using CandyboxPlugin.Geometry;
namespace Inspectron.Hawkeye.Vision.Geometry
{
public class GrahamConvexHull
{
/// <summary>
/// Find convex hull for the given set of points.
/// </summary>
///
/// <param name="points">Set of points to search convex hull for.</param>
///
/// <returns>Returns set of points, which form a convex hull for the given <paramref name="points"/>.
/// The first point in the list is the point with lowest X coordinate (and with lowest Y if there are
/// several points with the same X value). Points are provided in counter clockwise order
/// (<a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian
/// coordinate system</a>).</returns>
///
public List<IntPoint> FindHull(List<IntPoint> points)
{
// do nothing if there 3 points or less
if (points.Count <= 3)
{
return new List<IntPoint>(points);
}
// find a point, with lowest X and lowest Y
int firstCornerIndex = 0;
IntPoint pointFirstCorner = points[0];
for (int i = 1, n = points.Count; i < n; i++)
{
if ((points[i].X < pointFirstCorner.X) ||
((points[i].X == pointFirstCorner.X) && (points[i].Y < pointFirstCorner.Y)))
{
pointFirstCorner = points[i];
firstCornerIndex = i;
}
}
// convert input points to points we can process
PointToProcess firstCorner = new PointToProcess(pointFirstCorner);
// Points to process must exclude the first corner that we've already found
PointToProcess[] arrPointsToProcess = new PointToProcess[points.Count - 1];
for (int i = 0; i < points.Count - 1; i++)
{
IntPoint point = points[i >= firstCornerIndex ? i + 1 : i];
arrPointsToProcess[i] = new PointToProcess(point);
}
// find K (tangent of line's angle) and distance to the first corner
for (int i = 0, n = arrPointsToProcess.Length; i < n; i++)
{
int dx = arrPointsToProcess[i].X - firstCorner.X;
int dy = arrPointsToProcess[i].Y - firstCorner.Y;
// don't need square root, since it is not important in our case
arrPointsToProcess[i].Distance = dx * dx + dy * dy;
// tangent of lines angle
arrPointsToProcess[i].K = (dx == 0) ? float.PositiveInfinity : (float)dy / dx;
}
// sort points by angle and distance
Array.Sort(arrPointsToProcess);
// Convert points to process to a queue. Continually removing the first item of an array list
// is highly inefficient
Queue<PointToProcess> queuePointsToProcess = new Queue<PointToProcess>(arrPointsToProcess);
LinkedList<PointToProcess> convexHullTemp = new LinkedList<PointToProcess>();
// add first corner, which is always on the hull
PointToProcess prevPoint = convexHullTemp.AddLast(firstCorner).Value;
// add another point, which forms a line with lowest slope
PointToProcess lastPoint = convexHullTemp.AddLast(queuePointsToProcess.Dequeue()).Value;
while (queuePointsToProcess.Count != 0)
{
PointToProcess newPoint = queuePointsToProcess.Peek();
// skip any point, which has the same slope as the last one or
// has 0 distance to the first point
if ((newPoint.K == lastPoint.K) || (newPoint.Distance == 0))
{
queuePointsToProcess.Dequeue();
continue;
}
// check if current point is on the left side from two last points
if ((newPoint.X - prevPoint.X) * (lastPoint.Y - newPoint.Y) - (lastPoint.X - newPoint.X) * (newPoint.Y - prevPoint.Y) < 0)
{
// add the point to the hull
convexHullTemp.AddLast(newPoint);
// and remove it from the list of points to process
queuePointsToProcess.Dequeue();
prevPoint = lastPoint;
lastPoint = newPoint;
}
else
{
// remove the last point from the hull
convexHullTemp.RemoveLast();
lastPoint = prevPoint;
prevPoint = convexHullTemp.Last.Previous.Value;
}
}
// convert points back
List<IntPoint> convexHull = new List<IntPoint>();
foreach (PointToProcess pt in convexHullTemp)
{
convexHull.Add(pt.ToPoint());
}
return convexHull;
}
// Internal comparer for sorting points
private class PointToProcess : IComparable
{
public int X;
public int Y;
public float K;
public float Distance;
public PointToProcess(IntPoint point)
{
X = point.X;
Y = point.Y;
K = 0;
Distance = 0;
}
public int CompareTo(object obj)
{
PointToProcess another = (PointToProcess)obj;
return (K < another.K) ? -1 : (K > another.K) ? 1 :
((Distance > another.Distance) ? -1 : (Distance < another.Distance) ? 1 : 0);
}
public IntPoint ToPoint()
{
return new IntPoint(X, Y);
}
}
}
}

View File

@@ -0,0 +1,378 @@
// AForge Core Library
// AForge.NET framework
// http://www.aforgenet.com/framework/
//
// Copyright © AForge.NET, 2007-2011
// contacts@aforgenet.com
//
namespace CandyboxPlugin.Geometry
{
/// <summary>
/// Structure for representing a pair of coordinates of integer type.
/// </summary>
///
/// <remarks><para>The structure is used to store a pair of integer coordinates.</para>
///
/// <para>Sample usage:</para>
/// <code>
/// // assigning coordinates in the constructor
/// IntPoint p1 = new IntPoint( 10, 20 );
/// // creating a point and assigning coordinates later
/// IntPoint p2;
/// p2.X = 30;
/// p2.Y = 40;
/// // calculating distance between two points
/// float distance = p1.DistanceTo( p2 );
/// </code>
/// </remarks>
///
[Serializable]
public struct IntPoint : IComparable<IntPoint>
{
/// <summary>
/// X coordinate.
/// </summary>
///
public int X;
/// <summary>
/// Y coordinate.
/// </summary>
///
public int Y;
/// <summary>
/// Initializes a new instance of the <see cref="IntPoint"/> structure.
/// </summary>
///
/// <param name="x">X axis coordinate.</param>
/// <param name="y">Y axis coordinate.</param>
///
public IntPoint(int x, int y)
{
this.X = x;
this.Y = y;
}
/// <summary>
/// Calculate Euclidean distance between two points.
/// </summary>
///
/// <param name="anotherPoint">Point to calculate distance to.</param>
///
/// <returns>Returns Euclidean distance between this point and
/// <paramref name="anotherPoint"/> points.</returns>
///
public float DistanceTo(IntPoint anotherPoint)
{
int dx = X - anotherPoint.X;
int dy = Y - anotherPoint.Y;
return (float)System.Math.Sqrt(dx * dx + dy * dy);
}
/// <summary>
/// Calculate squared Euclidean distance between two points.
/// </summary>
///
/// <param name="anotherPoint">Point to calculate distance to.</param>
///
/// <returns>Returns squared Euclidean distance between this point and
/// <paramref name="anotherPoint"/> points.</returns>
///
public float SquaredDistanceTo(Point anotherPoint)
{
float dx = X - anotherPoint.X;
float dy = Y - anotherPoint.Y;
return dx * dx + dy * dy;
}
/// <summary>
/// Addition operator - adds values of two points.
/// </summary>
///
/// <param name="point1">First point for addition.</param>
/// <param name="point2">Second point for addition.</param>
///
/// <returns>Returns new point which coordinates equal to sum of corresponding
/// coordinates of specified points.</returns>
///
public static IntPoint operator +(IntPoint point1, IntPoint point2)
{
return new IntPoint(point1.X + point2.X, point1.Y + point2.Y);
}
/// <summary>
/// Addition operator - adds values of two points.
/// </summary>
///
/// <param name="point1">First point for addition.</param>
/// <param name="point2">Second point for addition.</param>
///
/// <returns>Returns new point which coordinates equal to sum of corresponding
/// coordinates of specified points.</returns>
///
public static IntPoint Add(IntPoint point1, IntPoint point2)
{
return new IntPoint(point1.X + point2.X, point1.Y + point2.Y);
}
/// <summary>
/// Subtraction operator - subtracts values of two points.
/// </summary>
///
/// <param name="point1">Point to subtract from.</param>
/// <param name="point2">Point to subtract.</param>
///
/// <returns>Returns new point which coordinates equal to difference of corresponding
/// coordinates of specified points.</returns>
///
public static IntPoint operator -(IntPoint point1, IntPoint point2)
{
return new IntPoint(point1.X - point2.X, point1.Y - point2.Y);
}
/// <summary>
/// Subtraction operator - subtracts values of two points.
/// </summary>
///
/// <param name="point1">Point to subtract from.</param>
/// <param name="point2">Point to subtract.</param>
///
/// <returns>Returns new point which coordinates equal to difference of corresponding
/// coordinates of specified points.</returns>
///
public static IntPoint Subtract(IntPoint point1, IntPoint point2)
{
return new IntPoint(point1.X - point2.X, point1.Y - point2.Y);
}
/// <summary>
/// Addition operator - adds scalar to the specified point.
/// </summary>
///
/// <param name="point">Point to increase coordinates of.</param>
/// <param name="valueToAdd">Value to add to coordinates of the specified point.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point increased by specified value.</returns>
///
public static IntPoint operator +(IntPoint point, int valueToAdd)
{
return new IntPoint(point.X + valueToAdd, point.Y + valueToAdd);
}
/// <summary>
/// Addition operator - adds scalar to the specified point.
/// </summary>
///
/// <param name="point">Point to increase coordinates of.</param>
/// <param name="valueToAdd">Value to add to coordinates of the specified point.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point increased by specified value.</returns>
///
public static IntPoint Add(IntPoint point, int valueToAdd)
{
return new IntPoint(point.X + valueToAdd, point.Y + valueToAdd);
}
/// <summary>
/// Subtraction operator - subtracts scalar from the specified point.
/// </summary>
///
/// <param name="point">Point to decrease coordinates of.</param>
/// <param name="valueToSubtract">Value to subtract from coordinates of the specified point.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point decreased by specified value.</returns>
///
public static IntPoint operator -(IntPoint point, int valueToSubtract)
{
return new IntPoint(point.X - valueToSubtract, point.Y - valueToSubtract);
}
/// <summary>
/// Subtraction operator - subtracts scalar from the specified point.
/// </summary>
///
/// <param name="point">Point to decrease coordinates of.</param>
/// <param name="valueToSubtract">Value to subtract from coordinates of the specified point.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point decreased by specified value.</returns>
///
public static IntPoint Subtract(IntPoint point, int valueToSubtract)
{
return new IntPoint(point.X - valueToSubtract, point.Y - valueToSubtract);
}
/// <summary>
/// Multiplication operator - multiplies coordinates of the specified point by scalar value.
/// </summary>
///
/// <param name="point">Point to multiply coordinates of.</param>
/// <param name="factor">Multiplication factor.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point multiplied by specified value.</returns>
///
public static IntPoint operator *(IntPoint point, int factor)
{
return new IntPoint(point.X * factor, point.Y * factor);
}
/// <summary>
/// Multiplication operator - multiplies coordinates of the specified point by scalar value.
/// </summary>
///
/// <param name="point">Point to multiply coordinates of.</param>
/// <param name="factor">Multiplication factor.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point multiplied by specified value.</returns>
///
public static IntPoint Multiply(IntPoint point, int factor)
{
return new IntPoint(point.X * factor, point.Y * factor);
}
/// <summary>
/// Division operator - divides coordinates of the specified point by scalar value.
/// </summary>
///
/// <param name="point">Point to divide coordinates of.</param>
/// <param name="factor">Division factor.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point divided by specified value.</returns>
///
public static IntPoint operator /(IntPoint point, int factor)
{
return new IntPoint(point.X / factor, point.Y / factor);
}
/// <summary>
/// Division operator - divides coordinates of the specified point by scalar value.
/// </summary>
///
/// <param name="point">Point to divide coordinates of.</param>
/// <param name="factor">Division factor.</param>
///
/// <returns>Returns new point which coordinates equal to coordinates of
/// the specified point divided by specified value.</returns>
///
public static IntPoint Divide(IntPoint point, int factor)
{
return new IntPoint(point.X / factor, point.Y / factor);
}
/// <summary>
/// Equality operator - checks if two points have equal coordinates.
/// </summary>
///
/// <param name="point1">First point to check.</param>
/// <param name="point2">Second point to check.</param>
///
/// <returns>Returns <see langword="true"/> if coordinates of specified
/// points are equal.</returns>
///
public static bool operator ==(IntPoint point1, IntPoint point2)
{
return ((point1.X == point2.X) && (point1.Y == point2.Y));
}
/// <summary>
/// Inequality operator - checks if two points have different coordinates.
/// </summary>
///
/// <param name="point1">First point to check.</param>
/// <param name="point2">Second point to check.</param>
///
/// <returns>Returns <see langword="true"/> if coordinates of specified
/// points are not equal.</returns>
///
public static bool operator !=(IntPoint point1, IntPoint point2)
{
return ((point1.X != point2.X) || (point1.Y != point2.Y));
}
/// <summary>
/// Check if this instance of <see cref="IntPoint"/> equal to the specified one.
/// </summary>
///
/// <param name="obj">Another point to check equalty to.</param>
///
/// <returns>Return <see langword="true"/> if objects are equal.</returns>
///
public override bool Equals(object obj)
{
return (obj is IntPoint) ? (this == (IntPoint)obj) : false;
}
/// <summary>
/// Get hash code for this instance.
/// </summary>
///
/// <returns>Returns the hash code for this instance.</returns>
///
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode();
}
/// <summary>
/// Implicit conversion to <see cref="Point"/>.
/// </summary>
///
/// <param name="point">Integer point to convert to single precision point.</param>
///
/// <returns>Returns new single precision point which coordinates are implicitly converted
/// to floats from coordinates of the specified integer point.</returns>
///
public static implicit operator Point(IntPoint point)
{
return new Point(point.X, point.Y);
}
/// <summary>
/// Get string representation of the class.
/// </summary>
///
/// <returns>Returns string, which contains values of the point in readable form.</returns>
///
public override string ToString()
{
return string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}, {1}", X, Y);
}
/// <summary>
/// Calculate Euclidean norm of the vector comprised of the point's
/// coordinates - distance from (0, 0) in other words.
/// </summary>
///
/// <returns>Returns point's distance from (0, 0) point.</returns>
///
public float EuclideanNorm()
{
return (float)System.Math.Sqrt(X * X + Y * Y);
}
/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary>
/// <param name="other">An object to compare with this instance.</param>
/// <returns>A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="other" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="other" />. Greater than zero This instance follows <paramref name="other" /> in the sort order.</returns>
public int CompareTo(IntPoint other)
{
int line = this.Y.CompareTo(other.Y);
if (line == 0)
return this.X.CompareTo(other.X);
return line;
}
}
}