From df8745eaf4d196b95fc5e2c3809edbeb17265f77 Mon Sep 17 00:00:00 2001 From: whats2000 Date: Fri, 30 Aug 2024 17:58:33 +0800 Subject: [PATCH] Update: Update PearlCalculatorLib.PearlCalculationLib to latest version --- .../GeneralFTL_General.razor.cs | 2 +- Components/ResultView.razor.cs | 2 +- PearlCalculatorLib/General/Calculation.cs | 277 +++++++++--------- PearlCalculatorLib/General/Data.cs | 5 +- .../PearlCalculationLib/AABB/AABBBox.cs | 84 ++++++ .../PearlCalculationLib/Entity/Entity.cs | 44 ++- .../PearlCalculationLib/Entity/PearlEntity.cs | 41 +-- .../PearlCalculationLib/Entity/TNTEntity.cs | 7 +- .../PearlCalculationLib/IDeepCloneable.cs | 12 + .../PearlCalculationLib/MathLib/MathHelper.cs | 12 +- .../Result/TNTCalculationResult.cs | 9 +- .../TNTCalculationResultSortComparer.cs | 28 +- ...CalculationResultSortComparerByWeighted.cs | 14 +- .../Result/TNTResultSortByWeightedArgs.cs | 6 +- .../PearlCalculationLib/World/Chunk.cs | 35 +-- .../PearlCalculationLib/World/Direction.cs | 37 ++- .../PearlCalculationLib/World/Space3D.cs | 178 +++++------ .../PearlCalculationLib/World/Surface2D.cs | 84 +++--- SettingsJsonConverter.cs | 2 +- 19 files changed, 501 insertions(+), 378 deletions(-) create mode 100644 PearlCalculatorLib/PearlCalculationLib/AABB/AABBBox.cs create mode 100644 PearlCalculatorLib/PearlCalculationLib/IDeepCloneable.cs diff --git a/Components/GeneralFTLComponents/GeneralFTL_General.razor.cs b/Components/GeneralFTLComponents/GeneralFTL_General.razor.cs index 2bb1b26..c494f3e 100644 --- a/Components/GeneralFTLComponents/GeneralFTL_General.razor.cs +++ b/Components/GeneralFTLComponents/GeneralFTL_General.razor.cs @@ -91,7 +91,7 @@ protected override void OnInitialized() { EventManager.Instance.AddListener("tntAmountSetRTCount", (sender, args) => { - Direction = Data.Pearl.Position.Direction(Data.Pearl.Position.WorldAngle(Data.Destination)); + Direction = DirectionUtils.GetDirection(Data.Pearl.Position.WorldAngle(Data.Destination)); RedTNT = (uint)args.Red; BlueTNT = (uint)args.Blue; StateHasChanged(); diff --git a/Components/ResultView.razor.cs b/Components/ResultView.razor.cs index 1868b32..77e4189 100644 --- a/Components/ResultView.razor.cs +++ b/Components/ResultView.razor.cs @@ -46,7 +46,7 @@ public static void ShowDirectionResult(Space3D pearlPos, Space3D destination) if (angle == 370) return; - ResultDirection = pearlPos.Direction(angle).ToString(); + ResultDirection = DirectionUtils.GetDirection(angle).ToString(); ResultAngle = angle.ToString(); } diff --git a/PearlCalculatorLib/General/Calculation.cs b/PearlCalculatorLib/General/Calculation.cs index b6f22a8..6e03820 100644 --- a/PearlCalculatorLib/General/Calculation.cs +++ b/PearlCalculatorLib/General/Calculation.cs @@ -1,28 +1,27 @@ -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using PearlCalculatorLib.Result; +using PearlCalculatorLib.Result; using PearlCalculatorLib.PearlCalculationLib; +using PearlCalculatorLib.PearlCalculationLib.Entity; using PearlCalculatorLib.PearlCalculationLib.World; using System; using System.Collections.Generic; -using System.Linq; using System.Collections; -using System.Net.NetworkInformation; -using System.Runtime.CompilerServices; -using System.Text; -using System.Xml.Serialization; -using PearlCalculatorLib.PearlCalculationLib.Entity; namespace PearlCalculatorLib.General { public static class Calculation { - private static PearlEntity PearlSimulation(int redTNT , int blueTNT , int ticks , Direction direction) + private static PearlEntity PearlSimulation(int redTNT, int blueTNT, int ticks, Direction direction) { + //Simulating the pearl and return the end point PearlEntity pearlEntity = new PearlEntity(Data.Pearl); - CalculateTNTVector(direction , out Space3D redTNTVector , out Space3D blueTNTVector); + + CalculateTNTVector(direction, out Space3D redTNTVector, out Space3D blueTNTVector); + pearlEntity.Motion = redTNT * redTNTVector + blueTNT * blueTNTVector; - for(int i = 0; i < ticks; i++) + + for (int i = 0; i < ticks; i++) pearlEntity.Tick(); + return pearlEntity; } @@ -36,54 +35,77 @@ private static PearlEntity PearlSimulation(int redTNT , int blueTNT , int ticks /// Returns a true or false value indicates whether the calculation is correctly executed or not /// TNT combination result will be stored into /// - public static bool CalculateTNTAmount(int maxTicks , double maxDistance) + public static bool CalculateTNTAmount(int maxTicks, double maxDistance) { - int redTNT; - int blueTNT; - Space3D distance; - double divider = 0; + int redTNT, blueTNT; + double trueRed, trueBlue; Direction direction; - distance = Data.Destination - Data.Pearl.Position; - if(Math.Abs(distance.X) == 0 && Math.Abs(distance.Z) == 0) + Space3D trueDistance, truePosition; + + double divider = 0; + + truePosition = Data.Pearl.Position + Data.PearlOffset.ToSpace3D(); + trueDistance = Data.Destination - truePosition; + + //trueDistance with zero in X and Z axis triggers DevidedByZeroEception + if (trueDistance.ToSurface2D() == 0) return false; + Data.TNTResult.Clear(); - direction = Data.Pearl.Position.Direction(Data.Pearl.Position.WorldAngle(Data.Destination)); - CalculateTNTVector(direction , out Space3D redTNTVector , out Space3D blueTNTVector); - for(int tick = 1; tick <= maxTicks; tick++) + direction = DirectionUtils.GetDirection(truePosition.WorldAngle(Data.Destination)); + CalculateTNTVector(direction, out Space3D redTNTVector, out Space3D blueTNTVector); + + //Calculate redTNT and blueTNT through simultaneous equations + trueRed = (trueDistance.Z * blueTNTVector.X - trueDistance.X * blueTNTVector.Z) / (redTNTVector.Z * blueTNTVector.X - blueTNTVector.Z * redTNTVector.X); + trueBlue = (trueDistance.X - trueRed * redTNTVector.X) / blueTNTVector.X; + + for (int tick = 1; tick <= maxTicks; tick++) { - divider += Math.Pow(0.99 , tick - 1); - distance = (Data.Destination - Data.Pearl.Position) / divider; - redTNT = Convert.ToInt32(Math.Round((distance.Z * blueTNTVector.X - distance.X * blueTNTVector.Z) / (redTNTVector.Z * blueTNTVector.X - blueTNTVector.Z * redTNTVector.X))); - blueTNT = Convert.ToInt32(Math.Round((distance.X - redTNT * redTNTVector.X) / blueTNTVector.X)); - for(int r = -5; r <= 5; r++) + //Factorization trueDistance to make a easier calculation + divider += Math.Pow(0.99, tick - 1); + + redTNT = Convert.ToInt32(trueRed / divider); + blueTNT = Convert.ToInt32(trueBlue / divider); + + //Run through the loops to get a better result around the redTNT and blueTNT + //It is not perfect dude to the round up + for (int r = -5; r <= 5; r++) { - for(int b = -5; b <= 5; b++) + for (int b = -5; b <= 5; b++) { - PearlEntity pearlEntity = PearlSimulation(redTNT + r , blueTNT + b , tick , direction); - if(Math.Abs(pearlEntity.Position.X - Data.Destination.X) <= maxDistance && Math.Abs(pearlEntity.Position.Z - Data.Destination.Z) <= maxDistance) + //Simulate the pearl and get it's end point + PearlEntity pearlEntity = PearlSimulation(redTNT + r, blueTNT + b, tick, direction); + + //Only the pearl with a difference smaller than 5 will pass the check + if ((pearlEntity.Position - Data.Destination).ToSurface2D().Absolute() <= maxDistance) { + TNTCalculationResult result = new TNTCalculationResult { - Distance = pearlEntity.Position.Distance2D(Data.Destination) , - Tick = tick , - Blue = blueTNT + b , - Red = redTNT + r , - TotalTNT = blueTNT + b + redTNT + r , + Distance = pearlEntity.Position.Distance2D(Data.Destination), + Tick = tick, + Blue = blueTNT + b, + Red = redTNT + r, + TotalTNT = blueTNT + b + redTNT + r, Pearl = pearlEntity }; - if(Data.MaxTNT <= 0) - Data.TNTResult.Add(result); - else if((blueTNT + b) <= Data.MaxTNT && (redTNT + r) <= Data.MaxTNT) + + //Bypass MaxTNT check if it is set to 0 + //If MaxTNT is greater than 0 , only add those result which is lesser than MaxTNT + //If both redTNT and blueTNT are not greater or equal to zero , ignore them + if ((Data.MaxTNT <= 0 || (result.Blue <= Data.MaxTNT && result.Red <= Data.MaxTNT)) && result.Blue >= 0 && result.Red >= 0) Data.TNTResult.Add(result); - if(Data.MaxCalculateTNT < result.TotalTNT) + + if (Data.MaxCalculateTNT < result.TotalTNT) Data.MaxCalculateTNT = result.TotalTNT; - if(Data.MaxCalculateDistance < result.Distance) + + if (Data.MaxCalculateDistance < result.Distance) Data.MaxCalculateDistance = result.Distance; } } } } - Data.TNTResult = Data.TNTResult.Where(result => result.Blue >= 0 && result.Red >= 0).ToList(); + return true; } @@ -97,18 +119,21 @@ public static bool CalculateTNTAmount(int maxTicks , double maxDistance) /// The Maximum Tick the Ender Pearl Allowed to travel /// The accelerating Direction of the Ender Pearl. Only Allow North, South, East, West /// Return A List of Entity contains the Motion and Position in each Ticks - public static List CalculatePearlTrace(int redTNT , int blueTNT , int ticks , Direction direction) + public static List CalculatePearlTrace(int redTNT, int blueTNT, int ticks, Direction direction) { - List result = new List(); - PearlEntity pearl = new PearlEntity(Data.Pearl); - CalculateTNTVector(direction , out Space3D redTNTVector , out Space3D blueTNTVector); - pearl.Motion = redTNT * redTNTVector + blueTNT * blueTNTVector + Data.Pearl.Motion; + List result = new List(ticks + 1); + PearlEntity pearl = new PearlEntity(Data.Pearl.AddPosition(Data.PearlOffset)); + + CalculateTNTVector(direction, out Space3D redTNTVector, out Space3D blueTNTVector); + pearl.Motion += redTNT * redTNTVector + blueTNT * blueTNTVector; result.Add(new PearlEntity(pearl)); - for(int i = 0; i < ticks; i++) + + for (int i = 0; i < ticks; i++) { pearl.Tick(); result.Add(new PearlEntity(pearl)); } + return result; } @@ -119,45 +144,53 @@ public static List CalculatePearlTrace(int redTNT , int blueTNT , int ti /// The amount of blue TNT /// Output the TNT combination /// Returns a true or false value indicates whether the calculation is correctly executed or not - public static bool CalculateTNTConfiguration(int redTNT , int blueTNT , out BitArray tntCombination) + public static bool CalculateTNTConfiguration(int redTNT, int blueTNT, out BitArray tntCombination) { int indexCount = Data.RedTNTConfiguration.Count + Data.BlueTNTConfiguration.Count; tntCombination = new BitArray(indexCount); - if(Data.RedTNTConfiguration.Count == 0 && Data.BlueTNTConfiguration.Count == 0) + + //How can i sort it if i don't know anything about the configuration + if (Data.RedTNTConfiguration.Count == 0 && Data.BlueTNTConfiguration.Count == 0) return false; - int red = redTNT; - int blue = blueTNT; + BitArray redBitArray = new BitArray(indexCount); BitArray blueBitArray = new BitArray(indexCount); - List sortedRedConfig = Data.RedTNTConfiguration; - List sortedBlueConfig = Data.BlueTNTConfiguration; - sortedRedConfig.Sort(); - sortedRedConfig.Reverse(); - sortedBlueConfig.Sort(); - sortedBlueConfig.Reverse(); - for(int i = 0; i < sortedRedConfig.Count; i++) + List sortedRedConfig = new List(Data.RedTNTConfiguration); + List sortedBlueConfig = new List(Data.BlueTNTConfiguration); + + //Sorts the list from large to small + sortedRedConfig.Sort((a, b) => a >= b ? (a == b ? 0 : -1) : 1); + sortedBlueConfig.Sort((a, b) => a >= b ? (a == b ? 0 : -1) : 1); + + for (int i = 0; i < sortedRedConfig.Count; i++) { - if(red >= sortedRedConfig[i]) + if (redTNT >= sortedRedConfig[i]) { - red -= sortedRedConfig[i]; - redBitArray.Set(Data.RedTNTConfiguration.FindIndex(x => x == sortedRedConfig[i]) , true); + redTNT -= sortedRedConfig[i]; + //Sets the corresponding bit to true according to the Data.RedTNTConfiguration + redBitArray.Set(Data.RedTNTConfiguration.FindIndex(x => x == sortedRedConfig[i]), true); } else - redBitArray.Set(Data.RedTNTConfiguration.FindIndex(x => x == sortedRedConfig[i]) , false); + redBitArray.Set(Data.RedTNTConfiguration.FindIndex(x => x == sortedRedConfig[i]), false); } - for(int i = 0; i < sortedBlueConfig.Count; i++) + + for (int i = 0; i < sortedBlueConfig.Count; i++) { - if(blue >= sortedBlueConfig[i]) + if (blueTNT >= sortedBlueConfig[i]) { - blue -= sortedBlueConfig[i]; - blueBitArray.Set(Data.BlueTNTConfiguration.FindIndex(x => x == sortedBlueConfig[i]) , true); + blueTNT -= sortedBlueConfig[i]; + //Sets the corresponding bit to true according to the Data.BlueTNTConfiguration + blueBitArray.Set(Data.BlueTNTConfiguration.FindIndex(x => x == sortedBlueConfig[i]), true); } else - blueBitArray.Set(Data.BlueTNTConfiguration.FindIndex(x => x == sortedBlueConfig[i]) , false); + blueBitArray.Set(Data.BlueTNTConfiguration.FindIndex(x => x == sortedBlueConfig[i]), false); } + + //Combine those result into tntCombination tntCombination.Or(redBitArray); blueBitArray.LeftShift(Data.RedTNTConfiguration.Count); tntCombination.Or(blueBitArray); + return true; } @@ -167,91 +200,55 @@ public static bool CalculateTNTConfiguration(int redTNT , int blueTNT , out BitA /// The Acceleration Direction of the Ender Pearl /// Return am accelerating vector of Red TNT /// Return an accelerating vector of Blue TNT - public static void CalculateTNTVector(Direction direction , out Space3D redTNTVector , out Space3D blueTNTVector) + public static void CalculateTNTVector(Direction direction, out Space3D redTNTVector, out Space3D blueTNTVector) { - Space3D aVector; - Space3D bVector; - redTNTVector = new Space3D(0 , 0 , 0); - blueTNTVector = new Space3D(0 , 0 , 0); Space3D pearlPosition = Data.PearlOffset.ToSpace3D(); + + redTNTVector = blueTNTVector = Space3D.Zero; pearlPosition.Y = Data.Pearl.Position.Y; - if(direction.IsSouth()) - { - aVector = VectorCalculation.CalculateMotion(pearlPosition , Data.NorthEastTNT); - bVector = VectorCalculation.CalculateMotion(pearlPosition , Data.NorthWestTNT); - if(Data.DefaultBlueDuper.IsNorth()) - { - blueTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultBlueDuper)); - redTNTVector = aVector + bVector - blueTNTVector; - } - else if(Data.DefaultRedDuper.IsNorth()) - { - redTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultBlueDuper)); - blueTNTVector = aVector + bVector - redTNTVector; - } - } - else if(direction.IsNorth()) - { - aVector = VectorCalculation.CalculateMotion(pearlPosition , Data.SouthEastTNT); - bVector = VectorCalculation.CalculateMotion(pearlPosition , Data.SouthWestTNT); - if(Data.DefaultBlueDuper.IsSouth()) - { - blueTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultBlueDuper)); - redTNTVector = aVector + bVector - blueTNTVector; - } - else if(Data.DefaultRedDuper.IsSouth()) - { - redTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultRedDuper)); - blueTNTVector = aVector + bVector - redTNTVector; - } - } - else if(direction.IsEast()) + + if ((Data.DefaultBlueDuper | Data.DefaultRedDuper) != (Direction.NorthEast | Direction.SouthWest)) + throw new ArgumentException("Wrong value in Data.DefaultBlueDuper and Data,DefaultRedDuper"); + + if ((direction & Data.DefaultBlueDuper) == 0) { - aVector = VectorCalculation.CalculateMotion(pearlPosition , Data.SouthWestTNT); - bVector = VectorCalculation.CalculateMotion(pearlPosition , Data.NorthWestTNT); - if(Data.DefaultBlueDuper.IsWest()) - { - blueTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultBlueDuper)); - redTNTVector = aVector + bVector - blueTNTVector; - } - else if(Data.DefaultRedDuper.IsWest()) - { - redTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultRedDuper)); - blueTNTVector = aVector + bVector - redTNTVector; - } + //There is always a TNT that is already stand by + //In this case, it is blue. + blueTNTVector = VectorCalculation.CalculateMotion(pearlPosition, TNTDirectionToCoordinate(Data.DefaultBlueDuper)); + redTNTVector = VectorCalculation.CalculateMotion + ( + pearlPosition, + TNTDirectionToCoordinate + ( + // 0b1111 = Direction.NorthEast | Direction.SouthWest + (Direction)(((int)~(direction | Data.DefaultBlueDuper) & 0b1111) | (int)direction.Invert()) + ) + ); } - else if(direction.IsWest()) + else { - aVector = VectorCalculation.CalculateMotion(pearlPosition , Data.SouthEastTNT); - bVector = VectorCalculation.CalculateMotion(pearlPosition , Data.NorthEastTNT); - if(Data.DefaultBlueDuper.IsEast()) - { - blueTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultBlueDuper)); - redTNTVector = aVector + bVector - blueTNTVector; - } - else if(Data.DefaultRedDuper.IsEast()) - { - redTNTVector = VectorCalculation.CalculateMotion(pearlPosition , TNTDirectionToCoordinate(Data.DefaultRedDuper)); - blueTNTVector = aVector + bVector - redTNTVector; - } + redTNTVector = VectorCalculation.CalculateMotion(pearlPosition, TNTDirectionToCoordinate(Data.DefaultRedDuper)); + blueTNTVector = VectorCalculation.CalculateMotion + ( + pearlPosition, + TNTDirectionToCoordinate + ( + (Direction)(((int)~(direction | Data.DefaultRedDuper) & 0b1111) | (int)direction.Invert()) + ) + ); } - else - throw new ArgumentException(); } private static Space3D TNTDirectionToCoordinate(Direction coner) { - Space3D tntCoordinate = new Space3D(0 , 0 , 0); - - if(coner == Direction.NorthEast) - tntCoordinate = Data.NorthEastTNT; - else if(coner == Direction.NorthWest) - tntCoordinate = Data.NorthWestTNT; - else if(coner == Direction.SouthEast) - tntCoordinate = Data.SouthEastTNT; - else if(coner == Direction.SouthWest) - tntCoordinate = Data.SouthWestTNT; - return tntCoordinate; + return coner switch + { + Direction.NorthEast => Data.NorthEastTNT, + Direction.NorthWest => Data.NorthWestTNT, + Direction.SouthEast => Data.SouthEastTNT, + Direction.SouthWest => Data.SouthWestTNT, + _ => Space3D.Zero + }; } } } diff --git a/PearlCalculatorLib/General/Data.cs b/PearlCalculatorLib/General/Data.cs index e66ea35..6b916a8 100644 --- a/PearlCalculatorLib/General/Data.cs +++ b/PearlCalculatorLib/General/Data.cs @@ -1,8 +1,5 @@ using System.Collections.Generic; -using System.Text; -using PearlCalculatorLib.PearlCalculationLib.MathLib; using PearlCalculatorLib.Result; -using PearlCalculatorLib.PearlCalculationLib; using PearlCalculatorLib.PearlCalculationLib.World; using PearlCalculatorLib.PearlCalculationLib.Entity; @@ -54,7 +51,7 @@ public static class Data /// Note : X and Z should be the gobal coordinate of the lava pool center /// Required for All Calculation in /// - public static PearlEntity Pearl = new PearlEntity().WithPosition(0 , 170.34722638929412, 0).WithVector(0 , 0.2716278719434352 , 0); + public static PearlEntity Pearl = new PearlEntity().WithPosition(0 , 170.34722638929412, 0).WithMotion(0 , 0.2716278719434352 , 0); diff --git a/PearlCalculatorLib/PearlCalculationLib/AABB/AABBBox.cs b/PearlCalculatorLib/PearlCalculationLib/AABB/AABBBox.cs new file mode 100644 index 0000000..82f560c --- /dev/null +++ b/PearlCalculatorLib/PearlCalculationLib/AABB/AABBBox.cs @@ -0,0 +1,84 @@ +using System; +using PearlCalculatorLib.PearlCalculationLib.MathLib; +using PearlCalculatorLib.PearlCalculationLib.World; + +namespace PearlCalculatorLib.PearlCalculationLib.AABB +{ + [Serializable] + public class AABBBox : IEquatable + { + public Space3D Min; + public Space3D Max; + + public Space3D Extents => Max - Min; + + public Space3D Center => (Min + Max) * 0.5; + + public AABBBox() + { + + } + + public AABBBox(double x2 , double y2 , double z2) + { + Min = Space3D.Zero; + Max = new Space3D(x2 , y2 , z2); + } + + public AABBBox(double x1 , double y1 , double z1 , double x2 , double y2 , double z2) + { + Min = new Space3D(x1 , y1 , z1); + Max = new Space3D(x2 , y2 , z2); + } + + public AABBBox(Space3D min , Space3D max) + { + Min = min; + Max = max; + } + + public AABBBox(Space3D max) : this(Space3D.Zero , max) { } + + public AABBBox ReSize(Space3D min , Space3D max) + { + Min = min; + Max = max; + return this; + } + + public bool Contains(Space3D point) + { + return MathHelper.IsInside(Min.X , Max.X , point.X) && + MathHelper.IsInside(Min.Y , Max.Y , point.Y) && + MathHelper.IsInside(Min.Z , Max.Z , point.Z); + } + + public bool Intersects(AABBBox bounds) + { + return Equals(bounds) || ( + Max.X >= bounds.Min.X && + Max.Y >= bounds.Min.Y && + Max.Z >= bounds.Min.Z && + Min.X <= bounds.Max.X && + Min.Y <= bounds.Max.Y && + Min.Z <= bounds.Max.Z); + } + + public override bool Equals(object obj) => obj is AABBBox s && Equals(s); + + public bool Equals(AABBBox other) + { + if(other is null) + return false; + if(ReferenceEquals(this , other)) + return true; + return Min == other.Min && Max == other.Max; + } + + public static bool operator ==(AABBBox left , AABBBox right) => left is { } && left.Equals(right); + + public static bool operator !=(AABBBox left , AABBBox right) => left is { } && !left.Equals(right); + + public override int GetHashCode() => Min.GetHashCode() ^ Max.GetHashCode(); + } +} diff --git a/PearlCalculatorLib/PearlCalculationLib/Entity/Entity.cs b/PearlCalculatorLib/PearlCalculationLib/Entity/Entity.cs index 646de9c..f23a4e9 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Entity/Entity.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Entity/Entity.cs @@ -1,8 +1,6 @@ -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using PearlCalculatorLib.PearlCalculationLib.World; +using PearlCalculatorLib.PearlCalculationLib.World; +using PearlCalculatorLib.PearlCalculationLib.AABB; using System; -using System.Collections.Generic; -using System.Text; namespace PearlCalculatorLib.PearlCalculationLib.Entity { @@ -11,9 +9,45 @@ public abstract class Entity { public Space3D Motion; public Space3D Position; + private AABBBox _aabb = new AABBBox(); + + public abstract void Tick(); public abstract Space3D Size { get; } - public abstract void Tick(); + public virtual AABBBox AABB => _aabb.ReSize(Position, Position + Size); + } + + public static class EntityExtension + { + public static T WithPosition(this T entity, double x, double y, double z) where T : Entity + { + entity.Position = new Space3D(x, y, z); + return entity; + } + + public static T WithMotion(this T entity, double x, double y, double z) where T : Entity + { + entity.Motion = new Space3D(x, y, z); + return entity; + } + + public static T AddPosition(this T entity, Space3D postion) where T : Entity + { + entity.Position += postion; + return entity; + } + + public static T AddPosition(this T entity, Surface2D postion) where T : Entity + { + entity.Position += postion.ToSpace3D(); + return entity; + } + + public static T AddMotion(this T entity, Space3D motion) where T : Entity + { + entity.Motion += motion; + return entity; + } } } diff --git a/PearlCalculatorLib/PearlCalculationLib/Entity/PearlEntity.cs b/PearlCalculatorLib/PearlCalculationLib/Entity/PearlEntity.cs index 22f8fbd..8d850cc 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Entity/PearlEntity.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Entity/PearlEntity.cs @@ -1,43 +1,26 @@ -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using PearlCalculatorLib.PearlCalculationLib.World; +using PearlCalculatorLib.PearlCalculationLib.World; using System; -using System.Collections.Generic; -using System.Text; namespace PearlCalculatorLib.PearlCalculationLib.Entity { [Serializable] - public class PearlEntity : Entity, ICloneable + public class PearlEntity : Entity, IDeepCloneable { - public override Space3D Size => new Space3D(0.25 , 0.25 , 0.25); + public override Space3D Size => new Space3D(0.25, 0.25, 0.25); - - - public PearlEntity(Space3D momemtum , Space3D position) + public PearlEntity(Space3D momemtum, Space3D position) { Motion = momemtum; Position = position; } - public PearlEntity(PearlEntity pearl) : this(pearl.Motion , pearl.Position) { } + public PearlEntity(PearlEntity pearl) : this(pearl.Motion, pearl.Position) { } public PearlEntity() { } - public PearlEntity WithPosition(double x , double y , double z) - { - Position = new Space3D(x , y , z); - return this; - } - - public PearlEntity WithVector(double x , double y , double z) - { - Motion = new Space3D(x , y , z); - return this; - } - public override void Tick() { Position += Motion; @@ -45,14 +28,12 @@ public override void Tick() Motion.Y -= 0.03; } - public object Clone() + public PearlEntity DeepClone() => new PearlEntity { - PearlEntity pearl = new PearlEntity - { - Position = Position , - Motion = Motion - }; - return pearl; - } + Position = Position, + Motion = Motion + }; + + object IDeepCloneable.DeepClone() => DeepClone(); } } diff --git a/PearlCalculatorLib/PearlCalculationLib/Entity/TNTEntity.cs b/PearlCalculatorLib/PearlCalculationLib/Entity/TNTEntity.cs index 0268210..ee2c48d 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Entity/TNTEntity.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Entity/TNTEntity.cs @@ -1,15 +1,12 @@ -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using PearlCalculatorLib.PearlCalculationLib.World; +using PearlCalculatorLib.PearlCalculationLib.World; using System; -using System.Collections.Generic; -using System.Text; namespace PearlCalculatorLib.PearlCalculationLib.Entity { [Serializable] public class TNTEntity : Entity { - public override Space3D Size => new Space3D(0.98 , 0.98 , 0.98); + public override Space3D Size => new Space3D(0.98, 0.98, 0.98); public override void Tick() => throw new NotImplementedException(); } diff --git a/PearlCalculatorLib/PearlCalculationLib/IDeepCloneable.cs b/PearlCalculatorLib/PearlCalculationLib/IDeepCloneable.cs new file mode 100644 index 0000000..dfbf17a --- /dev/null +++ b/PearlCalculatorLib/PearlCalculationLib/IDeepCloneable.cs @@ -0,0 +1,12 @@ +namespace PearlCalculatorLib.PearlCalculationLib +{ + public interface IDeepCloneable + { + object DeepClone(); + } + + public interface IDeepCloneable : IDeepCloneable + { + new T DeepClone(); + } +} diff --git a/PearlCalculatorLib/PearlCalculationLib/MathLib/MathHelper.cs b/PearlCalculatorLib/PearlCalculationLib/MathLib/MathHelper.cs index 9ece5d5..bfb3128 100644 --- a/PearlCalculatorLib/PearlCalculationLib/MathLib/MathHelper.cs +++ b/PearlCalculatorLib/PearlCalculationLib/MathLib/MathHelper.cs @@ -1,11 +1,11 @@ using System; -using System.Collections.Generic; -using System.Numerics; -using System.Security.Cryptography.X509Certificates; -using System.Text; namespace PearlCalculatorLib.PearlCalculationLib.MathLib { + /// + /// Ask Mojang for it's weird API + /// I have No clue about it + /// public static class MathHelper { public static float Sqrt(double value) => (float)Math.Sqrt(value); @@ -14,9 +14,9 @@ public static class MathHelper public static double RadiantToDegree(double radiant) => radiant * 180 / Math.PI; - public static bool IsInside(double border1 , double border2 , double num) + public static bool IsInside(double border1, double border2, double num) { - return num <= Math.Max(border1 , border2) && num >= Math.Min(border1 , border2); + return num <= Math.Max(border1, border2) && num >= Math.Min(border1, border2); } } } diff --git a/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResult.cs b/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResult.cs index f82790a..7eb1c99 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResult.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResult.cs @@ -1,9 +1,5 @@ using PearlCalculatorLib.PearlCalculationLib.Entity; -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using PearlCalculatorLib.PearlCalculationLib.World; -using System; using System.Collections.Generic; -using System.Text; namespace PearlCalculatorLib.Result { @@ -21,7 +17,7 @@ public struct TNTCalculationResult public static class TNTCalculationResultExtension { - public static void SortByWeightedDistance(this List results , TNTResultSortByWeightedArgs args) + public static void SortByWeightedDistance(this List results, TNTResultSortByWeightedArgs args) { results.Sort(new TNTCalculationResultSortComparerByWeighted(args).ByDistance); } @@ -41,10 +37,9 @@ public static void SortByTotal(this List results) results.Sort(TNTCalculationResultSortComparer.ByTotal); } - public static void SortByWeightedTotal(this List results , TNTResultSortByWeightedArgs args) + public static void SortByWeightedTotal(this List results, TNTResultSortByWeightedArgs args) { results.Sort(new TNTCalculationResultSortComparerByWeighted(args).ByTotal); } - } } diff --git a/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparer.cs b/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparer.cs index a1fdfe1..e3be241 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparer.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparer.cs @@ -1,34 +1,30 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace PearlCalculatorLib.Result +namespace PearlCalculatorLib.Result { static class TNTCalculationResultSortComparer { - public static int ByTick(TNTCalculationResult r1 , TNTCalculationResult r2) + public static int ByTick(TNTCalculationResult r1, TNTCalculationResult r2) { - if(r1.Tick < r2.Tick) + if (r1.Tick < r2.Tick) return -1; - else if(r1.Tick > r2.Tick) + else if (r1.Tick > r2.Tick) return 1; - return ByDefault(r1 , r2); + return ByDefault(r1, r2); } - public static int ByTotal(TNTCalculationResult r1 , TNTCalculationResult r2) + public static int ByTotal(TNTCalculationResult r1, TNTCalculationResult r2) { - if(r1.TotalTNT < r2.TotalTNT) + if (r1.TotalTNT < r2.TotalTNT) return -1; - else if(r1.TotalTNT > r2.TotalTNT) + else if (r1.TotalTNT > r2.TotalTNT) return 1; - return ByDefault(r1 , r2); + return ByDefault(r1, r2); } - public static int ByDefault(TNTCalculationResult r1 , TNTCalculationResult r2) + public static int ByDefault(TNTCalculationResult r1, TNTCalculationResult r2) { - if(r1.Distance < r2.Distance) + if (r1.Distance < r2.Distance) return -1; - else if(r1.Distance > r2.Distance) + else if (r1.Distance > r2.Distance) return 1; return 0; } diff --git a/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparerByWeighted.cs b/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparerByWeighted.cs index 64157b3..7ad2b84 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparerByWeighted.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Result/TNTCalculationResultSortComparerByWeighted.cs @@ -9,7 +9,7 @@ public TNTCalculationResultSortComparerByWeighted(TNTResultSortByWeightedArgs ar this.args = args; } - public int ByDistance(TNTCalculationResult r1 , TNTCalculationResult r2) + public int ByDistance(TNTCalculationResult r1, TNTCalculationResult r2) { double r1Ranking; double r2Ranking; @@ -17,22 +17,22 @@ public int ByDistance(TNTCalculationResult r1 , TNTCalculationResult r2) r1Ranking = r1.Distance * (101 - args.TNTWeight) / (args.MaxCalculateDistance) - (r1.TotalTNT * (args.TNTWeight + 1) * 80 / args.MaxCalculateTNT); r2Ranking = r2.Distance * (101 - args.TNTWeight) / (args.MaxCalculateDistance) - (r2.TotalTNT * (args.TNTWeight + 1) * 80 / args.MaxCalculateTNT); - if(r1Ranking < r2Ranking) + if (r1Ranking < r2Ranking) return -1; - else if(r1Ranking > r2Ranking) + else if (r1Ranking > r2Ranking) return 1; return 0; } - public int ByTotal(TNTCalculationResult r1 , TNTCalculationResult r2) + public int ByTotal(TNTCalculationResult r1, TNTCalculationResult r2) { double r1Ranking = r1.TotalTNT * (args.TNTWeight + 1) - r1.TotalTNT * (101 - args.TNTWeight); double r2Ranking = r2.TotalTNT * (args.TNTWeight + 1) - r2.TotalTNT * (101 - args.TNTWeight); - if(r1Ranking < r2Ranking) + if (r1Ranking > r2Ranking) return -1; - else if(r1Ranking > r2Ranking) + else if (r1Ranking < r2Ranking) return 1; - return TNTCalculationResultSortComparer.ByDefault(r1 , r2); + return TNTCalculationResultSortComparer.ByDefault(r1, r2); } } } diff --git a/PearlCalculatorLib/PearlCalculationLib/Result/TNTResultSortByWeightedArgs.cs b/PearlCalculatorLib/PearlCalculationLib/Result/TNTResultSortByWeightedArgs.cs index c34bd01..25a0dcf 100644 --- a/PearlCalculatorLib/PearlCalculationLib/Result/TNTResultSortByWeightedArgs.cs +++ b/PearlCalculatorLib/PearlCalculationLib/Result/TNTResultSortByWeightedArgs.cs @@ -6,9 +6,11 @@ public class TNTResultSortByWeightedArgs public readonly int MaxCalculateTNT; public readonly double MaxCalculateDistance; - public TNTResultSortByWeightedArgs(int tntWeight , int maxCalculateTNT , double maxCalculateDistance) + public TNTResultSortByWeightedArgs(int tntWeight, int maxCalculateTNT, double maxCalculateDistance) { - (this.TNTWeight, this.MaxCalculateTNT, this.MaxCalculateDistance) = (tntWeight, maxCalculateTNT, maxCalculateDistance); + this.TNTWeight = tntWeight; + this.MaxCalculateTNT = maxCalculateTNT == 0 ? 1 : maxCalculateTNT; + this.MaxCalculateDistance = maxCalculateDistance == 0 ? 1 : maxCalculateDistance; } } } diff --git a/PearlCalculatorLib/PearlCalculationLib/World/Chunk.cs b/PearlCalculatorLib/PearlCalculationLib/World/Chunk.cs index a67efec..6d33b55 100644 --- a/PearlCalculatorLib/PearlCalculationLib/World/Chunk.cs +++ b/PearlCalculatorLib/PearlCalculationLib/World/Chunk.cs @@ -1,23 +1,16 @@ -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using System; -using System.Collections.Generic; -using System.Text; - -namespace PearlCalculatorLib.PearlCalculationLib.World +namespace PearlCalculatorLib.PearlCalculationLib.World { public class Chunk { public int X; public int Z; - - public Chunk() { } - public Chunk(int x , int z) + public Chunk(int x, int z) { X = x; Z = z; @@ -29,37 +22,37 @@ public Chunk(Chunk chunk) Z = chunk.Z; } - public Space3D ToSpace3D() => new Space3D(16 * X , 0 , 16 * Z); + public Space3D ToSpace3D() => new Space3D(16 * X, 0, 16 * Z); - public Surface2D ToSurface2D() => new Surface2D(16 * X , 16 * Z); + public Surface2D ToSurface2D() => new Surface2D(16 * X, 16 * Z); - public static Chunk operator +(Chunk @this , Chunk other) => new Chunk() + public static Chunk operator +(Chunk @this, Chunk other) => new Chunk() { - X = @this.X + other.X , + X = @this.X + other.X, Z = @this.Z + other.Z }; - public static Chunk operator -(Chunk @this , Chunk other) => new Chunk() + public static Chunk operator -(Chunk @this, Chunk other) => new Chunk() { - X = @this.X - other.X , + X = @this.X - other.X, Z = @this.Z - other.Z }; - public static Chunk operator *(Chunk @this , int mutiplier) => new Chunk() + public static Chunk operator *(Chunk @this, int mutiplier) => new Chunk() { - X = @this.X * mutiplier , + X = @this.X * mutiplier, Z = @this.Z * mutiplier }; - public static Chunk operator *(int mutiplier , Chunk @this) => new Chunk() + public static Chunk operator *(int mutiplier, Chunk @this) => new Chunk() { - X = @this.X * mutiplier , + X = @this.X * mutiplier, Z = @this.Z * mutiplier }; - public static Chunk operator /(Chunk @this , int mutiplier) => new Chunk() + public static Chunk operator /(Chunk @this, int mutiplier) => new Chunk() { - X = @this.X / mutiplier , + X = @this.X / mutiplier, Z = @this.Z / mutiplier }; } diff --git a/PearlCalculatorLib/PearlCalculationLib/World/Direction.cs b/PearlCalculatorLib/PearlCalculationLib/World/Direction.cs index b12a202..3685985 100644 --- a/PearlCalculatorLib/PearlCalculationLib/World/Direction.cs +++ b/PearlCalculatorLib/PearlCalculationLib/World/Direction.cs @@ -1,10 +1,4 @@ using System; -using System.Collections.Generic; -using System.Diagnostics.Tracing; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using System.Threading; namespace PearlCalculatorLib.PearlCalculationLib.World { @@ -33,15 +27,26 @@ public static class DirectionExtension public static bool IsWest(this Direction direction) => (direction & Direction.West) > 0; + public static Direction Invert(this Direction direction) + { + int result = 0; + + if (((int)direction & 0b0011) > 0) + result = ~(int)direction & 0b0011; + if (((int)direction & 0b1100) > 0) + result |= ~(int)direction & 0b1100; + + return (Direction)result; + } } public static class DirectionUtils { - public static Direction FormName(string name) => Enum.TryParse(name , out var value) ? value : Direction.None; + public static Direction FormName(string name) => Enum.TryParse(name, out var value) ? value : Direction.None; - public static bool TryParse(string s , out Direction result) + public static bool TryParse(string s, out Direction result) { - switch(s) + switch (s) { case "N": case "North": @@ -83,7 +88,21 @@ public static bool TryParse(string s , out Direction result) result = Direction.None; return false; } + } + + public static Direction GetDirection(double angle) + { + Direction direction = Direction.None; + if (angle > -135 && angle <= -45) + direction = Direction.East; + else if (angle > -45 && angle <= 45) + direction = Direction.South; + else if (angle > 45 && angle <= 135) + direction = Direction.West; + else if ((angle > 135 && angle <= 180) || (angle > -180 && angle <= -135)) + direction = Direction.North; + return direction; } } } diff --git a/PearlCalculatorLib/PearlCalculationLib/World/Space3D.cs b/PearlCalculatorLib/PearlCalculationLib/World/Space3D.cs index c3349ea..2c748b6 100644 --- a/PearlCalculatorLib/PearlCalculationLib/World/Space3D.cs +++ b/PearlCalculatorLib/PearlCalculationLib/World/Space3D.cs @@ -1,70 +1,59 @@ -using PearlCalculatorLib.General; -using PearlCalculatorLib.PearlCalculationLib; -using PearlCalculatorLib.PearlCalculationLib.MathLib; -using PearlCalculatorLib.PearlCalculationLib.World; +using PearlCalculatorLib.PearlCalculationLib.MathLib; using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Xml.Serialization; namespace PearlCalculatorLib.PearlCalculationLib.World { [Serializable] public struct Space3D : IEquatable { - public static readonly Space3D zero = new Space3D(); - public static readonly Space3D one = new Space3D(1 , 1 , 1); + public static readonly Space3D Zero = new Space3D(); + public static readonly Space3D One = new Space3D(1, 1, 1); public double X; public double Y; public double Z; - - - public Space3D(double x , double y , double z) + public Space3D(double x, double y, double z) { X = x; Y = y; Z = z; } - public Space3D(Space3D space3D) : this(space3D.X , space3D.Y , space3D.Z) { } + public Space3D(Space3D space3D) : this(space3D.X, space3D.Y, space3D.Z) { } - public override string ToString() => $"Coordinate : {X} , {Y} , {Z}"; + public override string ToString() => $"{X} , {Y} , {Z}"; public double WorldAngle(Space3D position2) { Space3D distance = new Space3D { - X = position2.X - X , + X = position2.X - X, Z = position2.Z - Z }; - if(distance.X == 0 && distance.Z == 0) + if (distance.X == 0 && distance.Z == 0) return 370; - if(distance.X > 0) + if (distance.X > 0) { - if(distance.Z > 0) + if (distance.Z > 0) return -(Math.Atan(distance.X / distance.Z) * 180 / Math.PI); - else if(distance.Z == 0) + else if (distance.Z == 0) return -90; else return -(180 - Math.Atan(-distance.X / distance.Z) * 180 / Math.PI); } - else if(distance.X < 0) + else if (distance.X < 0) { - if(distance.Z > 0) + if (distance.Z > 0) return Math.Atan(-distance.X / distance.Z) * 180 / Math.PI; - else if(distance.Z == 0) + else if (distance.Z == 0) return 90; else return 180 - Math.Atan(distance.X / distance.Z) * 180 / Math.PI; } else { - if(distance.Z > 0) + if (distance.Z > 0) return 0; else return 180; @@ -72,22 +61,7 @@ public double WorldAngle(Space3D position2) throw new ArgumentOutOfRangeException(); } - public Direction Direction(double angle) - { - Direction direction = World.Direction.None; - - if(angle > -135 && angle <= -45) - direction = World.Direction.East; - else if(angle > -45 && angle <= 45) - direction = World.Direction.South; - else if(angle > 45 && angle <= 135) - direction = World.Direction.West; - else if((angle > 135 && angle <= 180) || (angle > -180 && angle <= -135)) - direction = World.Direction.North; - return direction; - } - - public double Distance2D(Space3D position2) => Math.Sqrt(Math.Pow(position2.X - X , 2) + Math.Pow(position2.Z - Z , 2)); + public double Distance2D(Space3D position2) => Math.Sqrt(Math.Pow(position2.X - X, 2) + Math.Pow(position2.Z - Z, 2)); public double DistanceSq() => X * X + Y * Y + Z * Z; @@ -100,8 +74,9 @@ public double Distance(Space3D other) return Math.Sqrt(dis3.DistanceSq()); } + public Space3D Absolute() => new Space3D(Math.Abs(X), Math.Abs(Y), Math.Abs(Z)); - public Surface2D ToSurface2D() => new Surface2D(X , Z); + public Surface2D ToSurface2D() => new Surface2D(X, Z); public bool IsNorth(Space3D position2) => position2.X > X; @@ -117,122 +92,147 @@ public double Distance(Space3D other) public double AngleInRad(Space3D position2) => Math.Atan((position2.Z - Z) / (position2.X - X)); + public double AngleInAbsPolarRad(Space3D position2) + { + double angle = Math.Atan2(position2.Z - Z, position2.X - X); + return angle < 0 ? angle + Math.PI * 2 : angle; + } + + public double AngleInPolarRad(Space3D position2) => Math.Atan2(position2.Z - Z, position2.X - X); + + public double AngleInRad() => Math.Atan2(Z, X) + Math.PI; + public Space3D Rotate(double degree) { Space3D result; + double distance = Math.Sqrt(X * X + Z * Z); - double angle = new Space3D(0 , 0 , 0).AngleInRad(this) + MathHelper.DegreeToRadiant(degree); - result = FromPolarCoordinate(new Space3D(0 , 0 , 0).Distance2D(this) , angle); + double angle = new Space3D(0, 0, 0).AngleInRad(this) + MathHelper.DegreeToRadiant(degree); + + result = FromPolarCoordinate(new Space3D(0, 0, 0).Distance2D(this), angle); result.X = distance * Math.Sin(angle); result.Z = distance * Math.Cos(angle); + return result; } - public Space3D Mirror(bool onXAxis , bool onZAxis) + public Space3D Mirror(bool onXAxis, bool onZAxis) { - Space3D result = new Space3D(0 , Y , 0); - if(onXAxis) + Space3D result = new Space3D(0, Y, 0); + + if (onXAxis) result.X = -X; - if(onZAxis) + + if (onZAxis) result.Z = -Z; + return result; } - public static Space3D FromPolarCoordinate(double lenght , double Radinat) + public static Space3D FromPolarCoordinate(double lenght, double Radinat) { - Space3D result = new Space3D(0 , 0 , 0) + Space3D result = new Space3D(0, 0, 0) { - X = lenght * Math.Sin(Radinat) , + X = lenght * Math.Sin(Radinat), Z = lenght * Math.Cos(Radinat) }; + return result; } - public Chunk ToChunk() => new Chunk((int)Math.Floor(X / 16) , (int)Math.Floor(Z / 16)); + public Chunk ToChunk() => new Chunk((int)Math.Floor(X / 16), (int)Math.Floor(Z / 16)); - public Space3D Round() => new Space3D(Math.Round(X) , Math.Round(Y) , Math.Round(Z)); + public Space3D Round() => new Space3D(Math.Round(X), Math.Round(Y), Math.Round(Z)); public override bool Equals(object obj) => obj is Space3D s && Equals(s); public override int GetHashCode() => base.GetHashCode(); public bool Equals(Space3D other) => X == other.X && Y == other.Y && Z == other.Z; - public static Space3D operator +(Space3D @this , Space3D other) => new Space3D() + public static Space3D operator +(Space3D @this, Space3D other) => new Space3D() { - X = @this.X + other.X , - Y = @this.Y + other.Y , + X = @this.X + other.X, + Y = @this.Y + other.Y, Z = @this.Z + other.Z }; - public static Space3D operator -(Space3D @this , Space3D other) => new Space3D() + public static Space3D operator -(Space3D @this, Space3D other) => new Space3D() { - X = @this.X - other.X , - Y = @this.Y - other.Y , + X = @this.X - other.X, + Y = @this.Y - other.Y, Z = @this.Z - other.Z }; - public static Space3D operator *(Space3D @this , double mutiplier) => new Space3D() + public static Space3D operator *(Space3D @this, double mutiplier) => new Space3D() { - X = @this.X * mutiplier , - Y = @this.Y * mutiplier , + X = @this.X * mutiplier, + Y = @this.Y * mutiplier, Z = @this.Z * mutiplier }; - public static Space3D operator *(double mutiplier , Space3D @this) => new Space3D() + public static Space3D operator *(double mutiplier, Space3D @this) => new Space3D() { - X = @this.X * mutiplier , - Y = @this.Y * mutiplier , + X = @this.X * mutiplier, + Y = @this.Y * mutiplier, Z = @this.Z * mutiplier }; - public static Space3D operator *(int mutiplier , Space3D @this) => new Space3D() + public static Space3D operator *(int mutiplier, Space3D @this) => new Space3D() { - X = @this.X * mutiplier , - Y = @this.Y * mutiplier , + X = @this.X * mutiplier, + Y = @this.Y * mutiplier, Z = @this.Z * mutiplier }; - public static Space3D operator *(Space3D @this , int mutiplier) => new Space3D() + public static Space3D operator *(Space3D @this, int mutiplier) => new Space3D() { - X = @this.X * mutiplier , - Y = @this.Y * mutiplier , + X = @this.X * mutiplier, + Y = @this.Y * mutiplier, Z = @this.Z * mutiplier }; - public static Space3D operator /(int mutiplier , Space3D @this) => new Space3D() + public static Space3D operator /(int mutiplier, Space3D @this) => new Space3D() { - X = @this.X / mutiplier , - Y = @this.Y / mutiplier , + X = @this.X / mutiplier, + Y = @this.Y / mutiplier, Z = @this.Z / mutiplier }; - public static Space3D operator /(Space3D @this , int divider) => new Space3D() + public static Space3D operator /(Space3D @this, int divider) => new Space3D() { - X = @this.X / divider , - Y = @this.Y / divider , + X = @this.X / divider, + Y = @this.Y / divider, Z = @this.Z / divider }; - public static Space3D operator /(double divider , Space3D @this) => new Space3D() + public static Space3D operator /(double divider, Space3D @this) => new Space3D() { - X = @this.X / divider , - Y = @this.Y / divider , + X = @this.X / divider, + Y = @this.Y / divider, Z = @this.Z / divider }; - public static Space3D operator /(Space3D @this , double divider) => new Space3D() + public static Space3D operator /(Space3D @this, double divider) => new Space3D() { - X = @this.X / divider , - Y = @this.Y / divider , + X = @this.X / divider, + Y = @this.Y / divider, Z = @this.Z / divider }; - public static bool operator ==(Space3D left , Space3D right) => left.Equals(right); + public static bool operator ==(Space3D left, Space3D right) => left.Equals(right); + + public static bool operator ==(Space3D left, double right) => left.X == right && left.Y == right && left.Z == right; + + public static bool operator >(Space3D left, double right) => left.X > right && left.Y > right && left.Z > right; + + public static bool operator >=(Space3D left, double right) => left.X >= right && left.Y >= right && left.Z >= right; + + public static bool operator <(Space3D left, double right) => left.X < right && left.Y < right && left.Z < right; - public static bool operator >(Space3D left , double right) => left.X > right && left.Y > right && left.Z > right; + public static bool operator <=(Space3D left, double right) => left.X <= right && left.Y <= right && left.Z <= right; - public static bool operator <(Space3D left , double right) => left.X < right && left.Y < right && left.Z < right; + public static bool operator !=(Space3D left, Space3D right) => !left.Equals(right); - public static bool operator !=(Space3D left , Space3D right) => !left.Equals(right); + public static bool operator !=(Space3D left, double right) => !(left == right); } -} \ No newline at end of file +} diff --git a/PearlCalculatorLib/PearlCalculationLib/World/Surface2D.cs b/PearlCalculatorLib/PearlCalculationLib/World/Surface2D.cs index 665765f..01fe25e 100644 --- a/PearlCalculatorLib/PearlCalculationLib/World/Surface2D.cs +++ b/PearlCalculatorLib/PearlCalculationLib/World/Surface2D.cs @@ -1,30 +1,26 @@ using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.NetworkInformation; -using System.Text; -using System.Xml.Serialization; namespace PearlCalculatorLib.PearlCalculationLib.World { [Serializable] - public class Surface2D + public struct Surface2D { + public static readonly Surface2D Zero = new Surface2D(); + public double X; public double Z; - public static readonly Surface2D zero = new Surface2D(); - public Surface2D() - { + public double Length => Math.Sqrt(X * X + Z * Z); - } - public Surface2D(double x , double z) + public Surface2D Normalized => Length == 0 ? Zero : this / Length; + + public Surface2D(double x, double z) { X = x; Z = z; } - public Space3D ToSpace3D() => new Space3D(X , 0 , Z); + public Space3D ToSpace3D() => new Space3D(X, 0, Z); public override string ToString() => $"Coordinate : {X} , {Z}"; @@ -36,26 +32,34 @@ public Surface2D(double x , double z) public bool IsWest(Surface2D position2) => position2.Z > Z; + public bool IsClockWise(Surface2D vector2) => vector2.Transform(Normalized, Zero) > 0; + + public bool IsCounterClockWise(Surface2D vector2) => vector2.Transform(Normalized, Zero) < 0; + public double Angle(Surface2D position2) => Math.Atan((position2.Z - Z) / (position2.X - X)) / Math.PI * 180; public bool IsOrigin() => X == 0 && Z == 0; - public bool IsInside(Surface2D SouthEastConer , Surface2D NorthWestConer) + public bool IsInside(Surface2D southEastConer, Surface2D northWestConer) { - return X < SouthEastConer.X && Z < SouthEastConer.Z && X > NorthWestConer.X && Z > NorthWestConer.Z; + return X < southEastConer.X && Z < southEastConer.Z && X > northWestConer.X && Z > northWestConer.Z; } public double AngleInRad(Surface2D position2) => Math.Atan(position2.Z - Z / position2.X - X); - public static Space3D FromPolarCoordinate(double lenght , double Radinat) + public static Space3D FromPolarCoordinate(double lenght, double radinat) => new Space3D { - Space3D result = new Space3D(0 , 0 , 0) - { - X = lenght * Math.Sin(Radinat) , - Z = lenght * Math.Cos(Radinat) - }; - return result; - } + X = lenght * Math.Sin(radinat), + Z = lenght * Math.Cos(radinat) + }; + + public Surface2D Absolute() => new Surface2D(Math.Abs(X), Math.Abs(Z)); + + public double Distance(Surface2D position2) => Math.Sqrt(Math.Pow(position2.X - X, 2) + Math.Pow(position2.Z - Z, 2)); + + public override bool Equals(object obj) => obj is Surface2D s && Equals(s); + + public Surface2D Transform(Surface2D iHat, Surface2D jHat) => X * iHat + Z * jHat; public bool AxialDistanceLessThan(double distance) => Math.Abs(X) < distance && Math.Abs(Z) < distance; @@ -67,30 +71,42 @@ public static Space3D FromPolarCoordinate(double lenght , double Radinat) public bool AxialDistanceLargerOrEqualTo(double distance) => AxialDistanceLargerThan(distance) || AxialDistanceEqualTo(distance); - public Chunk ToChunk() => new Chunk((int)Math.Floor(X / 16) , (int)Math.Floor(Z / 16)); + public Chunk ToChunk() => new Chunk((int)Math.Floor(X / 16), (int)Math.Floor(Z / 16)); + + public Surface2D Round() => new Surface2D(Math.Round(X), Math.Round(Z)); + + public override int GetHashCode() => X.GetHashCode() ^ Z.GetHashCode(); + + public static Surface2D operator +(Surface2D left, Surface2D right) => new Surface2D(left.X + right.X, left.Z + right.Z); + + public static Surface2D operator -(Surface2D left, Surface2D right) => new Surface2D(left.X - right.X, left.Z - right.Z); - public Surface2D Round() => new Surface2D(Math.Round(X) , Math.Round(Z)); + public static Surface2D operator *(Surface2D left, double right) => new Surface2D(left.X * right, left.Z * right); - public static Surface2D operator +(Surface2D left , Surface2D right) => new Surface2D(left.X + right.X , left.Z + right.Z); + public static Surface2D operator *(double left, Surface2D right) => new Surface2D(left * right.X, left * right.Z); - public static Surface2D operator -(Surface2D left , Surface2D right) => new Surface2D(left.X - right.X , left.Z - right.Z); + public static Surface2D operator /(Surface2D left, double right) => new Surface2D(left.X / right, left.Z / right); - public static bool operator <(Surface2D left , double right) => left.X < right && left.Z < right; + public static bool operator <(Surface2D left, double right) => left.X < right && left.Z < right; - public static bool operator >(Surface2D left , double right) => left.X > right && left.Z > right; + public static bool operator >(Surface2D left, double right) => left.X > right && left.Z > right; - public static bool operator <(Surface2D left , int right) => left.X < right && left.Z < right; + public static bool operator <(Surface2D left, int right) => left.X < right && left.Z < right; - public static bool operator >(Surface2D left , int right) => left.X > right && left.Z > right; + public static bool operator >(Surface2D left, int right) => left.X > right && left.Z > right; - public static bool operator <=(Surface2D left , double right) => left.X <= right && left.Z <= right; + public static bool operator <=(Surface2D left, double right) => left.X <= right && left.Z <= right; - public static bool operator >=(Surface2D left , double right) => left.X >= right && left.Z >= right; + public static bool operator >=(Surface2D left, double right) => left.X >= right && left.Z >= right; - public static bool operator <=(Surface2D left , int right) => left.X <= right && left.Z <= right; + public static bool operator <=(Surface2D left, int right) => left.X <= right && left.Z <= right; - public static bool operator >=(Surface2D left , int right) => left.X >= right && left.Z >= right; + public static bool operator >=(Surface2D left, int right) => left.X >= right && left.Z >= right; + public static bool operator ==(Surface2D left, double right) => left.X == right && left.Z == right; + public static bool operator !=(Surface2D left, double right) => !(left == right); + public static bool operator ==(Surface2D left, int right) => left.X == right && left.Z == right; + public static bool operator !=(Surface2D left, int right) => !(left == right); } } diff --git a/SettingsJsonConverter.cs b/SettingsJsonConverter.cs index 8970d33..c252e18 100644 --- a/SettingsJsonConverter.cs +++ b/SettingsJsonConverter.cs @@ -184,4 +184,4 @@ public override void Write(Utf8JsonWriter writer, Space3D value, JsonSerializerO writer.WriteNumber("Z", value.Z); } } -} \ No newline at end of file +}