First commit.
This commit is contained in:
30
Source/OpenNest.Engine/CirclePacking/Bin.cs
Normal file
30
Source/OpenNest.Engine/CirclePacking/Bin.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenNest.CirclePacking
|
||||
{
|
||||
internal class Bin : Box
|
||||
{
|
||||
public Bin()
|
||||
{
|
||||
Items = new List<Item>();
|
||||
}
|
||||
|
||||
public List<Item> Items { get; set; }
|
||||
|
||||
public double Density()
|
||||
{
|
||||
return Items.Sum(i => i.Area()) / Area();
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return new Bin
|
||||
{
|
||||
Location = this.Location,
|
||||
Size = this.Size,
|
||||
Items = new List<Item>(Items)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Source/OpenNest.Engine/CirclePacking/FillEndEven.cs
Normal file
79
Source/OpenNest.Engine/CirclePacking/FillEndEven.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
|
||||
namespace OpenNest.CirclePacking
|
||||
{
|
||||
internal class FillEndEven : FillEngine
|
||||
{
|
||||
public FillEndEven(Bin bin)
|
||||
: base(bin)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Fill(Item item)
|
||||
{
|
||||
var max = new Vector(
|
||||
Bin.Right - item.BoundingBox.Right + Tolerance.Epsilon,
|
||||
Bin.Top - item.BoundingBox.Top + Tolerance.Epsilon);
|
||||
|
||||
var rows = Math.Floor((Bin.Height + Tolerance.Epsilon) / (item.Diameter));
|
||||
|
||||
var diameter = item.Diameter;
|
||||
var remaining = Bin.Height - diameter * rows;
|
||||
var radius = diameter * 0.5;
|
||||
|
||||
if (remaining < radius)
|
||||
{
|
||||
var yodd = Bin.Y + remaining;
|
||||
var yoffset = diameter;
|
||||
var xoffset = Trigonometry.Base(remaining, diameter);
|
||||
int column = 0;
|
||||
|
||||
for (var x = Bin.X; x <= max.X; x += xoffset)
|
||||
{
|
||||
var y = column.IsOdd() ? yodd : Bin.Y;
|
||||
|
||||
for (; y <= max.Y; y += yoffset)
|
||||
{
|
||||
Bin.Items.Add(new Item
|
||||
{
|
||||
Center = new Vector(x, y)
|
||||
});
|
||||
}
|
||||
|
||||
column++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var yoffset = (Bin.Height - diameter) / (2 * rows - 1);
|
||||
var xoffset = Trigonometry.Base(yoffset, diameter);
|
||||
|
||||
var yodd = Bin.Y + yoffset;
|
||||
|
||||
yoffset *= 2.0;
|
||||
|
||||
int column = 0;
|
||||
|
||||
for (var x = Bin.X; x <= max.X; x += xoffset)
|
||||
{
|
||||
var y = column.IsOdd() ? yodd : Bin.Y;
|
||||
|
||||
for (; y <= max.Y; y += yoffset)
|
||||
{
|
||||
Bin.Items.Add(new Item
|
||||
{
|
||||
Center = new Vector(x, y)
|
||||
});
|
||||
}
|
||||
|
||||
column++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Fill(Item item, int maxCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
100
Source/OpenNest.Engine/CirclePacking/FillEndOdd.cs
Normal file
100
Source/OpenNest.Engine/CirclePacking/FillEndOdd.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
|
||||
namespace OpenNest.CirclePacking
|
||||
{
|
||||
internal class FillEndOdd : FillEngine
|
||||
{
|
||||
public FillEndOdd(Bin bin)
|
||||
: base(bin)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Fill(Item item)
|
||||
{
|
||||
var bin1 = FillHorizontal(item);
|
||||
var bin2 = FillVertical(item);
|
||||
|
||||
if (bin1.Items.Count > bin2.Items.Count)
|
||||
Bin.Items.AddRange(bin1.Items);
|
||||
else
|
||||
Bin.Items.AddRange(bin2.Items);
|
||||
}
|
||||
|
||||
public override void Fill(Item item, int maxCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Bin FillHorizontal(Item item)
|
||||
{
|
||||
var bin = Bin.Clone() as Bin;
|
||||
|
||||
var max = new Vector(
|
||||
bin.Right - item.BoundingBox.Right + Tolerance.Epsilon,
|
||||
bin.Top - item.BoundingBox.Top + Tolerance.Epsilon);
|
||||
|
||||
var count = Math.Floor((bin.Width + Tolerance.Epsilon) / item.Diameter);
|
||||
|
||||
if (count == 0)
|
||||
return bin;
|
||||
|
||||
var xoffset = (bin.Width - item.Diameter) / (count - 1);
|
||||
var yoffset = Trigonometry.Height(xoffset * 0.5, item.Diameter);
|
||||
|
||||
int row = 0;
|
||||
|
||||
for (var y = bin.Y; y <= max.Y; y += yoffset)
|
||||
{
|
||||
var x = row.IsOdd() ? bin.X + xoffset * 0.5 : bin.X;
|
||||
|
||||
for (; x <= max.X; x += xoffset)
|
||||
{
|
||||
var addedItem = item.Clone() as Item;
|
||||
addedItem.Center = new Vector(x, y);
|
||||
|
||||
bin.Items.Add(addedItem);
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
private Bin FillVertical(Item item)
|
||||
{
|
||||
var bin = Bin.Clone() as Bin;
|
||||
|
||||
var max = new Vector(
|
||||
Bin.Right - item.BoundingBox.Right + Tolerance.Epsilon,
|
||||
Bin.Top - item.BoundingBox.Top + Tolerance.Epsilon);
|
||||
|
||||
var count = Math.Floor((bin.Height + Tolerance.Epsilon) / item.Diameter);
|
||||
|
||||
if (count == 0)
|
||||
return bin;
|
||||
|
||||
var yoffset = (bin.Height - item.Diameter) / (count - 1);
|
||||
var xoffset = Trigonometry.Base(yoffset * 0.5, item.Diameter);
|
||||
|
||||
int column = 0;
|
||||
|
||||
for (var x = bin.X; x <= max.X; x += xoffset)
|
||||
{
|
||||
var y = column.IsOdd() ? bin.Y + yoffset * 0.5 : bin.Y;
|
||||
|
||||
for (; y <= max.Y; y += yoffset)
|
||||
{
|
||||
var addedItem = item.Clone() as Item;
|
||||
addedItem.Center = new Vector(x, y);
|
||||
|
||||
bin.Items.Add(addedItem);
|
||||
}
|
||||
|
||||
column++;
|
||||
}
|
||||
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Source/OpenNest.Engine/CirclePacking/FillEngine.cs
Normal file
17
Source/OpenNest.Engine/CirclePacking/FillEngine.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
namespace OpenNest.CirclePacking
|
||||
{
|
||||
internal abstract class FillEngine
|
||||
{
|
||||
public FillEngine(Bin bin)
|
||||
{
|
||||
Bin = bin;
|
||||
}
|
||||
|
||||
public Bin Bin { get; set; }
|
||||
|
||||
public abstract void Fill(Item item);
|
||||
|
||||
public abstract void Fill(Item item, int maxCount);
|
||||
}
|
||||
}
|
||||
19
Source/OpenNest.Engine/CirclePacking/Item.cs
Normal file
19
Source/OpenNest.Engine/CirclePacking/Item.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.CirclePacking
|
||||
{
|
||||
internal class Item : Circle
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return new Item
|
||||
{
|
||||
Radius = this.Radius,
|
||||
Center = this.Center,
|
||||
Id = this.Id
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user