From 94e419b928ac630f0047cd24feb95e9e69f4a766 Mon Sep 17 00:00:00 2001 From: chalwa Date: Sun, 1 Dec 2019 08:15:02 +0100 Subject: [PATCH 01/16] lazy vonNeuman fixed --- Model/Boundary/PeriodicBoundary.cs | 4 ++-- MsmGrainGrowthGui/CelluralAutomatonViewModel.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Model/Boundary/PeriodicBoundary.cs b/Model/Boundary/PeriodicBoundary.cs index 2c2e641..acc5216 100644 --- a/Model/Boundary/PeriodicBoundary.cs +++ b/Model/Boundary/PeriodicBoundary.cs @@ -70,7 +70,7 @@ public Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDire { if (y == 0) { - return space.GetCell(0, 2); + return space.GetCell(0, 2);//WTF?? } else { @@ -89,7 +89,7 @@ public Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDire { if (x == 0) { - return space.GetCell(2, 2); + return space.GetCell(2, 2);//WTF?? } else { diff --git a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs index 19d2e22..702cf07 100644 --- a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs +++ b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs @@ -132,7 +132,7 @@ void GenerateExecute() // TODO: Generate can be replaced by OnModelChange event. This also may enable "save" button // Lazy initialization of boundary. - //_neighbourhood = new MooreNeighbourhood(_boundary); + _neighbourhood = new MooreNeighbourhood(_boundary); _automaton = new CelluralAutomaton( _spaceSize, @@ -246,7 +246,7 @@ void worker_DoWork(object sender, DoWorkEventArgs e) } _automaton.NextStep(); _worker.ReportProgress(0); - System.Threading.Thread.Sleep(100); // TODO: Remove magic number! Add slider to GUI + System.Threading.Thread.Sleep(80); // TODO: Remove magic number! Add slider to GUI } } From 0f770fa76f8418cd45b0d95a6c010bf9457502dc Mon Sep 17 00:00:00 2001 From: chalwa Date: Mon, 2 Dec 2019 20:29:11 +0100 Subject: [PATCH 02/16] ruleOne added and refactoring --- Model/Boundary/AbsorbingBoundary.cs | 2 - Model/Boundary/IBoundaryCondition.cs | 2 +- Model/Boundary/PeriodicBoundary.cs | 11 +- Model/Microelements/InclusionExecutor.cs | 4 +- Model/Neighbourhood/INeighbourhood.cs | 2 +- Model/Transition/GrainGrowthRule.cs | 7 +- Model/Transition/ITransitionRule.cs | 2 +- Model/Transition/InclusionGrowthRule.cs | 4 +- Model/Transition/RuleFour.cs | 18 +++ Model/Transition/RuleOne.cs | 44 ++++++++ Model/Transition/RuleThree.cs | 14 +++ Model/Transition/RuleTwo.cs | 14 +++ MsmGrainGrowthGui/ApplicationState.cs | 1 + .../CelluralAutomatonViewModel.cs | 5 +- MsmGrainGrowthGui/XmlReader.cs | 2 +- MultiscaleModeling.sln | 6 - Test/GrainGrowthGui/XmlFactoryTest.cs | 1 + Test/GrainGrowthGui/XmlReaderTest.cs | 4 +- .../Neighbourhood/MooreNeighbourhoodTest.cs | 104 ++++++++++++++++++ ...dTest.cs => VonNeumanNeighbourhoodTest.cs} | 0 Test/Model/Transition/GrainGrowTest.cs | 53 +-------- Test/Model/Transition/RuleOneTest.cs | 10 ++ 22 files changed, 220 insertions(+), 90 deletions(-) create mode 100644 Model/Transition/RuleFour.cs create mode 100644 Model/Transition/RuleOne.cs create mode 100644 Model/Transition/RuleThree.cs create mode 100644 Model/Transition/RuleTwo.cs create mode 100644 Test/Model/Neighbourhood/MooreNeighbourhoodTest.cs rename Test/Model/Neighbourhood/{VonNeumanNeighborhoodTest.cs => VonNeumanNeighbourhoodTest.cs} (100%) create mode 100644 Test/Model/Transition/RuleOneTest.cs diff --git a/Model/Boundary/AbsorbingBoundary.cs b/Model/Boundary/AbsorbingBoundary.cs index c81b01a..cffcb5e 100644 --- a/Model/Boundary/AbsorbingBoundary.cs +++ b/Model/Boundary/AbsorbingBoundary.cs @@ -1,5 +1,3 @@ -using System; - namespace Model{ diff --git a/Model/Boundary/IBoundaryCondition.cs b/Model/Boundary/IBoundaryCondition.cs index 0a32684..f9740f6 100644 --- a/Model/Boundary/IBoundaryCondition.cs +++ b/Model/Boundary/IBoundaryCondition.cs @@ -8,7 +8,7 @@ public enum BoundaryDirection{ public interface IBoundaryCondition { - public Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDirection direction); + Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDirection direction); } diff --git a/Model/Boundary/PeriodicBoundary.cs b/Model/Boundary/PeriodicBoundary.cs index acc5216..fb7e701 100644 --- a/Model/Boundary/PeriodicBoundary.cs +++ b/Model/Boundary/PeriodicBoundary.cs @@ -14,13 +14,6 @@ public string Name } } - // AbsorbingBoundary always return null Cell - /// y -> - ///x |22|20|21|22|20| - ///| |02|00|01|02|00| - ///v |12|10|11|12|10| - /// |22|20|21|22|20| - /// |02|00|01|02|00| public Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDirection direction) { switch (direction) @@ -70,7 +63,7 @@ public Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDire { if (y == 0) { - return space.GetCell(0, 2);//WTF?? + return space.GetCell(0, space.GetYLength() - 1); } else { @@ -89,7 +82,7 @@ public Cell GetBoundaryNeighbour(CelluralSpace space, int x, int y, BoundaryDire { if (x == 0) { - return space.GetCell(2, 2);//WTF?? + return space.GetCell(space.GetXLength() - 1, space.GetYLength() - 1); } else { diff --git a/Model/Microelements/InclusionExecutor.cs b/Model/Microelements/InclusionExecutor.cs index 2377821..1655c4f 100644 --- a/Model/Microelements/InclusionExecutor.cs +++ b/Model/Microelements/InclusionExecutor.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; +using Model.Transition; namespace Model { diff --git a/Model/Neighbourhood/INeighbourhood.cs b/Model/Neighbourhood/INeighbourhood.cs index adc8e71..2ec5672 100644 --- a/Model/Neighbourhood/INeighbourhood.cs +++ b/Model/Neighbourhood/INeighbourhood.cs @@ -7,7 +7,7 @@ namespace Model{ public interface INeighbourhood //TODO: This code probably probably won't be use, to be deleted ! THere is static class instead { - public Cell[] GetNeighbours(CelluralSpace space, int x, int y); + Cell[] GetNeighbours(CelluralSpace space, int x, int y); } } diff --git a/Model/Transition/GrainGrowthRule.cs b/Model/Transition/GrainGrowthRule.cs index 9b5f3f7..16740c0 100644 --- a/Model/Transition/GrainGrowthRule.cs +++ b/Model/Transition/GrainGrowthRule.cs @@ -1,12 +1,9 @@ using System; -using System.Diagnostics; -using System.Drawing; using System.Linq; -using Model; +namespace Model.Transition +{ -namespace Model{ - public class GrainGrowthRule : ITransitionRule { public Microelement NextState(Cell cell, Cell[] neighbours){ diff --git a/Model/Transition/ITransitionRule.cs b/Model/Transition/ITransitionRule.cs index 47a72d6..c198332 100644 --- a/Model/Transition/ITransitionRule.cs +++ b/Model/Transition/ITransitionRule.cs @@ -4,7 +4,7 @@ namespace Model{ - public interface ITransitionRule //TODO: This code probably probably won't be use, to be deleted ! THere is static class instead + public interface ITransitionRule { Microelement NextState(Cell cell, Cell[] neighbours); } diff --git a/Model/Transition/InclusionGrowthRule.cs b/Model/Transition/InclusionGrowthRule.cs index c0869e1..a8df99f 100644 --- a/Model/Transition/InclusionGrowthRule.cs +++ b/Model/Transition/InclusionGrowthRule.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Linq; -namespace Model +namespace Model.Transition { public class InclusionGrowthRule : ITransitionRule { diff --git a/Model/Transition/RuleFour.cs b/Model/Transition/RuleFour.cs new file mode 100644 index 0000000..e38bfa5 --- /dev/null +++ b/Model/Transition/RuleFour.cs @@ -0,0 +1,18 @@ +using System; +using System.Linq; + +namespace Model.Transition +{ + class RuleFour : ITransitionRule + { + public Microelement NextState(Cell cell, Cell[] neighbours) + { + + + + + + throw new NotImplementedException(); + } + } +} diff --git a/Model/Transition/RuleOne.cs b/Model/Transition/RuleOne.cs new file mode 100644 index 0000000..ac586f5 --- /dev/null +++ b/Model/Transition/RuleOne.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + +namespace Model.Transition +{ + class RuleOne : ITransitionRule + { + public Microelement NextState(Cell cell, Cell[] neighbours) + { + Cell[] doubleNeighbours = (Cell[])neighbours.Concat(neighbours); + + int grainsStreak = 0; + int maxStreak = 0; + Microelement strongestElement = null; + + for (int i = 1 ; i < doubleNeighbours.Count(); i++) + { + if (doubleNeighbours[i]?.MicroelementMembership is Grain && + doubleNeighbours[i - 1]?.MicroelementMembership.Id == doubleNeighbours[i]?.MicroelementMembership.Id && + doubleNeighbours[i - 1]?.MicroelementMembership.Phase == doubleNeighbours[i]?.MicroelementMembership.Phase) + { + grainsStreak++; + } + else + { + grainsStreak = 0; + } + + if (grainsStreak > maxStreak) + { + maxStreak = grainsStreak; + strongestElement = doubleNeighbours[i].MicroelementMembership; + } + + } + + if (maxStreak < 5) return null; + return strongestElement; + } + } +} diff --git a/Model/Transition/RuleThree.cs b/Model/Transition/RuleThree.cs new file mode 100644 index 0000000..86fddf5 --- /dev/null +++ b/Model/Transition/RuleThree.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Model.Transition +{ + class RuleThree : ITransitionRule + { + public Microelement NextState(Cell cell, Cell[] neighbours) + { + throw new NotImplementedException(); + } + } +} diff --git a/Model/Transition/RuleTwo.cs b/Model/Transition/RuleTwo.cs new file mode 100644 index 0000000..92dc517 --- /dev/null +++ b/Model/Transition/RuleTwo.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Model.Transition +{ + class RuleTwo : ITransitionRule + { + public Microelement NextState(Cell cell, Cell[] neighbours) + { + throw new NotImplementedException(); + } + } +} diff --git a/MsmGrainGrowthGui/ApplicationState.cs b/MsmGrainGrowthGui/ApplicationState.cs index 0976956..9dafdd0 100644 --- a/MsmGrainGrowthGui/ApplicationState.cs +++ b/MsmGrainGrowthGui/ApplicationState.cs @@ -1,5 +1,6 @@ using System; using Model; +using Model.Transition; namespace GrainGrowthGui { diff --git a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs index 702cf07..300c778 100644 --- a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs +++ b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; -using System.Text; using System.ComponentModel; using System.Windows.Input; -using GrainGrowthGui; using Model; using System.Windows.Media.Imaging; -using System.Drawing.Imaging; -using System.Windows.Media; using System.Xml.Linq; using System.IO; using Microsoft.Win32; +using Model.Transition; namespace GrainGrowthGui { diff --git a/MsmGrainGrowthGui/XmlReader.cs b/MsmGrainGrowthGui/XmlReader.cs index b7fa485..59340ad 100644 --- a/MsmGrainGrowthGui/XmlReader.cs +++ b/MsmGrainGrowthGui/XmlReader.cs @@ -24,7 +24,7 @@ public class XmlReader private static bool _isSaved; private List _grains; private List _inclusions; - private int _step; + private int _step; // TODO: Add step public ApplicationState Read(XDocument doc) diff --git a/MultiscaleModeling.sln b/MultiscaleModeling.sln index de57977..4984ae4 100644 --- a/MultiscaleModeling.sln +++ b/MultiscaleModeling.sln @@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", {B694252B-2108-42C0-A530-3685B0B4DDC8} = {B694252B-2108-42C0-A530-3685B0B4DDC8} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{2686237F-5C59-408F-B350-38A417600C86}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -38,10 +36,6 @@ Global {0C15D3C3-3FA8-4986-9D31-A24B3F26E2A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {0C15D3C3-3FA8-4986-9D31-A24B3F26E2A9}.Release|Any CPU.ActiveCfg = Release|Any CPU {0C15D3C3-3FA8-4986-9D31-A24B3F26E2A9}.Release|Any CPU.Build.0 = Release|Any CPU - {2686237F-5C59-408F-B350-38A417600C86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2686237F-5C59-408F-B350-38A417600C86}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2686237F-5C59-408F-B350-38A417600C86}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2686237F-5C59-408F-B350-38A417600C86}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Test/GrainGrowthGui/XmlFactoryTest.cs b/Test/GrainGrowthGui/XmlFactoryTest.cs index bb05c54..0b33cd7 100644 --- a/Test/GrainGrowthGui/XmlFactoryTest.cs +++ b/Test/GrainGrowthGui/XmlFactoryTest.cs @@ -6,6 +6,7 @@ using Model; using System.Diagnostics; using GrainGrowthGui; +using Model.Transition; namespace Test { diff --git a/Test/GrainGrowthGui/XmlReaderTest.cs b/Test/GrainGrowthGui/XmlReaderTest.cs index fb28104..175e9d6 100644 --- a/Test/GrainGrowthGui/XmlReaderTest.cs +++ b/Test/GrainGrowthGui/XmlReaderTest.cs @@ -1,12 +1,10 @@ -using System; using Xunit; using System.Xml.Linq; using System.Drawing; using System.Collections.Generic; -using System.Text.RegularExpressions; using Model; -using System.Diagnostics; using GrainGrowthGui; +using Model.Transition; namespace Test { diff --git a/Test/Model/Neighbourhood/MooreNeighbourhoodTest.cs b/Test/Model/Neighbourhood/MooreNeighbourhoodTest.cs new file mode 100644 index 0000000..38ecd3f --- /dev/null +++ b/Test/Model/Neighbourhood/MooreNeighbourhoodTest.cs @@ -0,0 +1,104 @@ +using System.Collections; +using System.Collections.Generic; +using Xunit; +using System.Drawing; + +using Model; + +namespace Test +{ + public class MooreNeighbourhoodTest + { + public static Cell a = new Cell(new Grain(0, 0, Color.Red)); + public static Cell b = new Cell(new Grain(1, 0, Color.Green)); + public static Cell c = new Cell(new Grain(2, 0, Color.Blue)); + public static Cell d = new Cell(new Grain(10, 0, Color.Yellow)); + public static Cell e = new Cell(new Grain(11, 0, Color.Violet)); + public static Cell f = new Cell(new Grain(12, 0, Color.Gold)); + public static Cell g = new Cell(new Grain(20, 0, Color.Coral)); + public static Cell h = new Cell(new Grain(21, 0, Color.Orange)); + public static Cell i = new Cell(new Grain(22, 0, Color.Azure)); + public static CelluralSpace space; + + + [Theory] + [ClassData(typeof(AbsorbingTestData))] + [ClassData(typeof(PeriodicTestData))] + public static void Test(int x, int y, Cell[] expected) + { + space = new CelluralSpace(3); + + space.SetCellMembership(a.MicroelementMembership, 0, 0); + space.SetCellMembership(b.MicroelementMembership, 0, 1); + space.SetCellMembership(c.MicroelementMembership, 0, 2); + space.SetCellMembership(d.MicroelementMembership, 1, 0); + space.SetCellMembership(e.MicroelementMembership, 1, 1); + space.SetCellMembership(f.MicroelementMembership, 1, 2); + space.SetCellMembership(g.MicroelementMembership, 2, 0); + space.SetCellMembership(h.MicroelementMembership, 2, 1); + space.SetCellMembership(i.MicroelementMembership, 2, 2); + + IBoundaryCondition boundary = new AbsorbingBoundary(); + INeighbourhood neighbourhood = new VonNeumanNeighbourhood(boundary); + + var neighbours = neighbourhood.GetNeighbours(space, x, y); + + for (int i = 0; i < 4; i++) + { + if (expected[i] == null) + { + Assert.Null(neighbours[i]); + } + else + { + Assert.Same(expected[i].MicroelementMembership, neighbours[i].MicroelementMembership); + } + } + + } + + + private class AbsorbingTestData : IEnumerable + { ///x\y 0 1 2 + /// 0 |a|b|c| + /// 1 |d|e|f| + /// 2 |g|h|i| + public IEnumerator GetEnumerator() + { + yield return new object[] { 0, 0, new Cell[] { null, b, d, null, null, e, null, null } }; //a + yield return new object[] { 0, 1, new Cell[] { null, c, e, a, null, f, d, null } }; //b + yield return new object[] { 0, 2, new Cell[] { null, null, f, b, null, null, e, null } }; //c + yield return new object[] { 1, 0, new Cell[] { a, e, g, null, b, h, null, null } }; //d + yield return new object[] { 1, 1, new Cell[] { b, f, h, d, c, i, g, a } }; //e - center + yield return new object[] { 1, 2, new Cell[] { c, null, i, e, null, null, h, b } }; //f + yield return new object[] { 2, 0, new Cell[] { d, h, null, null, e, null, null, null } }; //g + yield return new object[] { 2, 1, new Cell[] { e, i, null, g, f, null, null, d } }; //h + yield return new object[] { 2, 2, new Cell[] { f, null, null, h, null, null, null, e } }; //i + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + private class PeriodicTestData : IEnumerable + { ///x\y 0 1 2 + /// 0 |a|b|c| + /// 1 |d|e|f| + /// 2 |g|h|i| + public IEnumerator GetEnumerator() + { //N E S W NE SE SW SE + yield return new object[] { 0, 0, new Cell[] { g, b, d, f, h, e, e, f } }; //a + yield return new object[] { 0, 1, new Cell[] { h, c, e, a, i, f, d, g } }; //b + yield return new object[] { 0, 2, new Cell[] { i, a, f, b, g, d, e, h } }; //c + yield return new object[] { 1, 0, new Cell[] { a, e, g, f, b, h, i, c } }; //d + yield return new object[] { 1, 1, new Cell[] { b, f, h, d, c, i, g, a } }; //e - center + yield return new object[] { 1, 2, new Cell[] { c, d, i, e, a, g, h, b } }; //f + yield return new object[] { 2, 0, new Cell[] { d, h, a, i, e, b, c, f } }; //g + yield return new object[] { 2, 1, new Cell[] { e, i, b, g, f, c, a, d } }; //h + yield return new object[] { 2, 2, new Cell[] { f, g, c, h, d, a, b, e } }; //i + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + } +} diff --git a/Test/Model/Neighbourhood/VonNeumanNeighborhoodTest.cs b/Test/Model/Neighbourhood/VonNeumanNeighbourhoodTest.cs similarity index 100% rename from Test/Model/Neighbourhood/VonNeumanNeighborhoodTest.cs rename to Test/Model/Neighbourhood/VonNeumanNeighbourhoodTest.cs diff --git a/Test/Model/Transition/GrainGrowTest.cs b/Test/Model/Transition/GrainGrowTest.cs index 52a9304..36270dc 100644 --- a/Test/Model/Transition/GrainGrowTest.cs +++ b/Test/Model/Transition/GrainGrowTest.cs @@ -4,6 +4,7 @@ using Model; using System.Diagnostics; +using Model.Transition; namespace Test { @@ -24,57 +25,7 @@ public void EmptyCellEmptyNeighbourhoodTest() Assert.Null(element); } - /*[Fact] - public void NullArgumentExceptionsTest() - { - CleanUp(); - - var ex = Assert.Throws(() => TransitionRule.NextState(null, 0, 0)); - Assert.Equal("Space cannot be null", ex.ParamName); - } - - [Fact] - public void SpaceSizeArgumentExceptionTest() - { - CleanUp(); - Cell[,] invalidSpace = new Cell[1, 1]; - - var ex = Assert.Throws(() => TransitionRule.NextState(invalidSpace, 0, 0)); - Assert.Equal("Space size [1,1] is less than minimum [2,2]", ex.Message); - - invalidSpace = new Cell[1, 2]; - ex = Assert.Throws(() => TransitionRule.NextState(invalidSpace, 0, 0)); - Assert.Equal("Space size [1,2] is less than minimum [2,2]", ex.Message); - - invalidSpace = new Cell[2, 1]; - ex = Assert.Throws(() => TransitionRule.NextState(invalidSpace, 0, 0)); - Assert.Equal("Space size [2,1] is less than minimum [2,2]", ex.Message); - } - - [Fact] - public void ArgumentOutOfRangeExceptionTest() - { - CleanUp(); - PopulateCells(); - - var ex = Assert.Throws - (() => TransitionRule.NextState(space, -1, 0)); - Assert.Equal($"-1,0 is out of space range [3,3]", ex.ParamName); - - ex = Assert.Throws - (() => TransitionRule.NextState(space, 0, -1)); - Assert.Equal($"0,-1 is out of space range [3,3]", ex.ParamName); - - ex = Assert.Throws - (() => TransitionRule.NextState(space, 3, 1)); - Assert.Equal($"3,1 is out of space range [3,3]", ex.ParamName); - - ex = Assert.Throws - (() => TransitionRule.NextState(space, 1, 3)); - Assert.Equal($"1,3 is out of space range [3,3]", ex.ParamName); - - } - */ + [Fact] public void VioletCellEmptyNeighbourhoodTest() { diff --git a/Test/Model/Transition/RuleOneTest.cs b/Test/Model/Transition/RuleOneTest.cs new file mode 100644 index 0000000..21818fa --- /dev/null +++ b/Test/Model/Transition/RuleOneTest.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Test.Model.Transition +{ + class RuleOneTest + { + } +} From 29296d881feaf597c22c399967bdbfdee311a115 Mon Sep 17 00:00:00 2001 From: maslankam Date: Tue, 3 Dec 2019 16:52:08 +0100 Subject: [PATCH 03/16] Create FurtherMooreNeighbourhood.cs --- .../FurtherMooreNeighbourhood.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Model/Neighbourhood/FurtherMooreNeighbourhood.cs diff --git a/Model/Neighbourhood/FurtherMooreNeighbourhood.cs b/Model/Neighbourhood/FurtherMooreNeighbourhood.cs new file mode 100644 index 0000000..a54a7fb --- /dev/null +++ b/Model/Neighbourhood/FurtherMooreNeighbourhood.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; + +namespace Model{ + /// Further Moore checks NE, SE, SW, NW neighbours and return as Cell[] + /// |X|_|X| + /// |_|c|_| + /// |X|_|X| + + public class FurtherMooreNeighbourhood : INeighbourhood + { + private IBoundaryCondition _boundary; + + + public string Name + { + get { return this.ToString(); } + } + + + public FurtherMooreNeighbourhood(IBoundaryCondition boundary){ + this._boundary = boundary; + } + + + public Cell[] GetNeighbours(CelluralSpace space, int x, int y){ + Cell[] result = new Cell[4]; + + //Check NE + if ( x - 1 >= 0 && y + 1 < space.GetYLength()) + { + result[0] = space.GetCell(x - 1, y + 1); + } + else + { + result[0] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.NE); + } + + //Check SE neighbour + if ( x + 1 < space.GetXLength() && y + 1 < space.GetYLength()) + { + result[1] = space.GetCell(x + 1, y + 1); + } + else + { + result[2] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SE); + } + + //Check SW neighbour + if (x + 1 < space.GetXLength() && y - 1 >= 0) + { + result[3] = space.GetCell(x + 1, y - 1); + } + else + { + result[4] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SW); + } + + //Check NW neighbour + if (x - 1 >= 0 && y - 1 >= 0) + { + result[5] = space.GetCell(x - 1, y - 1); + } + else + { + result[6] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.NW); + } + + return result; + + } + public override string ToString() + { + return "FurtherMooreNeighbourhood"; + } + } + + +} From 1d6147979447f4edea5e2427e13480789333a62c Mon Sep 17 00:00:00 2001 From: maslankam Date: Tue, 3 Dec 2019 17:05:50 +0100 Subject: [PATCH 04/16] Update MooreNeighbourhood.cs --- Model/Neighbourhood/MooreNeighbourhood.cs | 60 ++++++++++++++++++----- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/Model/Neighbourhood/MooreNeighbourhood.cs b/Model/Neighbourhood/MooreNeighbourhood.cs index 31f8648..f33eea1 100644 --- a/Model/Neighbourhood/MooreNeighbourhood.cs +++ b/Model/Neighbourhood/MooreNeighbourhood.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; namespace Model @@ -25,41 +25,75 @@ public MooreNeighbourhood(IBoundaryCondition boundary) public Cell[] GetNeighbours(CelluralSpace space, int x, int y) { Cell[] result = new Cell[8]; - var vonNeuman = new VonNeumanNeighbourhood(_boundary); - Cell[] vonNeumanNeighbourhood = vonNeuman.GetNeighbours(space, x, y); - result[0] = vonNeumanNeighbourhood[0]; - result[1] = vonNeumanNeighbourhood[1]; - result[2] = vonNeumanNeighbourhood[2]; - result[3] = vonNeumanNeighbourhood[3]; + + //Check N neighbour + if (x - 1 >= 0) + { + result[0] = space.GetCell(x - 1, y); + } + else + { + result[0] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.W); + } //Check NE if ( x - 1 >= 0 && y + 1 < space.GetYLength()) { - result[4] = space.GetCell(x - 1, y + 1); + result[1] = space.GetCell(x - 1, y + 1); + } + else + { + result[1] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.NE); + } + + //Check E neighbour + if (y + 1 <= space.GetXLength() - 1) + { + result[2] = space.GetCell(x, y + 1); } else { - result[4] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.NE); + result[2] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.S); } //Check SE neighbour if ( x + 1 < space.GetXLength() && y + 1 < space.GetYLength()) { - result[5] = space.GetCell(x + 1, y + 1); + result[3] = space.GetCell(x + 1, y + 1); } else { - result[5] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SE); + result[3] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SE); + } + + //Check S neighbour + if (x + 1 <= space.GetYLength() - 1) + { + result[4] = space.GetCell(x + 1, y); + } + else + { + result[4] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.E); } //Check SW neighbour if (x + 1 < space.GetXLength() && y - 1 >= 0) { - result[6] = space.GetCell(x + 1, y - 1); + result[5] = space.GetCell(x + 1, y - 1); + } + else + { + result[5] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SW); + } + + //Check W neighbour + if (y - 1 >= 0) + { + result[6] = space.GetCell(x, y - 1); } else { - result[6] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SW); + result[6] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.N); } //Check NW neighbour From 239640e40539b0e912388c70ba1e54d0c022e21c Mon Sep 17 00:00:00 2001 From: maslankam Date: Tue, 3 Dec 2019 18:10:02 +0100 Subject: [PATCH 05/16] Create RuleFour.cs --- Model/Transition/RuleFour.cs | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Model/Transition/RuleFour.cs diff --git a/Model/Transition/RuleFour.cs b/Model/Transition/RuleFour.cs new file mode 100644 index 0000000..29ab01a --- /dev/null +++ b/Model/Transition/RuleFour.cs @@ -0,0 +1,86 @@ +using System; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using Model; + + +namespace Model{ + + public class RuleFour : ITransitionRule + { + public int Threshhold + { + get {return _threshold;} + set + { + if(value > 100) _threshold = 100; + if(value < 0) _threshold = 0; + _threshold = value; + } + } + private Random _random; + private int _threshold; + + public RuleFour() + { + _random = new Random(); + Threshhold = 50; + } + + public Microelement NextState(Cell cell, Cell[] neighbours){ + + if (cell?.MicroelementMembership == null) + { + var groups = from c in neighbours + where c?.MicroelementMembership?.Id != null && c?.MicroelementMembership is Grain + group c by c.MicroelementMembership; + + if (groups.Count() == 0) + { + return null; + } + else if (groups.Count() > 1) + { + //Check if groups has this same count + var top = from g in groups + let maxPower = groups.Max(r => r.Count()) + where g.Count() == maxPower + select g.Key; + + int topCount = top.Count(); + if (topCount > 1) + { + //Take a random one + var r = new Random(); + int randomIndex = r.Next(0, topCount - 1); + if(_random.Next(0,100) < Threshhold) return null; + return top.ElementAt(randomIndex); + } + else + { + //Return the strongest neighbour + if(_random.Next(0,100) < Threshhold) return null; + return top.First(); + } + } + else + { + //return the only neighbour + if(_random.Next(0,100) < Threshhold) return null; + return groups.First().Key; + } + } + else + { + //return self + return cell.MicroelementMembership; + } + } + } + +} + + + + From 6c3381c0164a97c7d6fa60239da233b80220f7cd Mon Sep 17 00:00:00 2001 From: chalwa Date: Tue, 3 Dec 2019 21:23:43 +0100 Subject: [PATCH 06/16] rule two --- ...luralAutomaton.cs => CellularAutomaton.cs} | 23 +++++-------- Model/Transition/RuleTwo.cs | 34 +++++++++++++++++-- MsmGrainGrowthGui/ApplicationState.cs | 4 +-- .../CelluralAutomatonViewModel.cs | 6 ++-- MsmGrainGrowthGui/XmlReader.cs | 4 +-- Test/GrainGrowthGui/XmlFactoryTest.cs | 2 +- Test/GrainGrowthGui/XmlReaderTest.cs | 2 +- 7 files changed, 50 insertions(+), 25 deletions(-) rename Model/{CelluralAutomaton.cs => CellularAutomaton.cs} (85%) diff --git a/Model/CelluralAutomaton.cs b/Model/CellularAutomaton.cs similarity index 85% rename from Model/CelluralAutomaton.cs rename to Model/CellularAutomaton.cs index f6c1503..3be9a06 100644 --- a/Model/CelluralAutomaton.cs +++ b/Model/CellularAutomaton.cs @@ -1,20 +1,15 @@ using System; using System.Collections.Generic; -using System.Drawing; namespace Model{ - public class CelluralAutomaton { + public class CellularAutomaton { public List Grains { get; private set; } public List Inclusions { get; private set; } - public CelluralSpace Space { get; private set; } - public int Step - { - get { return this._executor.Step; } - private set { } - } + public CelluralSpace Space { get; } + public int Step => this._executor.Step; private CelluralSpace _lastStepSpace; private readonly ITransitionRule _transition; @@ -26,8 +21,8 @@ private set { } private readonly GrainSeeder _grainSeeder; private readonly InclusionSeeder _inclusionSeeder; - public CelluralAutomaton(int size, - int GrainsCount, + public CellularAutomaton(int size, + int grainsCount, int inclusionsCount, int minRadius, int maxRadius, @@ -47,11 +42,11 @@ public CelluralAutomaton(int size, _inclusionSeeder = new InclusionSeeder(boundary); Space = new CelluralSpace(size); - PopulateSimulation(GrainsCount, inclusionsCount, minRadius, maxRadius); + PopulateSimulation(grainsCount, inclusionsCount, minRadius, maxRadius); } //Constructor for opening saved state - public CelluralAutomaton( + public CellularAutomaton( CelluralSpace space, List grains, List inclusions, @@ -91,9 +86,9 @@ public void NextStep() _executor.NextState(Space, _lastStepSpace, _transition, _neighbourhood); } - public void PopulateSimulation(int GrainsCount, int inclusionsCount, int minRadius, int maxRadius) + public void PopulateSimulation(int grainsCount, int inclusionsCount, int minRadius, int maxRadius) { - Grains = _grainInitializer.Initialize(GrainsCount); + Grains = _grainInitializer.Initialize(grainsCount); _grainSeeder.Seed(Space, Grains); Inclusions = _inclusionInitializer.Initialize(inclusionsCount, minRadius, maxRadius); _inclusionSeeder.Seed(Space, Inclusions); diff --git a/Model/Transition/RuleTwo.cs b/Model/Transition/RuleTwo.cs index 92dc517..6e30134 100644 --- a/Model/Transition/RuleTwo.cs +++ b/Model/Transition/RuleTwo.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Text; namespace Model.Transition @@ -8,7 +10,35 @@ class RuleTwo : ITransitionRule { public Microelement NextState(Cell cell, Cell[] neighbours) { - throw new NotImplementedException(); + Cell[] doubleNeighbours = (Cell[])neighbours.Concat(neighbours); + + int grainsStreak = 0; + int maxStreak = 0; + Microelement strongestElement = null; + + for (int i = 1; i < doubleNeighbours.Count(); i++) + { + if (doubleNeighbours[i]?.MicroelementMembership is Grain && + doubleNeighbours[i - 1]?.MicroelementMembership.Id == doubleNeighbours[i]?.MicroelementMembership.Id && + doubleNeighbours[i - 1]?.MicroelementMembership.Phase == doubleNeighbours[i]?.MicroelementMembership.Phase) + { + grainsStreak++; + } + else + { + grainsStreak = 0; + } + + if (grainsStreak > maxStreak) + { + maxStreak = grainsStreak; + strongestElement = doubleNeighbours[i].MicroelementMembership; + } + + } + + if (maxStreak < 5) return null; + return strongestElement; } } -} +} \ No newline at end of file diff --git a/MsmGrainGrowthGui/ApplicationState.cs b/MsmGrainGrowthGui/ApplicationState.cs index 9dafdd0..3072724 100644 --- a/MsmGrainGrowthGui/ApplicationState.cs +++ b/MsmGrainGrowthGui/ApplicationState.cs @@ -6,7 +6,7 @@ namespace GrainGrowthGui { public class ApplicationState { - public CelluralAutomaton automaton; + public CellularAutomaton automaton; public int spaceSize; public int grainsCount; public int inclusionsCount; @@ -19,7 +19,7 @@ public class ApplicationState public bool isSaved; public ApplicationState( - CelluralAutomaton automaton, + CellularAutomaton automaton, int spaceSize, int grainsCount, int inclusionsCount, diff --git a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs index 300c778..4451a44 100644 --- a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs +++ b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs @@ -69,7 +69,7 @@ public string Boundary #endregion #region private members - private CelluralAutomaton _automaton; + private CellularAutomaton _automaton; private int _spaceSize; private int _grainsCount; private int _inclusionsCount; @@ -131,7 +131,7 @@ void GenerateExecute() // Lazy initialization of boundary. _neighbourhood = new MooreNeighbourhood(_boundary); - _automaton = new CelluralAutomaton( + _automaton = new CellularAutomaton( _spaceSize, _grainsCount, _inclusionsCount, @@ -183,7 +183,7 @@ public ICommand Next #region ResetCommand void ResetExecute() { - _automaton = new CelluralAutomaton( + _automaton = new CellularAutomaton( 2, 0, 0, diff --git a/MsmGrainGrowthGui/XmlReader.cs b/MsmGrainGrowthGui/XmlReader.cs index 59340ad..b686634 100644 --- a/MsmGrainGrowthGui/XmlReader.cs +++ b/MsmGrainGrowthGui/XmlReader.cs @@ -11,7 +11,7 @@ namespace GrainGrowthGui { public class XmlReader { - private static CelluralAutomaton _automaton; + private static CellularAutomaton _automaton; private static int _spaceSize; private static int _grainsCount; private static int _inclusionsCount; @@ -85,7 +85,7 @@ public ApplicationState Read(XDocument doc) var space = new CelluralSpace(cellsArray); - _automaton = new CelluralAutomaton( + _automaton = new CellularAutomaton( space, _grains, _inclusions, diff --git a/Test/GrainGrowthGui/XmlFactoryTest.cs b/Test/GrainGrowthGui/XmlFactoryTest.cs index 0b33cd7..42e3200 100644 --- a/Test/GrainGrowthGui/XmlFactoryTest.cs +++ b/Test/GrainGrowthGui/XmlFactoryTest.cs @@ -83,7 +83,7 @@ public void BasicTest() var space = new CelluralSpace(cells); - var automaton = new CelluralAutomaton( + var automaton = new CellularAutomaton( space, grains, inclusions, diff --git a/Test/GrainGrowthGui/XmlReaderTest.cs b/Test/GrainGrowthGui/XmlReaderTest.cs index 175e9d6..8a97615 100644 --- a/Test/GrainGrowthGui/XmlReaderTest.cs +++ b/Test/GrainGrowthGui/XmlReaderTest.cs @@ -118,7 +118,7 @@ private ApplicationState BuildMockState() var space = new CelluralSpace(cells); - var automaton = new CelluralAutomaton( + var automaton = new CellularAutomaton( space, grains, inclusions, From 57a6ad5a355ac6f5e1b07f8c235710e17f27c229 Mon Sep 17 00:00:00 2001 From: chalwa Date: Tue, 3 Dec 2019 23:53:55 +0100 Subject: [PATCH 07/16] New Rules Integrated --- Model/CellularAutomaton.cs | 11 ++- Model/CurvatureExecutor.cs | 98 +++++++++++++++++++ Model/ISimulationExecutor.cs | 14 +++ .../FurtherMooreNeighbourhood.cs | 10 +- Model/SimulationExecutor.cs | 20 +++- Model/Transition/RuleFour.cs | 2 +- Model/Transition/RuleOne.cs | 18 ++-- Model/Transition/RuleTwo.cs | 20 ++-- .../CelluralAutomatonViewModel.cs | 44 ++++++++- MsmGrainGrowthGui/MainWindow.xaml | 7 ++ 10 files changed, 212 insertions(+), 32 deletions(-) create mode 100644 Model/CurvatureExecutor.cs create mode 100644 Model/ISimulationExecutor.cs diff --git a/Model/CellularAutomaton.cs b/Model/CellularAutomaton.cs index 3be9a06..14d3e61 100644 --- a/Model/CellularAutomaton.cs +++ b/Model/CellularAutomaton.cs @@ -9,12 +9,12 @@ public class CellularAutomaton { public List Inclusions { get; private set; } public CelluralSpace Space { get; } - public int Step => this._executor.Step; + public int Step => this._executor.ReturnStep(); private CelluralSpace _lastStepSpace; private readonly ITransitionRule _transition; private readonly INeighbourhood _neighbourhood; - private readonly SimulationExecutor _executor; + private readonly ISimulationExecutor _executor; //private SpaceRenderingEngine _renderingEngine; private readonly GrainInitializer _grainInitializer; private readonly InclusionInitializer _inclusionInitializer; @@ -28,14 +28,15 @@ public CellularAutomaton(int size, int maxRadius, ITransitionRule transition, INeighbourhood neighbourhood, - IBoundaryCondition boundary) + IBoundaryCondition boundary, + ISimulationExecutor executor) { if(minRadius > maxRadius) throw new ArgumentException("MinRadius cannot be greater than MaxRadius"); if (transition == null || neighbourhood == null || boundary == null) throw new ArgumentNullException(); _transition = transition; _neighbourhood = neighbourhood; _lastStepSpace = new CelluralSpace(size); - _executor = new SimulationExecutor(); + _executor = executor; _grainInitializer = new GrainInitializer(); _inclusionInitializer = new InclusionInitializer(); _grainSeeder = new GrainSeeder(); @@ -65,7 +66,7 @@ public CellularAutomaton( _transition = transition; _neighbourhood = neighbourhood; - _executor = new SimulationExecutor(); + _grainInitializer = null; _inclusionInitializer = null; _grainSeeder = null; diff --git a/Model/CurvatureExecutor.cs b/Model/CurvatureExecutor.cs new file mode 100644 index 0000000..73e56bd --- /dev/null +++ b/Model/CurvatureExecutor.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using Model.Transition; + +namespace Model +{ + public class CurvatureExecutor : ISimulationExecutor + { + public string Name + { + get { return ToString(); } + set { } + } + + + public int Step { get; private set; } + + public CurvatureExecutor() + { + } + + public CurvatureExecutor(int step) + { + if (step < 0) throw new ArgumentException(); + Step = step; + } + + public int ReturnStep() + { + return Step; + } + + public void NextState(CelluralSpace space, CelluralSpace lastSpace, ITransitionRule transition, INeighbourhood neighbourhood) + { + for (int i = 0; i < space.GetXLength(); i++) + { + for (int j = 0; j < space.GetYLength(); j++) + { + // TODO: refactor + IBoundaryCondition boun = new AbsorbingBoundary(); + INeighbourhood nei = new MooreNeighbourhood(new AbsorbingBoundary()); + ITransitionRule rule = new RuleOne(); + Cell[] neighbours = nei.GetNeighbours(lastSpace, i, j); + var element = rule.NextState(space.GetCell(i, j), neighbours); + + if (element != null) + { + space.SetCellMembership(element, i, j); + continue; + } + + nei = new VonNeumanNeighbourhood(new AbsorbingBoundary()); + rule = new RuleTwo(); + neighbours = nei.GetNeighbours(lastSpace, i, j); + element = rule.NextState(space.GetCell(i, j), neighbours); + + if (element != null) + { + space.SetCellMembership(element, i, j); + continue; + } + + nei = new FurtherMooreNeighbourhood(new AbsorbingBoundary()); + rule = new RuleTwo(); + neighbours = nei.GetNeighbours(lastSpace, i, j); + element = rule.NextState(space.GetCell(i, j), neighbours); + + if (element != null) + { + space.SetCellMembership(element, i, j); + continue; + } + + nei = new FurtherMooreNeighbourhood(new AbsorbingBoundary()); + rule = new RuleFour(); + neighbours = nei.GetNeighbours(lastSpace, i, j); + element = rule.NextState(space.GetCell(i, j), neighbours); + space.SetCellMembership(element, i, j); + + } + } + Step++; + } + + public void Reset() + { + Step = 0; + throw new NotImplementedException(); + } + + public override string ToString() + { + return "CurvatureExecutor"; + } + } +} diff --git a/Model/ISimulationExecutor.cs b/Model/ISimulationExecutor.cs new file mode 100644 index 0000000..772d732 --- /dev/null +++ b/Model/ISimulationExecutor.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; + +namespace Model +{ + public interface ISimulationExecutor + { + + void NextState(CelluralSpace space, CelluralSpace lastSpace, ITransitionRule transition, INeighbourhood neighbourhood); + int ReturnStep(); + } +} \ No newline at end of file diff --git a/Model/Neighbourhood/FurtherMooreNeighbourhood.cs b/Model/Neighbourhood/FurtherMooreNeighbourhood.cs index a54a7fb..85e17c9 100644 --- a/Model/Neighbourhood/FurtherMooreNeighbourhood.cs +++ b/Model/Neighbourhood/FurtherMooreNeighbourhood.cs @@ -43,27 +43,27 @@ public Cell[] GetNeighbours(CelluralSpace space, int x, int y){ } else { - result[2] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SE); + result[1] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SE); } //Check SW neighbour if (x + 1 < space.GetXLength() && y - 1 >= 0) { - result[3] = space.GetCell(x + 1, y - 1); + result[2] = space.GetCell(x + 1, y - 1); } else { - result[4] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SW); + result[2] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.SW); } //Check NW neighbour if (x - 1 >= 0 && y - 1 >= 0) { - result[5] = space.GetCell(x - 1, y - 1); + result[3] = space.GetCell(x - 1, y - 1); } else { - result[6] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.NW); + result[3] = _boundary.GetBoundaryNeighbour(space, x, y, BoundaryDirection.NW); } return result; diff --git a/Model/SimulationExecutor.cs b/Model/SimulationExecutor.cs index 1df414a..df0582a 100644 --- a/Model/SimulationExecutor.cs +++ b/Model/SimulationExecutor.cs @@ -4,8 +4,13 @@ using System.Drawing; namespace Model{ - public class SimulationExecutor + public class SimulationExecutor : ISimulationExecutor { + public string Name + { + get { return ToString(); } + } + public int Step{get; private set;} public SimulationExecutor(){ @@ -17,13 +22,18 @@ public SimulationExecutor(int step) Step = step; } + public int ReturnStep() + { + return Step; + } + public void NextState(CelluralSpace space, CelluralSpace lastSpace, ITransitionRule transition, INeighbourhood neighbourhood){ for (int i = 0; i < space.GetXLength(); i++) { for (int j = 0; j < space.GetYLength(); j++) { Cell[] neighbours = neighbourhood.GetNeighbours(lastSpace, i, j); //TODO: Storing neighbourhood in Cell object will increase memory consumption - var element = transition.NextState(space.GetCell(i,j), neighbours); // but may increase performance, instead of O(n) -> O(1) + var element = transition.NextState(space.GetCell(i,j), neighbours); // but may increase performance space.SetCellMembership(element, i, j); } } @@ -35,6 +45,10 @@ public void Reset() Step = 0; throw new NotImplementedException(); } - + + public override string ToString() + { + return "SimulationExecutor"; + } } } diff --git a/Model/Transition/RuleFour.cs b/Model/Transition/RuleFour.cs index 5b5ab80..7247964 100644 --- a/Model/Transition/RuleFour.cs +++ b/Model/Transition/RuleFour.cs @@ -25,7 +25,7 @@ public int Threshhold public RuleFour() { _random = new Random(); - Threshhold = 50; + Threshhold = 90; } public Microelement NextState(Cell cell, Cell[] neighbours){ diff --git a/Model/Transition/RuleOne.cs b/Model/Transition/RuleOne.cs index ac586f5..d87337f 100644 --- a/Model/Transition/RuleOne.cs +++ b/Model/Transition/RuleOne.cs @@ -10,17 +10,23 @@ class RuleOne : ITransitionRule { public Microelement NextState(Cell cell, Cell[] neighbours) { - Cell[] doubleNeighbours = (Cell[])neighbours.Concat(neighbours); + + neighbours.Concat(neighbours).ToArray(); int grainsStreak = 0; int maxStreak = 0; Microelement strongestElement = null; - for (int i = 1 ; i < doubleNeighbours.Count(); i++) + for (int i = 1 ; i < neighbours.Count(); i++) { - if (doubleNeighbours[i]?.MicroelementMembership is Grain && - doubleNeighbours[i - 1]?.MicroelementMembership.Id == doubleNeighbours[i]?.MicroelementMembership.Id && - doubleNeighbours[i - 1]?.MicroelementMembership.Phase == doubleNeighbours[i]?.MicroelementMembership.Phase) + if (neighbours[i - 1]?.MicroelementMembership?.Id == null) + { + grainsStreak = 0; + continue; + } + if (neighbours[i]?.MicroelementMembership is Grain && + neighbours[i - 1]?.MicroelementMembership?.Id == neighbours[i]?.MicroelementMembership?.Id && + neighbours[i - 1]?.MicroelementMembership?.Phase == neighbours[i]?.MicroelementMembership?.Phase) { grainsStreak++; } @@ -32,7 +38,7 @@ public Microelement NextState(Cell cell, Cell[] neighbours) if (grainsStreak > maxStreak) { maxStreak = grainsStreak; - strongestElement = doubleNeighbours[i].MicroelementMembership; + strongestElement = neighbours[i].MicroelementMembership; } } diff --git a/Model/Transition/RuleTwo.cs b/Model/Transition/RuleTwo.cs index 6e30134..011edf7 100644 --- a/Model/Transition/RuleTwo.cs +++ b/Model/Transition/RuleTwo.cs @@ -10,17 +10,23 @@ class RuleTwo : ITransitionRule { public Microelement NextState(Cell cell, Cell[] neighbours) { - Cell[] doubleNeighbours = (Cell[])neighbours.Concat(neighbours); + neighbours.Concat(neighbours).ToArray(); int grainsStreak = 0; int maxStreak = 0; Microelement strongestElement = null; - for (int i = 1; i < doubleNeighbours.Count(); i++) + + for (int i = 1; i < neighbours.Count(); i++) { - if (doubleNeighbours[i]?.MicroelementMembership is Grain && - doubleNeighbours[i - 1]?.MicroelementMembership.Id == doubleNeighbours[i]?.MicroelementMembership.Id && - doubleNeighbours[i - 1]?.MicroelementMembership.Phase == doubleNeighbours[i]?.MicroelementMembership.Phase) + if (neighbours[i - 1]?.MicroelementMembership?.Id == null) + { + grainsStreak = 0; + continue; + } + if (neighbours[i]?.MicroelementMembership is Grain && + neighbours[i - 1]?.MicroelementMembership.Id == neighbours[i]?.MicroelementMembership.Id && + neighbours[i - 1]?.MicroelementMembership.Phase == neighbours[i]?.MicroelementMembership.Phase) { grainsStreak++; } @@ -32,12 +38,12 @@ public Microelement NextState(Cell cell, Cell[] neighbours) if (grainsStreak > maxStreak) { maxStreak = grainsStreak; - strongestElement = doubleNeighbours[i].MicroelementMembership; + strongestElement = neighbours[i].MicroelementMembership; } } - if (maxStreak < 5) return null; + if (maxStreak != 3) return null; return strongestElement; } } diff --git a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs index 4451a44..ec69d13 100644 --- a/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs +++ b/MsmGrainGrowthGui/CelluralAutomatonViewModel.cs @@ -59,6 +59,29 @@ public string Neighbourhood } } + public List Executors + { + get { return _executors; } + set { } + } + + public string Executor + { + get { return _executor.ToString(); } + set + { + _executor = GetExecutorByName("Model." + value); + } + } + + // TODO: Temporary solution + private ISimulationExecutor GetExecutorByName(string name) + { + if (name == "Model.SimulationExecutor") return new SimulationExecutor(); + if (name == "Model.CurvatureExecutor") return new CurvatureExecutor(); + else throw new ArgumentException(); + } + public List Boundaries { get { return _boundaries; } set { _boundaries = value; } } public string Boundary @@ -84,8 +107,10 @@ public string Boundary private bool _isSaved; private bool _isRunning; BackgroundWorker _worker; - List _boundaries; - List _neighbourhoods; + private List _boundaries; + private List _neighbourhoods; + private ISimulationExecutor _executor; + private List _executors; #endregion @@ -120,6 +145,13 @@ public CelluralAutomatonViewModel() new PentagonNeighbourhood(_boundary) }; _neighbourhood = new VonNeumanNeighbourhood(_boundary); + + _executors = new List() + { + new SimulationExecutor(), + new CurvatureExecutor() + }; + _executor = new SimulationExecutor(); } #endregion @@ -129,7 +161,7 @@ void GenerateExecute() // TODO: Generate can be replaced by OnModelChange event. This also may enable "save" button // Lazy initialization of boundary. - _neighbourhood = new MooreNeighbourhood(_boundary); + //_neighbourhood = new MooreNeighbourhood(_boundary); _automaton = new CellularAutomaton( _spaceSize, @@ -139,7 +171,8 @@ void GenerateExecute() _maxRadius, _transition, _neighbourhood, - _boundary + _boundary, + _executor ); _isAutomatonGenerated = true; @@ -191,7 +224,8 @@ void ResetExecute() _maxRadius, _transition, _neighbourhood, - _boundary + _boundary, + _executor ); _isAutomatonGenerated = false; diff --git a/MsmGrainGrowthGui/MainWindow.xaml b/MsmGrainGrowthGui/MainWindow.xaml index f25fc11..97ae30f 100644 --- a/MsmGrainGrowthGui/MainWindow.xaml +++ b/MsmGrainGrowthGui/MainWindow.xaml @@ -89,6 +89,13 @@ +