├── .editorconfig ├── .gitattributes ├── .gitignore ├── Binaries ├── Common.Collections.dll ├── Common.Collections.pdb ├── Common.Collections.xml ├── Common.Core.dll ├── Common.Core.pdb ├── Common.Core.xml ├── Common.Geometry.dll ├── Common.Geometry.pdb ├── Common.Geometry.xml ├── Common.GraphTheory.dll ├── Common.GraphTheory.pdb └── Common.GraphTheory.xml ├── Common.Collections.Test ├── Arrays │ ├── FloatArray1Test.cs │ └── SparseArray2Test.cs ├── Common.Collections.Test.csproj ├── Properties │ └── AssemblyInfo.cs ├── Queues │ ├── BinaryHeapTest.cs │ ├── PriorityListTest.cs │ └── TestComparable.cs └── Trees │ ├── AVLTreeTest.cs │ └── BinaryTreeTest.cs ├── Common.Collections ├── Arrays │ ├── Array1.cs │ ├── Array2.cs │ ├── ColorArray1.cs │ ├── ColorArray2.cs │ ├── FloatArray1.cs │ ├── FloatArray2.cs │ ├── IArray1.cs │ ├── IArray2.cs │ └── SparseArray2.cs ├── Common.Collections.csproj ├── Queues │ ├── BinaryHeap.cs │ ├── IPriorityQueue.cs │ └── PriorityList.cs ├── Sets │ ├── DisjointGridSet2.cs │ ├── DisjointMappedSet.cs │ └── DisjointSet.cs └── Trees │ ├── AVLTree.cs │ ├── BinaryTree.cs │ └── BinaryTreeNode.cs ├── Common.Console ├── App.config ├── Common.Console.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── Common.Core.Test ├── Bits │ └── BitTest.cs ├── Colors │ ├── ColorHSVTest.cs │ ├── ColorRGBATest.cs │ └── ColorRGBTest.cs ├── Common.Core.Test.csproj ├── Directions │ └── D26Test.cs ├── Extensions │ └── IListExtensionTest.cs ├── IO │ └── RawFileTest.cs ├── Numerics │ ├── MathTests.cs │ ├── Matrix2x2dTest.cs │ ├── Matrix2x2fTest.cs │ ├── Matrix3x3dTest.cs │ ├── Matrix3x3fTest.cs │ ├── Matrix4x4dTest.cs │ ├── Matrix4x4fTest.cs │ ├── Union32Test.cs │ ├── Vector2dTest.cs │ ├── Vector2fTest.cs │ ├── Vector3dTest.cs │ ├── Vector3fTest.cs │ ├── Vector4dTest.cs │ └── Vector4fTest.cs ├── Properties │ └── AssemblyInfo.cs └── Shapes │ ├── Box2fTest.cs │ ├── Box2iTest.cs │ ├── Circle2fTest.cs │ ├── Line2fTest.cs │ ├── Ray2fTest.cs │ ├── Segment2fTest.cs │ └── Triangle2fTest.cs ├── Common.Core ├── Bits │ └── Bit.cs ├── Colors │ ├── ColorHSV.cs │ ├── ColorRGB.cs │ └── ColorRGBA.cs ├── Common.Core.csproj ├── Directions │ ├── D26.cs │ ├── D4.cs │ └── D8.cs ├── Extensions │ ├── ArrayExtensions.cs │ ├── DictionaryExtensions.cs │ ├── IListExtension.cs │ ├── LinkedListExtensions.cs │ ├── ListExtensions.cs │ ├── RandomExtensions.cs │ └── StringExtensions.cs ├── IO │ └── RawFile.cs ├── Numerics │ ├── Degree.cs │ ├── HPoint2d.cs │ ├── HPoint2f.cs │ ├── HPoint3d.cs │ ├── HPoint3f.cs │ ├── MathUtil.cs │ ├── Matrix2x2d.cs │ ├── Matrix2x2f.cs │ ├── Matrix3x3d.cs │ ├── Matrix3x3f.cs │ ├── Matrix4x4d.cs │ ├── Matrix4x4f.cs │ ├── MinMax.cs │ ├── Point2d.cs │ ├── Point2f.cs │ ├── Point2i.cs │ ├── Point3d.cs │ ├── Point3f.cs │ ├── Point3i.cs │ ├── Point4d.cs │ ├── Point4f.cs │ ├── Point4i.cs │ ├── Quaternion3d.cs │ ├── Quaternion3f.cs │ ├── Radian.cs │ ├── Union16.cs │ ├── Union32.cs │ ├── Union64.cs │ ├── Vector2d.cs │ ├── Vector2f.cs │ ├── Vector3d.cs │ ├── Vector3f.cs │ ├── Vector4d.cs │ └── Vector4f.cs ├── RandomNum │ ├── LCHGenerator.cs │ ├── MersenneTwister.cs │ ├── RandomGenerator.cs │ └── SystemRandom.cs ├── Shapes │ ├── Box2d.cs │ ├── Box2f.cs │ ├── Box2i.cs │ ├── Box3d.cs │ ├── Box3f.cs │ ├── Box3i.cs │ ├── Circle2d.cs │ ├── Circle2f.cs │ ├── Line2d.cs │ ├── Line2f.cs │ ├── Line3d.cs │ ├── Line3f.cs │ ├── Plane3d.cs │ ├── Plane3f.cs │ ├── Ray2d.cs │ ├── Ray2f.cs │ ├── Ray3d.cs │ ├── Ray3f.cs │ ├── Segment2d.cs │ ├── Segment2f.cs │ ├── Segment3d.cs │ ├── Segment3f.cs │ ├── SegmentIndex.cs │ ├── Shape2d.cs │ ├── Shape2f.cs │ ├── Shape3d.cs │ ├── Shape3f.cs │ ├── Sphere3d.cs │ ├── Sphere3f.cs │ ├── Tetrahedron3d.cs │ ├── Tetrahedron3f.cs │ ├── Triangle2d.cs │ ├── Triangle2f.cs │ ├── Triangle3d.cs │ ├── Triangle3f.cs │ └── TriangleIndex.cs ├── Threading │ ├── ThreadingBlock1D.cs │ ├── ThreadingBlock2D.cs │ ├── ThreadingBlock3D.cs │ └── ThreadingToken.cs └── Time │ └── Timer.cs ├── Common.Geometry.Test ├── Bezier │ └── Bezier2fTest.cs ├── Collections │ └── BVHTree2fTest.cs ├── Common.Geometry.Test.csproj ├── Polygons │ ├── Polygon2fTest.cs │ └── Polyline2fTest.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Common.Geometry ├── Bezier │ ├── Bezier.cs │ ├── Bezier2d.cs │ ├── Bezier2f.cs │ ├── Bezier3d.cs │ ├── Bezier3f.cs │ ├── Polynomial3f.cs │ └── QuadraticBezier2f.cs ├── Collections │ ├── BVHTree2d.cs │ ├── BVHTree2f.cs │ ├── BVHTreeNode2d.cs │ ├── BVHTreeNode2f.cs │ ├── IShapeCollection2d.cs │ ├── IShapeCollection2f.cs │ ├── IShapeCollection3f.cs │ ├── ShapeCollection2d.cs │ ├── ShapeCollection2f.cs │ └── ShapeCollection3f.cs ├── Common.Geometry.csproj ├── DCEL │ ├── DCELExceptions.cs │ ├── DCELFace.cs │ ├── DCELGeometry.cs │ ├── DCELHalfedge.cs │ ├── DCELMesh.Insert.cs │ ├── DCELMesh.cs │ └── DCELVertex.cs ├── Meshes │ ├── IndexableMesh.cs │ ├── Mesh2f.cs │ ├── Mesh3f.cs │ └── MeshFactory.cs ├── Points │ ├── IPointCollection2f.cs │ ├── IPointCollection3f.cs │ ├── KdTree2f.cs │ ├── KdTree3f.cs │ ├── KdTreeNode2f.cs │ ├── KdTreeNode3f.cs │ ├── PointCollection2f.cs │ ├── PointCollection3f.cs │ ├── PointGrid2f.cs │ └── PointGrid3f.cs └── Polygons │ ├── Polygon2d.cs │ ├── Polygon2f.cs │ ├── Polyline2d.cs │ ├── Polyline2f.cs │ ├── Polyobject2d.cs │ └── Polyobject2f.cs ├── Common.GraphTheory.Test ├── AdjacencyGraphs │ ├── AdjacencyGraphTest.cs │ └── GraphTreeTest.cs ├── Common.GraphTheory.Test.csproj ├── GridsGraphs │ ├── GridFlowGraphTest.cs │ └── GridGraphTest.cs ├── MatrixGraphs │ └── MatrixGraphTest.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Common.GraphTheory ├── AdjacencyGraphs │ ├── AdjacencyGraph.BreadthFirst.cs │ ├── AdjacencyGraph.DepthFirst.cs │ ├── AdjacencyGraph.cs │ ├── DirectedGraph.AStar.cs │ ├── DirectedGraph.Djkstras.cs │ ├── DirectedGraph.FordFulkerson.cs │ ├── DirectedGraph.Khans.cs │ ├── DirectedGraph.PushRelabel.cs │ ├── DirectedGraph.cs │ ├── GraphEdge.cs │ ├── GraphForest.cs │ ├── GraphTree.cs │ ├── GraphVertex.cs │ ├── UndirectedGraph.Kruskals.cs │ ├── UndirectedGraph.Prims.cs │ └── UndirectedGraph.cs ├── Common.GraphTheory.csproj ├── GridGraphs │ ├── FlowGridGraph.FordFulkerson.cs │ ├── FlowGridGraph.cs │ ├── FlowGridSearch.cs │ ├── GridGraph.AStar.cs │ ├── GridGraph.BreadthFirst.cs │ ├── GridGraph.DepthFirst.cs │ ├── GridGraph.Dijkstras.cs │ ├── GridGraph.cs │ ├── GridSearch.cs │ ├── GridVertex.cs │ ├── WeighedGridEdge.cs │ ├── WeighedGridGraph.Kruskals.cs │ ├── WeighedGridGraph.Prims.cs │ └── WeighedGridGraph.cs └── MatrixGraphs │ ├── MatrixEdge.cs │ ├── MatrixGraph.FordFulkerson.cs │ ├── MatrixGraph.PushRelabel.cs │ └── MatrixGraph.cs ├── Common.sln └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # CS1591: Missing XML comment for publicly visible type or member 4 | dotnet_diagnostic.CS1591.severity = none 5 | 6 | # CS1573: Parameter has no matching param tag in the XML comment (but other parameters do) 7 | dotnet_diagnostic.CS1573.severity = none 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Binaries/Common.Collections.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.Collections.dll -------------------------------------------------------------------------------- /Binaries/Common.Collections.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.Collections.pdb -------------------------------------------------------------------------------- /Binaries/Common.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.Core.dll -------------------------------------------------------------------------------- /Binaries/Common.Core.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.Core.pdb -------------------------------------------------------------------------------- /Binaries/Common.Geometry.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.Geometry.dll -------------------------------------------------------------------------------- /Binaries/Common.Geometry.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.Geometry.pdb -------------------------------------------------------------------------------- /Binaries/Common.GraphTheory.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.GraphTheory.dll -------------------------------------------------------------------------------- /Binaries/Common.GraphTheory.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrawk/Common/a4e1915e655870962ea5b5ace51b73420488fcb8/Binaries/Common.GraphTheory.pdb -------------------------------------------------------------------------------- /Common.Collections.Test/Arrays/FloatArray1Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Collections.Arrays; 5 | 6 | namespace Common.Collections.Test.Arrays 7 | { 8 | [TestClass] 9 | public class FloatArray1Test 10 | { 11 | 12 | [TestMethod] 13 | public void GetClamped() 14 | { 15 | 16 | var array = new FloatArray1(10); 17 | array.Fill(x => x); 18 | 19 | //Console.WriteLine("Sum = " + array.Sum()); 20 | 21 | int samples = 20; 22 | float sum = 0; 23 | 24 | for(int i = 0; i < samples; i++) 25 | { 26 | float u = i / (samples-1.0f); 27 | 28 | float x = array.GetClamped(u); 29 | sum += x; 30 | 31 | //Console.WriteLine("i = " + i + " u = " + u + " x = " + x); 32 | } 33 | 34 | //Console.WriteLine("Sum2 = " + sum); 35 | 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Common.Collections.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Common.Collections.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Common.Collections.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fe9ef716-dbaa-457f-a28a-9ae3877ca3f8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Common.Collections.Test/Queues/BinaryHeapTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Collections.Queues; 5 | 6 | namespace Common.Collections.Test.Queues 7 | { 8 | [TestClass] 9 | public class BinaryHeapTest 10 | { 11 | 12 | 13 | [TestMethod] 14 | public void Add() 15 | { 16 | var list = TestQueue(); 17 | 18 | Assert.AreEqual(3, list.Count); 19 | CollectionAssert.AreEqual(new float[] { 0.5f, 1.0f, 1.5f }, list.ToList()); 20 | 21 | list.Clear(); 22 | list.Add(new float[] { 0.5f, 1.0f, 1.5f }); 23 | 24 | Assert.AreEqual(3, list.Count); 25 | CollectionAssert.AreEqual(new float[] { 0.5f, 1.0f, 1.5f }, list.ToList()); 26 | } 27 | 28 | [TestMethod] 29 | public void Peek() 30 | { 31 | var list = new BinaryHeap(); 32 | 33 | list.Add(1); 34 | Assert.AreEqual(1, list.Peek()); 35 | 36 | list.Add(0.5f); 37 | Assert.AreEqual(0.5f, list.Peek()); 38 | 39 | list.Add(1.5f); 40 | Assert.AreEqual(0.5f, list.Peek()); 41 | } 42 | 43 | [TestMethod] 44 | public void RemoveFirst() 45 | { 46 | var list = TestQueue(); 47 | 48 | Assert.AreEqual(0.5f, list.Pop()); 49 | Assert.AreEqual(2, list.Count); 50 | 51 | Assert.AreEqual(1.0f, list.Pop()); 52 | Assert.AreEqual(1, list.Count); 53 | 54 | Assert.AreEqual(1.5f, list.Pop()); 55 | Assert.AreEqual(0, list.Count); 56 | } 57 | 58 | [TestMethod] 59 | public void Clear() 60 | { 61 | var list = TestQueue(); 62 | 63 | list.Clear(); 64 | Assert.AreEqual(0, list.Count); 65 | } 66 | 67 | [TestMethod] 68 | public void ToList() 69 | { 70 | var list = TestQueue(); 71 | CollectionAssert.AreEqual(new float[] { 0.5f, 1.0f, 1.5f }, list.ToList()); 72 | } 73 | 74 | private BinaryHeap TestQueue() 75 | { 76 | var list = new BinaryHeap(); 77 | 78 | list.Add(1); 79 | list.Add(0.5f); 80 | list.Add(1.5f); 81 | 82 | return list; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Common.Collections.Test/Queues/PriorityListTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Collections.Queues; 5 | 6 | namespace Common.Collections.Test.Queues 7 | { 8 | [TestClass] 9 | public class PriorityListTest 10 | { 11 | 12 | [TestMethod] 13 | public void Count() 14 | { 15 | var list = new PriorityList(); 16 | list.Add(0); 17 | Assert.AreEqual(1, list.Count); 18 | list.Remove(0); 19 | Assert.AreEqual(0, list.Count); 20 | } 21 | 22 | [TestMethod] 23 | public void Capacity() 24 | { 25 | var list = new PriorityList(); 26 | list.Capacity = 10; 27 | Assert.AreEqual(10, list.Capacity); 28 | list.Capacity = 1; 29 | Assert.AreEqual(1, list.Capacity); 30 | list.Capacity = 0; 31 | Assert.AreEqual(0, list.Capacity); 32 | } 33 | 34 | [TestMethod] 35 | public void Peek() 36 | { 37 | var list = TestQueue(); 38 | Assert.AreEqual(0.5f, list.Peek()); 39 | } 40 | 41 | [TestMethod] 42 | public void Pop() 43 | { 44 | var list = TestQueue(); 45 | 46 | Assert.AreEqual(0.5f, list.Pop()); 47 | Assert.AreEqual(2, list.Count); 48 | 49 | Assert.AreEqual(1.0f, list.Pop()); 50 | Assert.AreEqual(1, list.Count); 51 | 52 | Assert.AreEqual(1.5f, list.Pop()); 53 | Assert.AreEqual(0, list.Count); 54 | } 55 | 56 | [TestMethod] 57 | public void Add() 58 | { 59 | var list = TestQueue(); 60 | 61 | Assert.AreEqual(3, list.Count); 62 | CollectionAssert.AreEqual(new float[] { 0.5f, 1.0f, 1.5f }, list.ToList()); 63 | 64 | list.Clear(); 65 | list.Add(new float[] { 0.5f, 1.0f, 1.5f }); 66 | 67 | Assert.AreEqual(3, list.Count); 68 | CollectionAssert.AreEqual(new float[] { 0.5f, 1.0f, 1.5f }, list.ToList()); 69 | } 70 | 71 | 72 | [TestMethod] 73 | public void Remove() 74 | { 75 | var list = new PriorityList(); 76 | 77 | var a = new TestComparable(0.5f); 78 | var b = new TestComparable(1.0f); 79 | var c = new TestComparable(1.5f); 80 | var d = new TestComparable(1.0f); 81 | 82 | list.Add(a); 83 | list.Add(b); 84 | list.Add(c); 85 | 86 | Assert.AreEqual(3, list.Count); 87 | Assert.IsFalse(list.Remove(d)); 88 | Assert.IsTrue(list.Remove(b)); 89 | Assert.AreEqual(2, list.Count); 90 | } 91 | 92 | [TestMethod] 93 | public void ToList() 94 | { 95 | var list = TestQueue(); 96 | CollectionAssert.AreEqual(new float[] { 0.5f, 1.0f, 1.5f }, list.ToList()); 97 | } 98 | 99 | [TestMethod] 100 | public void Clear() 101 | { 102 | var list = TestQueue(); 103 | 104 | list.Clear(); 105 | Assert.AreEqual(0, list.Count); 106 | } 107 | 108 | private PriorityList TestQueue() 109 | { 110 | var list = new PriorityList(); 111 | 112 | list.Add(1); 113 | list.Add(0.5f); 114 | list.Add(1.5f); 115 | 116 | return list; 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Common.Collections.Test/Queues/TestComparable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common.Collections.Test.Queues 8 | { 9 | public class TestComparable : IComparable 10 | { 11 | public float value; 12 | 13 | public TestComparable(float v) 14 | { 15 | value = v; 16 | } 17 | 18 | public int CompareTo(TestComparable other) 19 | { 20 | return value.CompareTo(other.value); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Common.Collections/Arrays/ColorArray1.cs: -------------------------------------------------------------------------------- 1 | using Common.Core.Numerics; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Common.Core.Colors; 6 | 7 | namespace Common.Collections.Arrays 8 | { 9 | public class ColorArray1 : Array1 10 | { 11 | 12 | /// 13 | /// Create a new array. 14 | /// 15 | /// The size of the arrays 1st dimention. 16 | public ColorArray1(int count) 17 | : base(count) 18 | { 19 | 20 | } 21 | 22 | /// 23 | /// Create a new array. 24 | /// 25 | /// The data form the array. Will be deep copied. 26 | public ColorArray1(ColorRGB[] data) 27 | : base(data) 28 | { 29 | 30 | } 31 | 32 | /// 33 | /// 34 | /// 35 | /// 36 | public override string ToString() 37 | { 38 | return string.Format("[ColorArray1: Count={0}]", Count); 39 | } 40 | 41 | /// 42 | /// Sample the array by clamped bilinear interpolation. 43 | /// 44 | public ColorRGB GetClamped(float u) 45 | { 46 | float x = u * (Count-1); 47 | 48 | int xi = (int)MathUtil.Floor(x); 49 | 50 | var v0 = base.GetClamped(xi); 51 | var v1 = base.GetClamped(xi + 1); 52 | 53 | ColorRGB col; 54 | col.r = MathUtil.Lerp(v0.r, v1.r, x - xi); 55 | col.g = MathUtil.Lerp(v0.g, v1.g, x - xi); 56 | col.b = MathUtil.Lerp(v0.b, v1.b, x - xi); 57 | return col; 58 | } 59 | 60 | /// 61 | /// Sample the array by wrapped bilinear interpolation. 62 | /// 63 | public ColorRGB GetWrapped(float u) 64 | { 65 | float x = u * (Count - 1); 66 | 67 | int xi = (int)MathUtil.Floor(x); 68 | 69 | var v0 = base.GetWrapped(xi); 70 | var v1 = base.GetWrapped(xi + 1); 71 | 72 | ColorRGB col; 73 | col.r = MathUtil.Lerp(v0.r, v1.r, x - xi); 74 | col.g = MathUtil.Lerp(v0.g, v1.g, x - xi); 75 | col.b = MathUtil.Lerp(v0.b, v1.b, x - xi); 76 | return col; 77 | } 78 | 79 | /// 80 | /// Sample the array by wrapped bilinear interpolation. 81 | /// 82 | public ColorRGB GetMirrored(float u) 83 | { 84 | float x = u * (Count - 1); 85 | 86 | int xi = (int)MathUtil.Floor(x); 87 | 88 | var v0 = base.GetMirrored(xi); 89 | var v1 = base.GetMirrored(xi + 1); 90 | 91 | ColorRGB col; 92 | col.r = MathUtil.Lerp(v0.r, v1.r, x - xi); 93 | col.g = MathUtil.Lerp(v0.g, v1.g, x - xi); 94 | col.b = MathUtil.Lerp(v0.b, v1.b, x - xi); 95 | return col; 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Common.Collections/Arrays/FloatArray1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Collections.Arrays 7 | { 8 | public class FloatArray1 : Array1 9 | { 10 | 11 | /// 12 | /// Create a new array. 13 | /// 14 | /// The size of the arrays 1st dimention. 15 | public FloatArray1(int count) 16 | : base(count) 17 | { 18 | 19 | } 20 | 21 | /// 22 | /// Create a new array. 23 | /// 24 | /// The data form the array. Will be deep copied. 25 | public FloatArray1(float[] data) 26 | : base(data) 27 | { 28 | 29 | } 30 | 31 | /// 32 | /// 33 | /// 34 | /// 35 | public override string ToString() 36 | { 37 | return string.Format("[FloatArray1: Count={0}]", Count); 38 | } 39 | 40 | /// 41 | /// Sample the array by clamped bilinear interpolation. 42 | /// 43 | public float GetClamped(float u) 44 | { 45 | float x = u * (Count - 1); 46 | 47 | int xi = (int)MathUtil.Floor(x); 48 | 49 | var v0 = base.GetClamped(xi); 50 | var v1 = base.GetClamped(xi + 1); 51 | 52 | return MathUtil.Lerp(v0, v1, x - xi); 53 | } 54 | 55 | /// 56 | /// Sample the array by wrapped bilinear interpolation. 57 | /// 58 | public float GetWrapped(float u) 59 | { 60 | float x = u * (Count - 1); 61 | 62 | int xi = (int)MathUtil.Floor(x); 63 | 64 | var v0 = base.GetWrapped(xi); 65 | var v1 = base.GetWrapped(xi + 1); 66 | 67 | return MathUtil.Lerp(v0, v1, x - xi); 68 | } 69 | 70 | /// 71 | /// Sample the array by mirrored bilinear interpolation. 72 | /// 73 | public float GetMirrored(float u) 74 | { 75 | float x = u * (Count - 1); 76 | 77 | int xi = (int)MathUtil.Floor(x); 78 | 79 | var v0 = base.GetMirrored(xi); 80 | var v1 = base.GetMirrored(xi + 1); 81 | 82 | return MathUtil.Lerp(v0, v1, x - xi); 83 | } 84 | 85 | /// 86 | /// The sum of all the values in the array. 87 | /// 88 | /// 89 | public float Sum() 90 | { 91 | float sum = 0; 92 | for (int i = 0; i < Count; i++) 93 | sum += Data[i]; 94 | 95 | return sum; 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Common.Collections/Arrays/FloatArray2.cs: -------------------------------------------------------------------------------- 1 | using Common.Core.Numerics; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Common.Collections.Arrays 6 | { 7 | public class FloatArray2 : Array2 8 | { 9 | 10 | /// 11 | /// Create a new array. 12 | /// 13 | /// The size of the arrays 1st dimention. 14 | /// The size of the arrays 2st dimention. 15 | public FloatArray2(int width, int height) 16 | : base(width, height) 17 | { 18 | 19 | } 20 | 21 | /// 22 | /// Create a new array. 23 | /// 24 | /// The size of the array. 25 | public FloatArray2(Point2i size) 26 | : base(size.x, size.y) 27 | { 28 | 29 | } 30 | 31 | /// 32 | /// Create a new array. 33 | /// 34 | /// The data form the array. Will be deep copied. 35 | public FloatArray2(float[,] data) 36 | : base(data) 37 | { 38 | 39 | } 40 | 41 | /// 42 | /// 43 | /// 44 | /// 45 | public override string ToString() 46 | { 47 | return string.Format("[FloatArray2: Width={0}, Height={1}, Count={2}]", Width, Height, Count); 48 | } 49 | 50 | /// 51 | /// Sample the array by clamped bilinear interpolation. 52 | /// 53 | public float GetClamped(float u, float v) 54 | { 55 | float x = u * (Width-1); 56 | float y = v * (Height-1); 57 | 58 | int xi = (int)MathUtil.Floor(x); 59 | int yi = (int)MathUtil.Floor(y); 60 | 61 | var v00 = base.GetClamped(xi, yi); 62 | var v10 = base.GetClamped(xi + 1, yi); 63 | var v01 = base.GetClamped(xi, yi + 1); 64 | var v11 = base.GetClamped(xi + 1, yi + 1); 65 | 66 | return MathUtil.BLerp(v00, v10, v01, v11, x - xi, y - yi); 67 | } 68 | 69 | /// 70 | /// Sample the array by wrapped bilinear interpolation. 71 | /// 72 | public float GetWrapped(float u, float v) 73 | { 74 | float x = u * (Width - 1); 75 | float y = v * (Height - 1); 76 | 77 | int xi = (int)MathUtil.Floor(x); 78 | int yi = (int)MathUtil.Floor(y); 79 | 80 | var v00 = base.GetWrapped(xi, yi); 81 | var v10 = base.GetWrapped(xi + 1, yi); 82 | var v01 = base.GetWrapped(xi, yi + 1); 83 | var v11 = base.GetWrapped(xi + 1, yi + 1); 84 | 85 | return MathUtil.BLerp(v00, v10, v01, v11, x - xi, y - yi); 86 | } 87 | 88 | /// 89 | /// Sample the array by wrapped bilinear interpolation. 90 | /// 91 | public float GetMirrored(float u, float v) 92 | { 93 | float x = u * (Width - 1); 94 | float y = v * (Height - 1); 95 | 96 | int xi = (int)MathUtil.Floor(x); 97 | int yi = (int)MathUtil.Floor(y); 98 | 99 | var v00 = base.GetMirrored(xi, yi); 100 | var v10 = base.GetMirrored(xi + 1, yi); 101 | var v01 = base.GetMirrored(xi, yi + 1); 102 | var v11 = base.GetMirrored(xi + 1, yi + 1); 103 | 104 | return MathUtil.BLerp(v00, v10, v01, v11, x - xi, y - yi); 105 | } 106 | 107 | /// 108 | /// The sum of all the values in the array. 109 | /// 110 | /// 111 | public float Sum() 112 | { 113 | float sum = 0; 114 | for (int y = 0; y < Height; y++) 115 | for (int x = 0; x < Width; x++) 116 | sum += Data[x, y]; 117 | 118 | return sum; 119 | } 120 | 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /Common.Collections/Arrays/IArray1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Collections.Arrays 5 | { 6 | /// 7 | /// General interface for a 1 dimensional array. 8 | /// 9 | /// The element type 10 | public interface IArray1 : IEnumerable 11 | { 12 | /// 13 | /// The number of elements in the array. 14 | /// 15 | int Count { get; } 16 | 17 | /// 18 | /// Access a element at index x. 19 | /// 20 | T this[int x] { get; set; } 21 | 22 | /// 23 | /// Sets all elements in the array to default value. 24 | /// 25 | void Clear(); 26 | 27 | /// 28 | /// Get the element at clamped index x. 29 | /// 30 | T GetClamped(int x); 31 | 32 | /// 33 | /// Get the element at wrapped index x. 34 | /// 35 | T GetWrapped(int x); 36 | 37 | /// 38 | /// Get the element at mirrored index x. 39 | /// 40 | T GetMirrored(int x); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Common.Collections/Arrays/IArray2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Collections.Arrays 7 | { 8 | /// 9 | /// General interface for a 2 dimensional array. 10 | /// 11 | /// The element type 12 | public interface IArray2 : IEnumerable 13 | { 14 | /// 15 | /// The number of elements in the array. 16 | /// 17 | int Count { get; } 18 | 19 | /// 20 | /// The size of the arrays 1st dimention. 21 | /// 22 | int Width { get; } 23 | 24 | /// 25 | /// The size of the arrays 2st dimention. 26 | /// 27 | int Height { get; } 28 | 29 | /// 30 | /// Access a element at index x,y. 31 | /// 32 | T this[int x, int y] { get; set; } 33 | 34 | /// 35 | /// Access a element at index x,y. 36 | /// 37 | T this[Point2i i] { get; set; } 38 | 39 | /// 40 | /// Sets all elements in the array to default value. 41 | /// 42 | void Clear(); 43 | 44 | /// 45 | /// Get the element at clamped index x,y. 46 | /// 47 | T GetClamped(int x, int y); 48 | 49 | /// 50 | /// Get the element at wrapped index x,y. 51 | /// 52 | T GetWrapped(int x, int y); 53 | 54 | /// 55 | /// Get the element at mirrored index x,y. 56 | /// 57 | T GetMirrored(int x, int y); 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Common.Collections/Common.Collections.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0 4 | 40 5 | F:\Projects\Visual Studio Projects\Common\Backup\Common.Collections\ 6 | 2.0 7 | 8 | 9 | F:\Projects\Visual Studio Projects\Common\Common.Collections\bin\Release\Common.Collections.xml 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Common.Collections/Queues/IPriorityQueue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Collections.Queues 5 | { 6 | 7 | /// 8 | /// Interface for a list of items sorted by their comparable. 9 | /// See PriorityList, BinaryHeap or BinaryTree. 10 | /// 11 | /// 12 | public interface IPriorityQueue : IEnumerable 13 | { 14 | 15 | /// 16 | /// The number of items in queue. 17 | /// 18 | int Count { get; } 19 | 20 | /// 21 | /// Clear the queue. 22 | /// 23 | void Clear(); 24 | 25 | /// 26 | /// Return the first item in the queue. 27 | /// 28 | /// 29 | T Peek(); 30 | 31 | /// 32 | /// Remove the first item from the queue. 33 | /// 34 | /// 35 | T Pop(); 36 | 37 | /// 38 | /// Add a list of items to the queue. 39 | /// 40 | /// 41 | void Add(IEnumerable items); 42 | 43 | /// 44 | /// Add a single item to the queue. 45 | /// 46 | /// 47 | /// 48 | bool Add(T item); 49 | 50 | /// 51 | /// Return queue as list. 52 | /// 53 | /// 54 | List ToList(); 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Common.Collections/Sets/DisjointMappedSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Collections.Sets 5 | { 6 | /// 7 | /// a disjoint-set data structure is a data 8 | /// structure that tracks a set of elements 9 | /// partitioned into a number of disjoint 10 | /// (non-overlapping) subsets. 11 | /// Elements in the set can be any integer. 12 | /// 13 | public class DisjointMappedSet 14 | { 15 | /// 16 | /// The parents of the element at each key. 17 | /// All elements with the same parent belong 18 | /// to the same set. A element may have its parent 19 | /// set to -1 to indicate this element has 20 | /// been deleted. If a elements parent is itsself 21 | /// then this is a root element. 22 | /// 23 | private Dictionary m_parent; 24 | 25 | private Dictionary m_rank; 26 | 27 | public DisjointMappedSet() 28 | { 29 | m_parent = new Dictionary(); 30 | m_rank = new Dictionary(); 31 | } 32 | 33 | public int Count => m_rank.Count; 34 | 35 | /// 36 | /// 37 | /// 38 | /// 39 | public override string ToString() 40 | { 41 | return string.Format("[DisjointMappedSet: Count={0}]", Count); 42 | } 43 | 44 | /// 45 | /// Clear the set. 46 | /// 47 | public void Clear() 48 | { 49 | m_parent.Clear(); 50 | m_rank.Clear(); 51 | } 52 | 53 | /// 54 | /// Does the set contain 55 | /// this element. 56 | /// 57 | public bool Contains(int id) 58 | { 59 | return m_parent.ContainsKey(id); 60 | } 61 | 62 | /// 63 | /// Added a new element and set what 64 | /// the elements parent is. 65 | /// 66 | public void Add(int id, int parent) 67 | { 68 | if(m_parent.ContainsKey(id)) 69 | m_parent[id] = parent; 70 | else 71 | { 72 | m_parent.Add(id, parent); 73 | m_rank.Add(id, 1); 74 | } 75 | } 76 | 77 | /// 78 | /// Find the elements parent. 79 | /// If the element has been deleted its parent is -1. 80 | /// If the elements parent is itself it is the root element. 81 | /// 82 | public int FindParent(int id) 83 | { 84 | int p = m_parent[id]; 85 | 86 | if (p == -1) return -1; 87 | 88 | if (p != m_parent[m_parent[id]]) 89 | m_parent[id] = FindParent(m_parent[id]); 90 | 91 | return m_parent[id]; 92 | } 93 | 94 | /// 95 | /// Merge the two sets. 96 | /// 97 | public bool Union(int from, int to) 98 | { 99 | int x = FindParent(from); 100 | int y = FindParent(to); 101 | 102 | if (x == y) return false; 103 | 104 | // make sure rank[xx] is smaller 105 | if (m_rank[x] > m_rank[y]) { int t = x; x = y; y = t; } 106 | 107 | // if both are equal, the combined tree becomes 1 deeper 108 | if (m_rank[x] == m_rank[y]) m_rank[y]++; 109 | 110 | m_parent[x] = y; 111 | 112 | return true; 113 | 114 | } 115 | 116 | } 117 | 118 | 119 | } -------------------------------------------------------------------------------- /Common.Collections/Sets/DisjointSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Collections.Sets 5 | { 6 | 7 | /// 8 | /// a disjoint-set data structure is a data 9 | /// structure that tracks a set of elements 10 | /// partitioned into a number of disjoint 11 | /// (non-overlapping) subsets. 12 | /// Elements in the set must be integer 13 | /// ranging from 0 to Count-1. 14 | /// 15 | public class DisjointSet 16 | { 17 | /// 18 | /// The parents of the element at each index. 19 | /// All elements with the same parent belong 20 | /// to the same set. A element may have its parent 21 | /// set to -1 to indicate this element has 22 | /// been deleted. If a elements parent is its self 23 | /// then this is a root element. 24 | /// 25 | private List m_parent; 26 | 27 | private List m_rank; 28 | 29 | public DisjointSet() 30 | { 31 | m_parent = new List(); 32 | m_rank = new List(); 33 | } 34 | 35 | public DisjointSet(int size) 36 | { 37 | m_parent = new List(size); 38 | m_rank = new List(size); 39 | AddRange(size); 40 | } 41 | 42 | public int Count => m_rank.Count; 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | public override string ToString() 49 | { 50 | return string.Format("[DisjointSet: Count={0}]", Count); 51 | } 52 | 53 | /// 54 | /// Clear the set. 55 | /// 56 | public void Clear() 57 | { 58 | m_parent.Clear(); 59 | m_rank.Clear(); 60 | } 61 | 62 | /// 63 | /// Added a new elements and set there 64 | /// parent to its self. 65 | /// 66 | public void AddRange(int count) 67 | { 68 | for (int i = 0; i < count; i++) 69 | AddNext(); 70 | } 71 | 72 | /// 73 | /// Added a new element and set its 74 | /// parent to its self. 75 | /// 76 | public int AddNext() 77 | { 78 | int parent = Count; 79 | m_parent.Add(parent); 80 | m_rank.Add(1); 81 | return parent; 82 | } 83 | 84 | /// 85 | /// Find the elements parent. 86 | /// If the element has been deleted its parent is -1. 87 | /// If the elements parent is itself it is the root element. 88 | /// 89 | public int FindParent(int id) 90 | { 91 | int p = m_parent[id]; 92 | if (p == -1) return -1; 93 | 94 | if (m_parent[id] != m_parent[m_parent[id]]) 95 | m_parent[id] = FindParent(m_parent[id]); 96 | 97 | return m_parent[id]; 98 | } 99 | 100 | /// 101 | /// Merge the two sets. 102 | /// 103 | public bool Union(int from, int to) 104 | { 105 | int x = FindParent(from); 106 | int y = FindParent(to); 107 | 108 | if (x == y) return false; 109 | 110 | // make sure rank[xx] is smaller 111 | if (m_rank[x] > m_rank[y]) { int t = x; x = y; y = t; } 112 | 113 | // if both are equal, the combined tree becomes 1 deeper 114 | if (m_rank[x] == m_rank[y]) m_rank[y]++; 115 | 116 | m_parent[x] = y; 117 | 118 | return true; 119 | } 120 | 121 | } 122 | 123 | 124 | } -------------------------------------------------------------------------------- /Common.Collections/Trees/BinaryTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace Common.Collections.Trees 6 | { 7 | 8 | /// 9 | /// Node for a binary tree 10 | /// 11 | /// 12 | public class BinaryTreeNode : IEnumerable> 13 | { 14 | 15 | /// 16 | /// The nodes item. 17 | /// 18 | public T Item { get; internal set; } 19 | 20 | /// 21 | /// The left node. Maybe null. 22 | /// 23 | public BinaryTreeNode Left { get; internal set; } 24 | 25 | /// 26 | /// The right node. Maybe null. 27 | /// 28 | public BinaryTreeNode Right { get; internal set; } 29 | 30 | /// 31 | /// Is this node a leaf. 32 | /// 33 | public bool IsLeaf 34 | { 35 | get { return Left == null && Right == null; } 36 | } 37 | 38 | /// 39 | /// Used internally to balance AVLTrees. 40 | /// 41 | internal int Balance { get; set; } 42 | 43 | /// 44 | /// The nodes parent. Null if node is the root. 45 | /// 46 | public BinaryTreeNode Parent { get; internal set; } 47 | 48 | internal BinaryTreeNode(BinaryTreeNode parent, T item) 49 | { 50 | Parent = parent; 51 | Item = item; 52 | } 53 | 54 | /// 55 | /// 56 | /// 57 | /// 58 | public override string ToString() 59 | { 60 | return string.Format("[BinaryTreeNode: IsLeaf={0}, Item={1}]", IsLeaf, Item); 61 | } 62 | 63 | /// 64 | /// Enumerate all items from this node. 65 | /// 66 | /// 67 | public IEnumerator> GetEnumerator() 68 | { 69 | if(Left != null) 70 | { 71 | foreach (var n in Left) 72 | yield return n; 73 | } 74 | 75 | yield return this; 76 | 77 | if (Right != null) 78 | { 79 | foreach (var n in Right) 80 | yield return n; 81 | } 82 | } 83 | 84 | IEnumerator IEnumerable.GetEnumerator() 85 | { 86 | return GetEnumerator(); 87 | } 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Common.Console/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Common.Console/Common.Console.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E753D97F-83BB-4A50-A55F-F3EEAD1C8DE8} 8 | Exe 9 | Common.Console 10 | Common.Console 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | x64 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\Common.Core\bin\Release\netstandard2.0\Common.Core.dll 39 | 40 | 41 | ..\Common.Meshing\bin\Release\netstandard2.0\Common.Meshing.dll 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | .editorconfig 59 | 60 | 61 | 62 | 63 | 64 | {d3e52eba-9643-4051-91ea-c49d0290fcd9} 65 | Common.Collections 66 | 67 | 68 | {f8e8054c-c677-4d42-ba29-17fc132dba05} 69 | Common.Geometry 70 | 71 | 72 | {aae15d50-f89f-4019-bb56-adcdf5db1955} 73 | Common.GraphTheory 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Common.Console/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | using Common.Core.Directions; 7 | using Common.Core.Time; 8 | 9 | using Common.GraphTheory.GridGraphs; 10 | 11 | using CONSOLE = System.Console; 12 | 13 | namespace Common.Console 14 | { 15 | class Program 16 | { 17 | 18 | static void Main(string[] args) 19 | { 20 | } 21 | 22 | static void WriteLine(object obj) 23 | { 24 | CONSOLE.WriteLine(obj?.ToString()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Common.Console/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Common.Console")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Common.Console")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e753d97f-83bb-4a50-a55f-f3eead1c8de8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Common.Core.Test/Bits/BitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | using Common.Core.Bits; 7 | 8 | namespace Common.Core.Test.Bits 9 | { 10 | [TestClass] 11 | public class BitTest 12 | { 13 | [TestMethod] 14 | public void SetBit() 15 | { 16 | 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Common.Core.Test/Colors/ColorHSVTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Colors; 5 | 6 | namespace Common.Core.Test.Colors 7 | { 8 | [TestClass] 9 | public class ColorHSVTest 10 | { 11 | [TestMethod] 12 | public void AreEqual() 13 | { 14 | Assert.IsTrue(ColorHSV.White.Equals(new ColorHSV(0, 0, 1))); 15 | } 16 | 17 | [TestMethod] 18 | public void AreNotEqual() 19 | { 20 | Assert.IsTrue(ColorHSV.White != new ColorHSV(2, 2, 2)); 21 | } 22 | 23 | [TestMethod] 24 | public void AreEqualWithError() 25 | { 26 | Assert.IsTrue(ColorHSV.AlmostEqual(Random(0), Random(0), 1e-6f)); 27 | } 28 | 29 | [TestMethod] 30 | public void Add() 31 | { 32 | Assert.AreEqual(ColorHSV.Green + ColorHSV.Green, new ColorHSV(240.0f / 360.0f, 2, 2)); 33 | } 34 | 35 | [TestMethod] 36 | public void Sub() 37 | { 38 | Assert.AreEqual(ColorHSV.Green - ColorHSV.Green, new ColorHSV(0, 0, 0)); 39 | } 40 | 41 | [TestMethod] 42 | public void Mul() 43 | { 44 | Assert.AreEqual(ColorHSV.Green * new ColorHSV(2, 2, 2), new ColorHSV(240.0f / 360.0f, 2, 2)); 45 | Assert.AreEqual(ColorHSV.Green * 2, new ColorHSV(240.0f / 360.0f, 2, 2)); 46 | } 47 | 48 | [TestMethod] 49 | public void Div() 50 | { 51 | Assert.AreEqual(ColorHSV.Green / new ColorHSV(2, 2, 2), new ColorHSV(60.0f / 360.0f, 0.5f, 0.5f)); 52 | Assert.AreEqual(ColorHSV.Green / 2, new ColorHSV(60.0f / 360.0f, 0.5f, 0.5f)); 53 | } 54 | 55 | 56 | [TestMethod] 57 | public void AccessedByIndex() 58 | { 59 | 60 | ColorHSV vd = new ColorHSV(); 61 | vd[0] = 1; 62 | vd[1] = 2; 63 | vd[2] = 3; 64 | 65 | Assert.AreEqual(vd[0], 1); 66 | Assert.AreEqual(vd[1], 2); 67 | Assert.AreEqual(vd[2], 3); 68 | 69 | } 70 | 71 | [TestMethod] 72 | public void DefaultColors() 73 | { 74 | Assert.IsTrue(ColorHSV.Black.rgb == ColorRGB.Black); 75 | Assert.IsTrue(ColorHSV.White.rgb == ColorRGB.White); 76 | Assert.IsTrue(ColorHSV.Green.rgb == ColorRGB.Green); 77 | Assert.IsTrue(ColorHSV.Red.rgb == ColorRGB.Red); 78 | Assert.IsTrue(ColorHSV.Blue.rgb == ColorRGB.Blue); 79 | } 80 | 81 | [TestMethod] 82 | public void ToHSV() 83 | { 84 | 85 | for (int i = 0; i < 10; i++) 86 | { 87 | ColorHSV hsv = Random(i); 88 | 89 | ColorRGB rgb = hsv.rgb; 90 | 91 | ColorHSV col = rgb.hsv; 92 | 93 | Assert.IsTrue(ColorHSV.AlmostEqual(hsv, col, 1e-6f)); 94 | } 95 | } 96 | 97 | ColorHSV Random(int seed) 98 | { 99 | Random rnd = new Random(seed); 100 | return new ColorHSV((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble()); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Common.Core.Test/Colors/ColorRGBATest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Colors; 5 | 6 | namespace Common.Core.Test.Colors 7 | { 8 | [TestClass] 9 | public class ColorRGBATest 10 | { 11 | [TestMethod] 12 | public void AreEqual() 13 | { 14 | Assert.IsTrue(ColorRGBA.White.Equals(new ColorRGBA(1, 1, 1, 1))); 15 | } 16 | 17 | [TestMethod] 18 | public void AreNotEqual() 19 | { 20 | Assert.IsTrue(ColorRGBA.White != new ColorRGBA(2, 2, 2, 2)); 21 | } 22 | 23 | [TestMethod] 24 | public void AreEqualWithError() 25 | { 26 | Assert.IsTrue(ColorRGBA.AlmostEqual(Random(0), Random(0), 1e-6f)); 27 | } 28 | 29 | [TestMethod] 30 | public void Add() 31 | { 32 | Assert.AreEqual(ColorRGBA.White + ColorRGBA.White, new ColorRGBA(2, 2, 2, 2)); 33 | } 34 | 35 | [TestMethod] 36 | public void Sub() 37 | { 38 | Assert.AreEqual(ColorRGBA.White - ColorRGBA.White, new ColorRGBA(0, 0, 0, 0)); 39 | } 40 | 41 | [TestMethod] 42 | public void Mul() 43 | { 44 | Assert.AreEqual(ColorRGBA.White * new ColorRGBA(2, 2, 2, 2), new ColorRGBA(2, 2, 2, 2)); 45 | Assert.AreEqual(ColorRGBA.White * 2, new ColorRGBA(2, 2, 2, 2)); 46 | } 47 | 48 | [TestMethod] 49 | public void Div() 50 | { 51 | Assert.AreEqual(ColorRGBA.White / new ColorRGBA(2, 2, 2, 2), new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f)); 52 | Assert.AreEqual(ColorRGBA.White / 2, new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f)); 53 | } 54 | 55 | 56 | [TestMethod] 57 | public void AccessedByIndex() 58 | { 59 | 60 | ColorRGBA vd = new ColorRGBA(); 61 | vd[0] = 1; 62 | vd[1] = 2; 63 | vd[2] = 3; 64 | vd[3] = 4; 65 | 66 | Assert.AreEqual(vd[0], 1); 67 | Assert.AreEqual(vd[1], 2); 68 | Assert.AreEqual(vd[2], 3); 69 | Assert.AreEqual(vd[3], 4); 70 | } 71 | 72 | [TestMethod] 73 | public void min() 74 | { 75 | ColorRGBA vd = ColorRGBA.White; 76 | vd = ColorRGBA.Min(vd, 0.5f); 77 | 78 | Assert.AreEqual(vd, new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f)); 79 | } 80 | 81 | [TestMethod] 82 | public void Max() 83 | { 84 | ColorRGBA vd = ColorRGBA.White; 85 | vd = ColorRGBA.Max(vd, 1.5f); 86 | 87 | Assert.AreEqual(vd, new ColorRGBA(1.5f, 1.5f, 1.5f, 1.5f)); 88 | } 89 | 90 | [TestMethod] 91 | public void Clamp() 92 | { 93 | ColorRGBA vd = new ColorRGBA(0.4f, 1.6f, 0.1f, 1.7f); 94 | vd = ColorRGBA.Clamp(vd, 0.5f, 1.5f); 95 | 96 | Assert.AreEqual(vd, new ColorRGBA(0.5f, 1.5f, 0.5f, 1.5f)); 97 | } 98 | 99 | ColorRGBA Random(int seed) 100 | { 101 | Random rnd = new Random(seed); 102 | return new ColorRGBA((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble()); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Common.Core.Test/Colors/ColorRGBTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Colors; 5 | 6 | namespace Common.Core.Test.Colors 7 | { 8 | [TestClass] 9 | public class ColorRGBTest 10 | { 11 | [TestMethod] 12 | public void AreEqual() 13 | { 14 | Assert.IsTrue(ColorRGB.White.Equals(new ColorRGB(1, 1, 1))); 15 | } 16 | 17 | [TestMethod] 18 | public void AreNotEqual() 19 | { 20 | Assert.IsTrue(ColorRGB.White != new ColorRGB(2, 2, 2)); 21 | } 22 | 23 | [TestMethod] 24 | public void AreEqualWithError() 25 | { 26 | Assert.IsTrue(ColorRGB.AlmostEqual(Random(0), Random(0), 1e-6f)); 27 | } 28 | 29 | [TestMethod] 30 | public void Add() 31 | { 32 | Assert.AreEqual(ColorRGB.White + ColorRGB.White, new ColorRGB(2, 2, 2)); 33 | } 34 | 35 | [TestMethod] 36 | public void Sub() 37 | { 38 | Assert.AreEqual(ColorRGB.White - ColorRGB.White, new ColorRGB(0, 0, 0)); 39 | } 40 | 41 | [TestMethod] 42 | public void Mul() 43 | { 44 | Assert.AreEqual(ColorRGB.White * new ColorRGB(2, 2, 2), new ColorRGB(2, 2, 2)); 45 | Assert.AreEqual(ColorRGB.White * 2, new ColorRGB(2, 2, 2)); 46 | } 47 | 48 | [TestMethod] 49 | public void Div() 50 | { 51 | Assert.AreEqual(ColorRGB.White / new ColorRGB(2, 2, 2), new ColorRGB(0.5f, 0.5f, 0.5f)); 52 | Assert.AreEqual(ColorRGB.White / 2, new ColorRGB(0.5f, 0.5f, 0.5f)); 53 | } 54 | 55 | 56 | [TestMethod] 57 | public void AccessedByIndex() 58 | { 59 | 60 | ColorRGB vd = new ColorRGB(); 61 | vd[0] = 1; 62 | vd[1] = 2; 63 | vd[2] = 3; 64 | 65 | Assert.AreEqual(vd[0], 1); 66 | Assert.AreEqual(vd[1], 2); 67 | Assert.AreEqual(vd[2], 3); 68 | 69 | } 70 | 71 | [TestMethod] 72 | public void Min() 73 | { 74 | ColorRGB vd = ColorRGB.White; 75 | vd = ColorRGB.Min(vd, 0.5f); 76 | 77 | Assert.AreEqual(vd, new ColorRGB(0.5f, 0.5f, 0.5f)); 78 | } 79 | 80 | [TestMethod] 81 | public void Max() 82 | { 83 | ColorRGB vd = ColorRGB.White; 84 | vd = ColorRGB.Max(vd, 1.5f); 85 | 86 | Assert.AreEqual(vd, new ColorRGB(1.5f, 1.5f, 1.5f)); 87 | } 88 | 89 | [TestMethod] 90 | public void Clamp() 91 | { 92 | ColorRGB vd = new ColorRGB(0.4f, 1.6f, 0.1f); 93 | vd = ColorRGB.Clamp(vd, 0.5f, 1.5f); 94 | 95 | Assert.AreEqual(vd, new ColorRGB(0.5f, 1.5f, 0.5f)); 96 | } 97 | 98 | [TestMethod] 99 | public void ToHSV() 100 | { 101 | 102 | for (int i = 0; i < 10; i++) 103 | { 104 | ColorRGB rgb = Random(i); 105 | 106 | ColorHSV hsv = rgb.hsv; 107 | 108 | ColorRGB col = hsv.rgb; 109 | 110 | Assert.IsTrue(ColorRGB.AlmostEqual(rgb, col, 1e-6f)); 111 | } 112 | } 113 | 114 | ColorRGB Random(int seed) 115 | { 116 | Random rnd = new Random(seed); 117 | return new ColorRGB((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble()); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Common.Core.Test/Directions/D26Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | using Common.Core.Directions; 6 | using Common.Core.Numerics; 7 | 8 | namespace Common.Core.Test.Directions 9 | { 10 | [TestClass] 11 | public class D26Test 12 | { 13 | [TestMethod] 14 | public void Offsets() 15 | { 16 | 17 | Assert.AreEqual(26, D26.OFFSETS.GetLength(0)); 18 | 19 | var set = new HashSet(); 20 | 21 | for (int i = 0; i < 26; i++) 22 | { 23 | int x = D26.OFFSETS[i, 0]; 24 | int y = D26.OFFSETS[i, 1]; 25 | int z = D26.OFFSETS[i, 2]; 26 | 27 | var idx = new Point3i(x, y, z); 28 | 29 | Assert.IsFalse(set.Contains(idx)); 30 | 31 | set.Add(idx); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Common.Core.Test/Extensions/IListExtensionTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | using Common.Core.Extensions; 6 | 7 | namespace Common.Core.Test.Extensions 8 | { 9 | [TestClass] 10 | public class IListExtensionTest 11 | { 12 | [TestMethod] 13 | public void Shuffle() 14 | { 15 | 16 | int[] array = new int[10]; 17 | for (int i = 0; i < 10; i++) 18 | array[i] = i; 19 | 20 | Random rnd = new Random(0); 21 | array.Shuffle(rnd); 22 | 23 | int[] result = new int[] 24 | { 25 | 0,4,5,8,2,1,3,6,9,7 26 | }; 27 | 28 | CollectionAssert.AreEqual(result, array); 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Common.Core.Test/Numerics/MathTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Core.Test.Numerics 7 | { 8 | [TestClass] 9 | public class MathUtilTests 10 | { 11 | [TestMethod] 12 | public void Pow() 13 | { 14 | Assert.AreEqual(11398895185373143, MathUtil.IntPow(7, 19)); 15 | Assert.AreEqual(29192926025390625, MathUtil.IntPow(15, 14)); 16 | } 17 | 18 | [TestMethod] 19 | public void Permutations() 20 | { 21 | Assert.AreEqual(1, MathUtil.Permutations(1)); 22 | Assert.AreEqual(2, MathUtil.Permutations(2)); 23 | Assert.AreEqual(6, MathUtil.Permutations(3)); 24 | Assert.AreEqual(24, MathUtil.Permutations(4)); 25 | Assert.AreEqual(120, MathUtil.Permutations(5)); 26 | Assert.AreEqual(2432902008176640000u, MathUtil.Permutations(20)); 27 | } 28 | 29 | [TestMethod] 30 | public void Factorial() 31 | { 32 | Assert.AreEqual(1u, MathUtil.Factorial(0)); 33 | Assert.AreEqual(1u, MathUtil.Factorial(1)); 34 | Assert.AreEqual(2u, MathUtil.Factorial(2)); 35 | Assert.AreEqual(6u, MathUtil.Factorial(3)); 36 | Assert.AreEqual(24u, MathUtil.Factorial(4)); 37 | Assert.AreEqual(120u, MathUtil.Factorial(5)); 38 | Assert.AreEqual(720u, MathUtil.Factorial(6)); 39 | Assert.AreEqual(2432902008176640000u, MathUtil.Factorial(20)); 40 | } 41 | 42 | [TestMethod] 43 | public void PermutationsOrderedWithRepeats() 44 | { 45 | //If you roll a six-sided dice twice, how many possible out comes are there? 46 | Assert.AreEqual(36, MathUtil.PermutationsOrderedWithRepeats(2, 6)); 47 | 48 | //If you flip a coin 4 times, how many possible out comes are there? 49 | Assert.AreEqual(16, MathUtil.PermutationsOrderedWithRepeats(4, 2)); 50 | } 51 | 52 | [TestMethod] 53 | public void PermutationsOrderedWithoutRepeats() 54 | { 55 | //How many different ordered pairs of people can be chosen from a group of 5 people. 56 | Assert.AreEqual(20, MathUtil.PermutationsOrderedWithoutRepeats(2,5)); 57 | } 58 | 59 | [TestMethod] 60 | public void PermutationsUnorderedWithRepeats() 61 | { 62 | //Put 3 letters in a hat. If you draw out 4, putting each drawn letter 63 | //back into the hat after a draw, how many unordered combinations could there be? 64 | Assert.AreEqual(15, MathUtil.PermutationsUnorderedWithRepeats(4, 3)); 65 | } 66 | 67 | [TestMethod] 68 | public void PermutationsUnorderedWithoutRepeats() 69 | { 70 | //How many different unordered pairs of people can be chosen from a group of 5 people. 71 | Assert.AreEqual(10, MathUtil.PermutationsUnorderedWithoutRepeats(2, 5)); 72 | 73 | //How many possible poker hands are possible in a deck of 52 cards? 74 | Assert.AreEqual(2598960, MathUtil.PermutationsUnorderedWithoutRepeats(5, 52)); 75 | } 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Common.Core.Test/Numerics/Union32Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Core.Test.Numerics 7 | { 8 | [TestClass] 9 | public class Union32Test 10 | { 11 | [TestMethod] 12 | public void Constuction() 13 | { 14 | Union32 data; 15 | 16 | data = -1; 17 | Assert.AreEqual(-1, data.Int); 18 | data = 123456789; 19 | Assert.AreEqual(123456789, data.Int); 20 | 21 | data = uint.MaxValue; 22 | Assert.AreEqual(uint.MaxValue, data.UInt); 23 | 24 | data = 1.0f; 25 | Assert.AreEqual(1.0f, data.Float); 26 | data = 0.33333f; 27 | Assert.AreEqual(0.33333f, data.Float); 28 | data = float.PositiveInfinity; 29 | Assert.AreEqual(float.PositiveInfinity, data.Float); 30 | data = float.NegativeInfinity; 31 | Assert.AreEqual(float.NegativeInfinity, data.Float); 32 | data = float.NaN; 33 | Assert.AreEqual(float.NaN, data.Float); 34 | 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Common.Core.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Common.Core.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Common.Core.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2559b36f-be71-4b30-95c7-9619afcc3df1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Box2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Core.Test.Shapes 8 | { 9 | [TestClass] 10 | public class Box2fTest 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Box2iTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | using Common.Core.Numerics; 7 | using Common.Core.Shapes; 8 | 9 | namespace Common.Core.Test.Shapes 10 | { 11 | [TestClass] 12 | public class Box2iTest 13 | { 14 | [TestMethod] 15 | public void EnumeratePerimeter() 16 | { 17 | 18 | var box = new Box2i(0, 10); 19 | var set = new HashSet(); 20 | 21 | foreach (var p in box.EnumeratePerimeter(1)) 22 | { 23 | Assert.IsFalse(set.Contains(p)); 24 | Assert.IsTrue(box.Contains(p)); 25 | set.Add(p); 26 | } 27 | 28 | set.Clear(); 29 | 30 | foreach (var p in box.EnumeratePerimeter(2)) 31 | { 32 | Assert.IsFalse(set.Contains(p)); 33 | Assert.IsTrue(box.Contains(p)); 34 | set.Add(p); 35 | } 36 | 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Circle2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Core.Test.Shapes 8 | { 9 | [TestClass] 10 | public class Circle2fTest 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Line2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Core.Test.Shapes 8 | { 9 | [TestClass] 10 | public class Line2fTest 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Ray2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | 8 | namespace Common.Core.Test.Shapes 9 | { 10 | [TestClass] 11 | public class Ray2fTest 12 | { 13 | [TestMethod] 14 | public void IntersectRay() 15 | { 16 | var ray1 = new Ray2f(new Point2f(0, 0), new Vector2f(1, 0)); 17 | var ray2 = new Ray2f(new Point2f(1, 2), new Vector2f(0, -1)); 18 | 19 | float s, t; 20 | ray1.Intersects(ray2, out s, out t); 21 | 22 | Assert.IsTrue(MathUtil.AlmostEqual(1, s)); 23 | Assert.IsTrue(MathUtil.AlmostEqual(2, t)); 24 | Assert.IsTrue(Point2f.AlmostEqual(new Point2f(1, 0), ray1.GetPosition(s))); 25 | Assert.IsTrue(Point2f.AlmostEqual(new Point2f(1, 0), ray2.GetPosition(t))); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Segment2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Core.Test.Shapes 8 | { 9 | [TestClass] 10 | public class Segment2fTest 11 | { 12 | 13 | [TestMethod] 14 | public void IntersectsBox() 15 | { 16 | var min = new Point2f(-2, -1); 17 | var max = new Point2f(1, 3); 18 | var box = new Box2f(min, max); 19 | 20 | var seg = new Segment2f(new Point2f(-6,-1), new Point2f(-3,-1)); 21 | Assert.IsFalse(seg.Intersects(box)); 22 | 23 | seg = new Segment2f(new Point2f(-1, -4), new Point2f(3, -1)); 24 | Assert.IsFalse(seg.Intersects(box)); 25 | 26 | seg = new Segment2f(new Point2f(1, 4), new Point2f(1, 6)); 27 | Assert.IsFalse(seg.Intersects(box)); 28 | 29 | seg = new Segment2f(new Point2f(-2, -3), new Point2f(-2, 5)); 30 | Assert.IsTrue(seg.Intersects(box)); 31 | 32 | seg = new Segment2f(new Point2f(-1, 2), new Point2f(-1, -2)); 33 | Assert.IsTrue(seg.Intersects(box)); 34 | 35 | seg = new Segment2f(new Point2f(-3, 1), new Point2f(2, 1)); 36 | Assert.IsTrue(seg.Intersects(box)); 37 | 38 | seg = new Segment2f(new Point2f(-3, 3), new Point2f(3, 2)); 39 | Assert.IsTrue(seg.Intersects(box)); 40 | 41 | seg = new Segment2f(new Point2f(-1, 0), new Point2f(2, 2)); 42 | Assert.IsTrue(seg.Intersects(box)); 43 | 44 | seg = new Segment2f(new Point2f(1, 3), new Point2f(1, 1)); 45 | Assert.IsTrue(seg.Intersects(box)); 46 | 47 | seg = new Segment2f(new Point2f(-2, -1), new Point2f(1, 1)); 48 | Assert.IsTrue(seg.Intersects(box)); 49 | 50 | seg = new Segment2f(new Point2f(-1, -1), new Point2f(2, -1)); 51 | Assert.IsTrue(seg.Intersects(box)); 52 | 53 | seg = new Segment2f(new Point2f(1, 3), new Point2f(1, 4)); 54 | Assert.IsTrue(seg.Intersects(box)); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Common.Core.Test/Shapes/Triangle2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Core.Test.Shapes 8 | { 9 | [TestClass] 10 | public class Triangle2fTest 11 | { 12 | [TestMethod] 13 | public void Area() 14 | { 15 | var a = new Point2f(0, 1); 16 | var b = new Point2f(0, 0); 17 | var c = new Point2f(1, 0); 18 | var triangle = new Triangle2f(a, b, c); 19 | 20 | Assert.AreEqual(0.5f, triangle.SignedArea); 21 | Assert.AreEqual(0.5f, triangle.Area); 22 | } 23 | 24 | [TestMethod] 25 | public void IntersectsBox() 26 | { 27 | var a = new Point2f(-2, -1); 28 | var b = new Point2f(1, -1); 29 | var c = new Point2f(1, 1); 30 | var triangle = new Triangle2f(a, b, c); 31 | 32 | var box = new Box2f(new Point2f(-3, -3), new Point2f(-2,-2)); 33 | //Assert.IsFalse(triangle.Intersects(box)); 34 | 35 | box = new Box2f(new Point2f(-2, -1), new Point2f(1, 2)); 36 | //Assert.IsFalse(triangle.Intersects(box)); 37 | 38 | box = new Box2f(new Point2f(1, -3), new Point2f(2, -2)); 39 | //Assert.IsFalse(triangle.Intersects(box)); 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Common.Core/Bits/Bit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Core.Bits 5 | { 6 | public static class Bit 7 | { 8 | 9 | public static int Set(int value, int position) 10 | { 11 | return value | (1 << position); 12 | } 13 | 14 | public static byte Set(byte value, int position) 15 | { 16 | return (byte)(value | (1 << position)); 17 | } 18 | 19 | public static void Set(ref int value, int position) 20 | { 21 | value |= (1 << position); 22 | } 23 | 24 | public static bool IsSet(int value, int position) 25 | { 26 | return (value & (1 << position)) != 0; 27 | } 28 | 29 | public static int Clear(int value, int position) 30 | { 31 | return value & ~(1 << position); 32 | } 33 | 34 | public static byte Clear(byte value, int position) 35 | { 36 | return (byte)(value & ~(1 << position)); 37 | } 38 | 39 | public static void Clear(ref int value, int position) 40 | { 41 | value &= ~(1 << position); 42 | } 43 | 44 | public static int Flip(int value, int position) 45 | { 46 | return value ^ (1 << position); 47 | } 48 | 49 | public static byte Flip(byte value, int position) 50 | { 51 | return (byte)(value ^ (1 << position)); 52 | } 53 | 54 | public static void Flip(ref int value, int position) 55 | { 56 | value ^= (1 << position); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Common.Core/Common.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0 4 | 40 5 | F:\Projects\Visual Studio Projects\Common\Backup\Common.Core\ 6 | 2.0 7 | 8 | 9 | true 10 | F:\Projects\Visual Studio Projects\Common\Common.Core\bin\Release\Common.Core.xml 11 | 12 | 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Common.Core/Directions/D26.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Common.Core.Directions 6 | { 7 | /// 8 | /// Represents the 26 directions around a 3D array 9 | /// including diagonals. 10 | /// 11 | public static class D26 12 | { 13 | /// 14 | /// Assign a number to each direction. 15 | /// 16 | public const int LEFT_TOP = 0; 17 | public const int LEFT_TOP_FRONT = 1; 18 | public const int TOP_FRONT = 2; 19 | public const int RIGHT_TOP_FRONT = 3; 20 | public const int RIGHT_TOP = 4; 21 | public const int RIGHT_TOP_BACK = 5; 22 | public const int TOP_BACK = 6; 23 | public const int LEFT_TOP_BACK = 7; 24 | public const int TOP = 8; 25 | 26 | public const int LEFT = 9; 27 | public const int LEFT_FRONT = 10; 28 | public const int FRONT = 11; 29 | public const int RIGHT_FRONT = 12; 30 | public const int RIGHT = 13; 31 | public const int RIGHT_BACK = 14; 32 | public const int BACK = 15; 33 | public const int LEFT_BACK = 16; 34 | 35 | public const int LEFT_BOTTOM = 17; 36 | public const int LEFT_BOTTOM_FRONT = 18; 37 | public const int BOTTOM_FRONT = 19; 38 | public const int RIGHT_BOTTOM_FRONT = 20; 39 | public const int RIGHT_BOTTOM = 21; 40 | public const int RIGHT_BOTTOM_BACK = 22; 41 | public const int BOTTOM_BACK = 23; 42 | public const int LEFT_BOTTOM_BACK = 24; 43 | public const int BOTTOM = 25; 44 | 45 | /// 46 | /// The offset needed to be applied to a 47 | /// index to move in that direction. 48 | /// 49 | public static readonly int[,] OFFSETS = new int[,] 50 | { 51 | {-1,1,0}, //LEFT_TOP = 0; 52 | {-1,1,1}, //LEFT_TOP_FRONT = 1; 53 | {0,1,1}, //TOP_FRONT = 2; 54 | {1,1,1}, //RIGHT_TOP_FRONT = 3; 55 | {1,1,0}, //RIGHT_TOP = 4; 56 | {1,1,-1}, //RIGHT_TOP_BACK = 5; 57 | {0,1,-1}, //TOP_BACK = 6; 58 | {-1,1,-1}, //LEFT_TOP_BACK = 7; 59 | {0,1,0}, //TOP = 8; 60 | 61 | {-1,0,0}, //LEFT = 9; 62 | {-1,0,1}, //LEFT_FRONT = 10; 63 | {0,0,1}, //FRONT = 11; 64 | {1,0,1}, //RIGHT_FRONT = 12; 65 | {1,0,0}, //RIGHT = 13; 66 | {1,0,-1}, //RIGHT_BACK = 14; 67 | {0,0,-1}, //BACK = 15; 68 | {-1,0,-1}, //LEFT_BACK = 16; 69 | 70 | {-1,-1,0}, //LEFT_BOTTOM = 17; 71 | {-1,-1,1}, //LEFT_BOTTOM_FRONT = 18; 72 | {0,-1,1}, //BOTTOM_FRONT = 19; 73 | {1,-1,1}, //RIGHT_BOTTOM_FRONT = 20; 74 | {1,-1,0}, //RIGHT_BOTTOM = 21; 75 | {1,-1,-1}, //RIGHT_BOTTOM_BACK = 22; 76 | {0,-1,-1}, //BOTTOM_BACK = 23; 77 | {-1,-1,-1}, //LEFT_BOTTOM_BACK = 24; 78 | {0,-1,0} //BOTTOM = 25; 79 | }; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Common.Core/Directions/D4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Core.Directions 5 | { 6 | /// 7 | /// Represents the 4 directions around a 2D array 8 | /// not including diagonals. 9 | /// 10 | public static class D4 11 | { 12 | /// 13 | /// Assign a number to each direction. 14 | /// 15 | public const int LEFT = 0; 16 | public const int TOP = 1; 17 | public const int RIGHT = 2; 18 | public const int BOTTOM = 3; 19 | 20 | /// 21 | /// The offset needed to be applied to a 22 | /// index to move in that direction. 23 | /// 24 | public static readonly int[,] OFFSETS = new int[,] 25 | { 26 | {-1,0}, 27 | {0,1}, 28 | {1,0}, 29 | {0,-1} 30 | }; 31 | 32 | /// 33 | /// The opposite direction. 34 | /// OPPOSITE[LEFT] == RIGHT 35 | /// 36 | public static readonly int[] OPPOSITES = new int[] 37 | { 38 | RIGHT, 39 | BOTTOM, 40 | LEFT, 41 | TOP 42 | }; 43 | 44 | /// 45 | /// The two adjacent directions. 46 | /// ADJACENT[LEFT, 0] == BOTTOM 47 | /// ADJACENT[LEFT, 1] == TOP 48 | /// 49 | public static readonly int[,] ADJACENT = new int[,] 50 | { 51 | { BOTTOM, TOP }, 52 | { LEFT, RIGHT }, 53 | { TOP, BOTTOM }, 54 | { RIGHT, LEFT } 55 | }; 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Common.Core/Extensions/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Core.Extensions 5 | { 6 | public static class KeyValuePairExtensions 7 | { 8 | public static void Deconstruct(this KeyValuePair tuple, out T1 key, out T2 value) 9 | { 10 | key = tuple.Key; 11 | value = tuple.Value; 12 | } 13 | } 14 | 15 | public static class DictionaryExtensions 16 | { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Common.Core/Extensions/IListExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.Core.Extensions 8 | { 9 | public static class IListExtension 10 | { 11 | /// 12 | /// Return the last item in list. 13 | /// 14 | public static T PeekLast(this IList list) 15 | { 16 | int count = list.Count; 17 | return list[count - 1]; 18 | } 19 | 20 | /// 21 | /// Shuffle the list into a random order. 22 | /// 23 | public static void Shuffle(this IList list) 24 | { 25 | var rnd = new Random(); 26 | Shuffle(list, rnd); 27 | } 28 | 29 | /// 30 | /// Shuffle the list into a random order. 31 | /// 32 | /// The random generators seed. 33 | public static void Shuffle(this IList list, int seed) 34 | { 35 | var rnd = new Random(seed); 36 | Shuffle(list, rnd); 37 | } 38 | 39 | /// 40 | /// Shuffle the list into a random order. 41 | /// 42 | /// The random generator. 43 | public static void Shuffle(this IList list, Random rnd) 44 | { 45 | int n = list.Count; 46 | while (n > 1) 47 | { 48 | int k = rnd.Next(n--); 49 | T temp = list[n]; 50 | list[n] = list[k]; 51 | list[k] = temp; 52 | } 53 | } 54 | 55 | /// 56 | /// Get the element at index i and wrap 57 | /// the index to the lists bounds. 58 | /// 59 | /// The index. 60 | /// The element at index i. 61 | public static T GetWrapped(this IList list, int i) 62 | { 63 | return list[MathUtil.Wrap(i, list.Count)]; 64 | } 65 | 66 | /// 67 | /// Get the element at index i and clamp 68 | /// the index to the lists bounds. 69 | /// 70 | /// The index. 71 | /// The element at index i. 72 | public static T GetClamped(this IList list, int i) 73 | { 74 | if (i < 0) i = 0; 75 | if (i > list.Count - 1) i = list.Count - 1; 76 | return list[i]; 77 | } 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Common.Core/Extensions/ListExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Common.Core.Extensions 6 | { 7 | public static class ListExtension 8 | { 9 | /// 10 | /// Add two items to the list. 11 | /// 12 | public static void Add(this List list, T item1, T item2) 13 | { 14 | list.Add(item1); 15 | list.Add(item2); 16 | } 17 | 18 | /// 19 | /// Add three items to the list. 20 | /// 21 | public static void Add(this List list, T item1, T item2, T item3) 22 | { 23 | list.Add(item1); 24 | list.Add(item2); 25 | list.Add(item3); 26 | } 27 | 28 | /// 29 | /// Add four items to the list. 30 | /// 31 | public static void Add(this List list, T item1, T item2, T item3, T item4) 32 | { 33 | list.Add(item1); 34 | list.Add(item2); 35 | list.Add(item3); 36 | list.Add(item4); 37 | } 38 | 39 | /// 40 | /// Add the same item to the list a number of times. 41 | /// 42 | public static void AddRange(this List list, int count, T item) 43 | { 44 | for (int i = 0; i < count; i++) 45 | list.Add(item); 46 | } 47 | 48 | /// 49 | /// Remove and return the first element in the list. 50 | /// 51 | public static T PopFirst(this List list) 52 | { 53 | var v = list[0]; 54 | list.RemoveAt(0); 55 | return v; 56 | } 57 | 58 | /// 59 | /// Remove and return the last element in the list. 60 | /// 61 | public static T PopLast(this List list) 62 | { 63 | int count = list.Count; 64 | var v = list[count - 1]; 65 | list.RemoveAt(count - 1); 66 | return v; 67 | } 68 | 69 | /// 70 | /// Remove the item at index i by moving the 71 | /// last element to index i and then removing 72 | /// the last element. 73 | /// 74 | public static void RemoveBySwap(this List list, int i) 75 | { 76 | int count = list.Count; 77 | 78 | if (count == 1) 79 | list.RemoveAt(i); 80 | else 81 | { 82 | list[i] = list[count - 1]; 83 | list.RemoveAt(count - 1); 84 | } 85 | } 86 | 87 | /// 88 | /// Remove the elements in the list and return as a seperate list. 89 | /// 90 | /// The index to start at. 91 | /// The number of elements to cut. 92 | /// The cut elements. 93 | public static List Cut(this List list, int index, int count) 94 | { 95 | var cut = new List(count); 96 | 97 | count = Math.Min(count, list.Count() - index); 98 | if (index < 0 || count < 0 || index >= list.Count) 99 | return cut; 100 | 101 | for (int i = 0; i < count; i++) 102 | cut.Add(list[index + i]); 103 | 104 | list.RemoveRange(index, count); 105 | return cut; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Common.Core/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Common.Core.Extensions 6 | { 7 | public static class StringExtensions 8 | { 9 | public static string RemoveWhitespaces(this string str) 10 | { 11 | return new string(str.ToCharArray() 12 | .Where(c => !Char.IsWhiteSpace(c)) 13 | .ToArray()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Common.Core/Numerics/MinMax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Common.Core.Numerics 7 | { 8 | [Serializable] 9 | [StructLayout(LayoutKind.Sequential)] 10 | public struct MinMax 11 | { 12 | public double Min; 13 | public double Max; 14 | 15 | public override string ToString() 16 | { 17 | return String.Format("[MinMax: Min={0}, Max={1}]", Min, Max); 18 | } 19 | } 20 | 21 | [Serializable] 22 | [StructLayout(LayoutKind.Sequential)] 23 | public struct MinMaxAvg 24 | { 25 | public double Min; 26 | public double Max; 27 | public double Average; 28 | 29 | public override string ToString() 30 | { 31 | return String.Format("[MinMax: Min={0}, Max={1}, Average={2}]", Min, Max, Average); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Common.Core/Numerics/Union16.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace Common.Core.Numerics 7 | { 8 | 9 | [Serializable] 10 | [StructLayout(LayoutKind.Explicit)] 11 | public struct Union16 : IEquatable 12 | { 13 | 14 | [FieldOffset(0)] 15 | public byte Byte0; 16 | 17 | [FieldOffset(1)] 18 | public byte Byte1; 19 | 20 | [FieldOffset(0)] 21 | public ushort UShort; 22 | 23 | [FieldOffset(0)] 24 | public short Short; 25 | 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | public static implicit operator Union16(short i) 28 | { 29 | var u = new Union16(); 30 | u.Short = i; 31 | return u; 32 | } 33 | 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public static implicit operator Union16(ushort ui) 36 | { 37 | var u = new Union16(); 38 | u.UShort = ui; 39 | return u; 40 | } 41 | 42 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 43 | public static bool operator ==(Union16 u1, Union16 u2) 44 | { 45 | return u1.Short == u2.Short; 46 | } 47 | 48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 49 | public static bool operator !=(Union16 u1, Union16 u2) 50 | { 51 | return u1.Short != u2.Short; 52 | } 53 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 55 | public override bool Equals(object obj) 56 | { 57 | if (!(obj is Union16)) return false; 58 | Union16 v = (Union16)obj; 59 | return this == v; 60 | } 61 | 62 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 63 | public bool Equals(Union16 v) 64 | { 65 | return this == v; 66 | } 67 | 68 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 69 | public override int GetHashCode() 70 | { 71 | return Short.GetHashCode(); 72 | } 73 | 74 | public float Half 75 | { 76 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 77 | get 78 | { 79 | float half = Byte0 * 256.0f + Byte1; 80 | half /= (float)ushort.MaxValue; 81 | return half; 82 | } 83 | } 84 | 85 | public override string ToString() 86 | { 87 | return string.Format("[Union16: Short={0}, UShort={1}, Half={2}]", Short, UShort, Half); 88 | } 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Common.Core/Numerics/Union32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace Common.Core.Numerics 7 | { 8 | 9 | [Serializable] 10 | [StructLayout(LayoutKind.Explicit)] 11 | public struct Union32 : IEquatable 12 | { 13 | 14 | [FieldOffset(0)] 15 | public byte Byte0; 16 | 17 | [FieldOffset(1)] 18 | public byte Byte1; 19 | 20 | [FieldOffset(2)] 21 | public byte Byte2; 22 | 23 | [FieldOffset(3)] 24 | public byte Byte3; 25 | 26 | [FieldOffset(0)] 27 | public ushort UShort0; 28 | 29 | [FieldOffset(2)] 30 | public ushort UShort1; 31 | 32 | [FieldOffset(0)] 33 | public short Short0; 34 | 35 | [FieldOffset(2)] 36 | public short Short1; 37 | 38 | [FieldOffset(0)] 39 | public int Int; 40 | 41 | [FieldOffset(0)] 42 | public uint UInt; 43 | 44 | [FieldOffset(0)] 45 | public float Float; 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static implicit operator Union32(int i) 49 | { 50 | var u = new Union32(); 51 | u.Int = i; 52 | return u; 53 | } 54 | 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static implicit operator Union32(uint ui) 57 | { 58 | var u = new Union32(); 59 | u.UInt = ui; 60 | return u; 61 | } 62 | 63 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 64 | public static implicit operator Union32(float f) 65 | { 66 | var u = new Union32(); 67 | u.Float = f; 68 | return u; 69 | } 70 | 71 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 72 | public static bool operator ==(Union32 u1, Union32 u2) 73 | { 74 | return u1.Int == u2.Int; 75 | } 76 | 77 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 78 | public static bool operator !=(Union32 u1, Union32 u2) 79 | { 80 | return u1.Int != u2.Int; 81 | } 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public override bool Equals(object obj) 85 | { 86 | if (!(obj is Union32)) return false; 87 | Union32 v = (Union32)obj; 88 | return this == v; 89 | } 90 | 91 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 92 | public bool Equals(Union32 v) 93 | { 94 | return this == v; 95 | } 96 | 97 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 98 | public override int GetHashCode() 99 | { 100 | return Int.GetHashCode(); 101 | } 102 | 103 | public override string ToString() 104 | { 105 | return string.Format("[Union32: Int={0}, UInt={1}, Float={2}]", Int, UInt, Float); 106 | } 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Common.Core/Numerics/Union64.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace Common.Core.Numerics 7 | { 8 | 9 | [Serializable] 10 | [StructLayout(LayoutKind.Explicit)] 11 | public struct Union64 : IEquatable 12 | { 13 | 14 | [FieldOffset(0)] 15 | public byte Byte0; 16 | 17 | [FieldOffset(1)] 18 | public byte Byte1; 19 | 20 | [FieldOffset(2)] 21 | public byte Byte2; 22 | 23 | [FieldOffset(3)] 24 | public byte Byte3; 25 | 26 | [FieldOffset(4)] 27 | public byte Byte4; 28 | 29 | [FieldOffset(5)] 30 | public byte Byte5; 31 | 32 | [FieldOffset(6)] 33 | public byte Byte6; 34 | 35 | [FieldOffset(7)] 36 | public byte Byte7; 37 | 38 | [FieldOffset(0)] 39 | public int Int1; 40 | 41 | [FieldOffset(4)] 42 | public int Int2; 43 | 44 | [FieldOffset(0)] 45 | public uint UInt1; 46 | 47 | [FieldOffset(4)] 48 | public uint UInt2; 49 | 50 | [FieldOffset(0)] 51 | public UInt64 UInt64; 52 | 53 | [FieldOffset(0)] 54 | public Int64 Int64; 55 | 56 | [FieldOffset(0)] 57 | public double Double; 58 | 59 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 60 | public static implicit operator Union64(uint ui) 61 | { 62 | var u = new Union64(); 63 | u.UInt1 = ui; 64 | return u; 65 | } 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public static implicit operator Union64(int i) 69 | { 70 | var u = new Union64(); 71 | u.Int1 = i; 72 | return u; 73 | } 74 | 75 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 76 | public static implicit operator Union64(UInt64 ui) 77 | { 78 | var u = new Union64(); 79 | u.UInt64 = ui; 80 | return u; 81 | } 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public static implicit operator Union64(Int64 i) 85 | { 86 | var u = new Union64(); 87 | u.Int64 = i; 88 | return u; 89 | } 90 | 91 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 92 | public static implicit operator Union64(double d) 93 | { 94 | var u = new Union64(); 95 | u.Double = d; 96 | return u; 97 | } 98 | 99 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 100 | public static bool operator ==(Union64 u1, Union64 u2) 101 | { 102 | return u1.Int64 == u2.Int64; 103 | } 104 | 105 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 106 | public static bool operator !=(Union64 u1, Union64 u2) 107 | { 108 | return u1.Int64 != u2.Int64; 109 | } 110 | 111 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 112 | public override bool Equals(object obj) 113 | { 114 | if (!(obj is Union64)) return false; 115 | Union64 v = (Union64)obj; 116 | return this == v; 117 | } 118 | 119 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 120 | public bool Equals(Union64 v) 121 | { 122 | return this == v; 123 | } 124 | 125 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 126 | public override int GetHashCode() 127 | { 128 | return Int64.GetHashCode(); 129 | } 130 | 131 | public override string ToString() 132 | { 133 | return string.Format("[Union64: Int64={0}, UInt64={1}, Double={2}]", Int64, UInt64, Double); 134 | } 135 | 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Common.Core/RandomNum/LCHGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Core.RandomNum 5 | { 6 | 7 | /// 8 | /// A linear congruential generator (LCG) is an algorithm that yields 9 | /// a sequence of pseudo-randomized numbers calculated with a discontinuous 10 | /// piecewise linear equation. The method represents one of the oldest 11 | /// and best-known pseudorandom number generator algorithms. 12 | /// If increment = 0, the generator is often called a multiplicative congruential generator 13 | /// https://en.wikipedia.org/wiki/Linear_congruential_generator 14 | /// 15 | public class LCHGenerator : RandomGenerator 16 | { 17 | 18 | private ulong m_modulus; 19 | 20 | private ulong m_multiplier; 21 | 22 | private ulong m_increment; 23 | 24 | private ulong m_next; 25 | 26 | public LCHGenerator() 27 | { 28 | m_modulus = 281474976710656; 29 | m_multiplier = 25214903917; 30 | m_increment = 11; 31 | } 32 | 33 | public LCHGenerator(int seed) : base(seed) 34 | { 35 | m_modulus = 281474976710656; 36 | m_multiplier = 25214903917; 37 | m_increment = 11; 38 | } 39 | 40 | /// 41 | /// 42 | /// 43 | /// 44 | public override string ToString() 45 | { 46 | return string.Format("[LCHGenerator: Seed={0}]", Seed); 47 | } 48 | 49 | /// 50 | /// A random int greater than or equal to 0 and less than MaxInt. 51 | /// 52 | public override int Next() 53 | { 54 | m_next = (m_multiplier * m_next + m_increment) % m_modulus; 55 | return (int)(m_next % int.MaxValue); 56 | } 57 | 58 | /// 59 | /// Update seed. 60 | /// Called when seed changes. 61 | /// 62 | public override void UpdateSeed(int seed) 63 | { 64 | Seed = seed; 65 | m_next = (uint)seed; 66 | } 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Common.Core/RandomNum/SystemRandom.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Core.RandomNum 5 | { 6 | public class SystemRandom : RandomGenerator 7 | { 8 | 9 | private System.Random Rnd { get; set; } 10 | 11 | public SystemRandom() 12 | { 13 | 14 | } 15 | 16 | public SystemRandom(int seed) : base(seed) 17 | { 18 | 19 | } 20 | 21 | /// 22 | /// 23 | /// 24 | /// 25 | public override string ToString() 26 | { 27 | return string.Format("[SystemRandom: Seed={0}]", Seed); 28 | } 29 | 30 | /// 31 | /// A random int between 0 - MaxInt. 32 | /// 33 | public override int Next() 34 | { 35 | return Rnd.Next(); 36 | } 37 | 38 | /// 39 | /// Update seed. 40 | /// Called when seed changes. 41 | /// 42 | public override void UpdateSeed(int seed) 43 | { 44 | Seed = seed; 45 | Rnd = new System.Random(seed); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Common.Core/Shapes/SegmentIndex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.Core.Shapes 8 | { 9 | /// 10 | /// A segment represented by indices instead of points. 11 | /// The indices represent a index into a array of points. 12 | /// 13 | [Serializable] 14 | [StructLayout(LayoutKind.Sequential)] 15 | public struct SegmentIndex : IEquatable 16 | { 17 | /// 18 | /// The segments first point index. 19 | /// 20 | public int A; 21 | 22 | /// 23 | /// The segments seconds point index. 24 | /// 25 | public int B; 26 | 27 | /// 28 | /// Consturct a new segment. 29 | /// 30 | /// The segments first point index. 31 | /// The segments second point index. 32 | public SegmentIndex(int a, int b) 33 | { 34 | A = a; 35 | B = b; 36 | } 37 | 38 | /// 39 | /// Does the segment have a null index. 40 | /// 41 | public bool HasNullIndex => A == MathUtil.NULL_INDEX || B == MathUtil.NULL_INDEX; 42 | 43 | /// 44 | /// The segment reverse where a is now b and b is now a. 45 | /// 46 | public SegmentIndex Reversed => new SegmentIndex(B, A); 47 | 48 | public static bool operator ==(SegmentIndex t1, SegmentIndex t2) 49 | { 50 | return t1.A == t2.A && t1.B == t2.B; 51 | } 52 | 53 | public static bool operator !=(SegmentIndex t1, SegmentIndex t2) 54 | { 55 | return t1.A != t2.A || t1.B != t2.B; 56 | } 57 | 58 | /// 59 | /// Is the segment equal to this object. 60 | /// 61 | /// The object. 62 | /// Is the segment equal to this object. 63 | public override bool Equals(object obj) 64 | { 65 | if (!(obj is SegmentIndex)) return false; 66 | SegmentIndex tri = (SegmentIndex)obj; 67 | return this == tri; 68 | } 69 | 70 | /// 71 | /// Is the segment equal to the other segment. 72 | /// 73 | /// The other segment. 74 | /// Is the segment equal to the other segment. 75 | public bool Equals(SegmentIndex seg) 76 | { 77 | return this == seg; 78 | } 79 | 80 | /// 81 | /// The segments hash code. 82 | /// 83 | /// The segments hash code. 84 | public override int GetHashCode() 85 | { 86 | unchecked 87 | { 88 | int hash = (int)MathUtil.HASH_PRIME_1; 89 | hash = (hash * MathUtil.HASH_PRIME_2) ^ A.GetHashCode(); 90 | hash = (hash * MathUtil.HASH_PRIME_2) ^ B.GetHashCode(); 91 | return hash; 92 | } 93 | } 94 | 95 | /// 96 | /// The segment as a string. 97 | /// 98 | /// The segment as a string. 99 | public override string ToString() 100 | { 101 | return string.Format("[SegmentIndex: A={0}, B={1}]", A, B); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Common.Core/Shapes/Shape2d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Core.Shapes 7 | { 8 | 9 | public interface IShape2d 10 | { 11 | /// 12 | /// The bounding box that contains the shape. 13 | /// 14 | Box2d Bounds { get; } 15 | 16 | /// 17 | /// Does the shape contain the point. 18 | /// Points on the shapes surface count as 19 | /// being contained in the shape. 20 | /// 21 | /// 22 | /// 23 | bool Contains(Point2d p, bool includeBorder = true); 24 | 25 | /// 26 | /// Does the shape intersect the box. 27 | /// 28 | /// 29 | /// 30 | bool Intersects(Box2d box, bool includeBorder = true); 31 | 32 | /// 33 | /// The closest point to the shape. 34 | /// If point inside shape return the same point. 35 | /// 36 | /// 37 | /// 38 | Point2d Closest(Point2d p); 39 | 40 | /// 41 | /// The signed distance between the shapes surface and the point. 42 | /// 43 | /// 44 | /// Positive if outside shape, negative if inside and 0 on boundary 45 | double SignedDistance(Point2d p); 46 | } 47 | 48 | public abstract class Shape2d : IShape2d 49 | { 50 | /// 51 | /// The bounding box that contains the shape. 52 | /// 53 | public abstract Box2d Bounds { get; } 54 | 55 | 56 | /// 57 | /// Does the shape contain the point. 58 | /// Points on the shapes surface count as 59 | /// being contained in the shape. 60 | /// 61 | /// 62 | /// 63 | public virtual bool Contains(Point2d p, bool includeBorder = true) 64 | { 65 | throw new NotImplementedException(); 66 | } 67 | 68 | /// 69 | /// Does the shape intersect the box. 70 | /// 71 | /// 72 | /// 73 | public virtual bool Intersects(Box2d box, bool includeBorder = true) 74 | { 75 | throw new NotImplementedException(); 76 | } 77 | 78 | /// 79 | /// The closest point to the shape. 80 | /// If point inside shape return the same point. 81 | /// 82 | /// 83 | /// 84 | public virtual Point2d Closest(Point2d p) 85 | { 86 | throw new NotImplementedException(); 87 | } 88 | 89 | /// 90 | /// The signed distance between the shapes surface and the point. 91 | /// 92 | /// 93 | /// Positive if outside shape, negative if inside and 0 on boundary 94 | public virtual double SignedDistance(Point2d p) 95 | { 96 | throw new NotImplementedException(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Common.Core/Shapes/Shape2f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Core.Shapes 7 | { 8 | 9 | public interface IShape2f 10 | { 11 | /// 12 | /// The bounding box that contains the shape. 13 | /// 14 | Box2f Bounds { get; } 15 | 16 | /// 17 | /// Does the shape contain the point. 18 | /// Points on the shapes surface count as 19 | /// being contained in the shape. 20 | /// 21 | /// The point. 22 | /// Does the shape contain the point. 23 | bool Contains(Point2f p, bool includeBorder); 24 | 25 | /// 26 | /// Does the shape intersect the box. 27 | /// 28 | /// The box. 29 | /// Does the shape intersect the box. 30 | bool Intersects(Box2f box, bool includeBorder); 31 | 32 | /// 33 | /// The closest point to the shape. 34 | /// If point inside shape return the same point. 35 | /// 36 | /// The point. 37 | /// The closest point to the shape. 38 | Point2f Closest(Point2f p); 39 | 40 | /// 41 | /// The signed distance between the shapes surface and the point. 42 | /// 43 | /// The point. 44 | /// Positive if outside shape, negative if inside and 0 on boundary 45 | float SignedDistance(Point2f p); 46 | } 47 | 48 | public abstract class Shape2f : IShape2f 49 | { 50 | /// 51 | /// The bounding box that contains the shape. 52 | /// 53 | public abstract Box2f Bounds { get; } 54 | 55 | 56 | /// 57 | /// Does the shape contain the point. 58 | /// Points on the shapes surface count as 59 | /// being contained in the shape. 60 | /// 61 | /// The point. 62 | /// Does the shape contain the point. 63 | public virtual bool Contains(Point2f p, bool includeBorder) 64 | { 65 | throw new NotImplementedException(); 66 | } 67 | 68 | /// 69 | /// Does the shape intersect the box. 70 | /// 71 | /// The box. 72 | /// Does the shape intersect the box. 73 | public virtual bool Intersects(Box2f box, bool includeBorder) 74 | { 75 | throw new NotImplementedException(); 76 | } 77 | 78 | /// 79 | /// The closest point to the shape. 80 | /// If point inside shape return the same point. 81 | /// 82 | /// The point. 83 | /// The closest point to the shape. 84 | public virtual Point2f Closest(Point2f p) 85 | { 86 | throw new NotImplementedException(); 87 | } 88 | 89 | /// 90 | /// The signed distance between the shapes surface and the point. 91 | /// 92 | /// The point. 93 | /// Positive if outside shape, negative if inside and 0 on boundary 94 | public virtual float SignedDistance(Point2f p) 95 | { 96 | throw new NotImplementedException(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Common.Core/Shapes/Shape3d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Core.Shapes 7 | { 8 | 9 | public interface IShape3d 10 | { 11 | Box3d Bounds { get; } 12 | 13 | bool Contains(Point3d p, bool includeBorder); 14 | 15 | bool Intersects(Box3d box, bool includeBorder); 16 | 17 | Point3d Closest(Point3d p); 18 | 19 | double SignedDistance(Point3d p); 20 | 21 | } 22 | 23 | public abstract class Shape3d : IShape3d 24 | { 25 | public abstract Box3d Bounds { get; } 26 | 27 | public virtual Point3d Closest(Point3d p) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public virtual bool Contains(Point3d p, bool includeBorder) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | public virtual bool Intersects(Box3d box, bool includeBorder) 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | 42 | public virtual double SignedDistance(Point3d p) 43 | { 44 | throw new NotImplementedException(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Common.Core/Shapes/Shape3f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.Core.Shapes 7 | { 8 | 9 | public interface IShape3f 10 | { 11 | Box3f Bounds { get; } 12 | 13 | bool Contains(Point3f p, bool includeBorder); 14 | 15 | bool Intersects(Box3f box, bool includeBorder); 16 | 17 | Point3f Closest(Point3f p); 18 | 19 | float SignedDistance(Point3f p); 20 | 21 | } 22 | 23 | public abstract class Shape3f : IShape3f 24 | { 25 | public abstract Box3f Bounds { get; } 26 | 27 | public virtual Point3f Closest(Point3f p) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public virtual bool Contains(Point3f p, bool includeBorder) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | public virtual bool Intersects(Box3f box, bool includeBorder) 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | 42 | public virtual float SignedDistance(Point3f p) 43 | { 44 | throw new NotImplementedException(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Common.Core/Shapes/TriangleIndex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.Core.Shapes 8 | { 9 | /// 10 | /// A triangle represented by indices instead of points. 11 | /// The indices represent a index into a array of points. 12 | /// 13 | [Serializable] 14 | [StructLayout(LayoutKind.Sequential)] 15 | public struct TriangleIndex : IEquatable 16 | { 17 | /// 18 | /// The triangles first point index. 19 | /// 20 | public int A; 21 | 22 | /// 23 | /// The triangles second point index. 24 | /// 25 | public int B; 26 | 27 | /// 28 | /// The triangles third point index. 29 | /// 30 | public int C; 31 | 32 | /// 33 | /// Consturct a new triangle. 34 | /// 35 | /// The triangles first point index. 36 | /// The triangles second point index. 37 | /// The triangles third point index. 38 | public TriangleIndex(int a, int b, int c) 39 | { 40 | A = a; 41 | B = b; 42 | C = c; 43 | } 44 | 45 | /// 46 | /// Does the triangle have a null index. 47 | /// 48 | public bool HasNullIndex => A == MathUtil.NULL_INDEX || B == MathUtil.NULL_INDEX || C == MathUtil.NULL_INDEX; 49 | 50 | /// 51 | /// The triangle reversed. 52 | /// 53 | public TriangleIndex Reversed => new TriangleIndex(C, B, A); 54 | 55 | public static bool operator ==(TriangleIndex t1, TriangleIndex t2) 56 | { 57 | return t1.A == t2.A && t1.B == t2.B && t1.C == t2.C; 58 | } 59 | 60 | public static bool operator !=(TriangleIndex t1, TriangleIndex t2) 61 | { 62 | return t1.A != t2.A || t1.B != t2.B || t1.C != t2.C; 63 | } 64 | 65 | /// 66 | /// Is the triangle equal to this object. 67 | /// 68 | /// The object. 69 | /// Is the triangle equal to this object. 70 | public override bool Equals(object obj) 71 | { 72 | if (!(obj is TriangleIndex)) return false; 73 | TriangleIndex tri = (TriangleIndex)obj; 74 | return this == tri; 75 | } 76 | 77 | /// 78 | /// Is the triangle equal to the other triangle. 79 | /// 80 | /// The other triangle. 81 | /// Is the triangle equal to the other triangle. 82 | public bool Equals(TriangleIndex tri) 83 | { 84 | return this == tri; 85 | } 86 | 87 | /// 88 | /// The triangles hash code. 89 | /// 90 | /// The triangles hash code. 91 | public override int GetHashCode() 92 | { 93 | unchecked 94 | { 95 | int hash = (int)MathUtil.HASH_PRIME_1; 96 | hash = (hash * MathUtil.HASH_PRIME_2) ^ A.GetHashCode(); 97 | hash = (hash * MathUtil.HASH_PRIME_2) ^ B.GetHashCode(); 98 | hash = (hash * MathUtil.HASH_PRIME_2) ^ C.GetHashCode(); 99 | return hash; 100 | } 101 | } 102 | 103 | /// 104 | /// The triangle as a string. 105 | /// 106 | /// The triangle as a string. 107 | public override string ToString() 108 | { 109 | return string.Format("[TriangleIndex: A={0}, B={1}, C={2}]", A, B, C); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Common.Geometry.Test/Collections/BVHTree2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | using Common.Geometry.Collections; 7 | using System.Collections.Generic; 8 | 9 | namespace Common.Geometry.Test.Collections 10 | { 11 | [TestClass] 12 | public class BVHTree2fTest 13 | { 14 | [TestMethod] 15 | public void Remove() 16 | { 17 | 18 | 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Common.Geometry.Test/Polygons/Polygon2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Geometry.Polygons; 6 | using Common.Core.Shapes; 7 | 8 | namespace Common.Geometry.Test.Polygons 9 | { 10 | [TestClass] 11 | public class Polygon2fTest 12 | { 13 | [TestMethod] 14 | public void Calculate() 15 | { 16 | var polygon = CreatePolygon(); 17 | 18 | Assert.AreEqual(12, polygon.Area); 19 | Assert.AreEqual(16, polygon.Length); 20 | Assert.AreEqual(true, polygon.IsCW); 21 | Assert.AreEqual(new Point2f(0), polygon.Centroid); 22 | Assert.AreEqual(new Box2f(-2,2), polygon.Bounds); 23 | } 24 | 25 | [TestMethod] 26 | public void GetPosition() 27 | { 28 | var polygon = CreatePolygon(); 29 | float eps = 1e-4f; 30 | float len = polygon.Length; 31 | 32 | Assert.IsTrue(Point2f.AlmostEqual(polygon.GetPosition(0.0f), new Point2f(1, 2), eps)); 33 | Assert.IsTrue(Point2f.AlmostEqual(polygon.GetPosition(1.0f), new Point2f(1, 2), eps)); 34 | Assert.IsTrue(Point2f.AlmostEqual(polygon.GetPosition(3.0f / len), new Point2f(2, 0), eps)); 35 | Assert.IsTrue(Point2f.AlmostEqual(polygon.GetPosition(5.2f / len), new Point2f(1, -1.2f), eps)); 36 | Assert.IsTrue(Point2f.AlmostEqual(polygon.GetPosition(9.8f / len), new Point2f(-1.8f, -1), eps)); 37 | } 38 | 39 | private Polygon2f CreatePolygon() 40 | { 41 | var positions = new Point2f[] 42 | { 43 | new Point2f(1,2), 44 | new Point2f(1,1), 45 | new Point2f(2,1), 46 | new Point2f(2,-1), 47 | new Point2f(1,-1), 48 | new Point2f(1,-2), 49 | new Point2f(-1,-2), 50 | new Point2f(-1,-1), 51 | new Point2f(-2,-1), 52 | new Point2f(-2,1), 53 | new Point2f(-1,1), 54 | new Point2f(-1,2) 55 | }; 56 | 57 | var polygon = new Polygon2f(positions); 58 | polygon.Calculate(); 59 | 60 | return polygon; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Common.Geometry.Test/Polygons/Polyline2fTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Geometry.Polygons; 6 | using Common.Core.Shapes; 7 | 8 | namespace Common.Geometry.Test.Polygons 9 | { 10 | [TestClass] 11 | public class Polyline2fTest 12 | { 13 | [TestMethod] 14 | public void Calculate() 15 | { 16 | var polyline = CreatePolyline(); 17 | 18 | Assert.AreEqual(14, polyline.Length); 19 | Assert.AreEqual(new Box2f(-2, 2), polyline.Bounds); 20 | } 21 | 22 | [TestMethod] 23 | public void GetPosition() 24 | { 25 | var polyline = CreatePolyline(); 26 | float eps = 1e-4f; 27 | float len = polyline.Length; 28 | 29 | Assert.IsTrue(Point2f.AlmostEqual(polyline.GetPosition(0.0f), new Point2f(1, 2), eps)); 30 | Assert.IsTrue(Point2f.AlmostEqual(polyline.GetPosition(1.0f), new Point2f(-1, 2), eps)); 31 | Assert.IsTrue(Point2f.AlmostEqual(polyline.GetPosition(3.0f / len), new Point2f(2, 0), eps)); 32 | Assert.IsTrue(Point2f.AlmostEqual(polyline.GetPosition(5.2f / len), new Point2f(1, -1.2f), eps)); 33 | Assert.IsTrue(Point2f.AlmostEqual(polyline.GetPosition(9.8f / len), new Point2f(-1.8f, -1), eps)); 34 | } 35 | 36 | private Polyline2f CreatePolyline() 37 | { 38 | var positions = new Point2f[] 39 | { 40 | new Point2f(1,2), 41 | new Point2f(1,1), 42 | new Point2f(2,1), 43 | new Point2f(2,-1), 44 | new Point2f(1,-1), 45 | new Point2f(1,-2), 46 | new Point2f(-1,-2), 47 | new Point2f(-1,-1), 48 | new Point2f(-2,-1), 49 | new Point2f(-2,1), 50 | new Point2f(-1,1), 51 | new Point2f(-1,2) 52 | }; 53 | 54 | var polyline = new Polyline2f(0.01f, positions); 55 | polyline.Calculate(); 56 | 57 | return polyline; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Common.Geometry.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Common.Geometry.Test")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("Common.Geometry.Test")] 10 | [assembly: AssemblyCopyright("Copyright © 2018")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("112ef9ed-5877-42e1-b1c0-ef653ae32b78")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /Common.Geometry.Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Common.Geometry/Bezier/Bezier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.Geometry.Bezier 5 | { 6 | 7 | public enum BEZIER_DEGREE { LINEAR = 1, QUADRATIC = 2, CUBIC = 3, QUARTIC = 4, QUINTIC = 5 }; 8 | 9 | public abstract class Bezier 10 | { 11 | 12 | public const int MIN_DEGREE = 1; 13 | 14 | public const int MAX_DEGREE = 31; 15 | 16 | protected float Bernstein(int n, int i, float t) 17 | { 18 | double basis; 19 | double ti; /* t^i */ 20 | double tni; /* (1 - t)^i */ 21 | 22 | if (t == 0.0 && i == 0) 23 | ti = 1.0; 24 | else 25 | ti = Math.Pow(t, i); 26 | 27 | if (n == i && t == 1.0) 28 | tni = 1.0; 29 | else 30 | tni = Math.Pow((1 - t), (n - i)); 31 | 32 | basis = Ni(n, i) * ti * tni; 33 | return (float)basis; 34 | } 35 | 36 | protected double Bernstein(int n, int i, double t) 37 | { 38 | double basis; 39 | double ti; /* t^i */ 40 | double tni; /* (1 - t)^i */ 41 | 42 | if (t == 0.0 && i == 0) 43 | ti = 1.0; 44 | else 45 | ti = Math.Pow(t, i); 46 | 47 | if (n == i && t == 1.0) 48 | tni = 1.0; 49 | else 50 | tni = Math.Pow((1 - t), (n - i)); 51 | 52 | basis = Ni(n, i) * ti * tni; 53 | return basis; 54 | } 55 | 56 | private static double Ni(int n, int i) 57 | { 58 | double ni; 59 | double a1 = FactorialTable[n]; 60 | double a2 = FactorialTable[i]; 61 | double a3 = FactorialTable[n - i]; 62 | ni = a1 / (a2 * a3); 63 | return ni; 64 | } 65 | 66 | private static readonly double[] FactorialTable = new double[] 67 | { 68 | 1.0, 69 | 1.0, 70 | 2.0, 71 | 6.0, 72 | 24.0, 73 | 120.0, 74 | 720.0, 75 | 5040.0, 76 | 40320.0, 77 | 362880.0, 78 | 3628800.0, 79 | 39916800.0, 80 | 479001600.0, 81 | 6227020800.0, 82 | 87178291200.0, 83 | 1307674368000.0, 84 | 20922789888000.0, 85 | 355687428096000.0, 86 | 6402373705728000.0, 87 | 121645100408832000.0, 88 | 2432902008176640000.0, 89 | 51090942171709440000.0, 90 | 1124000727777607680000.0, 91 | 25852016738884976640000.0, 92 | 620448401733239439360000.0, 93 | 15511210043330985984000000.0, 94 | 403291461126605635584000000.0, 95 | 10888869450418352160768000000.0, 96 | 304888344611713860501504000000.0, 97 | 8841761993739701954543616000000.0, 98 | 265252859812191058636308480000000.0, 99 | 8222838654177922817725562880000000.0, 100 | 263130836933693530167218012160000000.0 101 | }; 102 | 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Common.Geometry/Collections/BVHTreeNode2d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using Common.Core.Numerics; 6 | using Common.Core.Shapes; 7 | 8 | using BOX2 = Common.Core.Shapes.Box2d; 9 | 10 | namespace Common.Geometry.Collections 11 | { 12 | /// 13 | /// A node in a BVH tree. 14 | /// 15 | public class BVHTreeNode2d : IEnumerable> 16 | where T : class, IShape2d 17 | { 18 | 19 | public BVHTreeNode2d(T shape) 20 | { 21 | Shape = shape; 22 | Bounds = shape.Bounds; 23 | } 24 | 25 | public BVHTreeNode2d(BOX2 bounds) 26 | { 27 | Shape = null; 28 | Bounds = bounds; 29 | } 30 | 31 | /// 32 | /// The nodes left child. 33 | /// 34 | public BVHTreeNode2d Left { get; internal set; } 35 | 36 | /// 37 | /// The nodes right child. 38 | /// 39 | public BVHTreeNode2d Right { get; internal set; } 40 | 41 | /// 42 | /// The nodes parent. 43 | /// 44 | public BVHTreeNode2d Parent { get; internal set; } 45 | 46 | /// 47 | /// The bounds of the nodes shape if its a leaf 48 | /// or the bounds of its child if not a leaf. 49 | /// 50 | public BOX2 Bounds; 51 | 52 | /// 53 | /// The nodes shape. 54 | /// Will be null if this node is not a leaf. 55 | /// 56 | public T Shape { get; internal set; } 57 | 58 | /// 59 | /// If this node in a leaf in the tree. 60 | /// Leaves have no childern. 61 | /// 62 | public bool IsLeaf => Shape != null; 63 | 64 | /// 65 | /// The nodes sibling is its parents other child. 66 | /// 67 | internal BVHTreeNode2d Sibling => Parent.Left == this ? Parent.Right : Parent.Left; 68 | 69 | /// 70 | /// 71 | /// 72 | /// 73 | public override string ToString() 74 | { 75 | if(IsLeaf) 76 | return string.Format("[BVHNode2d: IsLeaf={0}, Shape={1}]", IsLeaf, Shape); 77 | else 78 | return string.Format("[BVHNode2d: IsLeaf={0}, Bounds={1}]", IsLeaf, Bounds); 79 | } 80 | 81 | /// 82 | /// Enumerate all leaf nodes. 83 | /// 84 | public IEnumerator> GetEnumerator() 85 | { 86 | if (Left != null) 87 | { 88 | foreach (var n in Left) 89 | yield return n; 90 | } 91 | 92 | if (IsLeaf) 93 | yield return this; 94 | 95 | if (Right != null) 96 | { 97 | foreach (var n in Right) 98 | yield return n; 99 | } 100 | } 101 | 102 | /// 103 | /// Enumerate all leaf nodes. 104 | /// 105 | IEnumerator IEnumerable.GetEnumerator() 106 | { 107 | return GetEnumerator(); 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Common.Geometry/Collections/BVHTreeNode2f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using Common.Core.Numerics; 6 | using Common.Core.Shapes; 7 | 8 | using BOX2 = Common.Core.Shapes.Box2f; 9 | 10 | namespace Common.Geometry.Collections 11 | { 12 | /// 13 | /// A node in a BVH tree. 14 | /// 15 | public class BVHTreeNode2f : IEnumerable> 16 | where T : class, IShape2f 17 | { 18 | 19 | public BVHTreeNode2f(T shape) 20 | { 21 | Shape = shape; 22 | Bounds = shape.Bounds; 23 | } 24 | 25 | public BVHTreeNode2f(BOX2 bounds) 26 | { 27 | Shape = null; 28 | Bounds = bounds; 29 | } 30 | 31 | /// 32 | /// The nodes left child. 33 | /// 34 | public BVHTreeNode2f Left { get; internal set; } 35 | 36 | /// 37 | /// The nodes right child. 38 | /// 39 | public BVHTreeNode2f Right { get; internal set; } 40 | 41 | /// 42 | /// The nodes parent. 43 | /// 44 | public BVHTreeNode2f Parent { get; internal set; } 45 | 46 | /// 47 | /// The bounds of the nodes shape if its a leaf 48 | /// or the bounds of its child if not a leaf. 49 | /// 50 | public BOX2 Bounds; 51 | 52 | /// 53 | /// The nodes shape. 54 | /// Will be null if this node is not a leaf. 55 | /// 56 | public T Shape { get; internal set; } 57 | 58 | /// 59 | /// If this node in a leaf in the tree. 60 | /// Leaves have no childern. 61 | /// 62 | public bool IsLeaf => Shape != null; 63 | 64 | /// 65 | /// The nodes sibling is its parents other child. 66 | /// 67 | internal BVHTreeNode2f Sibling => Parent.Left == this ? Parent.Right : Parent.Left; 68 | 69 | /// 70 | /// 71 | /// 72 | /// 73 | public override string ToString() 74 | { 75 | if (IsLeaf) 76 | return string.Format("[BVHNode2f: IsLeaf={0}, Shape={1}]", IsLeaf, Shape); 77 | else 78 | return string.Format("[BVHNode2f: IsLeaf={0}, Bounds={1}]", IsLeaf, Bounds); 79 | } 80 | 81 | /// 82 | /// Enumerate all leaf nodes. 83 | /// 84 | public IEnumerator> GetEnumerator() 85 | { 86 | if (Left != null) 87 | { 88 | foreach (var n in Left) 89 | yield return n; 90 | } 91 | 92 | if (IsLeaf) 93 | yield return this; 94 | 95 | if (Right != null) 96 | { 97 | foreach (var n in Right) 98 | yield return n; 99 | } 100 | } 101 | 102 | /// 103 | /// Enumerate all leaf nodes. 104 | /// 105 | IEnumerator IEnumerable.GetEnumerator() 106 | { 107 | return GetEnumerator(); 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Common.Geometry/Collections/IShapeCollection2d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | using REAL = System.Double; 8 | using POINT2 = Common.Core.Numerics.Point2d; 9 | using BOX2 = Common.Core.Shapes.Box2d; 10 | 11 | namespace Common.Geometry.Collections 12 | { 13 | public interface IStaticShapeCollection2d : IEnumerable 14 | where T : class, IShape2d 15 | { 16 | /// 17 | /// The number of shapes in the collection. 18 | /// 19 | int Count { get; } 20 | 21 | /// 22 | /// Does a shape contain point. 23 | /// 24 | /// 25 | /// 26 | T Contains(POINT2 point); 27 | 28 | /// 29 | /// Find all the shapes that contain the point and 30 | /// add them to the list 31 | /// 32 | /// 33 | /// 34 | void Containing(POINT2 point, List shapes); 35 | 36 | /// 37 | /// Does a shape intersect the box. 38 | /// 39 | /// 40 | /// 41 | T Intersects(BOX2 box); 42 | 43 | /// 44 | /// Find all the shapes that intersect the box and 45 | /// add them to the list. 46 | /// 47 | /// 48 | /// 49 | void Intersecting(BOX2 box, List shapes); 50 | 51 | /// 52 | /// Return the signed distance field from 53 | /// the union of all shapes in the collection. 54 | /// 55 | /// 56 | /// 57 | REAL SignedDistance(POINT2 point); 58 | 59 | /// 60 | /// Return a list of all the shapes in the collection. 61 | /// 62 | /// 63 | List ToList(); 64 | } 65 | 66 | public interface IShapeCollection2d : IStaticShapeCollection2d 67 | where T : class, IShape2d 68 | { 69 | 70 | /// 71 | /// Clear the collection. 72 | /// 73 | void Clear(); 74 | 75 | /// 76 | /// Add the shapes to the collection. 77 | /// 78 | /// 79 | void Add(IEnumerable shapes); 80 | 81 | /// 82 | /// Add a shape to the collection. 83 | /// 84 | /// 85 | void Add(T shape); 86 | 87 | /// 88 | /// Remove a shape from the collection. 89 | /// 90 | /// 91 | /// 92 | bool Remove(T shape); 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Common.Geometry/Collections/IShapeCollection2f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | using REAL = System.Single; 8 | using POINT2 = Common.Core.Numerics.Point2f; 9 | using BOX2 = Common.Core.Shapes.Box2f; 10 | 11 | namespace Common.Geometry.Collections 12 | { 13 | public interface IStaticShapeCollection2f : IEnumerable 14 | where T : class, IShape2f 15 | { 16 | /// 17 | /// The number of shapes in the collection. 18 | /// 19 | int Count { get; } 20 | 21 | /// 22 | /// Does a shape contain point. 23 | /// 24 | /// 25 | /// 26 | T Contains(POINT2 point); 27 | 28 | /// 29 | /// Find all the shapes that contain the point and 30 | /// add them to the list 31 | /// 32 | /// 33 | /// 34 | void Containing(POINT2 point, List shapes); 35 | 36 | /// 37 | /// Does a shape intersect the box. 38 | /// 39 | /// 40 | /// 41 | T Intersects(BOX2 box); 42 | 43 | /// 44 | /// Find all the shapes that intersect the box and 45 | /// add them to the list. 46 | /// 47 | /// 48 | /// 49 | void Intersecting(BOX2 box, List shapes); 50 | 51 | /// 52 | /// Return the signed distance field from 53 | /// the union of all shapes in the collection. 54 | /// 55 | /// 56 | /// 57 | REAL SignedDistance(POINT2 point); 58 | 59 | /// 60 | /// Return a list of all the shapes in the collection. 61 | /// 62 | /// 63 | List ToList(); 64 | } 65 | 66 | public interface IShapeCollection2f : IStaticShapeCollection2f 67 | where T : class, IShape2f 68 | { 69 | 70 | /// 71 | /// Clear the collection. 72 | /// 73 | void Clear(); 74 | 75 | /// 76 | /// Add the shapes to the collection. 77 | /// 78 | /// 79 | void Add(IEnumerable shapes); 80 | 81 | /// 82 | /// Add a shape to the collection. 83 | /// 84 | /// 85 | void Add(T shape); 86 | 87 | /// 88 | /// Remove a shape from the collection. 89 | /// 90 | /// 91 | /// 92 | bool Remove(T shape); 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Common.Geometry/Collections/IShapeCollection3f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Geometry.Collections 8 | { 9 | public interface IStaticShapeCollection3f : IEnumerable 10 | where T : class, IShape3f 11 | { 12 | int Count { get; } 13 | 14 | float SignedDistance(Point3f point); 15 | 16 | T Contains(Point3f point); 17 | 18 | List ToList(); 19 | } 20 | 21 | public interface IShapeCollection3f : IStaticShapeCollection3f 22 | where T : class, IShape3f 23 | { 24 | 25 | void Clear(); 26 | 27 | void Add(IEnumerable shapes); 28 | 29 | void Add(T shape); 30 | 31 | bool Remove(T shape); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Common.Geometry/Common.Geometry.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0 4 | 40 5 | F:\Projects\Visual Studio Projects\Common\Backup\Common.Geometry\ 6 | 2.0 7 | 8 | 9 | true 10 | F:\Projects\Visual Studio Projects\Common\Common.Geometry\bin\Release\Common.Geometry.xml 11 | 12 | 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Common.Geometry/DCEL/DCELExceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Common.Geometry.DCEL 6 | { 7 | 8 | public class InvalidDCELException : Exception 9 | { 10 | 11 | public InvalidDCELException() { } 12 | 13 | public InvalidDCELException(string msg) : base(msg) { } 14 | 15 | } 16 | 17 | public class EdgeNotClosedException : Exception 18 | { 19 | 20 | public EdgeNotClosedException() { } 21 | 22 | public EdgeNotClosedException(string msg) : base(msg) { } 23 | 24 | } 25 | 26 | public class BetweenEdgeNotFoundException : Exception 27 | { 28 | public BetweenEdgeNotFoundException() { } 29 | 30 | public BetweenEdgeNotFoundException(string msg) : base(msg) { } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Common.Geometry/DCEL/DCELFace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Common.Geometry.DCEL 6 | { 7 | /// 8 | /// A half edge based face. Presumes face is CCW. 9 | /// 10 | public partial class DCELFace 11 | { 12 | 13 | internal DCELFace(int index) 14 | { 15 | Index = index; 16 | } 17 | 18 | /// 19 | /// Used for temporary making the face. 20 | /// 21 | public int Tag { get; set; } 22 | 23 | /// 24 | /// The faces index in the mesh. 25 | /// 26 | public int Index { get; private set; } 27 | 28 | /// 29 | /// The edge this face connects to. 30 | /// 31 | public DCELHalfedge Edge { get; internal set; } 32 | 33 | /// 34 | /// The faces optional data. 35 | /// 36 | public object Data { get; set; } 37 | 38 | /// 39 | /// Convert face to string. 40 | /// 41 | /// Face as string 42 | public override string ToString() 43 | { 44 | return string.Format("[DCELFace: Id={0}, Edge={1},]", 45 | Tag, DCELMesh.IndexOrDefault(Edge)); 46 | } 47 | 48 | /// 49 | /// The number of edges in face. 50 | /// 51 | public int EdgeCount 52 | { 53 | get 54 | { 55 | if (Edge == null) return 0; 56 | return Edge.EdgeCount; 57 | } 58 | } 59 | 60 | /// 61 | /// Clear face of all connections. 62 | /// 63 | internal void Clear() 64 | { 65 | Data = null; 66 | Edge = null; 67 | Index = -1; 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Common.Geometry/DCEL/DCELGeometry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.Geometry.DCEL 8 | { 9 | internal static class DCELGeometry 10 | { 11 | /// 12 | /// Do the 3 points form a striaght line. 13 | /// 14 | internal static bool Collinear(Point2d a, Point2d b, Point2d c) 15 | { 16 | return MathUtil.IsZero(Area2(a, b, c)); 17 | } 18 | 19 | /// 20 | /// Do the 3 points form a striaght line. 21 | /// 22 | internal static bool Collinear(Vector2d a, Vector2d b, Vector2d c) 23 | { 24 | return MathUtil.IsZero(Area2(a, b, c)); 25 | } 26 | 27 | /// 28 | /// True if b is within the cone formed by the 29 | /// edges incident at the from vertex of edge. 30 | /// 31 | internal static bool InCone(Point2d a0, Point2d a, Point2d a1, Point2d b) 32 | { 33 | //if a is a convex vertex. 34 | if (LeftOn(a, a1, a0)) 35 | return Left(a, b, a0) && Left(b, a, a1); 36 | 37 | //else a is reflex vertex. 38 | return !(LeftOn(a, b, a1) && LeftOn(b, a, a0)); 39 | } 40 | 41 | /// 42 | /// True if b is within the cone formed by the 43 | /// edges incident at the from vertex of edge. 44 | /// 45 | internal static bool InCone(Vector2d a0, Vector2d a, Vector2d a1, Vector2d b) 46 | { 47 | //if a is a convex vertex. 48 | if (LeftOn(a, a1, a0)) 49 | return Left(a, b, a0) && Left(b, a, a1); 50 | 51 | //else a is reflex vertex. 52 | return !(LeftOn(a, b, a1) && LeftOn(b, a, a0)); 53 | } 54 | 55 | /// 56 | /// Is c left of the line ab. 57 | /// 58 | internal static bool Left(Point2d a, Point2d b, Point2d c) 59 | { 60 | return Area2(a, b, c) > 0.0; 61 | } 62 | 63 | /// 64 | /// Is c left of the line ab. 65 | /// 66 | internal static bool Left(Vector2d a, Vector2d b, Vector2d c) 67 | { 68 | return Area2(a, b, c) > 0.0; 69 | } 70 | 71 | /// 72 | /// Is c left of or on the line ab. 73 | /// 74 | internal static bool LeftOn(Point2d a, Point2d b, Point2d c) 75 | { 76 | return Area2(a, b, c) >= 0.0; 77 | } 78 | 79 | /// 80 | /// Is c left of or on the line ab. 81 | /// 82 | internal static bool LeftOn(Vector2d a, Vector2d b, Vector2d c) 83 | { 84 | return Area2(a, b, c) >= 0.0; 85 | } 86 | 87 | /// 88 | /// Cross product area of a quadrilateral. 89 | /// 90 | internal static double Area2(Point2d a, Point2d b, Point2d c) 91 | { 92 | return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); 93 | } 94 | 95 | /// 96 | /// Cross product area of a quadrilateral. 97 | /// 98 | internal static double Area2(Vector2d a, Vector2d b, Vector2d c) 99 | { 100 | return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Common.Geometry/DCEL/DCELMesh.Insert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.Geometry.DCEL 8 | { 9 | public partial class DCELMesh 10 | { 11 | /// 12 | /// Add a new vertex to the mesh. 13 | /// 14 | /// The vertices point. 15 | /// The new vertex. 16 | public DCELVertex InsertVertex(Point2d point) 17 | { 18 | int i = NextVertexIndex(); 19 | var vert = new DCELVertex(i, point); 20 | 21 | Vertices[i] = vert; 22 | VertexCount++; 23 | 24 | return vert; 25 | } 26 | 27 | /// 28 | /// Add a new edge connecting the two vertices. 29 | /// 30 | /// The new edge that goes from v0 and to v1. 31 | public DCELHalfedge InsertEdge(DCELVertex v0, DCELVertex v1) 32 | { 33 | if (v0 == v1) 34 | throw new Exception("Can not connect the same vertex objects."); 35 | 36 | if (v0.Point == v1.Point) 37 | throw new Exception("Can not connect the same vertex positions."); 38 | 39 | int count0 = v0.Degree; 40 | int count1 = v1.Degree; 41 | 42 | int i = NextEdgeIndex(); 43 | 44 | var e0 = new DCELHalfedge(i); 45 | var e1 = new DCELHalfedge(i); 46 | e0.Opposite = e1; 47 | e1.Opposite = e0; 48 | 49 | if (count0 == 0 && count1 == 0) 50 | { 51 | 52 | } 53 | else if (count0 <= 1 && count1 <= 1) 54 | { 55 | DCELHalfedge.SetPrevious(e0, v0.Edge?.Opposite); 56 | DCELHalfedge.SetNext(e0, v1?.Edge); 57 | 58 | DCELHalfedge.SetPrevious(e1, v1.Edge?.Opposite); 59 | DCELHalfedge.SetNext(e1, v0?.Edge); 60 | } 61 | else if (count0 > 1 && count1 <= 1) 62 | { 63 | var edge = v0.FindInBetweenEdges(v1.Point); 64 | var previous = edge.Previous; 65 | 66 | DCELHalfedge.SetPrevious(e0, previous); 67 | DCELHalfedge.SetNext(e0, v1?.Edge); 68 | 69 | DCELHalfedge.SetPrevious(e1, v1.Edge?.Opposite); 70 | DCELHalfedge.SetNext(e1, edge); 71 | } 72 | else if (count0 <= 1 && count1 > 1) 73 | { 74 | var edge = v1.FindInBetweenEdges(v0.Point); 75 | var previous = edge.Previous; 76 | 77 | DCELHalfedge.SetPrevious(e0, v0.Edge?.Opposite); 78 | DCELHalfedge.SetNext(e0, edge); 79 | 80 | DCELHalfedge.SetPrevious(e1, previous); 81 | DCELHalfedge.SetNext(e1, v0?.Edge); 82 | } 83 | else if (count0 > 1 && count1 > 1) 84 | { 85 | var edge0 = v0.FindInBetweenEdges(v1.Point); 86 | var previous0 = edge0.Previous; 87 | 88 | var edge1 = v1.FindInBetweenEdges(v0.Point); 89 | var previous1 = edge1.Previous; 90 | 91 | DCELHalfedge.SetPrevious(e0, previous0); 92 | DCELHalfedge.SetNext(e0, edge1); 93 | 94 | DCELHalfedge.SetPrevious(e1, previous1); 95 | DCELHalfedge.SetNext(e1, edge0); 96 | } 97 | else 98 | { 99 | throw new Exception("Unhandled case connecting vertices."); 100 | } 101 | 102 | DCELHalfedge.SetFrom(e0, v0); 103 | DCELHalfedge.SetFrom(e1, v1); 104 | 105 | Edges[i] = e0; 106 | EdgeCount++; 107 | 108 | return e0; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Common.Geometry/Meshes/IndexableMesh.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Colors; 6 | 7 | namespace Common.Geometry.Meshes 8 | { 9 | 10 | public abstract class IndexableMesh 11 | { 12 | 13 | /// 14 | /// The number of positions in mesh. 15 | /// 16 | public abstract int PositionCount { get; } 17 | 18 | /// 19 | /// Does the mesh have indices. 20 | /// 21 | public bool HasIndices { get { return Indices != null; } } 22 | 23 | /// 24 | /// The number of indices in mesh. 25 | /// 26 | public int IndexCount { get { return (Indices != null) ? Indices.Length : 0; } } 27 | 28 | /// 29 | /// The mesh indices. 30 | /// 31 | public int[] Indices { get; protected set; } 32 | 33 | /// 34 | /// The does the mesh have colors.. 35 | /// 36 | public bool HasColors => Colors != null; 37 | 38 | /// 39 | /// The mesh colors. 40 | /// 41 | public ColorRGBA[] Colors { get; protected set; } 42 | 43 | /// 44 | /// Creates the color array. 45 | /// 46 | public void CreateColors() 47 | { 48 | int size = PositionCount; 49 | if (Colors == null || Colors.Length != size) 50 | Colors = new ColorRGBA[size]; 51 | } 52 | 53 | /// 54 | /// Create the color array. 55 | /// 56 | /// Array to copy from. 57 | public void SetColors(IList colors) 58 | { 59 | if (colors.Count != PositionCount) 60 | throw new Exception("Color array must match positions count"); 61 | 62 | CreateColors(); 63 | colors.CopyTo(Colors, 0); 64 | } 65 | 66 | /// 67 | /// Creates the index array. 68 | /// 69 | /// The size of the array. 70 | public void CreateIndices(int size) 71 | { 72 | if (Indices == null || Indices.Length != size) 73 | Indices = new int[size]; 74 | } 75 | 76 | /// 77 | /// Create the index array. 78 | /// 79 | /// Array to copy from. 80 | public void SetIndices(IList indices) 81 | { 82 | CreateIndices(indices.Count); 83 | indices.CopyTo(Indices, 0); 84 | } 85 | 86 | /// 87 | /// Add a triangle to the index array. 88 | /// 89 | /// The index in the indices array to add triangle. 90 | /// The index in the position array for the first point. 91 | /// The index in the position array for the second point. 92 | /// The index in the position array for the third point. 93 | public void AddTriangle(int i, int a, int b, int c) 94 | { 95 | Indices[i * 3 + 0] = a; 96 | Indices[i * 3 + 1] = b; 97 | Indices[i * 3 + 2] = c; 98 | } 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Common.Geometry/Points/IPointCollection2f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Geometry.Points 8 | { 9 | public interface IStaticPointCollection2f : IEnumerable 10 | { 11 | 12 | int Count { get; } 13 | 14 | void Search(Circle2f region, List points); 15 | 16 | Point2f Closest(Point2f point); 17 | 18 | List ToList(); 19 | 20 | } 21 | 22 | public interface IPointCollection2f : IStaticPointCollection2f 23 | { 24 | 25 | void Clear(); 26 | 27 | bool Add(IEnumerable points); 28 | 29 | bool Add(Point2f point); 30 | 31 | bool Remove(Point2f point); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Common.Geometry/Points/IPointCollection3f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | using Common.Core.Shapes; 6 | 7 | namespace Common.Geometry.Points 8 | { 9 | public interface IStaticPointCollection3f : IEnumerable 10 | { 11 | int Count { get; } 12 | 13 | void Search(Sphere3f region, List points); 14 | 15 | Point3f Closest(Point3f point); 16 | 17 | List ToList(); 18 | } 19 | 20 | public interface IPointCollection3f : IStaticPointCollection3f 21 | { 22 | void Clear(); 23 | 24 | bool Add(IEnumerable points); 25 | 26 | bool Add(Point3f point); 27 | 28 | bool Remove(Point3f point); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Common.Geometry/Points/KdTreeNode2f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.Geometry.Points 8 | { 9 | public class KdTreeNode2f : IEnumerable 10 | { 11 | 12 | public KdTreeNode2f(Point2f point, int depth) 13 | { 14 | Point = point; 15 | Depth = depth; 16 | } 17 | 18 | public Point2f Point { get; private set; } 19 | 20 | public KdTreeNode2f Left { get; internal set; } 21 | 22 | public KdTreeNode2f Right { get; internal set; } 23 | 24 | /// 25 | /// The depth of this node in the tree. 26 | /// 27 | public int Depth { get; private set; } 28 | 29 | public bool IsLeaf { get { return Left == null && Right == null; } } 30 | 31 | public bool IsVertical { get { return Depth % 2 == 0; } } 32 | 33 | /// 34 | /// Enumerate all points from this node. 35 | /// 36 | public IEnumerator GetEnumerator() 37 | { 38 | if (Left != null) 39 | { 40 | foreach (var n in Left) 41 | yield return n; 42 | } 43 | 44 | yield return this; 45 | 46 | if (Right != null) 47 | { 48 | foreach (var n in Right) 49 | yield return n; 50 | } 51 | } 52 | 53 | IEnumerator IEnumerable.GetEnumerator() 54 | { 55 | return GetEnumerator(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Common.Geometry/Points/KdTreeNode3f.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using Common.Core.Numerics; 6 | using Common.Core.Shapes; 7 | 8 | namespace Common.Geometry.Points 9 | { 10 | public class KdTreeNode3f : IEnumerable 11 | { 12 | public KdTreeNode3f(Point3f point, int depth) 13 | { 14 | Point = point; 15 | Depth = depth; 16 | } 17 | 18 | public Point3f Point { get; private set; } 19 | 20 | public KdTreeNode3f Left { get; internal set; } 21 | 22 | public KdTreeNode3f Right { get; internal set; } 23 | 24 | /// 25 | /// The depth of this node in the tree. 26 | /// 27 | public int Depth { get; private set; } 28 | 29 | public bool IsLeaf { get { return Left == null && Right == null; } } 30 | 31 | /// 32 | /// Enumerate all points from this node. 33 | /// 34 | public IEnumerator GetEnumerator() 35 | { 36 | if (Left != null) 37 | { 38 | foreach (var n in Left) 39 | yield return n; 40 | } 41 | 42 | yield return this; 43 | 44 | if (Right != null) 45 | { 46 | foreach (var n in Right) 47 | yield return n; 48 | } 49 | } 50 | 51 | IEnumerator IEnumerable.GetEnumerator() 52 | { 53 | return GetEnumerator(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Common.GraphTheory.Test/GridsGraphs/GridFlowGraphTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | using Common.Core.Directions; 6 | using Common.Core.Numerics; 7 | using Common.Core.Extensions; 8 | using Common.GraphTheory.GridGraphs; 9 | 10 | namespace Common.GraphTheory.Test.GridsGraphs 11 | { 12 | [TestClass] 13 | public class GridFlowGraphTest 14 | { 15 | [TestMethod] 16 | public void PushRelabel() 17 | { 18 | var graph = new FlowGridGraph(6, 6); 19 | 20 | //int maxFlow = graph.PushRelabel(0, 5); 21 | //Assert.AreEqual(4, maxFlow); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Common.GraphTheory.Test/GridsGraphs/GridGraphTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | using Common.Core.Directions; 6 | using Common.Core.Numerics; 7 | using Common.Core.Extensions; 8 | using Common.GraphTheory.GridGraphs; 9 | 10 | namespace Common.GraphTheory.Test.GridGraphs 11 | { 12 | [TestClass] 13 | public class GridGraphTest 14 | { 15 | 16 | [TestMethod] 17 | public void DijkstrasShortestPathTree() 18 | { 19 | 20 | //var graph = RandomGraph(0); 21 | var graph = ConstGraph(); 22 | 23 | var source = new Point2i(0, 0); 24 | var target = new Point2i(3, 3); 25 | 26 | var search = graph.DijkstrasShortestPathTree(source); 27 | 28 | var path = search.GetPath(target); 29 | 30 | //search.Print(); 31 | 32 | //foreach (var p in path) 33 | // Console.WriteLine(p); 34 | 35 | } 36 | 37 | private WeightedGridGraph RandomGraph(int seed) 38 | { 39 | var graph = new WeightedGridGraph(4, 4); 40 | 41 | var rnd = new Random(seed); 42 | 43 | graph.Iterate((x, y, i) => 44 | { 45 | if (rnd.NextBool()) 46 | { 47 | float weight = rnd.NextFloat(0, 10); 48 | graph.AddDirectedWeightedEdge(x, y, i, weight); 49 | } 50 | }); 51 | 52 | return graph; 53 | } 54 | 55 | private WeightedGridGraph ConstGraph() 56 | { 57 | var graph = new WeightedGridGraph(4, 4); 58 | 59 | graph.Iterate((x, y, i) => 60 | { 61 | int xi = x + D8.OFFSETS[i, 0]; 62 | int yi = y + D8.OFFSETS[i, 1]; 63 | 64 | if(graph.InBounds(xi, yi)) 65 | { 66 | graph.AddDirectedWeightedEdge(x, y, i, 1); 67 | } 68 | 69 | }); 70 | 71 | return graph; 72 | } 73 | 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /Common.GraphTheory.Test/MatrixGraphs/MatrixGraphTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System; 3 | 4 | using Common.Core.Directions; 5 | using Common.Core.Numerics; 6 | using Common.Core.Extensions; 7 | using Common.GraphTheory.MatrixGraphs; 8 | 9 | namespace Common.GraphTheory.Test.MatrixGraphs 10 | { 11 | [TestClass] 12 | public class MatrixGraphTest 13 | { 14 | [TestMethod] 15 | public void PushRelabel() 16 | { 17 | 18 | int[,] flow = new int[6, 6]; 19 | int[,] capacities = new int[6, 6]; 20 | 21 | capacities[0,1] = 2; 22 | capacities[0,2] = 9; 23 | capacities[1,2] = 1; 24 | capacities[1,3] = 0; 25 | capacities[1,4] = 0; 26 | capacities[2,4] = 7; 27 | capacities[3,5] = 7; 28 | capacities[4,5] = 4; 29 | 30 | int maxFlow = MatrixGraph.PushRelabel(capacities, flow, 0, 5); 31 | 32 | Assert.AreEqual(4, maxFlow); 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Common.GraphTheory.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Common.GraphTheory.Test")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("Common.GraphTheory.Test")] 10 | [assembly: AssemblyCopyright("Copyright © 2019")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("90986382-062e-4e92-81ff-8d48988904be")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /Common.GraphTheory.Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/AdjacencyGraph.DepthFirst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Common.GraphTheory.AdjacencyGraphs 6 | { 7 | 8 | public abstract partial class AdjacencyGraph 9 | { 10 | /// 11 | /// Return a list of vertex indices ordered depth first. 12 | /// 13 | /// The vertex index to start at. 14 | /// The vertices in depth first order. 15 | public List DepthFirstOrder(int root) 16 | { 17 | TagVertices(NOT_VISITED_TAG); 18 | int count = VertexCount; 19 | 20 | var queue = new Stack(count); 21 | queue.Push(root); 22 | 23 | Vertices[root].Tag = IS_VISITED_TAG; 24 | 25 | var ordering = new List(count); 26 | 27 | while (queue.Count != 0) 28 | { 29 | int u = queue.Pop(); 30 | ordering.Add(u); 31 | 32 | var edges = Edges[u]; 33 | if (edges == null) continue; 34 | 35 | for (int i = 0; i < edges.Count; i++) 36 | { 37 | int to = edges[i].To; 38 | 39 | if (Vertices[to].Tag == IS_VISITED_TAG) continue; 40 | 41 | queue.Push(to); 42 | Vertices[to].Tag = IS_VISITED_TAG; 43 | } 44 | } 45 | 46 | return ordering; 47 | } 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/DirectedGraph.AStar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.GraphTheory.AdjacencyGraphs 8 | { 9 | public partial class DirectedGraph 10 | { 11 | private struct AStarNode 12 | { 13 | public int idx; 14 | public float g, h, f; 15 | 16 | public AStarNode(int i) 17 | { 18 | idx = i; 19 | g = h = f = 0; 20 | } 21 | } 22 | 23 | public List AStar(int start, int end, Func Heuristic) 24 | { 25 | 26 | TagVertices(NOT_VISITED_TAG); 27 | 28 | var path = new List(); 29 | var open = new List(); 30 | open.Add(new AStarNode(start)); 31 | 32 | bool found = false; 33 | 34 | int g = 0; 35 | 36 | while (open.Count > 0) 37 | { 38 | var lowest = open.Min(n => n.f); 39 | var u = open.First(n => n.f == lowest); 40 | 41 | open.Remove(u); 42 | path.Add(u.idx); 43 | base.Vertices[u.idx].Tag = IS_VISITED_TAG; 44 | 45 | if (base.Vertices[end].Tag == IS_VISITED_TAG) 46 | { 47 | found = true; 48 | break; 49 | } 50 | 51 | var edges = base.Edges[u.idx]; 52 | if (edges == null) continue; 53 | 54 | for (int i = 0; i < edges.Count; i++) 55 | { 56 | int to = edges[i].To; 57 | if (base.Vertices[to].Tag == IS_VISITED_TAG) continue; 58 | 59 | int idx = Contains(open, to); 60 | if (idx == -1) 61 | { 62 | var n = new AStarNode(to); 63 | n.g = g; 64 | n.h = Heuristic(base.Vertices[end], base.Vertices[to]); 65 | n.f = n.g + n.h; 66 | 67 | open.Add(n); 68 | } 69 | else 70 | { 71 | var n = open[idx]; 72 | if (g + n.h < n.f) 73 | { 74 | n.g = g; 75 | n.f = n.g + n.h; 76 | 77 | open[idx] = n; 78 | } 79 | } 80 | } 81 | 82 | } 83 | 84 | if (!found) 85 | path.Clear(); 86 | 87 | return path; 88 | } 89 | 90 | public static float EuclideanDistance(Vector3f a, Vector3f b) 91 | { 92 | return (a - b).Magnitude; 93 | } 94 | 95 | private static int Contains(List open, int idx) 96 | { 97 | for (int i = 0; i < open.Count; i++) 98 | if (open[i].idx == idx) return i; 99 | 100 | return -1; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/DirectedGraph.Djkstras.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.GraphTheory.AdjacencyGraphs 7 | { 8 | public partial class DirectedGraph : AdjacencyGraph 9 | { 10 | /// 11 | /// Create a graph tree representing the shortest paths 12 | /// between the vertices in the graph. 13 | /// 14 | /// The vertex index to start at. 15 | /// The shortest path tree. 16 | public GraphTree DijkstrasShortestPathTree(int root) 17 | { 18 | TagVertices(NOT_VISITED_TAG); 19 | int count = VertexCount; 20 | 21 | for (int i = 0; i < count; i++) 22 | base.Vertices[i].Cost = float.PositiveInfinity; 23 | 24 | base.Vertices[root].Cost = 0; 25 | base.Vertices[root].Tag = IS_VISITED_TAG; 26 | 27 | var tree = new GraphTree(this, root); 28 | var queue = new List(base.Vertices); 29 | 30 | while (queue.Count != 0) 31 | { 32 | queue.Sort(); 33 | 34 | var vertex = queue[0]; 35 | queue.RemoveAt(0); 36 | int u = vertex.Index; 37 | 38 | base.Vertices[u].Tag = IS_VISITED_TAG; 39 | 40 | if (base.Edges[u] != null) 41 | { 42 | foreach (var e in base.Edges[u]) 43 | { 44 | int v = e.To; 45 | if (base.Vertices[v].Tag == IS_VISITED_TAG) continue; 46 | 47 | float alt = base.Vertices[u].Cost + e.Weight; 48 | 49 | if (alt < base.Vertices[v].Cost) 50 | { 51 | if (!MathUtil.IsFinite(alt)) 52 | throw new ArithmeticException("Cost is not finite."); 53 | 54 | base.Vertices[v].Cost = alt; 55 | tree.Parent[v] = u; 56 | } 57 | } 58 | } 59 | } 60 | 61 | return tree; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/DirectedGraph.Khans.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Common.GraphTheory.AdjacencyGraphs 6 | { 7 | 8 | public partial class DirectedGraph : AdjacencyGraph 9 | { 10 | /// 11 | /// Presuming the edges represent the order the 12 | /// vertices must be iterated return a list of 13 | /// vertex indices that conform to this order. 14 | /// 15 | /// 16 | public List KhansTopologicalSort() 17 | { 18 | var list = new List(); 19 | var vertices = new LinkedList(); 20 | 21 | int edgeCount = base.Edges.Count; 22 | var edges = new List[edgeCount]; 23 | 24 | for (int i = 0; i < edgeCount; i++) 25 | { 26 | if (base.Edges[i] == null) continue; 27 | edges[i] = new List(base.Edges[i]); 28 | } 29 | 30 | for (int i = 0; i < base.Vertices.Count; i++) 31 | { 32 | int idegree = Khans_GetInverseDegree(edges, i); 33 | 34 | if (idegree == 0) 35 | vertices.AddLast(base.Vertices[i]); 36 | } 37 | 38 | while (vertices.Count > 0) 39 | { 40 | GraphVertex v = vertices.Last.Value; 41 | vertices.RemoveLast(); 42 | 43 | list.Add(v); 44 | int i = v.Index; 45 | 46 | if (edges[i] == null || edges[i].Count == 0) continue; 47 | 48 | for (int j = 0; j < edges[i].Count; j++) 49 | { 50 | int to = edges[i][j].To; 51 | 52 | int idegree = Khans_GetInverseDegree(edges, to); 53 | if (idegree == 1) 54 | { 55 | vertices.AddLast(base.Vertices[to]); 56 | } 57 | } 58 | 59 | edges[i].Clear(); 60 | } 61 | 62 | if (Khans_CountEdges(edges) > 0) 63 | throw new InvalidOperationException("Can not find a topological sort on a cyclic graph"); 64 | else 65 | return list; 66 | } 67 | 68 | /// 69 | /// Find the number of vertices that go to this vertex. 70 | /// 71 | /// A list of the edges for each vertex. 72 | /// The vertex index. 73 | /// 74 | private int Khans_GetInverseDegree(List[] Edges, int i) 75 | { 76 | int degree = 0; 77 | 78 | foreach (var edges in Edges) 79 | { 80 | if (edges == null || edges.Count == 0) continue; 81 | 82 | foreach (var edge in edges) 83 | { 84 | if (edge.To == i) degree++; 85 | } 86 | } 87 | 88 | return degree; 89 | } 90 | 91 | /// 92 | /// Count the number of edges in the list of lists. 93 | /// 94 | /// A list of the edges for each vertex. 95 | /// 96 | private int Khans_CountEdges(List[] Edges) 97 | { 98 | int count = 0; 99 | 100 | foreach (var edges in Edges) 101 | { 102 | if (edges == null) continue; 103 | count += edges.Count; 104 | } 105 | 106 | return count; 107 | } 108 | 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/GraphForest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.GraphTheory.AdjacencyGraphs 5 | { 6 | /// 7 | /// A list of graph trees. 8 | /// 9 | public class GraphForest 10 | { 11 | 12 | private Dictionary m_forest; 13 | 14 | public GraphForest(AdjacencyGraph graph) 15 | { 16 | Graph = graph; 17 | m_forest = new Dictionary(); 18 | } 19 | 20 | public GraphForest(AdjacencyGraph graph, int size) 21 | { 22 | Graph = graph; 23 | m_forest = new Dictionary(size); 24 | } 25 | 26 | /// 27 | /// The number of trees in the forest. 28 | /// 29 | public int Count => m_forest.Count; 30 | 31 | /// 32 | /// The graph the trees were constructed from. 33 | /// 34 | public AdjacencyGraph Graph { get; private set; } 35 | 36 | /// 37 | /// The vertex indices of the tree roots. 38 | /// 39 | public IEnumerable Roots => m_forest.Keys; 40 | 41 | /// 42 | /// The trees in the forest. 43 | /// 44 | public IEnumerable Trees => m_forest.Values; 45 | 46 | 47 | /// 48 | /// 49 | /// 50 | public override string ToString() 51 | { 52 | return string.Format("[GraphForest: Count={0}]", Count); 53 | } 54 | 55 | /// 56 | /// Does the forest contain this tree. 57 | /// 58 | public bool ContainsTree(int root) 59 | { 60 | return m_forest.ContainsKey(root); 61 | } 62 | 63 | /// 64 | /// Get the tree with this root. 65 | /// 66 | public GraphTree GetTree(int root) 67 | { 68 | return m_forest[root]; 69 | } 70 | 71 | /// 72 | /// Add a tree to the forest. 73 | /// 74 | public void AddTree(GraphTree tree) 75 | { 76 | m_forest.Add(tree.Root, tree); 77 | } 78 | 79 | /// 80 | /// Remove a tree from the forest. 81 | /// 82 | public bool RemoveTree(int root) 83 | { 84 | return m_forest.Remove(root); 85 | } 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/GraphVertex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.GraphTheory.AdjacencyGraphs 5 | { 6 | 7 | public sealed class GraphVertex : IComparable 8 | { 9 | /// 10 | /// Default constructor. 11 | /// 12 | public GraphVertex() 13 | { 14 | Index = -1; 15 | } 16 | 17 | /// 18 | /// Create a vertex with a index. 19 | /// 20 | /// The index of the vertex in its graph. 21 | public GraphVertex(int index) 22 | { 23 | Index = index; 24 | } 25 | 26 | /// 27 | /// Create a vertex with a index and data. 28 | /// 29 | /// The index of the vertex in its graph. 30 | /// The vertices data. 31 | public GraphVertex(int index, object data) 32 | { 33 | Index = index; 34 | Data = data; 35 | } 36 | 37 | /// 38 | /// The index of this vertex in the graph. 39 | /// 40 | public int Index { get; set; } 41 | 42 | /// 43 | ///Use to tempory mark the vertex. 44 | /// 45 | public int Tag { get; set; } 46 | 47 | /// 48 | /// The cost of this vertex. 49 | /// Used in some search algorithms. 50 | /// ie shortest paths. 51 | /// 52 | public float Cost { get; set; } 53 | 54 | /// 55 | /// The vertices data. 56 | /// 57 | public object Data { get; set; } 58 | 59 | 60 | /// 61 | /// 62 | /// 63 | public override string ToString() 64 | { 65 | return string.Format("[GraphVertex: Index={0}, Cost={1}, Data={2}]", 66 | Index, Cost, Data != null ? Data.ToString() : "Null"); 67 | } 68 | 69 | /// 70 | /// Used to sort vertices by cost. 71 | /// 72 | public int CompareTo(GraphVertex other) 73 | { 74 | return Cost.CompareTo(other.Cost); 75 | } 76 | 77 | /// 78 | /// Create deep copy of vertex. 79 | /// 80 | /// Function to copy data. If null shallow copy will be used. 81 | /// A copy of the vertex. 82 | public GraphVertex Copy(Func dataCopy = null) 83 | { 84 | GraphVertex copy = new GraphVertex(); 85 | copy.Index = Index; 86 | copy.Cost = Cost; 87 | 88 | if (dataCopy != null) 89 | copy.Data = dataCopy.Invoke(Data); 90 | else 91 | copy.Data = Data; 92 | 93 | return copy; 94 | } 95 | } 96 | 97 | 98 | } 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/UndirectedGraph.Kruskals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Collections.Sets; 5 | 6 | namespace Common.GraphTheory.AdjacencyGraphs 7 | { 8 | 9 | public partial class UndirectedGraph : AdjacencyGraph 10 | { 11 | /// 12 | /// Create a forest of trees from the graph. 13 | /// Each tree represents connected sets of vertices 14 | /// ordered as a minimum spanning tree. 15 | /// 16 | /// 17 | public GraphForest KruskalsMinimumSpanningForest() 18 | { 19 | var set = new DisjointSet(VertexCount); 20 | 21 | var sorted = new List(); 22 | GetAllEdges(sorted); 23 | sorted.Sort(); 24 | 25 | int edgeCount = sorted.Count; 26 | var edges = new List(edgeCount); 27 | 28 | for (int i = 0; i < edgeCount; i++) 29 | { 30 | int u = sorted[i].From; 31 | int v = sorted[i].To; 32 | 33 | if (set.Union(v, u)) 34 | edges.Add(sorted[i]); 35 | } 36 | 37 | var table = new Dictionary>(); 38 | 39 | edgeCount = edges.Count; 40 | for (int i = 0; i < edgeCount; i++) 41 | { 42 | int root = set.FindParent(edges[i].From); 43 | 44 | if (!table.ContainsKey(root)) 45 | table.Add(root, new List()); 46 | 47 | table[root].Add(edges[i]); 48 | } 49 | 50 | var forest = new GraphForest(this); 51 | var graph = new UndirectedGraph(VertexCount); 52 | 53 | foreach (var kvp in table) 54 | { 55 | int root = kvp.Key; 56 | var list = kvp.Value; 57 | 58 | graph.ClearEdges(); 59 | graph.TagVertices(NOT_VISITED_TAG); 60 | foreach(var edge in list) 61 | { 62 | int from = edge.From; 63 | int to = edge.To; 64 | graph.AddUndirectedEdge(from, to); 65 | } 66 | 67 | var tree = Kruskals_BuildTree(root, graph); 68 | forest.AddTree(tree); 69 | } 70 | 71 | return forest; 72 | } 73 | 74 | private GraphTree Kruskals_BuildTree(int root, UndirectedGraph graph) 75 | { 76 | int count = graph.VertexCount; 77 | 78 | var queue = new Stack(count); 79 | queue.Push(root); 80 | 81 | graph.Vertices[root].Tag = IS_VISITED_TAG; 82 | 83 | var tree = new GraphTree(this, root); 84 | tree.Parent[root] = root; 85 | 86 | while (queue.Count != 0) 87 | { 88 | int u = queue.Pop(); 89 | 90 | var edges = graph.Edges[u]; 91 | if (edges == null) continue; 92 | 93 | for (int i = 0; i < edges.Count; i++) 94 | { 95 | int to = edges[i].To; 96 | if (graph.Vertices[to].Tag == IS_VISITED_TAG) continue; 97 | 98 | tree.Parent[to] = u; 99 | queue.Push(to); 100 | graph.Vertices[to].Tag = IS_VISITED_TAG; 101 | } 102 | } 103 | 104 | return tree; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Common.GraphTheory/AdjacencyGraphs/UndirectedGraph.Prims.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Collections.Queues; 5 | 6 | namespace Common.GraphTheory.AdjacencyGraphs 7 | { 8 | public partial class UndirectedGraph : AdjacencyGraph 9 | { 10 | /// 11 | /// Create a graph tree representing the minimum 12 | /// spanning tree between the vertices in the graph. 13 | /// 14 | /// The vertex index to start at. 15 | /// The minimum spanning tree. 16 | public GraphTree PrimsMinimumSpanningTree(int root) 17 | { 18 | TagVertices(NOT_VISITED_TAG); 19 | int count = VertexCount; 20 | 21 | Vertices[root].Tag = IS_VISITED_TAG; 22 | 23 | var tree = new GraphTree(this, root); 24 | var queue = new BinaryHeap(); 25 | 26 | if (Edges[root] != null) 27 | { 28 | foreach (var edge in Edges[root]) 29 | queue.Add(edge); 30 | } 31 | 32 | while (queue.Count != 0) 33 | { 34 | var edge = queue.Pop(); 35 | 36 | int v = edge.To; 37 | if (Vertices[v].Tag == IS_VISITED_TAG) continue; 38 | 39 | Vertices[v].Tag = IS_VISITED_TAG; 40 | tree.Parent[v] = edge.From; 41 | 42 | if (Edges[v] != null) 43 | { 44 | foreach (var e in Edges[v]) 45 | { 46 | if (Vertices[e.To].Tag == IS_VISITED_TAG) continue; 47 | queue.Add(e); 48 | } 49 | } 50 | } 51 | 52 | return tree; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Common.GraphTheory/Common.GraphTheory.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0 4 | 40 5 | F:\Projects\Visual Studio Projects\Common\Backup\Common.GraphTheory\ 6 | 2.0 7 | 8 | 9 | F:\Projects\Visual Studio Projects\Common\Common.GraphTheory\bin\Release\Common.GraphTheory.xml 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/GridGraph.BreadthFirst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Directions; 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.GraphTheory.GridGraphs 8 | { 9 | public partial class GridGraph 10 | { 11 | 12 | public GridSearch BreadthFirst(Point2i root) 13 | { 14 | var search = new GridSearch(Width, Height); 15 | BreadthFirst(search, root.x, root.y); 16 | return search; 17 | } 18 | 19 | public GridSearch BreadthFirst(int x, int y) 20 | { 21 | var search = new GridSearch(Width, Height); 22 | BreadthFirst(search, x, y); 23 | return search; 24 | } 25 | 26 | public void BreadthFirst(GridSearch search, int x, int y) 27 | { 28 | int width = Width; 29 | int height = Height; 30 | 31 | Queue queue = new Queue(); 32 | queue.Enqueue(new Point2i(x, y)); 33 | 34 | search.SetParent(x, y, new Point2i(x, y)); 35 | search.SetIsVisited(x, y, true); 36 | 37 | while (queue.Count != 0) 38 | { 39 | Point2i u = queue.Dequeue(); 40 | search.AddOrder(u); 41 | 42 | int edge = Edges[u.x, u.y]; 43 | 44 | for (int j = 0; j < Directions.Count; j++) 45 | { 46 | int i = Directions[j]; 47 | int xi = u.x + D8.OFFSETS[i, 0]; 48 | int yi = u.y + D8.OFFSETS[i, 1]; 49 | 50 | if (xi < 0 || xi > width - 1) continue; 51 | if (yi < 0 || yi > height - 1) continue; 52 | 53 | if ((edge & 1 << i) == 0) continue; 54 | if (search.GetIsVisited(xi, yi)) continue; 55 | 56 | queue.Enqueue(new Point2i(xi, yi)); 57 | search.SetIsVisited(xi, yi, true); 58 | search.SetParent(xi, yi, u); 59 | } 60 | } 61 | 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/GridGraph.DepthFirst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Directions; 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.GraphTheory.GridGraphs 8 | { 9 | public partial class GridGraph 10 | { 11 | public GridSearch DepthFirst(Point2i root) 12 | { 13 | var search = new GridSearch(Width, Height); 14 | DepthFirst(search, root.x, root.y); 15 | return search; 16 | } 17 | 18 | public GridSearch DepthFirst(int x, int y) 19 | { 20 | var search = new GridSearch(Width, Height); 21 | DepthFirst(search, x, y); 22 | return search; 23 | } 24 | 25 | public void DepthFirst(GridSearch search, int x, int y) 26 | { 27 | int width = Width; 28 | int height = Height; 29 | 30 | Stack queue = new Stack(); 31 | queue.Push(new Point2i(x, y)); 32 | 33 | search.SetParent(x, y, new Point2i(x, y)); 34 | search.SetIsVisited(x, y, true);; 35 | 36 | while (queue.Count != 0) 37 | { 38 | Point2i u = queue.Pop(); 39 | search.AddOrder(u); 40 | 41 | int edge = Edges[u.x, u.y]; 42 | 43 | for (int j = 0; j < Directions.Count; j++) 44 | { 45 | int i = Directions[j]; 46 | int xi = u.x + D8.OFFSETS[i, 0]; 47 | int yi = u.y + D8.OFFSETS[i, 1]; 48 | 49 | if (xi < 0 || xi > width - 1) continue; 50 | if (yi < 0 || yi > height - 1) continue; 51 | 52 | if ((edge & 1 << i) == 0) continue; 53 | if (search.GetIsVisited(xi, yi)) continue; 54 | 55 | queue.Push(new Point2i(xi, yi)); 56 | search.SetIsVisited(xi, yi, true); 57 | search.SetParent(xi, yi, u); 58 | } 59 | } 60 | 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/GridGraph.Dijkstras.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Directions; 5 | using Common.Core.Numerics; 6 | 7 | namespace Common.GraphTheory.GridGraphs 8 | { 9 | public partial class GridGraph 10 | { 11 | 12 | public GridSearch DijkstrasShortestPathTree(Point2i root) 13 | { 14 | var search = new GridSearch(Width, Height); 15 | DijkstrasShortestPathTree(search, root.x, root.y); 16 | return search; 17 | } 18 | 19 | public GridSearch DijkstrasShortestPathTree(int x, int y) 20 | { 21 | var search = new GridSearch(Width, Height); 22 | DijkstrasShortestPathTree(search, x, y); 23 | return search; 24 | } 25 | 26 | public void DijkstrasShortestPathTree(GridSearch search, int x, int y) 27 | { 28 | int width = Width; 29 | int height = Height; 30 | 31 | var queue = new List(width * height); 32 | GetAllVertices(queue); 33 | var vertexGrid = new GridVertex[width, height]; 34 | 35 | for (int i = 0; i < queue.Count; i++) 36 | { 37 | var v = queue[i]; 38 | int xi = v.Index.x; 39 | int yi = v.Index.y; 40 | v.Cost = float.PositiveInfinity; 41 | 42 | vertexGrid[xi, yi] = v; 43 | } 44 | 45 | search.SetIsVisited(x, y, true); 46 | search.SetParent(x, y, new Point2i(x, y)); 47 | vertexGrid[x, y].Cost = 0; 48 | 49 | while (queue.Count != 0) 50 | { 51 | queue.Sort(); 52 | 53 | var vertex = queue[0]; 54 | queue.RemoveAt(0); 55 | var u = vertex.Index; 56 | 57 | search.AddOrder(u); 58 | search.SetIsVisited(u, true); 59 | 60 | int edge = Edges[u.x, u.y]; 61 | if (edge != 0) 62 | { 63 | float cost = vertexGrid[u.x, u.y].Cost; 64 | 65 | for (int j = 0; j < Directions.Count; j++) 66 | { 67 | int i = Directions[j]; 68 | int xi = u.x + D8.OFFSETS[i, 0]; 69 | int yi = u.y + D8.OFFSETS[i, 1]; 70 | 71 | if (xi < 0 || xi > width - 1) continue; 72 | if (yi < 0 || yi > height - 1) continue; 73 | 74 | if ((edge & 1 << i) == 0) continue; 75 | if (search.GetIsVisited(xi, yi)) continue; 76 | 77 | var v = vertexGrid[xi, yi]; 78 | if (v == null) 79 | { 80 | v = new GridVertex(xi, yi, 0); 81 | vertexGrid[xi, yi] = v; 82 | } 83 | 84 | float alt = cost + (float)Point2i.Distance(u, v.Index); 85 | 86 | if (alt < v.Cost) 87 | { 88 | if (!MathUtil.IsFinite(alt)) 89 | throw new ArithmeticException("Cost is not finite."); 90 | 91 | v.Cost = alt; 92 | search.SetParent(xi, yi, u); 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/GridVertex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.GraphTheory.GridGraphs 7 | { 8 | /// 9 | /// A vertex for a grid graph. A grid graph normally 10 | /// use a grid of indices to represent vertices 11 | /// but if they need to be instantied into objects 12 | /// this class is used. 13 | /// 14 | public class GridVertex : IComparable 15 | { 16 | /// 17 | /// The index in the grid this vertex 18 | /// belongs to. 19 | /// 20 | public Point2i Index { get; set; } 21 | 22 | /// 23 | /// The cost of the vertex. used in 24 | /// algorithms such as shortest paths. 25 | /// 26 | public float Cost { get; set; } 27 | 28 | public GridVertex() 29 | { 30 | 31 | } 32 | 33 | public GridVertex(Point2i index) 34 | { 35 | Index = index; 36 | } 37 | 38 | public GridVertex(Point2i index, float cost) 39 | { 40 | Index = index; 41 | Cost = cost; 42 | } 43 | 44 | public GridVertex(int x, int y, float cost) 45 | { 46 | Index = new Point2i(x, y); 47 | Cost = cost; 48 | } 49 | 50 | public override string ToString() 51 | { 52 | return string.Format("[GridVertex: Index={0}, Cost={1}]", Index, Cost); 53 | } 54 | 55 | /// 56 | /// Used to sort vertices by their cost. 57 | /// 58 | public int CompareTo(GridVertex other) 59 | { 60 | return Cost.CompareTo(other.Cost); 61 | } 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/WeighedGridEdge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Numerics; 5 | 6 | namespace Common.GraphTheory.GridGraphs 7 | { 8 | /// 9 | /// A edge for a grid graph. A grid graph normally 10 | /// use a grid of byte flags to represent edges 11 | /// but if they need to be instantied into objects 12 | /// this class is used. 13 | /// 14 | public class WeighedGridEdge : IComparable 15 | { 16 | /// 17 | /// The index of the vertex this edge starts at. 18 | /// 19 | public Point2i From { get; set; } 20 | 21 | /// 22 | /// The index of the vertex this edge ends at. 23 | /// 24 | public Point2i To { get; set; } 25 | 26 | /// 27 | /// The weight of this edge. 28 | /// used in algorithms like spanning trees. 29 | /// 30 | public float Weight { get; set; } 31 | 32 | public WeighedGridEdge() 33 | { 34 | 35 | } 36 | 37 | public WeighedGridEdge(Point2i from, Point2i to) 38 | { 39 | From = from; 40 | To = to; 41 | } 42 | 43 | public WeighedGridEdge(int fx, int fy, int tx, int ty) 44 | { 45 | From = new Point2i(fx, fy); 46 | To = new Point2i(tx, ty); 47 | } 48 | 49 | public override string ToString() 50 | { 51 | return string.Format("[GridEdge: From={0}, To={1}, Weight={2}]", From, To, Weight); 52 | } 53 | 54 | /// 55 | /// Used to sort edges by their weight. 56 | /// 57 | public int CompareTo(WeighedGridEdge other) 58 | { 59 | return Weight.CompareTo(other.Weight); 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/WeighedGridGraph.Kruskals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Directions; 5 | using Common.Collections.Sets; 6 | using Common.Core.Numerics; 7 | 8 | namespace Common.GraphTheory.GridGraphs 9 | { 10 | public partial class WeightedGridGraph 11 | { 12 | public Dictionary> KruskalsMinimumSpanningForest(Func GetWeight) 13 | { 14 | int width = Width; 15 | int height = Height; 16 | 17 | DisjointGridSet2 set = new DisjointGridSet2(width, height); 18 | 19 | for (int y = 0; y < height; y++) 20 | { 21 | for (int x = 0; x < width; x++) 22 | { 23 | set.Add(x, y, x, y); 24 | } 25 | } 26 | 27 | var sorted = new List(width * height); 28 | GetAllEdges(sorted, GetWeight); 29 | sorted.Sort(); 30 | 31 | int edgeCount = sorted.Count; 32 | List edges = new List(); 33 | 34 | for (int i = 0; i < edgeCount; i++) 35 | { 36 | Point2i from = sorted[i].From; 37 | Point2i to = sorted[i].To; 38 | 39 | if (set.Union(to.x, to.y, from.x, from.y)) 40 | edges.Add(sorted[i]); 41 | } 42 | 43 | Dictionary> forest = new Dictionary>(); 44 | 45 | edgeCount = edges.Count; 46 | for (int i = 0; i < edgeCount; i++) 47 | { 48 | Point2i root = set.FindParent(edges[i].From.x, edges[i].From.y); 49 | 50 | if (!forest.ContainsKey(root)) 51 | forest.Add(root, new List()); 52 | 53 | forest[root].Add(edges[i]); 54 | } 55 | 56 | return forest; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Common.GraphTheory/GridGraphs/WeighedGridGraph.Prims.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Common.Core.Directions; 5 | using Common.Collections.Queues; 6 | using Common.Core.Numerics; 7 | 8 | namespace Common.GraphTheory.GridGraphs 9 | { 10 | public partial class WeightedGridGraph 11 | { 12 | 13 | public GridSearch PrimsMinimumSpanningTree(Point2i root) 14 | { 15 | var search = new GridSearch(Width, Height); 16 | PrimsMinimumSpanningTree(search, root.x, root.y); 17 | return search; 18 | } 19 | 20 | public GridSearch PrimsMinimumSpanningTree(int x, int y) 21 | { 22 | var search = new GridSearch(Width, Height); 23 | PrimsMinimumSpanningTree(search, x, y); 24 | return search; 25 | } 26 | 27 | public void PrimsMinimumSpanningTree(GridSearch search, int x, int y, Func GetWeight = null) 28 | { 29 | int width = Width; 30 | int height = Height; 31 | 32 | search.SetIsVisited(x, y, true);; 33 | search.AddOrder(new Point2i(x, y)); 34 | search.SetParent(x, y, new Point2i(x, y)); 35 | 36 | var queue = new BinaryHeap(8); 37 | 38 | List edges = new List(8); 39 | GetEdges(x, y, edges, GetWeight); 40 | 41 | if (edges.Count != 0) 42 | { 43 | foreach (WeighedGridEdge edge in edges) 44 | queue.Add(edge); 45 | 46 | edges.Clear(); 47 | } 48 | 49 | while (queue.Count != 0) 50 | { 51 | WeighedGridEdge edge = queue.Pop(); 52 | 53 | Point2i v = edge.To; 54 | if (search.GetIsVisited(v)) continue; 55 | 56 | search.AddOrder(v); 57 | search.SetIsVisited(v, true); 58 | search.SetParent(v, edge.From); 59 | 60 | if (Edges[v.x, v.y] == 0) continue; 61 | 62 | GetEdges(v.x, v.y, edges, GetWeight); 63 | 64 | foreach (WeighedGridEdge e in edges) 65 | { 66 | if (search.GetIsVisited(e.To)) continue; 67 | queue.Add(e); 68 | } 69 | 70 | edges.Clear(); 71 | } 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Common.GraphTheory/MatrixGraphs/MatrixEdge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.GraphTheory.MatrixGraphs 5 | { 6 | public class MatrixEdge 7 | { 8 | /// 9 | /// Default constructor. 10 | /// 11 | public MatrixEdge() 12 | { 13 | 14 | } 15 | 16 | /// 17 | /// Create a edge going from and to these vertex indices. 18 | /// 19 | /// The from vertex index. 20 | /// The to vertex index. 21 | public MatrixEdge(int from, int to) 22 | { 23 | From = from; 24 | To = to; 25 | } 26 | 27 | /// 28 | /// Create a edge going from and to these vertex indices 29 | /// with a edge weight. 30 | /// 31 | /// The from vertex index. 32 | /// The to vertex index. 33 | /// The weight of the edge. 34 | public MatrixEdge(int from, int to, float weight) 35 | { 36 | From = from; 37 | To = to; 38 | Weight = weight; 39 | } 40 | 41 | /// 42 | /// The vertex index the edge starts at. 43 | /// 44 | public int From { get; set; } 45 | 46 | /// 47 | /// The vertex index the edge ends at. 48 | /// 49 | public int To { get; set; } 50 | 51 | /// 52 | /// The edges weight. Used in some search algorithms. 53 | /// ie spanning trees. 54 | /// 55 | public float Weight { get; set; } 56 | 57 | /// 58 | /// 59 | /// 60 | /// 61 | public override string ToString() 62 | { 63 | return string.Format("[MatrixEdge: From={0}, To={1}, Weight={2}]", 64 | From, To, Weight); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Common.GraphTheory/MatrixGraphs/MatrixGraph.FordFulkerson.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.GraphTheory.MatrixGraphs 5 | { 6 | public partial class MatrixGraph 7 | { 8 | public float FordFulkersonMaxFlow(int source, int target) 9 | { 10 | var rGraph = Copy(); 11 | return MaxFlow(rGraph, source, target); 12 | } 13 | 14 | private float MaxFlow(MatrixGraph rGraph, int source, int target) 15 | { 16 | int[] parent = new int[Size]; 17 | 18 | float max_flow = 0; 19 | 20 | while (bfs(rGraph, source, target, parent)) 21 | { 22 | float path_flow = int.MaxValue; 23 | 24 | for (int v = target; v != source; v = parent[v]) 25 | { 26 | int u = parent[v]; 27 | path_flow = Math.Min(path_flow, rGraph[u,v]); 28 | } 29 | 30 | for (int v = target; v != source; v = parent[v]) 31 | { 32 | int u = parent[v]; 33 | rGraph[u,v] -= path_flow; 34 | rGraph[v,u] += path_flow; 35 | } 36 | 37 | max_flow += path_flow; 38 | } 39 | 40 | return max_flow; 41 | } 42 | 43 | public List FordFulkersonMinCut(int source, int target) 44 | { 45 | var rGraph = Copy(); 46 | MaxFlow(rGraph, source, target); 47 | 48 | int size = rGraph.Size; 49 | 50 | bool[] visited = new bool[size]; 51 | 52 | dfs(rGraph, source, visited); 53 | 54 | var cut = new List(); 55 | 56 | for (int i = 0; i < size; i++) 57 | { 58 | for (int j = 0; j < size; j++) 59 | { 60 | if (visited[i] && !visited[j] && this[i, j] != 0) 61 | cut.Add(new MatrixEdge(i, j, this[i, j])); 62 | } 63 | } 64 | 65 | return cut; 66 | } 67 | 68 | private static void dfs(MatrixGraph rGraph, int s, bool[] visited) 69 | { 70 | visited[s] = true; 71 | for (int i = 0; i < rGraph.Size; i++) 72 | if (rGraph[s,i]!= 0 && !visited[i]) 73 | dfs(rGraph, i, visited); 74 | } 75 | 76 | private static bool bfs(MatrixGraph rGraph, int s, int t, int[] parent) 77 | { 78 | int size = rGraph.Size; 79 | 80 | bool[] visited = new bool[size]; 81 | 82 | Queue q = new Queue(); 83 | q.Enqueue(s); 84 | visited[s] = true; 85 | parent[s] = -1; 86 | 87 | while (q.Count > 0) 88 | { 89 | int u = q.Dequeue(); 90 | 91 | for (int v = 0; v < size; v++) 92 | { 93 | if (visited[v] == false && rGraph[u,v] > 0) 94 | { 95 | q.Enqueue(v); 96 | parent[v] = u; 97 | visited[v] = true; 98 | } 99 | } 100 | } 101 | 102 | return visited[t]; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Common.GraphTheory/MatrixGraphs/MatrixGraph.PushRelabel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Common.GraphTheory.MatrixGraphs 5 | { 6 | public partial class MatrixGraph 7 | { 8 | //const int NODES = 6; 9 | const int INFINITE = 10000000; 10 | 11 | private static void Push(int[,] C, int[,] F, int[] excess, int u, int v) 12 | { 13 | int send = Math.Min(excess[u], C[u, v] - F[u, v]); 14 | F[u, v] += send; 15 | F[v, u] -= send; 16 | excess[u] -= send; 17 | excess[v] += send; 18 | } 19 | 20 | private static void Relabel(int[,] C, int[,] F, int[] height, int u) 21 | { 22 | int NODES = C.GetLength(0); 23 | int min_height = INFINITE; 24 | 25 | for (int v = 0; v < NODES; v++) 26 | { 27 | if (C[u, v] - F[u, v] > 0) 28 | { 29 | min_height = Math.Min(min_height, height[v]); 30 | height[u] = min_height + 1; 31 | } 32 | } 33 | } 34 | 35 | private static void Discharge(int[,] C, int[,] F, int[] excess, int[] height, int[] seen, int u) 36 | { 37 | int NODES = C.GetLength(0); 38 | 39 | while (excess[u] > 0) 40 | { 41 | if (seen[u] < NODES) 42 | { 43 | int v = seen[u]; 44 | if ((C[u, v] - F[u, v] > 0) && (height[u] > height[v])) 45 | { 46 | Push(C, F, excess, u, v); 47 | } 48 | else 49 | { 50 | seen[u] += 1; 51 | } 52 | } 53 | else 54 | { 55 | Relabel(C, F, height, u); 56 | seen[u] = 0; 57 | } 58 | } 59 | } 60 | 61 | private static void MoveToFront(int i, int[] A) 62 | { 63 | int temp = A[i]; 64 | 65 | for (int n = i; n > 0; n--) 66 | { 67 | A[n] = A[n - 1]; 68 | } 69 | A[0] = temp; 70 | } 71 | 72 | public static int PushRelabel(int[,] C, int[,] F, int source, int sink) 73 | { 74 | int NODES = C.GetLength(0); 75 | 76 | int[] excess = new int[NODES]; 77 | int[] height = new int[NODES]; 78 | int[] list = new int[NODES - 2]; 79 | int[] seen = new int[NODES]; 80 | 81 | for (int i = 0, j = 0; i < NODES; i++) 82 | { 83 | if ((i != source) && (i != sink)) 84 | { 85 | list[j] = i; 86 | j++; 87 | } 88 | } 89 | 90 | height[source] = NODES; 91 | excess[source] = INFINITE; 92 | for (int i = 0; i < NODES; i++) 93 | Push(C, F, excess, source, i); 94 | 95 | int p = 0; 96 | while (p < NODES - 2) 97 | { 98 | int u = list[p]; 99 | int old_height = height[u]; 100 | Discharge(C, F, excess, height, seen, u); 101 | if (height[u] > old_height) 102 | { 103 | MoveToFront(p, list); 104 | p = 0; 105 | } 106 | else 107 | { 108 | p += 1; 109 | } 110 | } 111 | 112 | int maxflow = 0; 113 | for (int i = 0; i < NODES; i++) 114 | maxflow += F[source, i]; 115 | 116 | return maxflow; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Common.GraphTheory/MatrixGraphs/MatrixGraph.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Common.GraphTheory.MatrixGraphs 6 | { 7 | public partial class MatrixGraph 8 | { 9 | 10 | public MatrixGraph(int count) 11 | { 12 | Matrix = new float[count, count]; 13 | } 14 | 15 | public MatrixGraph(float[,] matrix) 16 | { 17 | Size = matrix.GetLength(0); 18 | 19 | if (Size != matrix.GetLength(1)) 20 | throw new ArgumentException("Matrix must be square."); 21 | 22 | Matrix = new float[Size, Size]; 23 | 24 | for(int i = 0; i < Size; i++) 25 | for(int j = 0; j < Size; j++) 26 | Matrix[i, j] = matrix[i, j]; 27 | } 28 | 29 | public int Size { get; private set; } 30 | 31 | private float[,] Matrix { get; set; } 32 | 33 | public float this[int i, int j] 34 | { 35 | get { return Matrix[i, j]; } 36 | set { Matrix[i, j] = value; } 37 | } 38 | 39 | public override string ToString() 40 | { 41 | return string.Format("[MatrixGraph: Size={0}]", Size); 42 | } 43 | 44 | public void Print() 45 | { 46 | var builder = new StringBuilder(); 47 | Print(builder); 48 | Console.WriteLine(builder.ToString()); 49 | } 50 | 51 | public void Print(StringBuilder builder) 52 | { 53 | builder.AppendLine(this.ToString()); 54 | 55 | for (int x = 0; x < Size; x++) 56 | { 57 | for (int y = 0; y < Size; y++) 58 | { 59 | float e = Matrix[x, y]; 60 | 61 | if(y == Size-1) 62 | builder.Append(string.Format("{0}", e)); 63 | else 64 | builder.Append(string.Format("{0}, ", e)); 65 | 66 | } 67 | 68 | builder.AppendLine(); 69 | } 70 | } 71 | 72 | public MatrixGraph Copy() 73 | { 74 | var copy = new MatrixGraph(this.Matrix); 75 | return copy; 76 | } 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Common 2 | 3 | This is a collection of common code I use, organised into a few libs. 4 | 5 | Its for personal use but feel free to pick though it and use what you like. 6 | 7 | The projects with Test in their name are the unit tests. 8 | --------------------------------------------------------------------------------