-
Notifications
You must be signed in to change notification settings - Fork 6
/
test.ts
123 lines (103 loc) · 3.75 KB
/
test.ts
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
import tape from 'tape';
import Constrainautor from './Constrainautor';
import Delaunator from 'delaunator';
import {validateDelaunator, validateVertMap, validateConstraint, validateFlips, validateAllConstraints, validateDelaunay} from './validators';
import {findTest, loadTests} from './delaunaytests/loader';
import type {Test} from 'tape';
import type {TestFile} from './delaunaytests/loader';
const testFiles = loadTests(true);
type P2 = [number, number];
function testFile(t: Test, test: TestFile){
const {points, edges, error} = test,
del = Delaunator.from(points),
con = new Constrainautor(del),
conEdges = new Set<number>();
t.comment(`pre-constrainment`);
validateDelaunator(t, points, con.del);
validateVertMap(t, points, con);
validateFlips(t, con, true);
// pre-delaunify since Delaunator may miss some edge cases
con.delaunify(true);
//validateDelaunay(t, con);
let caught: Error | null = null;
for(const [p1, p2] of edges){
let ret: number | undefined = undefined;
try{
ret = con.constrainOne(p1, p2);
conEdges.add(ret);
}catch(ex){
if(!error){
throw ex;
}
caught = ex as Error;
}
if(ret !== undefined){
validateConstraint(t, points, con, ret, p1, p2);
}
}
if(error){
t.equal(caught && caught.message, error, `threw expected error: ${error}`);
}else{
t.assert(!caught, "did not throw");
}
t.comment(`post-constrainment, pre-delaunify`);
// The internal structures must be consistent, even in case of an error
validateDelaunator(t, points, con.del);
validateVertMap(t, points, con);
validateFlips(t, con, !error);
if(!error){
t.comment(`shallow delaunify`);
//con.delaunify();
validateFlips(t, con, false);
t.comment(`deep delaunify`);
//con.delaunify(true);
validateFlips(t, con, true);
validateDelaunay(t, con);
t.comment(`post delaunify constraints`);
validateAllConstraints(t, points, edges, con);
}
t.end();
}
function testConstructor(t: Test){
// @ts-ignore
t.throws(() => new Constrainautor(), /Expected an object with Delaunator output/, "throws on no argument");
// @ts-ignore
t.throws(() => new Constrainautor({}), /Expected an object with Delaunator output/, "throws on empty object");
// @ts-ignore
t.throws(() => new Constrainautor({foo: 12}), /Expected an object with Delaunator output/, "throws on invalid object");
// @ts-ignore
t.throws(() => new Constrainautor({triangles: [1], halfedges: [1], coords: [1, 2]}),
/Delaunator output appears inconsistent/, "throws on inconsistent Delaunation");
// @ts-ignore
t.throws(() => new Constrainautor({triangles: [1, 2, 3], halfedges: [1], coords: [1, 2]}),
/Delaunator output appears inconsistent/, "throws on inconsistent Delaunation");
// @ts-ignore
t.throws(() => new Constrainautor({triangles: [1, 2, 3], halfedges: [0, 1, 2], coords: [1]}),
/Delaunator output appears inconsistent/, "throws on inconsistent Delaunation");
// @ts-ignore
t.throws(() => new Constrainautor({triangles: [], halfedges: [], coords: [1, 2]}),
/No edges in triangulation/, "throws on empty Delaunation");
t.end();
}
function testExample(t: Test){
const points: P2[] = [[150, 50], [50, 200], [150, 350], [250, 200]],
del = Delaunator.from(points),
con = new Constrainautor(del);
con.constrainAll([[0, 2]]);
validateConstraint(t, points, con, undefined, 0, 2);
validateDelaunator(t, points, con.del);
validateVertMap(t, points, con);
validateFlips(t, con, true);
t.end();
}
function main(args: string[]){
const files = args.length ? args.map(name => findTest(testFiles, name)).filter(t => !!t) as TestFile[] : testFiles;
if(!args.length){
tape("Example", testExample);
tape("Constructor", testConstructor);
}
for(const test of files){
tape(test.name, (t) => testFile(t, test));
}
}
main(process.argv.slice(2));