forked from MatterHackers/agg-sharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTilingUtil.cs
136 lines (111 loc) · 3.63 KB
/
TilingUtil.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections.Generic;
namespace g3
{
public static class TilingUtil
{
/// <summary>
/// Regular-grid tiling of element inside bounds, with spacing between elements
/// Returns list of translations to element.
/// Always allows at least one row and column, even if element overflows bounds in that dimension.
/// </summary>
public static List<Vector2d> BoundedRegularTiling2(AxisAlignedBox2d element, AxisAlignedBox2d bounds,
double spacing)
{
Vector2d oshift = -element.Min;
double w = element.Width; double h = element.Height;
int nx = Math.Max(1, (int)(bounds.Width / w));
double spacew = (nx - 1) * spacing;
while (nx > 1 && bounds.Width - (w * nx + spacew) < 0)
{
nx--;
}
int ny = Math.Max(1, (int)(bounds.Height / h));
double spaceh = (ny - 1) * spacing;
while (ny > 1 && bounds.Height - (h * ny + spaceh) < 0)
{
ny--;
}
var translations = new List<Vector2d>();
for (int yi = 0; yi < ny; ++yi)
{
double dy = yi * h + yi * spacing;
for (int xi = 0; xi < nx; ++xi)
{
double dx = xi * w + xi * spacing;
translations.Add(new Vector2d(dx, dy) + oshift + bounds.Min);
}
}
return translations;
}
/// <summary>
/// hex-grid tiling of circles inside bounds, with spacing between elements
/// Returns list of translations to element.
/// Always allows at least one row and column, even if element overflows bounds in that dimension.
/// </summary>
public static List<Vector2d> BoundedCircleTiling2(AxisAlignedBox2d element, AxisAlignedBox2d bounds,
double spacing)
{
Vector2d oshift = -element.Min;
double w = element.Width; double h = element.Height;
if (MathUtil.EpsilonEqual(w, h, MathUtil.Epsilonf) == false)
{
throw new Exception("BoundedHexTiling2: input box is not square");
}
// note: this is a circle tiling, not a hex tiling, so even though we are
// starting in top-left with a "tip" hex, we don't have to offset down so that tip is inside
// the box (circle cuts off)
double r = w / 2;
var hex = new Hexagon2d(element.Center, r, Hexagon2d.TopModes.Tip);
hex.InnerRadius = r;
double stepx = hex.HorzSpacing;
double stepy = hex.VertSpacing;
double spacingy = spacing;
double spacingx = spacing;
// half-rows on top and bottom add up to full row-height
int ny = Math.Max(1, (int)(bounds.Height / stepy));
// reduce count so that we fit w/ spacing
double spaceh = (ny - 1) * spacingy;
while (ny > 1 && bounds.Height - (stepy * ny + spaceh) < 0)
{
ny--;
}
// even rows start at x=0
int nx_even = Math.Max(1, (int)(bounds.Width / stepx));
// reduce count if we spill over w/ spacing
double spacew = (nx_even - 1) * spacingx;
while (nx_even > 1 && bounds.Width - (stepx * nx_even + spacew) < 0)
{
nx_even--;
}
// odd rows have an extra half-step added to left side,
// so we may need to reduce count
int nx_odd = nx_even;
spacew = (nx_odd - 1) * spacingx;
if (ny > 0 && (stepx * nx_odd + spacew + stepx * 0.5) > bounds.Width)
{
nx_odd--;
spacew = (nx_odd - 1) * spacingx;
}
var translations = new List<Vector2d>();
for (int yi = 0; yi < ny; ++yi)
{
double dy = yi * stepy + yi * spacingy;
// x shift and count are different on odd rows
double shiftx = stepx * 0.5;
int nx = nx_odd;
if (yi % 2 == 0)
{
shiftx = 0;
nx = nx_even;
}
for (int xi = 0; xi < nx; ++xi)
{
double dx = shiftx + xi * stepx + xi * spacingx;
translations.Add(new Vector2d(dx, dy) + oshift + bounds.Min);
}
}
return translations;
}
}
}