1include<../std.scad>
  2
  3
  4module test_is_path() {
  5    assert(is_path([[1,2,3],[4,5,6]]));
  6    assert(is_path([[1,2,3],[4,5,6],[7,8,9]]));
  7    assert(!is_path(123));
  8    assert(!is_path("foo"));
  9    assert(!is_path(true));
 10    assert(!is_path([]));
 11    assert(!is_path([[]]));
 12    assert(!is_path([["foo","bar","baz"]]));
 13    assert(!is_path([[1,2,3]]));
 14    assert(!is_path([["foo","bar","baz"],["qux","quux","quuux"]]));
 15}
 16test_is_path();
 17
 18
 19module test_is_1region() {
 20    assert(!is_1region([[3,4],[5,6],[7,8]]));
 21    assert(is_1region([[[3,4],[5,6],[7,8]]]));
 22}
 23test_is_1region();
 24
 25
 26module force_path() {
 27    assert_equal(force_path([[3,4],[5,6],[7,8]]), [[3,4],[5,6],[7,8]]);  
 28    assert_equal(force_path([[[3,4],[5,6],[7,8]]]), [[3,4],[5,6],[7,8]]);  
 29    assert_equal(force_path("abc"), "abc");
 30    assert_equal(force_path(13), 13);    
 31}
 32test_is_1region();
 33
 34    
 35
 36module test_is_closed_path() {
 37    assert(!is_closed_path([[1,2,3],[4,5,6],[1,8,9]]));
 38    assert(is_closed_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]));
 39}
 40test_is_closed_path();
 41
 42
 43module test_close_path() {
 44    assert(close_path([[1,2,3],[4,5,6],[1,8,9]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
 45    assert(close_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
 46}
 47test_close_path();
 48
 49
 50module test_cleanup_path() {
 51    assert(cleanup_path([[1,2,3],[4,5,6],[1,8,9]]) == [[1,2,3],[4,5,6],[1,8,9]]);
 52    assert(cleanup_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]) == [[1,2,3],[4,5,6],[1,8,9]]);
 53}
 54test_cleanup_path();
 55
 56
 57module test_path_merge_collinear() {
 58    path = [[-20,-20], [-10,-20], [0,-10], [10,0], [20,10], [20,20], [15,30]];
 59    assert(path_merge_collinear(path) == [[-20,-20], [-10,-20], [20,10], [20,20], [15,30]]);
 60    assert(path_merge_collinear([path]) == [[-20,-20], [-10,-20], [20,10], [20,20], [15,30]]);
 61    sq=square(10);
 62    assert_equal(path_merge_collinear(subdivide_path(square(10), refine=25),closed=true), sq);
 63}
 64test_path_merge_collinear();
 65
 66
 67module test_path_length(){
 68    sq = square(10);
 69    assert_equal(path_length(sq),30);
 70    assert_equal(path_length(sq,true),40);
 71    c = circle($fn=1000, r=1);
 72    assert(approx(path_length(c,closed=true), 2*PI,eps=.0001));
 73}
 74test_path_length();
 75
 76
 77module test_path_segment_lengths(){
 78    sq = square(10);
 79    assert_equal(path_segment_lengths(sq), [10,10,10]);
 80    assert_equal(path_segment_lengths(sq,true), [10,10,10,10]);
 81    c = circle($fn=1000, r=1);
 82    assert(approx(path_segment_lengths(c,closed=true), repeat(2*PI/1000,1000),eps=1e-7));
 83}
 84test_path_segment_lengths();
 85
 86
 87module test_path_length_fractions(){
 88    sq = square(10);
 89    assert_approx(path_length_fractions(sq), [0,1/3, 2/3, 1]);
 90    assert_approx(path_length_fractions(sq,true), [0,1/4, 2/4,3/4, 1]);    
 91}
 92test_path_length_fractions();
 93
 94
 95
 96module test_subdivide_path(){
 97     assert(approx(subdivide_path(square([2,2],center=true), 12), [[1, -1], [1/3, -1], [-1/3, -1], [-1, -1], [-1, -1/3], [-1, 1/3], [-1, 1], [-1/3, 1], [1/3, 1], [1, 1], [1, 1/3], [1, -1/3]]));
 98     assert_equal(subdivide_path(square([8,2],center=true), 12), [[4, -1], [2, -1], [0, -1], [-2, -1], [-4, -1], [-4, 0], [-4, 1], [-2, 1], [0, 1], [2, 1], [4, 1], [4, 0]]);
 99    assert_approx(subdivide_path(square([8,2],center=true), 12, method="segment"), [[4, -1], [4/3, -1], [-4/3, -1], [-4, -1], [-4, -1/3], [-4, 1/3], [-4, 1], [-4/3, 1], [4/3, 1], [4, 1], [4, 1/3], [4, -1/3]]);
100    assert_approx(subdivide_path(square([2,2],center=true), 17, closed=false), [[1, -1], [0.6, -1], [0.2, -1], [-0.2, -1], [-0.6, -1], [-1, -1], [-1, -2/3], [-1, -1/3], [-1, 0], [-1, 1/3], [-1, 2/3], [-1, 1], [-0.6, 1], [-0.2, 1], [0.2, 1], [0.6, 1], [1, 1]]);
101    assert_approx(subdivide_path(hexagon(side=2), [2,3,4,5,6,7], method="segment"),
102                [[2, 0], [1.5, -0.866025403784], [1, -1.73205080757],
103                [0.333333333333, -1.73205080757], [-0.333333333333,
104                -1.73205080757], [-1, -1.73205080757], [-1.25,
105                -1.29903810568], [-1.5, -0.866025403784], [-1.75,
106                -0.433012701892], [-2, 0], [-1.8, 0.346410161514],
107                [-1.6, 0.692820323028], [-1.4, 1.03923048454], [-1.2,
108                1.38564064606], [-1, 1.73205080757], [-0.666666666667,
109                1.73205080757], [-0.333333333333, 1.73205080757], [0,
110                1.73205080757], [0.333333333333, 1.73205080757],
111                [0.666666666667, 1.73205080757], [1, 1.73205080757],
112                [1.14285714286, 1.48461497792], [1.28571428571,
113                1.23717914826], [1.42857142857, 0.989743318611],
114                [1.57142857143, 0.742307488958], [1.71428571429,
115                0.494871659305], [1.85714285714, 0.247435829653]]);
116    assert_approx(subdivide_path(pentagon(side=2), [3,4,3,4], method="segment", closed=false),
117           [[1.7013016167, 0], [1.30944478184, -0.539344662917],
118           [0.917587946981, -1.07868932583], [0.525731112119,
119           -1.61803398875], [0.0502028539716, -1.46352549156],
120           [-0.425325404176, -1.30901699437], [-0.900853662324,
121           -1.15450849719], [-1.37638192047, -1], [-1.37638192047,
122           -0.333333333333], [-1.37638192047, 0.333333333333],
123           [-1.37638192047, 1], [-0.900853662324, 1.15450849719],
124           [-0.425325404176, 1.30901699437], [0.0502028539716,
125           1.46352549156], [0.525731112119, 1.61803398875]]);
126    assert_approx(subdivide_path(pentagon(side=2), 17),
127                  [[1.7013016167, 0], [1.30944478184,
128                  -0.539344662917], [0.917587946981, -1.07868932583],
129                  [0.525731112119, -1.61803398875], [0.0502028539716,
130                  -1.46352549156], [-0.425325404176, -1.30901699437],
131                  [-0.900853662324, -1.15450849719], [-1.37638192047,
132                  -1], [-1.37638192047, -0.333333333333],
133                  [-1.37638192047, 0.333333333333], [-1.37638192047,
134                  1], [-0.900853662324, 1.15450849719],
135                  [-0.425325404176, 1.30901699437], [0.0502028539716,
136                  1.46352549156], [0.525731112119, 1.61803398875],
137                  [0.917587946981, 1.07868932583], [1.30944478184,
138                  0.539344662917]]);
139    assert_approx(subdivide_path(pentagon(side=2), 17, exact=false),
140                  [[1.7013016167, 0], [1.30944478184,
141                  -0.539344662917], [0.917587946981, -1.07868932583],
142                  [0.525731112119, -1.61803398875], [-0.108306565411,
143                  -1.41202265917], [-0.742344242941, -1.20601132958],
144                  [-1.37638192047, -1], [-1.37638192047,
145                  -0.333333333333], [-1.37638192047, 0.333333333333],
146                  [-1.37638192047, 1], [-0.742344242941,
147                  1.20601132958], [-0.108306565411, 1.41202265917],
148                  [0.525731112119, 1.61803398875], [0.917587946981,
149                  1.07868932583], [1.30944478184, 0.539344662917]]);
150    assert_approx(subdivide_path(pentagon(side=2), 18, exact=false),
151                    [[1.7013016167, 0], [1.40740899056,
152                    -0.404508497187], [1.11351636441,
153                    -0.809016994375], [0.819623738265,
154                    -1.21352549156], [0.525731112119, -1.61803398875],
155                    [0.0502028539716, -1.46352549156],
156                    [-0.425325404176, -1.30901699437],
157                    [-0.900853662324, -1.15450849719],
158                    [-1.37638192047, -1], [-1.37638192047, -0.5],
159                    [-1.37638192047, 0], [-1.37638192047, 0.5],
160                    [-1.37638192047, 1], [-0.900853662324,
161                    1.15450849719], [-0.425325404176, 1.30901699437],
162                    [0.0502028539716, 1.46352549156], [0.525731112119,
163                    1.61803398875], [0.819623738265, 1.21352549156],
164                    [1.11351636441, 0.809016994375], [1.40740899056,
165                    0.404508497187]]);
166    assert_approx(subdivide_path([[0,0,0],[2,0,1],[2,3,2]], 12),
167          [[0, 0, 0], [2/3, 0, 1/3], [4/3, 0, 2/3], [2, 0, 1], [2, 0.75, 1.25], [2, 1.5, 1.5], [2, 2.25, 1.75], [2, 3, 2], [1.6, 2.4, 1.6], [1.2, 1.8, 1.2], [0.8, 1.2, 0.8], [0.4, 0.6, 0.4]]);
168
169   path = pentagon(d=100);
170   spath = subdivide_path(path, maxlen=10, closed=true);
171   assert_approx(spath,
172         [[50, 0], [44.2418082865, -7.92547096913], [38.4836165729,
173         -15.8509419383], [32.7254248594, -23.7764129074], [26.9672331458,
174         -31.7018838765], [21.2090414323, -39.6273548456], [15.4508497187,
175         -47.5528258148], [6.1338998125, -44.5255652814], [-3.18305009375,
176         -41.498304748], [-12.5, -38.4710442147], [-21.8169499062,
177         -35.4437836813], [-31.1338998125, -32.416523148], [-40.4508497187,
178         -29.3892626146], [-40.4508497187, -19.5928417431], [-40.4508497187,
179         -9.79642087154], [-40.4508497187, 0], [-40.4508497187, 9.79642087154],
180         [-40.4508497187, 19.5928417431], [-40.4508497187, 29.3892626146],
181         [-31.1338998125, 32.416523148], [-21.8169499062, 35.4437836813],
182         [-12.5, 38.4710442147], [-3.18305009375, 41.498304748], [6.1338998125,
183         44.5255652814], [15.4508497187, 47.5528258148], [21.2090414323,
184         39.6273548456], [26.9672331458, 31.7018838765], [32.7254248594,
185         23.7764129074], [38.4836165729, 15.8509419383], [44.2418082865,
186         7.92547096913]]);
187}
188test_subdivide_path();
189
190
191module test_subdivide_long_segments(){
192}
193test_subdivide_long_segments();
194
195
196module test_resample_path(){
197    path = xscale(2,circle($fn=250, r=10));
198    sampled = resample_path(path, 16);
199    assert_approx(sampled,
200              [[20, 0], [17.1657142861, -5.13020769642],
201              [11.8890531315, -8.04075246881], [6.03095737128,
202              -9.53380030092], [1.72917236085e-14, -9.99921044204],
203              [-6.03095737128, -9.53380030092], [-11.8890531315,
204              -8.04075246881], [-17.1657142861, -5.13020769642], [-20,
205              -3.19176120946e-14], [-17.1657142861, 5.13020769642],
206              [-11.8890531315, 8.04075246881], [-6.03095737128,
207              9.53380030092], [-4.20219414821e-14, 9.99921044204],
208              [6.03095737128, 9.53380030092], [11.8890531315,
209              8.04075246881], [17.1657142861, 5.13020769642]]);
210    path2 = square(20);
211    assert_approx(resample_path(path2, spacing=6), 
212        [[20, 0], [13.8461538462, 0], [7.69230769231, 0], [1.53846153846, 0],
213         [0, 4.61538461538], [0, 10.7692307692], [0, 16.9230769231], [3.07692307692, 20],
214         [9.23076923077, 20], [15.3846153846, 20], [20, 18.4615384615], [20, 12.3076923077], [20, 6.15384615385]]);
215    assert_equal(resample_path(path2, spacing=6,closed=false),[[20, 0], [14, 0], [8, 0], [2, 0], [0, 4], [0, 10], [0, 16], [2, 20], [8, 20], [14, 20], [20, 20]]);
216    assert_approx(resample_path(path, spacing=17), 
217                 [[20, 0], [8.01443073309, -9.16170407964],
218                 [-8.01443073309, -9.16170407964], [-20,
219                 -1.59309060367e-14], [-8.01443073309, 9.16170407964],
220                 [8.01443073309, 9.16170407964]]);
221}
222test_resample_path();
223
224
225module test_path_closest_point(){
226   path = circle(d=100,$fn=6);
227   pt = [20,10];
228   closest = path_closest_point(path, pt);
229   assert_approx(closest, [5, [38.1698729811, 20.4903810568]]);
230}
231test_path_closest_point();
232
233
234
235module test_path_tangents(){
236   path = circle(r=1, $fn=200);
237   path_t = path_tangents(path,closed=true);
238   assert_approx(path_t, hstack(column(path,1), -column(path,0)));
239   rect = square([10,3]);
240   tr1 = path_tangents(rect,closed=true);
241   tr2 = path_tangents(rect,closed=true,uniform=false);
242   tr3 = path_tangents(rect,closed=false);
243   tr4 = path_tangents(rect,closed=false,uniform=false);   
244   assert_approx(tr1,  [[-0.957826285221, -0.287347885566], [-0.957826285221, 0.287347885566], [0.957826285221, 0.287347885566], [0.957826285221, -0.287347885566]]);
245   assert_approx(tr2,  [[-0.707106781187, -0.707106781187], [-0.707106781187, 0.707106781187], [0.707106781187, 0.707106781187], [0.707106781187, -0.707106781187]]);
246   assert_approx(tr3,  [[-0.99503719021, -0.099503719021], [-0.957826285221, 0.287347885566], [0.957826285221, 0.287347885566], [0.99503719021, -0.099503719021]]);
247   assert_approx(tr4,  [[-1, 0], [-0.707106781187, 0.707106781187], [0.707106781187, 0.707106781187], [1, 0]]);
248}
249test_path_tangents();
250
251
252
253module test_path_curvature(){
254    c8 = path3d(circle(r=8, $fn=100));
255    c28 = path3d(circle(r=28, $fn=100));
256    assert(approx(path_curvature(c8,closed=true), repeat(1/8, 100), 4e-4));
257    assert(approx(path_curvature(c28,closed=true), repeat(1/28, 100), 4e-4));
258}
259test_path_curvature();
260
261
262module test_path_torsion(){
263    c = path3d(circle(r=1, $fn=100));
264    tc = path_torsion(c, closed=true);
265    assert(all_zero(tc));
266    a=3;b=7;
267    helix = [for(t=[0:1:20]) [a*cos(t), a*sin(t), b*t*PI/180]];
268    th = path_torsion(helix, closed=false);
269    assert(approx(th[5], b/(a*a+b*b), 1e-5));
270}
271test_path_torsion();
272
273
274
275//echo(fmt_float(sampled));
276