Skip to content

Commit d4898b9

Browse files
authored
Merge pull request #2 from aothms/test-cases
add test cases
2 parents 2f692e9 + 2027d9e commit d4898b9

File tree

13 files changed

+317
-9
lines changed

13 files changed

+317
-9
lines changed

docs/viewer/compose.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ export function getChildByName(root: ComposedObject, childName, skip=0) {
2020
fragments.shift();
2121
}
2222
let start: ComposedObject | undefined = root;
23-
while (fragments.length && start) {
23+
while (fragments.length && start && start.children) {
24+
console.log(start, fragments[0]);
2425
let f = fragments.shift();
25-
start = root.children!.find(i => i.name.split('/').reverse()[0] === f);
26+
start = start.children!.find(i => i.name.split('/').reverse()[0] === f);
27+
}
28+
if (fragments.length == 0) {
29+
return start;
2630
}
27-
return start;
2831
}
2932

3033
export function compose(datas: Ifc5FileJson[]) {
@@ -220,15 +223,13 @@ export function compose(datas: Ifc5FileJson[]) {
220223
}
221224
};
222225

223-
console.log(compositionEdgesUnique);
224-
225226
// Essentially we do an 'interactive' topological sort. Where we process the composition edges for
226227
// those prims that do not have any dependencies left. However, as a consequence of composition,
227228
// novel prim paths can also be formed which can resolve the dependencies for other prims.
228229
let maxIterations = 100;
229230
while (maxIterations --) {
230231
const bottomRankNodes = Object.entries(compositionEdgesUnique).filter(([_, dep]) => dep.size === 0 && (composed[_] || built.has(_) || _.endsWith(' complete'))).map(([k, v]) => k);
231-
console.log('Bottom rank prims to resolve:', ...bottomRankNodes);
232+
// console.log('Bottom rank prims to resolve:', ...bottomRankNodes);
232233

233234
if (bottomRankNodes.length === 0) {
234235
break;
@@ -243,7 +244,7 @@ export function compose(datas: Ifc5FileJson[]) {
243244
// (An array does not really function as a tuple). So we need to reverse engineer
244245
// the type of the edge (and therefore what composition action to apply) based on
245246
// the names of the vertices.
246-
console.log('Processing edge:', k, ' --- ', v);
247+
// console.log('Processing edge:', k, ' --- ', v);
247248
if (k.endsWith(' complete') && v.endsWith(' over')) {
248249
// Only for life cycle dependency management, no action associated
249250
} else if (v.startsWith(k + '/')) {
@@ -307,7 +308,7 @@ export function compose(datas: Ifc5FileJson[]) {
307308
});
308309
});
309310

310-
console.log('Constructed prims:', ...definedPrims);
311+
// console.log('Constructed prims:', ...definedPrims);
311312

312313
Array.from(definedPrims).forEach(a => built.add(a));
313314

@@ -323,6 +324,6 @@ export function compose(datas: Ifc5FileJson[]) {
323324
console.error("Unresolved nodes:", ...Object.keys(compositionEdgesUnique));
324325
}
325326

326-
console.log(composed['']);
327+
// console.log(composed['']);
327328
return composed[''];
328329
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[
2+
{
3+
"def": "def",
4+
"type": "UsdGeom:Xform",
5+
"name": "node1",
6+
"inherits": [
7+
"</node2>"]
8+
},{
9+
"def": "class",
10+
"type": "UsdGeom:Xform",
11+
"name": "node2",
12+
"inherits": [
13+
"</node3>"]
14+
},{
15+
"def": "class",
16+
"type": "UsdGeom:Xform",
17+
"name": "node3"
18+
},{
19+
"def": "over",
20+
"name": "node3",
21+
"attributes": {
22+
"customdata": {
23+
"a": 3
24+
}
25+
}
26+
},{
27+
"def": "over",
28+
"name": "node2",
29+
"attributes": {
30+
"customdata": {
31+
"a": 2
32+
}
33+
}
34+
}
35+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"children": [
3+
{
4+
"attributes": {
5+
"customdata:a": 2
6+
},
7+
"children": [],
8+
"name": "/node1",
9+
"type": "UsdGeom:Xform"
10+
}
11+
],
12+
"name": ""
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[
2+
{
3+
"def": "def",
4+
"type": "UsdGeom:Xform",
5+
"name": "node1",
6+
"inherits": [
7+
"</node2>"]
8+
},{
9+
"def": "def",
10+
"type": "UsdGeom:Xform",
11+
"name": "node2",
12+
"inherits": [
13+
"</node3>"]
14+
},{
15+
"def": "def",
16+
"type": "UsdGeom:Xform",
17+
"name": "node3"
18+
},{
19+
"def": "over",
20+
"name": "node3",
21+
"attributes": {
22+
"customdata": {
23+
"a": 3
24+
}
25+
}
26+
},{
27+
"def": "over",
28+
"name": "node2",
29+
"attributes": {
30+
"customdata": {
31+
"a": 2
32+
}
33+
}
34+
}
35+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"children": [
3+
{
4+
"attributes": {
5+
"customdata:a": 2
6+
},
7+
"children": [],
8+
"name": "/node1",
9+
"type": "UsdGeom:Xform"
10+
},
11+
{
12+
"attributes": {
13+
"customdata:a": 2
14+
},
15+
"children": [],
16+
"name": "/node2",
17+
"type": "UsdGeom:Xform"
18+
},
19+
{
20+
"attributes": {
21+
"customdata:a": 3
22+
},
23+
"children": [],
24+
"name": "/node3",
25+
"type": "UsdGeom:Xform"
26+
}
27+
],
28+
"name": ""
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[
2+
{
3+
"def": "class",
4+
"type": "UsdGeom:Xform",
5+
"name": "lib",
6+
"children": [
7+
{
8+
"def": "def",
9+
"type": "UsdGeom:Xform",
10+
"name": "toilet",
11+
"inherits": [
12+
"</toiletclass>"
13+
]
14+
}
15+
]
16+
},{
17+
"def": "class",
18+
"type": "UsdGeom:Xform",
19+
"name": "toiletclass"
20+
},{
21+
"def": "over",
22+
"name": "toiletclass",
23+
"attributes": {
24+
"customdata": {
25+
"a": 1
26+
}
27+
}
28+
}
29+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[
2+
{
3+
"def": "def",
4+
"type": "UsdGeom:Xform",
5+
"name": "node1",
6+
"inherits": [
7+
"</lib/toilet>"]
8+
}
9+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"children": [
3+
{
4+
"attributes": {
5+
"customdata:a": 1
6+
},
7+
"children": [],
8+
"name": "/node1",
9+
"type": "UsdGeom:Xform"
10+
}
11+
],
12+
"name": ""
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[
2+
{
3+
"def": "def",
4+
"type": "UsdGeom:Xform",
5+
"name": "node1",
6+
"inherits": [
7+
"</node2>",
8+
"</node3>"]
9+
},{
10+
"def": "class",
11+
"type": "UsdGeom:Xform",
12+
"name": "node2"
13+
},{
14+
"def": "class",
15+
"type": "UsdGeom:Xform",
16+
"name": "node3"
17+
},{
18+
"def": "over",
19+
"name": "node3",
20+
"attributes": {
21+
"customdata": {
22+
"a": 1
23+
}
24+
}
25+
},{
26+
"def": "over",
27+
"name": "node2",
28+
"attributes": {
29+
"customdata": {
30+
"b": 2
31+
}
32+
}
33+
}
34+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"children": [
3+
{
4+
"attributes": {
5+
"customdata:a": 1,
6+
"customdata:b": 2
7+
},
8+
"children": [],
9+
"name": "/node1",
10+
"type": "UsdGeom:Xform"
11+
}
12+
],
13+
"name": ""
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[
2+
{
3+
"def": "def",
4+
"type": "UsdGeom:Xform",
5+
"name": "node1",
6+
"children": [{
7+
"def": "def",
8+
"name": "child1",
9+
"inherits": [
10+
"</child1class>"
11+
]
12+
}]
13+
},{
14+
"def": "class",
15+
"type": "UsdGeom:Xform",
16+
"name": "child1class"
17+
},{
18+
"def": "over",
19+
"name": "child1class",
20+
"attributes": {
21+
"customdata": {
22+
"a": 1
23+
}
24+
}
25+
},{
26+
"def": "over",
27+
"name": "/node1/child1",
28+
"attributes": {
29+
"customdata": {
30+
"a": 2
31+
}
32+
}
33+
}
34+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"children": [
3+
{
4+
"children": [{
5+
"name": "/node1/child1",
6+
"type": "UsdGeom:Xform",
7+
"attributes": {
8+
"customdata:a": 1
9+
}
10+
}],
11+
"name": "/node1",
12+
"type": "UsdGeom:Xform"
13+
}
14+
],
15+
"name": ""
16+
}

docs/viewer/test2.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import * as fs from 'fs';
2+
import * as path from 'path';
3+
import * as glob from 'glob';
4+
import { compose } from './compose';
5+
import { compose2 } from './compose2';
6+
7+
let { describe, it } = global;
8+
let composeFuncs = {'compose': compose, 'compose2': compose2};
9+
10+
const fixtureDirectories = glob.sync('test/fixtures/*');
11+
12+
const replacer = (key, value) => {
13+
if (value instanceof Object && !(value instanceof Array)) {
14+
return Object.keys(value)
15+
.sort()
16+
.filter(k => k !== 'def')
17+
.filter(k => k !== 'attributes' || Object.keys(value.attributes || {}).length > 0)
18+
.filter(k => k !== 'children' || (value.children || []).length > 0)
19+
.reduce((sorted, key) => {
20+
sorted[key] = value[key];
21+
return sorted
22+
}, {});
23+
} else if (value instanceof Array) {
24+
return value.toSorted((a, b) => {
25+
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
26+
})
27+
} else {
28+
return value;
29+
}
30+
}
31+
32+
describe('Composition', () => {
33+
describe.each(Object.keys(composeFuncs))('composition function: %s', (compFunc) => {
34+
it.each(fixtureDirectories)('fixture: %s', (fixtureDir) => {
35+
const inputFiles = glob.sync(`${fixtureDir.replace(/\\/g, '/')}/input_*.ifcx`);
36+
expect(inputFiles.length).toBeGreaterThan(0);
37+
const inputs = inputFiles.map((inputFile) => {
38+
return JSON.parse(fs.readFileSync(inputFile, 'utf8'));
39+
});
40+
const actualResult = JSON.stringify(composeFuncs[compFunc](inputs), replacer, 1);
41+
const outputFile = path.join(fixtureDir, 'output.json');
42+
const expectedOutput = JSON.stringify(JSON.parse(fs.readFileSync(outputFile, 'utf8')), replacer, 1);
43+
expect(actualResult).toEqual(expectedOutput);
44+
});
45+
});
46+
});

0 commit comments

Comments
 (0)