public void ShouldGenerateSubSectorWithHoleWhenSectorHasHole() { // *--------* // | | // | *--* | // | | | | // | *--* | // | | // *--------* var map = new MapData { NameSpace = "Doom", Vertices = { new Vertex // 0 { X = 0, Y = 0, }, new Vertex // 1 { X = 1000, Y = 0, }, new Vertex // 2 { X = 1000, Y = 1000, }, new Vertex // 3 { X = 0, Y = 1000, }, new Vertex // 4 { X = 250, Y = 250, }, new Vertex // 5 { X = 750, Y = 250, }, new Vertex // 6 { X = 750, Y = 750, }, new Vertex // 7 { X = 250, Y = 750, }, }, LineDefs = { new LineDef // 0 { V1 = 0, V2 = 1, SideFront = 0, Blocking = true, }, new LineDef // 1 { V1 = 1, V2 = 2, SideFront = 0, Blocking = true, }, new LineDef // 2 { V1 = 2, V2 = 3, SideFront = 0, Blocking = true, }, new LineDef // 3 { V1 = 3, V2 = 0, SideFront = 0, Blocking = true, }, new LineDef // 4 { V1 = 4, V2 = 7, SideFront = 0, Blocking = true, }, new LineDef // 5 { V1 = 7, V2 = 6, SideFront = 0, Blocking = true, }, new LineDef // 6 { V1 = 6, V2 = 5, SideFront = 0, Blocking = true, }, new LineDef // 7 { V1 = 5, V2 = 4, SideFront = 0, Blocking = true, }, }, SideDefs = { new SideDef // 0 { Sector = 0, TextureMiddle = "STARTAN1", }, }, Sectors = { new Sector { HeightFloor = 0, HeightCeiling = 128, TextureFloor = "FLOOR0_1", TextureCeiling = "CEIL1_1", LightLevel = 192, }, }, Things = { new Thing { X = 100, Y = 100, Angle = 90, Type = 1, Skill1 = true, Skill2 = true, Skill3 = true, Skill4 = true, Skill5 = true, Single = true, Dm = true, Coop = true, } } }; var graph = SectorGraph.BuildFrom(map); Assert.That(graph.LogicalSectors, Has.Count.EqualTo(1)); Assert.That(graph.LogicalSectors.First(), Has.Count.EqualTo(1)); }
public static void Export(MapData mapData, string filePath) { using var outputStream = new FileStream(filePath, FileMode.Create); using var w = new StreamWriter(outputStream, Encoding.UTF8); var sectorGraph = SectorGraph.BuildFrom(mapData); const int Padding = 10; var height = mapData.Height; var minY = mapData.MinY; double FlipY(double y) => height - (y - minY); w.WriteLine($"<svg viewBox=\"{mapData.MinX - Padding} " + $"{FlipY(mapData.MaxY) - Padding} " + $"{mapData.Width + 2 * Padding} " + $"{mapData.Height + 2 * Padding}\" " + $"xmlns=\"http://www.w3.org/2000/svg\">"); w.WriteLine("\t<style>"); w.WriteLine("\t\t.sector {fill:#202020;}"); w.WriteLine("\t\t.sector:hover {fill:#404040;}"); w.WriteLine("\t\t.sub-sector {}"); w.WriteLine("\t\t.two-sided {stroke:yellow;}"); w.WriteLine("\t\t.one-sided {stroke:red;}"); w.WriteLine("\t</style>"); w.WriteLine($"\t<rect " + $"x=\"{mapData.MinX - Padding}\" " + $"y=\"{FlipY(mapData.MaxY) - Padding}\" " + $"width=\"{mapData.Width + 2 * Padding}\" " + $"height=\"{mapData.Height + 2 * Padding}\" " + $"fill=\"black\"/>"); foreach (var logicalSector in sectorGraph.LogicalSectors) { w.WriteLine($"\t<g id=\"{logicalSector.SectorId}\" class=\"sector\">"); foreach (var(ssIndex, subSector) in logicalSector.Indexed()) { var pointString = string.Join(" ", subSector.Select(line => { var v = line.Start; return($"{v.X},{FlipY(v.Y)}"); })); w.WriteLine($"\t\t<polygon points=\"{pointString}\" class=\"sub-sector\">"); w.WriteLine($"\t\t\t<title>Sector {logicalSector.SectorId} (SS {ssIndex})</title>"); w.WriteLine($"\t\t</polygon>"); foreach (var line in subSector) { w.WriteLine($"\t\t<line " + $"x1=\"{line.Start.X}\" " + $"y1=\"{FlipY(line.Start.Y)}\" " + $"x2=\"{line.End.X}\" " + $"y2=\"{FlipY(line.End.Y)}\" " + $"class=\"{(line.Definition.TwoSided ? "two-sided" : "one-sided")}\"/>"); } } w.WriteLine("\t</g>"); } w.WriteLine("</svg>"); }
public void ShouldGenerateMultipleSubSectorsWhenSectorHasTwoConnectedAreas() { // This map has one sector composed of two squares that are connected, and the inside connections have multiple lines // ASCII ART // // *----*----* // | | | // | * | // | | | // *----*----* var map = new MapData { NameSpace = "Doom", Vertices = { new Vertex // 0 { X = 0, Y = 0, }, new Vertex // 1 { X = 100, Y = 0, }, new Vertex // 2 { X = 200, Y = 0, }, new Vertex // 3 { X = 200, Y = 100, }, new Vertex // 4 { X = 100, Y = 100, }, new Vertex // 5 { X = 0, Y = 100, }, new Vertex // 6 { X = 100, Y = 50, }, }, LineDefs = { new LineDef // 0 { V1 = 0, V2 = 1, SideFront = 0, Blocking = true, }, new LineDef // 1 { V1 = 1, V2 = 2, SideFront = 0, Blocking = true, }, new LineDef // 2 { V1 = 2, V2 = 3, SideFront = 0, Blocking = true, }, new LineDef // 3 { V1 = 3, V2 = 4, SideFront = 0, Blocking = true, }, new LineDef // 4 { V1 = 4, V2 = 5, SideFront = 0, Blocking = true, }, new LineDef // 5 { V1 = 5, V2 = 0, SideFront = 0, Blocking = true, }, new LineDef // 6 { V1 = 1, V2 = 6, SideFront = 1, SideBack = 1, TwoSided = true, }, new LineDef // 7 { V1 = 6, V2 = 4, SideFront = 1, SideBack = 1, TwoSided = true, }, }, SideDefs = { new SideDef // 0 { Sector = 0, TextureMiddle = "STARTAN1", }, new SideDef // 1 { Sector = 0, }, }, Sectors = { new Sector { HeightFloor = 0, HeightCeiling = 128, TextureFloor = "FLOOR0_1", TextureCeiling = "CEIL1_1", LightLevel = 192, }, }, Things = { new Thing { X = 50, Y = 50, Angle = 90, Type = 1, Skill1 = true, Skill2 = true, Skill3 = true, Skill4 = true, Skill5 = true, Single = true, Dm = true, Coop = true, } } }; var graph = SectorGraph.BuildFrom(map); Assert.That(graph.LogicalSectors, Has.Count.EqualTo(1)); Assert.That(graph.LogicalSectors.First(), Has.Count.EqualTo(2)); }