Added Base Project

This commit is contained in:
Müller Wayan
2025-02-23 14:29:32 +01:00
parent cda7948be9
commit a6130d4ff0
364 changed files with 12117 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public class AVL_Tree<T> : BinarySearchTree<T>
{
public AVL_Tree(IComparer<T> comparer) : base(comparer) { }
internal AVL_Tree(BinaryNode<T> node, IComparer<T> comparer) : base (node, comparer) {}
public new void InsertItem(T item)
{
InsertItem(item, ref root);
}
private void InsertItem(T item, ref BinaryNode<T>? node)
{
if(node == null)
{
node = new BinaryNode<T>(item);
}
else if (Comparer.Compare(item,node.content) < 0)
{
InsertItem(item, ref node.left);
}
else if (Comparer.Compare(item, node.content) > 0)
{
InsertItem(item, ref node.right);
}
else
{
InsertItem(item, ref node.left);
}
balanceTree(ref node);
}
public new void RemoveItem(T item)
{
}
private void RemoveItem(T item, ref BinaryNode<T>? node)
{
if (node != null)
{
if(Comparer.Compare(item, node.content) < 0)
{
RemoveItem(item, ref node.left);
}
else if (Comparer.Compare(item, node.content) > 0)
{
RemoveItem(item, ref node.right);
}
else if (Comparer.Compare(item, node.content) == 0)
{
if (node.left == null)
{
node = node.right;
}
else if (node.right == null)
{
node = node.left;
}
else
{
T newRoot = leastItem(node.right);
node.content = newRoot;
RemoveItem(newRoot, ref node.right);
}
}
}
else
{
return;
}
balanceTree(ref node);
}
private void balanceTree(ref BinaryNode<T> node)
{
if (node != null)
{
node.balanceFactor = height(node.left) - height(node.right);
if(node.balanceFactor <= -2)
{
rotateLeft(ref node);
}
if(node.balanceFactor >= 2)
{
rotateRight(ref node);
}
}
}
private void rotateLeft(ref BinaryNode<T> node)
{
if ( node.left.balanceFactor > 0)
{
rotateRight(ref node);
}
BinaryNode<T> oldRoot = node;
BinaryNode<T> newRoot = node.right;
oldRoot.right = newRoot.left;
newRoot.left = oldRoot;
node = newRoot;
}
private void rotateRight(ref BinaryNode<T> node)
{
if (node.left.balanceFactor < 0)
{
rotateLeft(ref node.left);
}
BinaryNode<T> oldRoot = node;
BinaryNode <T> newRoot = node.left;
oldRoot.left = newRoot.right;
newRoot.right = oldRoot;
node = newRoot;
}
}
}
+24
View File
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
internal class BinaryNode<T>
{
public T content;
public int balanceFactor;
public BinaryNode<T>? left;
public BinaryNode<T>? right;
public BinaryNode(T item)
{
content = item;
left = null;
right = null;
}
}
}
+139
View File
@@ -0,0 +1,139 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public class BinarySearchTree<T> : BinaryTree<T>
{
public int Height { get { return height(root); } }
protected readonly IComparer<T> Comparer;
public BinarySearchTree(IComparer<T> comparer)
{
root = null;
Comparer = comparer;
}
internal BinarySearchTree(BinaryNode<T> node, IComparer<T> comparer)
{
root = node;
Comparer = comparer;
}
public void InsertItem(T item)
{
InsertItem(item, ref root);
}
private void InsertItem(T item, ref BinaryNode<T>? node)
{
if (node == null)
{
node = new BinaryNode<T>(item);
}
else if(Comparer.Compare(item, node.content) < 0)
{
InsertItem(item, ref node.left);
}
else if(Comparer.Compare(item, node.content) > 0)
{
InsertItem(item, ref node.right);
}
}
internal int height(BinaryNode<T>? tree)
{
if(tree == null)
{
return 0;
}
else
{
return 1 + Math.Max(height(tree.left), height(tree.right));
}
}
public bool Contains(T item)
{
return Contains(item, root);
}
private bool Contains(T item, BinaryNode<T>? node)
{
if(node != null)
{
if(item.Equals(node.content))
return true;
if(Comparer.Compare(item, node.content) < 0)
{
return Contains(item, node.left);
}
else
{
return Contains(item, node.right);
}
}
else
{
return false;
}
}
public void RemoveItem(T item)
{
RemoveItem(item, ref root);
}
private void RemoveItem(T item, ref BinaryNode<T>? node)
{
if (node == null)
{
return;
}
else if (Comparer.Compare(item, node.content) < 0)
{
RemoveItem(item, ref node.left);
}
else if (Comparer.Compare(item, node.content) > 0)
{
RemoveItem(item, ref node.right);
}
if (item.Equals(node.content))
{
if(node.left == null)
{
node = node.right;
}
else if (node.right == null)
{
node = node.left;
}
else
{
T newRoot = leastItem(node.right);
node.content = newRoot;
RemoveItem(newRoot, ref node.right );
}
}
}
internal T leastItem(BinaryNode<T> node)
{
if(node.left == null)
{
return node.content;
}
else
{
return leastItem(node.left);
}
}
}
}
+137
View File
@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public abstract class BinaryTree<T>
{
internal BinaryNode<T> root = null;
public int Count { get {
int counter = 0;
count(root, ref counter);
return counter;
} }
public T[]? InOrder()
{
if (root == null)
return Array.Empty<T>();
List<T> result = new();
Stack<BinaryNode<T>> stack = new();
BinaryNode<T>? current = root;
while (current != null || stack.Count > 0)
{
// Gehe nach links, so weit wie möglich
while (current != null)
{
stack.Push(current);
current = current.left;
}
// Knoten aus dem Stack holen
current = stack.Pop();
result.Add(current.content);
// Gehe nach rechts
current = current.right;
}
return result.ToArray();
}
public T[]? PreOrder()
{
if (root == null)
return Array.Empty<T>();
List<T> result = new();
Stack<BinaryNode<T>> stack = new();
stack.Push(root);
while (stack.Count > 0)
{
// Knoten aus dem Stack holen
var current = stack.Pop();
result.Add(current.content);
// Zuerst den rechten Knoten hinzufügen (wird später bearbeitet)
if (current.right != null)
stack.Push(current.right);
// Dann den linken Knoten hinzufügen
if (current.left != null)
stack.Push(current.left);
}
return result.ToArray();
}
public T[]? PostOrder()
{
if (root == null)
return Array.Empty<T>();
List<T> result = new();
Stack<BinaryNode<T>> stack1 = new();
Stack<BinaryNode<T>> stack2 = new();
stack1.Push(root);
while (stack1.Count > 0)
{
// Knoten aus dem ersten Stack holen
var current = stack1.Pop();
stack2.Push(current);
// Linken und rechten Knoten in den ersten Stack schieben
if (current.left != null)
stack1.Push(current.left);
if (current.right != null)
stack1.Push(current.right);
}
// Ergebnis aus dem zweiten Stack lesen (umgekehrte Reihenfolge)
while (stack2.Count > 0)
{
result.Add(stack2.Pop().content);
}
return result.ToArray();
}
public void Copy(BinaryTree<T> tree2)
{
Copy(ref root, tree2.root);
}
private void Copy(ref BinaryNode<T>? tree, BinaryNode<T>? tree2)
{
if(tree == null && tree2 != null)
{
tree = new BinaryNode<T>(tree2.content);
}
if(tree != null && tree2 != null)
{
tree.content = tree2.content;
Copy(ref tree.left, tree2.left);
Copy(ref tree.right, tree2.right);
}
}
private void count(BinaryNode<T>? tree, ref int counter)
{
if (root != null)
{
counter++;
count(tree.left, ref counter);
count(tree.right, ref counter);
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using SFML.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public interface ISpatial
{
public FloatRect Bounds { get; }
}
}
+257
View File
@@ -0,0 +1,257 @@
using Firebird2D.Requirement;
using SFML.Graphics;
using System.Diagnostics.CodeAnalysis;
using Firebird2D.SFMLExtensions;
using System.Drawing;
using SFML.System;
using System.Collections;
namespace Firebird2D.Datatypes
{
public class Quadtree<T> where T : ISpatial
{
private readonly List<T> _elements = [];
private readonly int _bucketCapacity;
private readonly int _maxDepth;
private Quadtree<T>? _topLeft, _topRight, _bottomLeft, _bottomRight;
public FloatRect Bounds { get; }
public int Level { get; init; }
[MemberNotNullWhen(false, nameof(_topLeft), nameof(_topRight), nameof(_bottomLeft), nameof(_bottomRight))]
public bool IsLeaf
=> _topLeft == null || _topRight == null || _bottomLeft == null || _bottomRight == null;
public bool AllowOutOfBounds { get; set; }
public Quadtree(FloatRect bounds, int bucketCapacity, int maxDepth)
{
Bounds = bounds;
_bucketCapacity = bucketCapacity;
_maxDepth = maxDepth;
}
public Quadtree(FloatRect bounds): this(bounds,32,5) { }
public void Insert(T element)
{
Require.NotNull(element, nameof(element));
if (!(Bounds.Contains(element.Bounds) || AllowOutOfBounds))
throw new ArgumentException(string.Format("{0} is out of Quadtreebounds", nameof(element)), nameof(element));
if (_elements.Count >= _bucketCapacity)
Split();
Quadtree<T>? containingChild = GetContainingChild(element.Bounds);
if (containingChild != null)
{
containingChild.Insert(element);
}
else
{
_elements.Add(element);
}
}
public bool Remove(T element)
{
Require.NotNull(element, nameof(element));
Quadtree<T>? containingChild = GetContainingChild(element.Bounds);
bool removed = containingChild?.Remove(element) ?? _elements.Remove(element);
if (removed && CountElements() <= _bucketCapacity)
Merge();
return removed;
}
public int CountElements()
{
int count = _elements.Count;
if(!IsLeaf)
{
count += _topLeft.CountElements();
count += _topRight.CountElements();
count += _bottomLeft.CountElements();
count += _bottomRight.CountElements();
}
return count;
}
public IEnumerable<T> GetElements()
{
List<T> children = new();
Queue<Quadtree<T>> nodes = new Queue<Quadtree<T>>();
nodes.Enqueue(this);
while (nodes.Count > 0)
{
Quadtree<T> node = nodes.Dequeue();
if (!node.IsLeaf)
{
nodes.Enqueue(node._topLeft);
nodes.Enqueue(node._topRight);
nodes.Enqueue(node._bottomLeft);
nodes.Enqueue(node._bottomRight);
}
children.AddRange(node._elements);
}
return children;
}
private void Split()
{
if (!IsLeaf)
return;
if (Level + 1 > _maxDepth)
return;
_topLeft = CreateChild(Bounds.Location());
_topRight = CreateChild(new Vector2f(Bounds.Center().X, Bounds.Location().Y));
_bottomLeft = CreateChild(new Vector2f(Bounds.Location().X, Bounds.Center().Y));
_bottomRight = CreateChild(Bounds.Center());
List<T> elements = _elements.ToList();
foreach (T element in elements)
{
Quadtree<T>? containingChild = GetContainingChild(element.Bounds);
if (containingChild != null)
{
_elements.Remove(element);
containingChild.Insert(element);
}
}
}
private Quadtree<T> CreateChild(Vector2f location)
=> new(new FloatRect(location, Bounds.Size / 2), _bucketCapacity, _maxDepth) { Level = Level + 1 };
private void Merge()
{
if (IsLeaf)
return;
_elements.AddRange(_topLeft._elements);
_elements.AddRange(_topRight._elements);
_elements.AddRange(_bottomLeft._elements);
_elements.AddRange(_bottomRight._elements);
_topLeft = _topRight = _bottomLeft = _bottomRight = null;
}
private Quadtree<T>? GetContainingChild(FloatRect bounds)
{
if (IsLeaf)
return null;
if(_topLeft.Bounds.Contains(bounds))
return _topLeft;
if (_topRight.Bounds.Contains(bounds))
return _topRight;
if (_bottomLeft.Bounds.Contains(bounds))
return _bottomLeft;
if (_bottomRight.Bounds.Contains(bounds))
return _bottomRight;
return null;
}
public IEnumerable<T> FindCollisions(T element)
{
Require.NotNull(element, nameof(element));
var nodes = new Queue<Quadtree<T>>();
var collisions = new List<T>();
nodes.Enqueue(this);
while (nodes.Count > 0)
{
var node = nodes.Dequeue();
if (!element.Bounds.Intersects(node.Bounds))
continue;
collisions.AddRange(node._elements.Where(e => e.Bounds.Intersects(element.Bounds)));
if (!node.IsLeaf)
{
if (element.Bounds.Intersects(node._topLeft.Bounds))
nodes.Enqueue(node._topLeft);
if (element.Bounds.Intersects(node._topRight.Bounds))
nodes.Enqueue(node._topRight);
if (element.Bounds.Intersects(node._bottomLeft.Bounds))
nodes.Enqueue(node._bottomLeft);
if (element.Bounds.Intersects(node._bottomRight.Bounds))
nodes.Enqueue(node._bottomRight);
}
}
return collisions;
}
public IEnumerable<T> FindInRegion(FloatRect region)
{
var results = new List<T>();
var stack = new Stack<Quadtree<T>>();
stack.Push(this);
while (stack.Count > 0)
{
var node = stack.Pop();
if (!node.Bounds.Intersects(region))
continue;
results.AddRange(node._elements.Where(e => region.Intersects(e.Bounds)));
if (!node.IsLeaf)
{
stack.Push(node._topLeft);
stack.Push(node._topRight);
stack.Push(node._bottomLeft);
stack.Push(node._bottomRight);
}
}
return results;
}
public AVL_Tree<T> FindInRegionAVL(FloatRect region, IComparer<T> comparer)
{
List<T> values = (List<T>)FindInRegion(region);
AVL_Tree<T> returnTree = new(comparer);
foreach (T elment in values)
{
returnTree.InsertItem(elment);
}
return returnTree;
}
}
}