public void SvgFloorplan() { var r = new Random(23523); const int FLOOR_COUNT = 1; for (int i = 0; i < FLOOR_COUNT; i++) { var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new[] { new Vector2(-25, -25), new Vector2(-25, 25), new Vector2(25, 25), new Vector2(25, -25) })); for (int j = 0; j < 3; j++) { var minX = r.Next(-25, 20); var minY = r.Next(-25, 20); var width = r.Next(10, 20); var height = r.Next(10, 20); plan.Add(new[] { new Vector2(minX, minY), new Vector2(minX, minY + height), new Vector2(minX + width, minY + height), new Vector2(minX + width, minY) }, r.Next(1, 5) ); } plan.Freeze(); //Console.WriteLine(FloorplanToSvg(plan, 500, 0, 0, (i * floorHeight - floorCount * floorHeight))); } }
public void RegressionTest_UnmatchedWallSections() { // This is a case generated from fuzz testing (i.e. generate random data, see what breaks). // Sometimes matching up inner and outer sections of wall data used to fail (fixed in EpimetheusPlugins). // This test will fail in that case var r = new Random(189); var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new[] { new Vector2(-25, -25), new Vector2(-25, 25), new Vector2(25, 25), new Vector2(25, -25) })); for (int j = 0; j < 3; j++) { var minX = r.Next(-25, 20); var minY = r.Next(-25, 20); var width = r.Next(10, 20); var height = r.Next(10, 20); plan.Add(new[] { new Vector2(minX, minY), new Vector2(minX, minY + height), new Vector2(minX + width, minY + height), new Vector2(minX + width, minY) }, 1 ); } plan.Freeze(); Console.WriteLine(SvgRoomVisualiser.FloorplanToSvg(_plan)); }
public void RegressionTest_ShrinkingSplitsFootprint() { // This is a case generated from fuzz testing (i.e. generate random data, see what breaks). // Shrinking a shape can generate *several* separate shapes if the original shape was convex. // This used to fail, now shrinking discards all the generated shapes except the largest (fixed with a change in EpimetheusPlugins). var r = new Random(738); var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new[] { new Vector2(-25, -25), new Vector2(-25, 25), new Vector2(25, 25), new Vector2(25, -25) })); for (int j = 0; j < 3; j++) { var minX = r.Next(-25, 20); var minY = r.Next(-25, 20); var width = r.Next(10, 20); var height = r.Next(10, 20); plan.Add(new[] { new Vector2(minX, minY), new Vector2(minX, minY + height), new Vector2(minX + width, minY + height), new Vector2(minX + width, minY) }, 1 ); } plan.Freeze(); Console.WriteLine(SvgRoomVisualiser.FloorplanToSvg(_plan)); }
public IFloorPlanBuilder Design(Func <double> random, INamedDataCollection metadata, Func <KeyValuePair <string, string>[], Type[], ScriptReference> finder, IReadOnlyList <Vector2> footprint, IReadOnlyList <IReadOnlyList <Subsection> > sections, float wallThickness, IReadOnlyList <IReadOnlyList <Vector2> > overlappingVerticals, IReadOnlyList <ConstrainedVerticalSelection> startingVerticals) { Contract.Requires(random != null); Contract.Requires(metadata != null); Contract.Requires(finder != null); Contract.Requires(footprint != null && footprint.Count >= 3); Contract.Requires(sections != null && sections.Count == footprint.Count); Contract.Requires(overlappingVerticals != null && Contract.ForAll(overlappingVerticals, o => o != null)); Contract.Requires(startingVerticals != null && Contract.ForAll(startingVerticals, s => s != null)); Contract.Ensures(Contract.Result <IFloorPlanBuilder>() != null); var plan = new GeometricFloorplan(footprint); Design(random, metadata, finder, plan, sections, wallThickness, overlappingVerticals, startingVerticals); return(plan); }
public void FuzzTest() { Action <int, bool> iterate = (seed, catchit) => { Random r = new Random(seed); try { var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new[] { new Vector2(-25, -25), new Vector2(-25, 25), new Vector2(25, 25), new Vector2(25, -25) })); for (int j = 0; j < 3; j++) { var minX = r.Next(-25, 20); var minY = r.Next(-25, 20); var width = r.Next(10, 20); var height = r.Next(10, 20); plan.Add(new[] { new Vector2(minX, minY), new Vector2(minX, minY + height), new Vector2(minX + width, minY + height), new Vector2(minX + width, minY) }, 1); } plan.Freeze(); Console.WriteLine(SvgRoomVisualiser.FloorplanToSvg(_plan).ToString()); } catch { if (!catchit) { throw; } else { Assert.Fail(string.Format("Failing seed = {0}", seed.ToString())); } } }; for (var s = 0; s < 100; s++) { iterate(s * 2389, true); } }
public void TrainCarriageTest2() { // ReSharper disable InconsistentNaming var r = new Random(); Func <double> Random = r.NextDouble; const int Length = 20; const int Width = 10; Func <Vector2, float, float, Vector2> Offset = (start, length, width) => start + new Vector2(Length * length, -Width * width); Func <IFloorPlanBuilder, bool, float, IEnumerable <IRoomPlan> > CreateBalcony = (pl, start, bl) => { var p = pl.ExternalFootprint.First(); const float wt = 0.11f; if (start) { return(pl.Add(new Vector2[] { Offset(p, 0, 0.01f), Offset(p, bl / Length, 0.01f), Offset(p, bl / Length, 0.99f), Offset(p, 0, 0.99f), }, wt)); } else { return(pl.Add(new Vector2[] { Offset(p, 1 - (bl / Length), 0.01f), Offset(p, 1, 0.01f), Offset(p, 1, 0.99f), Offset(p, 1 - bl / Length, 0.99f), }, wt)); } }; var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new Vector2[] { new Vector2(-Length / 2f, Width / 2f), new Vector2(Length / 2f, Width / 2f), new Vector2(Length / 2f, -Width / 2f), new Vector2(-Length / 2f, -Width / 2f), })); // ReSharper restore InconsistentNaming //Create balconies on either end float balconyLength = Math.Min(3, Length / 10f); CreateBalcony(plan, true, balconyLength); CreateBalcony(plan, false, balconyLength); //Reference point to create rooms relative to var point = plan.ExternalFootprint.First(); //Create corridor section along entire train (along one side) const float CORRIDOR_WIDTH = 3; plan.Add(new Vector2[] { Offset(point, (balconyLength + 0.05f) / Length, 0), Offset(point, (Length - balconyLength - 0.05f) / Length, 0), Offset(point, (Length - balconyLength - 0.05f) / Length, CORRIDOR_WIDTH / Width), Offset(point, (balconyLength + 0.05f) / Length, CORRIDOR_WIDTH / Width), }, 0.55f); //Create compartments var compartmentAreaLength = Length - (balconyLength + 0.05f) * 2; var compartmentCount = Random.CompartmentalizeSpace(compartmentAreaLength, 1, int.MaxValue, 6, 10); var compartmentLength = compartmentAreaLength / compartmentCount; var compartments = new IRoomPlan[compartmentCount]; for (var i = 0; i < compartmentCount; i++) { var xStart = balconyLength + 0.05f + i * compartmentLength; var xEnd = xStart + compartmentLength - 0.05f; const float Y_START = CORRIDOR_WIDTH; compartments[i] = plan.Add(new Vector2[] { Offset(point, xStart / Length, Y_START / Width), Offset(point, xEnd / Length, Y_START / Width), Offset(point, xEnd / Length, 1), Offset(point, xStart / Length, 1), }, 0.55f).Single(); } plan.Freeze(); DrawPlan(plan); }
public void TrainCarriageTest() { // ReSharper disable InconsistentNaming var HierarchicalParameters = new NamedBoxCollection(); var r = new Random(); Func <double> Random = r.NextDouble; const float Length = 60; const float Width = 20; Func <Vector2, float, float, Vector2> Offset = (start, length, width) => start + new Vector2(Length * length, -Width * width); Func <IFloorPlanBuilder, bool, float, IEnumerable <IRoomPlan> > CreateBalcony = (pl, start, bl) => { var p = pl.ExternalFootprint.First(); var wt = HierarchicalParameters.InternalWallThickness(Random); if (start) { return(pl.Add(new Vector2[] { Offset(p, 0, 0.01f), Offset(p, bl / Length, 0.01f), Offset(p, bl / Length, 0.99f), Offset(p, 0, 0.99f), }, wt)); } else { return(pl.Add(new Vector2[] { Offset(p, 1 - (bl / Length), 0.01f), Offset(p, 1, 0.01f), Offset(p, 1, 0.99f), Offset(p, 1 - bl / Length, 0.99f), }, wt)); } }; var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new Vector2[] { new Vector2(-Length / 2f, Width / 2f), new Vector2(Length / 2f, Width / 2f), new Vector2(Length / 2f, -Width / 2f), new Vector2(-Length / 2f, -Width / 2f), })); // ReSharper restore InconsistentNaming //Get some style values var wallThickness = HierarchicalParameters.InternalWallThickness(Random); var doorWidth = HierarchicalParameters.StandardDoorWidth(Random); //Create balconies on either end float balconyLength = Math.Min(3, Length / 10f); var balcony1 = CreateBalcony(plan, true, balconyLength).Single(); var balcony2 = CreateBalcony(plan, false, balconyLength).Single(); //Reference point to create rooms relative to var point = plan.ExternalFootprint.First(); //Add toilets at one end of the carriage float toiletLength = balconyLength; //Left of the corridor var toiletLeft = plan.Add(new Vector2[] { Offset(point, balconyLength / Length, 0), Offset(point, (balconyLength + toiletLength) / Length, 0), Offset(point, (balconyLength + toiletLength) / Length, (Width / 2 - doorWidth / 2) / Width), Offset(point, balconyLength / Length, (Width / 2 - doorWidth / 2) / Width), }, wallThickness).Single(); //Right of the corridor var toiletRight = plan.Add(new Vector2[] { Offset(point, balconyLength / Length, (Width / 2 + doorWidth / 2) / Width), Offset(point, (balconyLength + toiletLength) / Length, (Width / 2 + doorWidth / 2) / Width), Offset(point, (balconyLength + toiletLength) / Length, 1), Offset(point, balconyLength / Length, 1), }, wallThickness).Single(); //Corridor var corridorL = (Width / 2 - doorWidth / 2 + 0.01f) / Width; var corridorR = (Width / 2 + doorWidth / 2 - 0.01f) / Width; var corridor = plan.Add(new Vector2[] { Offset(point, balconyLength / Length, corridorL), Offset(point, (balconyLength + toiletLength) / Length, corridorL), Offset(point, (balconyLength + toiletLength) / Length, corridorR), Offset(point, balconyLength / Length, corridorR), }, wallThickness).Single(); //Add dining room var diningRoom = plan.Add(new Vector2[] { Offset(point, (balconyLength + toiletLength + 0.05f) / Length, 0), Offset(point, (Length - balconyLength - 0.05f) / Length, 0), Offset(point, (Length - balconyLength - 0.05f) / Length, 1), Offset(point, (balconyLength + toiletLength + 0.05f) / Length, 1), }, wallThickness).Single(); plan.Freeze(); DrawPlan(plan); Assert.IsFalse(balcony2.Neighbours.Any(a => a.Other(balcony2) != diningRoom)); Assert.IsNotNull(balcony1); Assert.IsNotNull(balcony2); Assert.IsNotNull(toiletLeft); Assert.IsNotNull(toiletRight); Assert.IsNotNull(corridor); Assert.IsNotNull(diningRoom); }
public void TestMethod1() { var rnd = new Random(3); var random = (Func <double>)rnd.NextDouble; var metadata = new NamedBoxCollection(); var designer = FloorDesigner.Deserialize(new StringReader(@" # root node !Floorplan # tags for this floorplan Tags: Type: Residential Style: None # Aliases block is just a list of items, not used by the system. Handy place to define objects which will be used later in the markup Aliases: # A single room, with a set of constraints - &office !Room Id: Office Walkthrough: false Tags: 1: { Office } # Constraints: [] # - { Strength: 1, Req: !ExteriorWindow { } } # - { Strength: 0.5, Req: !ExteriorDoor { Deny: true } } # - { Strength: 0.5, Req: !Area { Min: 11 } } # A group of rooms - &office_group !Group Id: Offices Children: - *office - *office GrowthParameters: SeedSpacing: !NormalValue { Min: 2.5, Mean: 5, Max: 6.5, Vary: true } SeedChance: 0.75 IntersectionContinuationChance: 0.3 ParallelCheck: Length: 1 Width: 3.5 Angle: 15 MergeParameters: AngularDeviation: Weight: 0.4 Threshold: 0.5 Convexity: Weight: 0.3 Threshold: 0.5 Area: Weight: 0.3 Threshold: 45 Cutoff: 5 CorridorParameters: Width: 1 Spaces: - !Repeat Count: !NormalValue { Min: 1, Max: 100 } Space: *office_group ")); Func <IEnumerable <KeyValuePair <string, string> >, Type[], ScriptReference> finder = (tags, types) => { var tagsClean = from tag in tags let k = string.IsNullOrEmpty(tag.Key) let v = string.IsNullOrEmpty(tag.Value) where !k || !v select(!k && !v) ? (tag.Key + ":" + tag.Value) : (k ? tag.Value : tag.Key); return(ScriptReferenceFactory.Create(typeof(TestScript), Guid.NewGuid(), string.Join(",", tagsClean))); }; ////Corner shape //var shape = new[] { // new Vector2(9, 5), new Vector2(9, -6), new Vector2(0, -6), new Vector2(0, 0), new Vector2(-4, 0), new Vector2(-4, 5) //}; //var sections = new[] { // new Subsection[] { new Subsection(0, 1, Subsection.Types.Window) }, // new Subsection[0], // new Subsection[0], // new Subsection[0], // new Subsection[] { new Subsection(0, 1, Subsection.Types.Window) }, // new Subsection[0] //}; //Diagonal bend shape var shape = new[] { new Vector2(10, 10), new Vector2(20, 0), new Vector2(23, 0), new Vector2(33, 10), new Vector2(43, 0), new Vector2(28, -15), new Vector2(15, -15), new Vector2(0, 0) }; var sections = new[] { new Subsection[0], new Subsection[0], new Subsection[0], new Subsection[0], new Subsection[0], new Subsection[0], new Subsection[0], new Subsection[0] }; var verticals = new Vector2[][] { }; ////Actual office floorplan //var shape = new[] { // new Vector2(-25, 17), // new Vector2(0, 17), // new Vector2(3, 15), // new Vector2(33, 15), // new Vector2(38, 0), // new Vector2(-25, -25) //}; //var sections = new[] { // new Subsection[0], // new Subsection[0], // new Subsection[0], // new Subsection[0], // new Subsection[0], // new Subsection[0] //}; //var verticals = new[] { // new[] { // new Vector2(0, 0), // new Vector2(7, 0), // new Vector2(7, -7), // new Vector2(0, -7), // } //}; ////rectangle //var shape = new[] { // new Vector2(9, 0), // new Vector2(9, -6), // new Vector2(0, -6), // new Vector2(0, 0) //}; //var sections = new[] { // new Subsection[0], // new Subsection[0], // new Subsection[0], // new Subsection[0], //}; var plan = new GeometricFloorplan(shape); designer.Design(random, metadata, finder, plan, sections, 0.175f, verticals, new List <ConstrainedVerticalSelection>()); Console.WriteLine(SvgRoomVisualiser.FloorplanToSvg(plan, 55, basic: false)); }