public void Calculate_does_not_produce_textures_that_overlap_2() { var WIDTH = 512; var HEIGHT = 512; var input = new TextureAtlasInput(GetSettings(WIDTH, HEIGHT, 1)); var calc = new CornersPacker(); AddTexture(input, 100, 50, "a"); AddTexture(input, 80, 80, "c1"); AddTexture(input, 100, 50, "b"); AddTexture(input, 80, 80, "c3"); AddTexture(input, 80, 80, "c4"); AddTexture(input, 80, 80, "c2"); for (int i = 0; i < 40; i++) AddTexture(input, 20, 20, "a" + i); for (int i = 0; i < 10; i++) AddTexture(input, 80 + 10 * i, 40, "b" + i); var result = calc.Calculate(input); var nodes = result.Nodes.ToList(); var failures = new List<TextureAtlasNode>(); for (int i = 0; i < nodes.Count(); i++) for (int j = i + 1; j < nodes.Count(); j++) { if (nodes[i].GetBounds().IntersectsWith(nodes[j].GetBounds())) { failures.Add(nodes[i]); j = nodes.Count; } } Assert.Equal(0, failures.Count); Render(result); }
public TextureAtlas Calculate(TextureAtlasInput input) { ValidateInput(input); var unplacedNodes = input.Nodes.Select(n => n).ToList(); var placedNodes = new List<TextureAtlasNode>(); while (unplacedNodes.Any()) { var validPlacements = unplacedNodes .SelectMany(n => GetScoredPlacements(n, placedNodes, input.Settings)) .Where(n => n.Score.IsVaildPlacement) .ToList(); var best = validPlacements .OrderBy(n => n.Score.CornerParity) .ThenBy(n => n.Score.WastageScore) .ThenByDescending(n => n.Score.UtilizationScore) .FirstOrDefault(); if (best == null) throw new InvalidDataException("Insufficient free space available after " + placedNodes.Count + " textures placed"); best.PlaceNode(); placedNodes.Add(best.SourceNode); unplacedNodes.Remove(best.SourceNode); // TODO: Raise event node placed } return new TextureAtlas { Nodes = placedNodes, Size = input.Settings.Size, }; }
public void Add_throws_when_any_input_image_exceeds_output_size() { var settings = GetCalculatorSettings(100, 100, 0); var input = new TextureAtlasInput(settings); Assert.Throws<ArgumentOutOfRangeException>(() => input.AddSprite(GetBitmap(256, 10, "Invalid"), "Invalid") ); }
private static void ValidateInput(TextureAtlasInput input) { if (!input.Nodes.Any()) throw new InvalidOperationException("No input textures provided"); var totalInputArea = input.Nodes.Sum(x => x.Size.Pad(input.Settings.Padding).Area()); var totalOutputArea = input.Settings.Size.Pad(-input.Settings.Padding).Area(); if (totalInputArea > totalOutputArea) throw new ArgumentException("Input images (and padding) exceed the maximum total output area"); }
public void Calculate_does_not_produce_textures_outside_atlas_bounds() { var WIDTH = 512; var HEIGHT = 512; var input = new TextureAtlasInput(GetSettings(WIDTH, HEIGHT,1)); var calc = new CornersPacker(); for (int i = 0; i < 40; i++) AddTexture(input, 20, 20, "a" + i); for (int i = 0; i < 10; i++) AddTexture(input, 80 + 10 * i, 40, "b" + i); for (int i = 0; i < 40; i++) AddTexture(input, 40 + i, 10, "c" + i); var result = calc.Calculate(input); var failures = new List<TextureAtlasNode>(); result.Nodes.ToList().ForEach(n => { if (n.X < 0 || n.Y < 0 || n.X > WIDTH - n.Texture.Width || n.Y > HEIGHT - n.Texture.Height) failures.Add(n); }); Assert.Equal(0, failures.Count); Render(result); }
private void AddTexture(TextureAtlasInput input, int width, int height, string reference) { input.AddSprite(GetBitmap(width,height,reference),reference); }
public void Calculate_throws_when_no_images_added() { var input = new TextureAtlasInput(GetSettings()); var calc = new CornersPacker(); Assert.Throws<InvalidOperationException>(() => calc.Calculate(input)); }
public void Calculate_throws_when_insufficient_output_size_to_fit_all_images_with_padding() { var input = new TextureAtlasInput(GetSettings(100, 100, 1)); var calc = new CornersPacker(); AddTexture(input, 50, 50, "a"); AddTexture(input, 50, 50, "b"); AddTexture(input, 50, 50, "c"); AddTexture(input, 50, 50, "d"); Assert.Throws<ArgumentException>(() => calc.Calculate(input)); }
public void Calculate_returns_all_added_references() { var input = new TextureAtlasInput(GetSettings(100, 100, 1)); var calc = new CornersPacker(); AddTexture(input, 10, 10, "a"); AddTexture(input, 10, 10, "b"); AddTexture(input, 10, 10, "c"); var result = calc.Calculate(input); Assert.NotNull(result.Nodes.SingleOrDefault(n => n.Reference == "a")); Assert.NotNull(result.Nodes.SingleOrDefault(n => n.Reference == "b")); Assert.NotNull(result.Nodes.SingleOrDefault(n => n.Reference == "c")); Render(result); }
public void Calculate_non_test() { var WIDTH = 512; var HEIGHT = 512; var input = new TextureAtlasInput(GetSettings(WIDTH, HEIGHT, 1)); var calc = new CornersPacker(); for (int i = 0; i < 40; i++) AddTexture(input, 20, 20, "a" + i); for (int i = 0; i < 10; i++) AddTexture(input, 80 + 10 * i, 40, "b" + i); for (int i = 0; i < 40; i++) AddTexture(input, 40 + i, 10, "c" + i); AddTexture(input, 300, 40, "a"); AddTexture(input, 50, 400, "d"); AddTexture(input, 80, 80, "d2"); for (int i = 0; i < 40; i++) AddTexture(input, 20, 20, "e" + i); for (int i = 0; i < 10; i++) AddTexture(input, 80 + 10 * i, 40, "f" + i); var result = calc.Calculate(input); Render(result); }
public void Calculate_does_not_throw_when_images_fit_within_output() { var input = new TextureAtlasInput(GetSettings()); var calc = new CornersPacker(); AddTexture(input, 50, 50, "a"); AddTexture(input, 50, 50, "b"); AddTexture(input, 50, 50, "c"); AddTexture(input, 50, 50, "d"); calc.Calculate(input); }
public void Add_throws_on_null_reference() { var settings = GetCalculatorSettings(100, 100, 0); var input = new TextureAtlasInput(settings); Assert.Throws<ArgumentNullException>(() => input.AddSprite(GetBitmap(10, 10, "a"), null)); }
public void Add_throws_on_null_image() { var settings = GetCalculatorSettings(100, 100, 0); var input = new TextureAtlasInput(settings); Assert.Throws<ArgumentNullException>(() => input.AddSprite(null, "invalid")); }
public void Add_throws_on_empty_reference(string reference) { var settings = GetCalculatorSettings(100, 100, 0); var input = new TextureAtlasInput(settings); Assert.Throws<ArgumentOutOfRangeException>(() => input.AddSprite(GetBitmap(10, 10, "a"), reference)); }