From 2eee36bb3f9e81114900804305565720db1c6890 Mon Sep 17 00:00:00 2001 From: Orual Date: Sun, 2 Aug 2026 01:00:57 -0400 Subject: [PATCH] PM-77: build LDraw corpus and oracle harness Epic: PM-86 Task: PM-77 PM-77: finish oracle package and command gates Epic: PM-86 Task: PM-77 PM-77: resolve worker.rs conflict (take epic-86 version) --- .gitignore | 2 + .../corpus/artifact-provenance.json | 20 +- .../adversarial-regressions.expected.json | 2 +- .../expected/bfc-invertnext.expected.json | 2 +- .../expected/colours-ldconfig.expected.json | 2 +- .../expected/conditional-lines.expected.json | 2 +- .../expected/external-ldr-tools.expected.json | 2 +- .../expected/external-thomas.expected.json | 2 +- .../expected/external-weldr.expected.json | 2 +- .../expected/fuzz-regressions.expected.json | 2 +- .../expected/graph-instances.expected.json | 2 +- .../h-conditional-ambiguous.expected.json | 2 +- .../h-conditional-degenerate.expected.json | 2 +- .../h-conditional-interior.expected.json | 2 +- .../h-conditional-invalid.expected.json | 2 +- .../h-conditional-offscreen.expected.json | 2 +- .../h-conditional-visible.expected.json | 2 +- .../corpus/expected/mpd-data.expected.json | 2 +- .../expected/numeric-finiteness.expected.json | 2 +- .../corpus/expected/omr-10030-1.expected.json | 1 + .../expected/path-contexts.expected.json | 2 +- .../corpus/expected/path-policy.expected.json | 2 +- .../expected/profile-matrix.expected.json | 2 +- .../expected/semantic-limits.expected.json | 2 +- .../expected/steps-transforms.expected.json | 2 +- .../expected/syntax-types.expected.json | 2 +- .../corpus/omr-10030-1.mpd | 4711 +++++++++++++++++ .../corpus/steps-transforms.ldr | 5 + crates/polymodel-ldraw-testkit/src/gates.rs | 545 ++ .../polymodel-ldraw-testkit/src/inventory.rs | 450 ++ crates/polymodel-ldraw-testkit/src/lib.rs | 1051 +--- crates/polymodel-ldraw-testkit/src/schema.rs | 279 + crates/polymodel-renderer-ledger/src/lib.rs | 20 +- .../src/load_state.rs | 14 +- flake.nix | 76 + justfile | 12 +- patches/ldparse-gcc15.patch | 10 + patches/ldparse-oracle-access.patch | 13 + src/viewer.rs | 24 +- tools/ldraw-compat-harness/.python-version | 1 - tools/ldraw-compat-harness/README.md | 29 +- tools/ldraw-compat-harness/ldparse_driver.py | 105 - tools/ldraw-compat-harness/pyproject.toml | 8 - tools/ldraw-compat-harness/src/main.rs | 778 ++- tools/ldraw-compat-harness/uv.lock | 8 - .../vendor/ldparse-master/REVISION | 3 - .../vendor/ldparse-modernization/REVISION | 3 - tools/ldraw-oracle/oracle.cpp | 174 + 48 files changed, 6677 insertions(+), 1711 deletions(-) create mode 100644 crates/polymodel-ldraw-testkit/corpus/expected/omr-10030-1.expected.json create mode 100644 crates/polymodel-ldraw-testkit/corpus/omr-10030-1.mpd create mode 100644 crates/polymodel-ldraw-testkit/src/gates.rs create mode 100644 crates/polymodel-ldraw-testkit/src/inventory.rs create mode 100644 crates/polymodel-ldraw-testkit/src/schema.rs create mode 100644 patches/ldparse-gcc15.patch create mode 100644 patches/ldparse-oracle-access.patch delete mode 100644 tools/ldraw-compat-harness/.python-version delete mode 100644 tools/ldraw-compat-harness/ldparse_driver.py delete mode 100644 tools/ldraw-compat-harness/pyproject.toml delete mode 100644 tools/ldraw-compat-harness/uv.lock delete mode 100644 tools/ldraw-compat-harness/vendor/ldparse-master/REVISION delete mode 100644 tools/ldraw-compat-harness/vendor/ldparse-modernization/REVISION create mode 100644 tools/ldraw-oracle/oracle.cpp diff --git a/.gitignore b/.gitignore index 75561a0..63e069f 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ rustc-ice-*.txt !/public/models/box_textured.png !.cargo/ !.cargo/config.toml +target/ unanchored +tools/ldraw-compat-harness/target/ diff --git a/crates/polymodel-ldraw-testkit/corpus/artifact-provenance.json b/crates/polymodel-ldraw-testkit/corpus/artifact-provenance.json index 791770e..7c383bf 100644 --- a/crates/polymodel-ldraw-testkit/corpus/artifact-provenance.json +++ b/crates/polymodel-ldraw-testkit/corpus/artifact-provenance.json @@ -83,7 +83,7 @@ "path": "corpus/steps-transforms.ldr", "source_url": "https://www.ldraw.org/article/218.html", "source_revision": "PM-77-authored-2026-03-09", - "sha256": "cc05ca48001e747ee6374b2079346a1464e45b750a3cdda00510ca58d5eb1787", + "sha256": "1d53cd944b049d52d7f05d06798cc56e93bc53501248e51509a6a309e52ee083", "license": "LDraw.org specification; minimized authored vector", "original_test": "LDraw.org STEP/ROTSTEP specification \u00a72", "modifications": "minimized exact-byte fixture; expected record independently authored from the cited source/spec section", @@ -188,6 +188,17 @@ "modifications": "minimized exact-byte fixture; expected record independently authored from the cited source/spec section", "authority": "observation" }, + { + "id": "omr-10030-1", + "path": "corpus/omr-10030-1.mpd", + "source_url": "https://library.ldraw.org/library/omr/10030-1.mpd", + "source_revision": "OMR catalogue 308 retrieved 2026-08-02; SHA-256 pinned", + "sha256": "64b86baafbc4b5b1c1026017f354eaf4107fd255e07010c46f3921a05ddbdd19", + "license": "CCAL version 2.0; LDraw.org attribution retained", + "original_test": "OMR 10030-1 Imperial Star Destroyer, Roland Dahl [rolandd]", + "modifications": "verbatim MPD download; expected record independently authored for PM-78 graph/MPD coverage", + "authority": "observation" + }, { "id": "h-conditional-visible", "path": "corpus/h-conditional-visible.ldr", @@ -256,10 +267,9 @@ } ], "ldparse_acquisition": { - "status": "blocked", - "source_url": "https://github.com/taliesin/LDParse", + "status": "nix-built differential oracle", + "source_url": "https://github.com/elfprince13/LDParse", "master_revision": "877667417d6cab57c04aed9cb3d5bfe7efa0589c", - "modernization_revision": "0fe78dcee22982f26cceced1b483340faa4d04e9", - "reason": "Pinned repository and archive URLs returned HTTP 404/repository-not-found during implementation; no source bytes are claimed." + "modernization_revision": "0fe78dcee22982f26cceced1b483340faa4d04e9" } } diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json index 607a795..caae777 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-adversarial-regressions","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:adversarial-regressions:0"],"lines":0,"model_id":"adversarial-regressions","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"certified_ccw_invertnext","cache_identity":"cache:adversarial-regressions","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"adversarial-regressions"},"syntax":[{"fields":["0","PM77","adversarial","regressions"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 adversarial regressions","span":{"column":1,"end":31,"line":1,"start":0}},{"fields":["0","unterminated","final","line"],"line_ending":"lf","line_type":0,"raw_tail":"unterminated final line","span":{"column":1,"end":57,"line":2,"start":31}},{"fields":["0","../","traversal","%","backslash",":","query#fragment"],"line_ending":"lf","line_type":0,"raw_tail":"../ traversal % backslash : query#fragment","span":{"column":1,"end":102,"line":3,"start":57}},{"fields":["0","duplicate","FILE","cycle","deep-chain","DATA","truncation"],"line_ending":"lf","line_type":0,"raw_tail":"duplicate FILE cycle deep-chain DATA truncation","span":{"column":1,"end":152,"line":4,"start":102}},{"fields":["0","BFC","INVERTNEXT","blank","malformed"],"line_ending":"lf","line_type":0,"raw_tail":"BFC INVERTNEXT blank malformed","span":{"column":1,"end":185,"line":5,"start":152}}]},"outcome":"cancelled","profile":"lossless"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-adversarial-regressions","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:adversarial-regressions:0"],"lines":0,"model_id":"adversarial-regressions","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"certified_ccw_invertnext","cache_identity":"cache:adversarial-regressions","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"adversarial-regressions","texmap_events":[]},"syntax":[{"fields":["0","PM77","adversarial","regressions"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 adversarial regressions","span":{"column":1,"end":31,"line":1,"start":0}},{"fields":["0","unterminated","final","line"],"line_ending":"lf","line_type":0,"raw_tail":"unterminated final line","span":{"column":1,"end":57,"line":2,"start":31}},{"fields":["0","../","traversal","%","backslash",":","query#fragment"],"line_ending":"lf","line_type":0,"raw_tail":"../ traversal % backslash : query#fragment","span":{"column":1,"end":102,"line":3,"start":57}},{"fields":["0","duplicate","FILE","cycle","deep-chain","DATA","truncation"],"line_ending":"lf","line_type":0,"raw_tail":"duplicate FILE cycle deep-chain DATA truncation","span":{"column":1,"end":152,"line":4,"start":102}},{"fields":["0","BFC","INVERTNEXT","blank","malformed"],"line_ending":"lf","line_type":0,"raw_tail":"BFC INVERTNEXT blank malformed","span":{"column":1,"end":185,"line":5,"start":152}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-adversarial-regressions","model_index":0,"certify":"unknown","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"cancelled","profile":"lossless","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/adversarial-regressions.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/bfc-invertnext.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/bfc-invertnext.expected.json index 760d5c5..f2bd137 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/bfc-invertnext.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/bfc-invertnext.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-bfc-invertnext","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:bfc-invertnext:0"],"lines":0,"model_id":"bfc-invertnext","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:bfc-invertnext","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"bfc-invertnext"},"syntax":[{"fields":["0","BFC","CERTIFY","CCW"],"line_ending":"lf","line_type":0,"raw_tail":"BFC CERTIFY CCW","span":{"column":1,"end":18,"line":1,"start":0}},{"fields":["0","BFC","INVERTNEXT"],"line_ending":"lf","line_type":0,"raw_tail":"BFC INVERTNEXT","span":{"column":1,"end":35,"line":2,"start":18}},{"fields":["3","16","0","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":60,"line":3,"start":35}},{"fields":["0","BFC","NOCERTIFY"],"line_ending":"lf","line_type":0,"raw_tail":"BFC NOCERTIFY","span":{"column":1,"end":76,"line":4,"start":60}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-bfc-invertnext","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:bfc-invertnext:0"],"lines":0,"model_id":"bfc-invertnext","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:bfc-invertnext","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"bfc-invertnext","texmap_events":[]},"syntax":[{"fields":["0","BFC","CERTIFY","CCW"],"line_ending":"lf","line_type":0,"raw_tail":"BFC CERTIFY CCW","span":{"column":1,"end":18,"line":1,"start":0}},{"fields":["0","BFC","INVERTNEXT"],"line_ending":"lf","line_type":0,"raw_tail":"BFC INVERTNEXT","span":{"column":1,"end":35,"line":2,"start":18}},{"fields":["3","16","0","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":60,"line":3,"start":35}},{"fields":["0","BFC","NOCERTIFY"],"line_ending":"lf","line_type":0,"raw_tail":"BFC NOCERTIFY","span":{"column":1,"end":76,"line":4,"start":60}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-bfc-invertnext","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/bfc-invertnext.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/colours-ldconfig.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/colours-ldconfig.expected.json index 9ead66a..3166c81 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/colours-ldconfig.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/colours-ldconfig.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-colours-ldconfig","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:colours-ldconfig:0"],"lines":0,"model_id":"colours-ldconfig","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:part.dat","canonical_path":"part.dat","colour_state":"ldconfig:PMBlue#300;direct:24","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"part.dat"},"syntax":[{"fields":["0","!COLOUR","PMBlue","CODE","300","VALUE","#0057B8","EDGE","#333333","ALPHA","128","LUMINANCE","10"],"line_ending":"lf","line_type":0,"raw_tail":"!COLOUR PMBlue CODE 300 VALUE #0057B8 EDGE #333333 ALPHA 128 LUMINANCE 10\n","span":{"column":1,"end":76,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat\n","span":{"column":1,"end":114,"line":2,"start":76}},{"fields":["1","24","0","0","0","1","0","0","0","1","0","0","0","1","direct.dat"],"line_ending":"lf","line_type":1,"raw_tail":"24 0 0 0 1 0 0 0 1 0 0 0 1 direct.dat\n","span":{"column":1,"end":154,"line":3,"start":114}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-colours-ldconfig","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:colours-ldconfig:0"],"lines":0,"model_id":"colours-ldconfig","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:part.dat","canonical_path":"part.dat","colour_state":"ldconfig:PMBlue#300;direct:24","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"part.dat","texmap_events":[]},"syntax":[{"fields":["0","!COLOUR","PMBlue","CODE","300","VALUE","#0057B8","EDGE","#333333","ALPHA","128","LUMINANCE","10"],"line_ending":"lf","line_type":0,"raw_tail":"!COLOUR PMBlue CODE 300 VALUE #0057B8 EDGE #333333 ALPHA 128 LUMINANCE 10\n","span":{"column":1,"end":76,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat\n","span":{"column":1,"end":114,"line":2,"start":76}},{"fields":["1","24","0","0","0","1","0","0","0","1","0","0","0","1","direct.dat"],"line_ending":"lf","line_type":1,"raw_tail":"24 0 0 0 1 0 0 0 1 0 0 0 1 direct.dat\n","span":{"column":1,"end":154,"line":3,"start":114}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-colours-ldconfig","model_index":0,"certify":"uncertified","local_colors":[{"code":300,"slot":0}],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/colours-ldconfig.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/conditional-lines.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/conditional-lines.expected.json index fc42d57..eac4d2f 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/conditional-lines.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/conditional-lines.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-conditional-lines","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:conditional-lines:0"],"lines":1,"model_id":"conditional-lines","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:conditional-lines","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"conditional-lines"},"syntax":[{"fields":["0","PM77","H-owned","conditional-line","vectors","PM-81"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 H-owned conditional-line vectors PM-81\n","span":{"column":1,"end":46,"line":1,"start":0}},{"fields":["0","Visible","same-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"Visible same-side controls\n","span":{"column":1,"end":75,"line":2,"start":46}},{"fields":["0","SuppressedInterior","opposite-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedInterior opposite-side controls\n","span":{"column":1,"end":119,"line":3,"start":75}},{"fields":["0","SuppressedOffscreen","no","surviving","clip","interval"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedOffscreen no surviving clip interval\n","span":{"column":1,"end":168,"line":4,"start":119}},{"fields":["0","SuppressedAmbiguous","unsafe","w"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedAmbiguous unsafe w\n","span":{"column":1,"end":199,"line":5,"start":168}},{"fields":["0","SuppressedDegenerate","shorter","than","epsilon"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedDegenerate shorter than epsilon\n","span":{"column":1,"end":243,"line":6,"start":199}},{"fields":["0","Invalid","non-finite","homogeneous","input"],"line_ending":"lf","line_type":0,"raw_tail":"Invalid non-finite homogeneous input\n","span":{"column":1,"end":282,"line":7,"start":243}},{"fields":["0","epsilon","below","exact","above;","w_epsilon","below","exact","above"],"line_ending":"lf","line_type":0,"raw_tail":"epsilon below exact above; w_epsilon below exact above\n","span":{"column":1,"end":339,"line":8,"start":282}},{"fields":["5","16","0","0","0","1","1","1","0","0","0","0","1","1","0","1","0","0","1","0","0"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0\n","span":{"column":1,"end":382,"line":9,"start":339}}]},"outcome":"preserved","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-conditional-lines","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:conditional-lines:0"],"lines":1,"model_id":"conditional-lines","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:conditional-lines","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"conditional-lines","texmap_events":[]},"syntax":[{"fields":["0","PM77","H-owned","conditional-line","vectors","PM-81"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 H-owned conditional-line vectors PM-81\n","span":{"column":1,"end":46,"line":1,"start":0}},{"fields":["0","Visible","same-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"Visible same-side controls\n","span":{"column":1,"end":75,"line":2,"start":46}},{"fields":["0","SuppressedInterior","opposite-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedInterior opposite-side controls\n","span":{"column":1,"end":119,"line":3,"start":75}},{"fields":["0","SuppressedOffscreen","no","surviving","clip","interval"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedOffscreen no surviving clip interval\n","span":{"column":1,"end":168,"line":4,"start":119}},{"fields":["0","SuppressedAmbiguous","unsafe","w"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedAmbiguous unsafe w\n","span":{"column":1,"end":199,"line":5,"start":168}},{"fields":["0","SuppressedDegenerate","shorter","than","epsilon"],"line_ending":"lf","line_type":0,"raw_tail":"SuppressedDegenerate shorter than epsilon\n","span":{"column":1,"end":243,"line":6,"start":199}},{"fields":["0","Invalid","non-finite","homogeneous","input"],"line_ending":"lf","line_type":0,"raw_tail":"Invalid non-finite homogeneous input\n","span":{"column":1,"end":282,"line":7,"start":243}},{"fields":["0","epsilon","below","exact","above;","w_epsilon","below","exact","above"],"line_ending":"lf","line_type":0,"raw_tail":"epsilon below exact above; w_epsilon below exact above\n","span":{"column":1,"end":339,"line":8,"start":282}},{"fields":["5","16","0","0","0","1","1","1","0","0","0","0","1","1","0","1","0","0","1","0","0"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0\n","span":{"column":1,"end":382,"line":9,"start":339}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-lines","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/conditional-lines.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json index 8fe4b98..b96d7dd 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-ldr-tools","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-ldr-tools:0"],"lines":0,"model_id":"external-ldr-tools","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-ldr-tools","canonical_path":null,"colour_state":"direct","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-ldr-tools"},"syntax":[{"fields":["0","ldr_tools","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"ldr_tools fixture minimized by PM-77","span":{"column":1,"end":39,"line":1,"start":0}},{"fields":["2","24","0","0","0","10","10","0"],"line_ending":"lf","line_type":2,"raw_tail":"24 0 0 0 10 10 0","span":{"column":1,"end":58,"line":2,"start":39}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-ldr-tools","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-ldr-tools:0"],"lines":0,"model_id":"external-ldr-tools","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-ldr-tools","canonical_path":null,"colour_state":"direct","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-ldr-tools","texmap_events":[]},"syntax":[{"fields":["0","ldr_tools","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"ldr_tools fixture minimized by PM-77","span":{"column":1,"end":39,"line":1,"start":0}},{"fields":["2","24","0","0","0","10","10","0"],"line_ending":"lf","line_type":2,"raw_tail":"24 0 0 0 10 10 0","span":{"column":1,"end":58,"line":2,"start":39}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-external-ldr-tools","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":"Accepted as observation for this corpus row."},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":"Accepted as observation for this corpus row."},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-ldr-tools.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json index e2cf719..80cd403 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-thomas","scene":{"bounds":["0","0","0","20","20","20"],"instance_ids":["instance:external-thomas:0"],"lines":0,"model_id":"external-thomas","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-thomas","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-thomas"},"syntax":[{"fields":["0","Thomas","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"Thomas fixture minimized by PM-77","span":{"column":1,"end":36,"line":1,"start":0}},{"fields":["0","!LDRAW_ORG","Unofficial_Model"],"line_ending":"lf","line_type":0,"raw_tail":"!LDRAW_ORG Unofficial_Model","span":{"column":1,"end":66,"line":2,"start":36}},{"fields":["3","16","0","0","0","20","0","0","0","20","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 20 0 0 0 20 0","span":{"column":1,"end":91,"line":3,"start":66}}]},"outcome":"accepted","profile":"compatibility"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-thomas","scene":{"bounds":["0","0","0","20","20","20"],"instance_ids":["instance:external-thomas:0"],"lines":0,"model_id":"external-thomas","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-thomas","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-thomas","texmap_events":[]},"syntax":[{"fields":["0","Thomas","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"Thomas fixture minimized by PM-77","span":{"column":1,"end":36,"line":1,"start":0}},{"fields":["0","!LDRAW_ORG","Unofficial_Model"],"line_ending":"lf","line_type":0,"raw_tail":"!LDRAW_ORG Unofficial_Model","span":{"column":1,"end":66,"line":2,"start":36}},{"fields":["3","16","0","0","0","20","0","0","0","20","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 20 0 0 0 20 0","span":{"column":1,"end":91,"line":3,"start":66}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-external-thomas","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"compatibility","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":"Accepted as observation for this corpus row."},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":"Accepted as observation for this corpus row."},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-thomas.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json index ac3a1bd..9bffc01 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-weldr","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-weldr:0"],"lines":0,"model_id":"external-weldr","reflection":false,"triangles":2},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-weldr","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-weldr"},"syntax":[{"fields":["0","weldr","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"weldr fixture minimized by PM-77","span":{"column":1,"end":35,"line":1,"start":0}},{"fields":["4","4","0","0","0","10","0","0","10","10","0","0","10","0","0"],"line_ending":"lf","line_type":4,"raw_tail":"4 0 0 0 10 0 0 10 10 0 0 10 0 0","span":{"column":1,"end":69,"line":2,"start":35}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-weldr","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-weldr:0"],"lines":0,"model_id":"external-weldr","reflection":false,"triangles":2},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-weldr","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-weldr","texmap_events":[]},"syntax":[{"fields":["0","weldr","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"weldr fixture minimized by PM-77","span":{"column":1,"end":35,"line":1,"start":0}},{"fields":["4","4","0","0","0","10","0","0","10","10","0","0","10","0","0"],"line_ending":"lf","line_type":4,"raw_tail":"4 0 0 0 10 0 0 10 10 0 0 10 0 0","span":{"column":1,"end":69,"line":2,"start":35}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-external-weldr","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":"Accepted as observation for this corpus row."},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":"Accepted as observation for this corpus row."},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/external-weldr.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json index 7b13b04..4dec162 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-fuzz-regressions","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:fuzz-regressions:0"],"lines":0,"model_id":"fuzz-regressions","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:cycle.ldr","canonical_path":"cycle.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"cycle.ldr"},"syntax":[{"fields":["0","PM77","bounded","fuzz","regression","corpus"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 bounded fuzz regression corpus","span":{"column":1,"end":38,"line":1,"start":0}},{"fields":["0","whitespace","tabs","and","CRLF"],"line_ending":"crlf","line_type":0,"raw_tail":"whitespace tabs and CRLF","span":{"column":1,"end":66,"line":2,"start":38}},{"fields":["3","16","-0","1e-3","0","1","0","0","0","1","0","0"],"line_ending":"crlf","line_type":3,"raw_tail":"16 -0 1e-3 0 1 0 0 0 1 0 0","span":{"column":1,"end":96,"line":3,"start":66}},{"fields":["0","FILE","cycle.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE cycle.ldr","span":{"column":1,"end":113,"line":4,"start":96}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","cycle.ldr"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 cycle.ldr","span":{"column":1,"end":152,"line":5,"start":113}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":161,"line":6,"start":152}},{"fields":["0","FILE","../escape.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE ../escape.ldr","span":{"column":1,"end":182,"line":7,"start":161}},{"fields":["0","!DATA","truncated"],"line_ending":"lf","line_type":0,"raw_tail":"!DATA truncated","span":{"column":1,"end":200,"line":8,"start":182}}]},"outcome":"rejected","profile":"lossless"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-fuzz-regressions","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:fuzz-regressions:0"],"lines":0,"model_id":"fuzz-regressions","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:cycle.ldr","canonical_path":"cycle.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"cycle.ldr","texmap_events":[]},"syntax":[{"fields":["0","PM77","bounded","fuzz","regression","corpus"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 bounded fuzz regression corpus","span":{"column":1,"end":38,"line":1,"start":0}},{"fields":["0","whitespace","tabs","and","CRLF"],"line_ending":"crlf","line_type":0,"raw_tail":"whitespace tabs and CRLF","span":{"column":1,"end":66,"line":2,"start":38}},{"fields":["3","16","-0","1e-3","0","1","0","0","0","1","0","0"],"line_ending":"crlf","line_type":3,"raw_tail":"16 -0 1e-3 0 1 0 0 0 1 0 0","span":{"column":1,"end":96,"line":3,"start":66}},{"fields":["0","FILE","cycle.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE cycle.ldr","span":{"column":1,"end":113,"line":4,"start":96}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","cycle.ldr"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 cycle.ldr","span":{"column":1,"end":152,"line":5,"start":113}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":161,"line":6,"start":152}},{"fields":["0","FILE","../escape.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE ../escape.ldr","span":{"column":1,"end":182,"line":7,"start":161}},{"fields":["0","!DATA","truncated"],"line_ending":"lf","line_type":0,"raw_tail":"!DATA truncated","span":{"column":1,"end":200,"line":8,"start":182}}],"oracle_projection":{"status":"ok","models":[{"name":"cycle.ldr","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"../escape.ldr","model_index":1,"certify":"unknown","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"rejected","profile":"lossless","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/fuzz-regressions.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/graph-instances.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/graph-instances.expected.json index 17a47a3..1252a14 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/graph-instances.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/graph-instances.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-graph-instances","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:graph-instances:0"],"lines":0,"model_id":"graph-instances","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:root.ldr","canonical_path":"root.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"root.ldr"},"syntax":[{"fields":["0","FILE","root.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE root.ldr","span":{"column":1,"end":16,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","child.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 child.dat","span":{"column":1,"end":55,"line":2,"start":16}},{"fields":["1","16","10","0","0","1","0","0","0","1","0","0","0","1","child.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 10 0 0 1 0 0 0 1 0 0 0 1 child.dat","span":{"column":1,"end":95,"line":3,"start":55}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":104,"line":4,"start":95}},{"fields":["0","FILE","child.dat"],"line_ending":"lf","line_type":0,"raw_tail":"FILE child.dat","span":{"column":1,"end":121,"line":5,"start":104}},{"fields":["3","16","0","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":146,"line":6,"start":121}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":155,"line":7,"start":146}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-graph-instances","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:graph-instances:0"],"lines":0,"model_id":"graph-instances","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:root.ldr","canonical_path":"root.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"root.ldr","texmap_events":[]},"syntax":[{"fields":["0","FILE","root.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE root.ldr","span":{"column":1,"end":16,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","child.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 child.dat","span":{"column":1,"end":55,"line":2,"start":16}},{"fields":["1","16","10","0","0","1","0","0","0","1","0","0","0","1","child.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 10 0 0 1 0 0 0 1 0 0 0 1 child.dat","span":{"column":1,"end":95,"line":3,"start":55}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":104,"line":4,"start":95}},{"fields":["0","FILE","child.dat"],"line_ending":"lf","line_type":0,"raw_tail":"FILE child.dat","span":{"column":1,"end":121,"line":5,"start":104}},{"fields":["3","16","0","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":146,"line":6,"start":121}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":155,"line":7,"start":146}}],"oracle_projection":{"status":"ok","models":[{"name":"root.ldr","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"child.dat","model_index":1,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/graph-instances.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-ambiguous.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-ambiguous.expected.json index 3bc658b..7fc010a 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-ambiguous.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-ambiguous.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-ambiguous","scene":{"bounds":["-0.0000001","-0.0000001","-0.0000001","10","10","10"],"instance_ids":["instance:h-conditional-ambiguous:0"],"lines":1,"model_id":"h-conditional-ambiguous","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-ambiguous","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-ambiguous"},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedAmbiguous","unsafe","w"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedAmbiguous unsafe w\n","span":{"column":1,"end":51,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","1","0","0","-0.0000001","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 1 0 0 -0.0000001 0 0 0 1 0 0 1\n","span":{"column":1,"end":105,"line":2,"start":51}}]},"outcome":"preserved","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-ambiguous","scene":{"bounds":["-0.0000001","-0.0000001","-0.0000001","10","10","10"],"instance_ids":["instance:h-conditional-ambiguous:0"],"lines":1,"model_id":"h-conditional-ambiguous","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-ambiguous","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-ambiguous","texmap_events":[]},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedAmbiguous","unsafe","w"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedAmbiguous unsafe w\n","span":{"column":1,"end":51,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","1","0","0","-0.0000001","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 1 0 0 -0.0000001 0 0 0 1 0 0 1\n","span":{"column":1,"end":105,"line":2,"start":51}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-ambiguous","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-ambiguous.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-degenerate.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-degenerate.expected.json index 44f2b75..5b5a4e8 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-degenerate.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-degenerate.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-degenerate","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:h-conditional-degenerate:0"],"lines":1,"model_id":"h-conditional-degenerate","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-degenerate","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-degenerate"},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedDegenerate","epsilon","boundary"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedDegenerate epsilon boundary\n","span":{"column":1,"end":60,"line":1,"start":0}},{"fields":["5","16","0","0","0","0.000001","0","0","0","0","1","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 0.000001 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":110,"line":2,"start":60}}]},"outcome":"preserved","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-degenerate","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:h-conditional-degenerate:0"],"lines":1,"model_id":"h-conditional-degenerate","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-degenerate","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-degenerate","texmap_events":[]},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedDegenerate","epsilon","boundary"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedDegenerate epsilon boundary\n","span":{"column":1,"end":60,"line":1,"start":0}},{"fields":["5","16","0","0","0","0.000001","0","0","0","0","1","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 0.000001 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":110,"line":2,"start":60}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-degenerate","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-degenerate.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-interior.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-interior.expected.json index bb19f56..8272b4e 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-interior.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-interior.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-interior","scene":{"bounds":["-1","-1","-1","10","10","10"],"instance_ids":["instance:h-conditional-interior:0"],"lines":1,"model_id":"h-conditional-interior","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-interior","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-interior"},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedInterior","opposite-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedInterior opposite-side controls\n","span":{"column":1,"end":64,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","-1","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 -1 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":110,"line":2,"start":64}}]},"outcome":"preserved","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-interior","scene":{"bounds":["-1","-1","-1","10","10","10"],"instance_ids":["instance:h-conditional-interior:0"],"lines":1,"model_id":"h-conditional-interior","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-interior","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-interior","texmap_events":[]},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedInterior","opposite-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedInterior opposite-side controls\n","span":{"column":1,"end":64,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","-1","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 -1 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":110,"line":2,"start":64}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-interior","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-interior.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-invalid.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-invalid.expected.json index 2b59af0..6fdd451 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-invalid.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-invalid.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-NONFINITE","message":"non-finite numeric token","severity":"error","span":{"column":1,"end":106,"line":2,"start":59}}],"provenance_id":"pm77-h-conditional-invalid","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:h-conditional-invalid:0"],"lines":1,"model_id":"h-conditional-invalid","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-invalid","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-invalid"},"syntax":[{"fields":["0","H/PM-81","conditional","Invalid","non-finite","homogeneous","input"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional Invalid non-finite homogeneous input\n","span":{"column":1,"end":59,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","nan","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 nan 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":106,"line":2,"start":59}}]},"outcome":"rejected","profile":"strict"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-NONFINITE","message":"non-finite numeric token","severity":"error","span":{"column":1,"end":106,"line":2,"start":59}}],"provenance_id":"pm77-h-conditional-invalid","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:h-conditional-invalid:0"],"lines":1,"model_id":"h-conditional-invalid","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-invalid","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-invalid","texmap_events":[]},"syntax":[{"fields":["0","H/PM-81","conditional","Invalid","non-finite","homogeneous","input"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional Invalid non-finite homogeneous input\n","span":{"column":1,"end":59,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","nan","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 nan 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":106,"line":2,"start":59}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-invalid","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"rejected","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-invalid.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-offscreen.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-offscreen.expected.json index 8c06451..3020880 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-offscreen.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-offscreen.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-offscreen","scene":{"bounds":["0","0","0","210","210","210"],"instance_ids":["instance:h-conditional-offscreen:0"],"lines":1,"model_id":"h-conditional-offscreen","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-offscreen","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-offscreen"},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedOffscreen","no","clip","interval"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedOffscreen no clip interval\n","span":{"column":1,"end":59,"line":1,"start":0}},{"fields":["5","16","200","200","0","210","200","0","0","0","1","0","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 200 200 0 210 200 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":112,"line":2,"start":59}}]},"outcome":"preserved","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-offscreen","scene":{"bounds":["0","0","0","210","210","210"],"instance_ids":["instance:h-conditional-offscreen:0"],"lines":1,"model_id":"h-conditional-offscreen","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-offscreen","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-offscreen","texmap_events":[]},"syntax":[{"fields":["0","H/PM-81","conditional","SuppressedOffscreen","no","clip","interval"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional SuppressedOffscreen no clip interval\n","span":{"column":1,"end":59,"line":1,"start":0}},{"fields":["5","16","200","200","0","210","200","0","0","0","1","0","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 200 200 0 210 200 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":112,"line":2,"start":59}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-offscreen","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-offscreen.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-visible.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-visible.expected.json index c37d1e5..15500ba 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-visible.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/h-conditional-visible.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-visible","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:h-conditional-visible:0"],"lines":1,"model_id":"h-conditional-visible","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-visible","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-visible"},"syntax":[{"fields":["0","H/PM-81","conditional","Visible","same-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional Visible same-side controls\n","span":{"column":1,"end":49,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","1","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 1 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":94,"line":2,"start":49}}]},"outcome":"preserved","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-h-conditional-visible","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:h-conditional-visible:0"],"lines":1,"model_id":"h-conditional-visible","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:h-conditional-visible","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"h-conditional-visible","texmap_events":[]},"syntax":[{"fields":["0","H/PM-81","conditional","Visible","same-side","controls"],"line_ending":"lf","line_type":0,"raw_tail":"H/PM-81 conditional Visible same-side controls\n","span":{"column":1,"end":49,"line":1,"start":0}},{"fields":["5","16","0","0","0","10","0","0","0","10","1","0","0","1","0","0","0","1","0","0","1"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 10 0 0 0 10 1 0 0 1 0 0 0 1 0 0 1\n","span":{"column":1,"end":94,"line":2,"start":49}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-h-conditional-visible","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/h-conditional-visible.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/mpd-data.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/mpd-data.expected.json index 6e378b4..554725a 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/mpd-data.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/mpd-data.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-mpd-data","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:mpd-data:0"],"lines":0,"model_id":"mpd-data","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:main.ldr","canonical_path":"main.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"main.ldr"},"syntax":[{"fields":["0","FILE","main.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE main.ldr","span":{"column":1,"end":16,"line":1,"start":0}},{"fields":["0","!DATA","payload"],"line_ending":"lf","line_type":0,"raw_tail":"!DATA payload","span":{"column":1,"end":32,"line":2,"start":16}},{"fields":["SGVsbG8="],"line_ending":"lf","line_type":0,"raw_tail":"","span":{"column":1,"end":41,"line":3,"start":32}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":50,"line":4,"start":41}},{"fields":["0","FILE","child.dat"],"line_ending":"lf","line_type":0,"raw_tail":"FILE child.dat","span":{"column":1,"end":67,"line":5,"start":50}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat","span":{"column":1,"end":105,"line":6,"start":67}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":114,"line":7,"start":105}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-mpd-data","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:mpd-data:0"],"lines":0,"model_id":"mpd-data","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:main.ldr","canonical_path":"main.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"main.ldr","texmap_events":[]},"syntax":[{"fields":["0","FILE","main.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE main.ldr","span":{"column":1,"end":16,"line":1,"start":0}},{"fields":["0","!DATA","payload"],"line_ending":"lf","line_type":0,"raw_tail":"!DATA payload","span":{"column":1,"end":32,"line":2,"start":16}},{"fields":["SGVsbG8="],"line_ending":"lf","line_type":0,"raw_tail":"","span":{"column":1,"end":41,"line":3,"start":32}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":50,"line":4,"start":41}},{"fields":["0","FILE","child.dat"],"line_ending":"lf","line_type":0,"raw_tail":"FILE child.dat","span":{"column":1,"end":67,"line":5,"start":50}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat","span":{"column":1,"end":105,"line":6,"start":67}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":114,"line":7,"start":105}}],"oracle_projection":{"status":"ok","models":[{"name":"main.ldr","model_index":0,"certify":"unknown","local_colors":[],"step_count":0},{"name":"child.dat","model_index":1,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/mpd-data.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/numeric-finiteness.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/numeric-finiteness.expected.json index 1f8d22f..b18f0e4 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/numeric-finiteness.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/numeric-finiteness.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-FIELD-COUNT","message":"primitive has too few fields","severity":"error","span":{"column":1,"end":85,"line":2,"start":32}},{"code":"E-LDRAW-NONFINITE","message":"non-finite numeric token","severity":"error","span":{"column":1,"end":112,"line":3,"start":85}}],"provenance_id":"pm77-numeric-finiteness","scene":{"bounds":["0","0","0","340282350000000000000000000000000000000","340282350000000000000000000000000000000","340282350000000000000000000000000000000"],"instance_ids":["instance:numeric-finiteness:0"],"lines":0,"model_id":"numeric-finiteness","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:numeric-finiteness","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"numeric-finiteness"},"syntax":[{"fields":["0","PM77","numeric","raw","preservation"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 numeric raw preservation","span":{"column":1,"end":32,"line":1,"start":0}},{"fields":["2","16","-0","1e-3","340282350000000000000000000000000000000"],"line_ending":"lf","line_type":2,"raw_tail":"16 -0 1e-3 340282350000000000000000000000000000000","span":{"column":1,"end":85,"line":2,"start":32}},{"fields":["3","16","nan","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 nan 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":112,"line":3,"start":85}}]},"outcome":"rejected","profile":"lossless"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-FIELD-COUNT","message":"primitive has too few fields","severity":"error","span":{"column":1,"end":85,"line":2,"start":32}},{"code":"E-LDRAW-NONFINITE","message":"non-finite numeric token","severity":"error","span":{"column":1,"end":112,"line":3,"start":85}}],"provenance_id":"pm77-numeric-finiteness","scene":{"bounds":["0","0","0","340282350000000000000000000000000000000","340282350000000000000000000000000000000","340282350000000000000000000000000000000"],"instance_ids":["instance:numeric-finiteness:0"],"lines":0,"model_id":"numeric-finiteness","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:numeric-finiteness","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"numeric-finiteness","texmap_events":[]},"syntax":[{"fields":["0","PM77","numeric","raw","preservation"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 numeric raw preservation","span":{"column":1,"end":32,"line":1,"start":0}},{"fields":["2","16","-0","1e-3","340282350000000000000000000000000000000"],"line_ending":"lf","line_type":2,"raw_tail":"16 -0 1e-3 340282350000000000000000000000000000000","span":{"column":1,"end":85,"line":2,"start":32}},{"fields":["3","16","nan","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 nan 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":112,"line":3,"start":85}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-numeric-finiteness","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"rejected","profile":"lossless","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/numeric-finiteness.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/omr-10030-1.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/omr-10030-1.expected.json new file mode 100644 index 0000000..864022d --- /dev/null +++ b/crates/polymodel-ldraw-testkit/corpus/expected/omr-10030-1.expected.json @@ -0,0 +1 @@ +{"canonical":{"diagnostics":[],"provenance_id":"pm77-omr-10030-1","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:omr-10030-1:0"],"lines":0,"model_id":"omr-10030-1","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:3297.dat","canonical_path":"3297.dat","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"3297.dat","texmap_events":[]},"syntax":[],"oracle_projection":{"status":"ok","models":[{"name":"10030 - main.ldr","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-1.ldr","model_index":1,"certify":"uncertified","local_colors":[],"step_count":38},{"name":"10030 - subModel-2.ldr","model_index":2,"certify":"uncertified","local_colors":[],"step_count":7},{"name":"10030 - subModel-3.ldr","model_index":3,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-4.ldr","model_index":4,"certify":"uncertified","local_colors":[],"step_count":2},{"name":"10030 - subModel-5.ldr","model_index":5,"certify":"uncertified","local_colors":[],"step_count":4},{"name":"10030 - subModel-6.ldr","model_index":6,"certify":"uncertified","local_colors":[],"step_count":4},{"name":"10030 - subModel-7.ldr","model_index":7,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-8.ldr","model_index":8,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-9.ldr","model_index":9,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-10.ldr","model_index":10,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-11.ldr","model_index":11,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-12.ldr","model_index":12,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-13.ldr","model_index":13,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-14.ldr","model_index":14,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-15.ldr","model_index":15,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-16.ldr","model_index":16,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-17.ldr","model_index":17,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-18.ldr","model_index":18,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-19.ldr","model_index":19,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-20.ldr","model_index":20,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-21.ldr","model_index":21,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-22.ldr","model_index":22,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-23.ldr","model_index":23,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-24.ldr","model_index":24,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-25.ldr","model_index":25,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-26.ldr","model_index":26,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-27.ldr","model_index":27,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-28.ldr","model_index":28,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-29.ldr","model_index":29,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-30.ldr","model_index":30,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-31.ldr","model_index":31,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-32.ldr","model_index":32,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-33.ldr","model_index":33,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-34.ldr","model_index":34,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-35.ldr","model_index":35,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-36.ldr","model_index":36,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-37.ldr","model_index":37,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-38.ldr","model_index":38,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-39.ldr","model_index":39,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-40.ldr","model_index":40,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-41.ldr","model_index":41,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-42.ldr","model_index":42,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-43.ldr","model_index":43,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-44.ldr","model_index":44,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-45.ldr","model_index":45,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-46.ldr","model_index":46,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-47.ldr","model_index":47,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-48.ldr","model_index":48,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-49.ldr","model_index":49,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-50.ldr","model_index":50,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-51.ldr","model_index":51,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-52.ldr","model_index":52,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-53.ldr","model_index":53,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-54.ldr","model_index":54,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-55.ldr","model_index":55,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-56.ldr","model_index":56,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-57.ldr","model_index":57,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-58.ldr","model_index":58,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-59.ldr","model_index":59,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-60.ldr","model_index":60,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-61.ldr","model_index":61,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-62.ldr","model_index":62,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-63.ldr","model_index":63,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-64.ldr","model_index":64,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-65.ldr","model_index":65,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-66.ldr","model_index":66,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-67.ldr","model_index":67,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-68.ldr","model_index":68,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-69.ldr","model_index":69,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-70.ldr","model_index":70,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-71.ldr","model_index":71,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-72.ldr","model_index":72,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-73.ldr","model_index":73,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-74.ldr","model_index":74,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-75.ldr","model_index":75,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-76.ldr","model_index":76,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-77.ldr","model_index":77,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-78.ldr","model_index":78,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-79.ldr","model_index":79,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-80.ldr","model_index":80,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-81.ldr","model_index":81,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-82.ldr","model_index":82,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-83.ldr","model_index":83,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-84.ldr","model_index":84,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-85.ldr","model_index":85,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-86.ldr","model_index":86,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-87.ldr","model_index":87,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-88.ldr","model_index":88,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-89.ldr","model_index":89,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-90.ldr","model_index":90,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-91.ldr","model_index":91,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-92.ldr","model_index":92,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-93.ldr","model_index":93,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-94.ldr","model_index":94,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-95.ldr","model_index":95,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-96.ldr","model_index":96,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-97.ldr","model_index":97,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-98.ldr","model_index":98,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-99.ldr","model_index":99,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-100.ldr","model_index":100,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-101.ldr","model_index":101,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-102.ldr","model_index":102,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-103.ldr","model_index":103,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-104.ldr","model_index":104,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-105.ldr","model_index":105,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-106.ldr","model_index":106,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-107.ldr","model_index":107,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-108.ldr","model_index":108,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-109.ldr","model_index":109,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-110.ldr","model_index":110,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-111.ldr","model_index":111,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-112.ldr","model_index":112,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-113.ldr","model_index":113,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-114.ldr","model_index":114,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-115.ldr","model_index":115,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-116.ldr","model_index":116,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-117.ldr","model_index":117,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-118.ldr","model_index":118,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-119.ldr","model_index":119,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-120.ldr","model_index":120,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-121.ldr","model_index":121,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-122.ldr","model_index":122,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-123.ldr","model_index":123,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-124.ldr","model_index":124,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-125.ldr","model_index":125,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-126.ldr","model_index":126,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-127.ldr","model_index":127,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-128.ldr","model_index":128,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-129.ldr","model_index":129,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-130.ldr","model_index":130,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-131.ldr","model_index":131,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-132.ldr","model_index":132,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-133.ldr","model_index":133,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-134.ldr","model_index":134,"certify":"uncertified","local_colors":[],"step_count":0},{"name":"10030 - subModel-135.ldr","model_index":135,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"compatibility","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:syntax","basis":"External observation fixture; the complete raw MPD is retained verbatim at corpus/omr-10030-1.mpd and its graph markers were independently inspected from the 4,711-line byte stream.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:diagnostics","basis":"Direct inspection found no malformed numeric tokens, TEXMAP/DATA directives, or profile-policy error markers in the downloaded MPD; the authored observation record therefore has an empty diagnostic list.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:bfc_state","basis":"No BFC CERTIFY, NOCERTIFY, or INVERTNEXT directive occurs in the inspected MPD; the initial file-local state remains uncertified.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:bounds","basis":"The MPD contains 2,450 type-1 references and no type-2/3/4/5 primitive records; the graph-only projection therefore has the neutral six-axis bounds [0,0,0,0,0,0].","decision":null},{"field":"graph","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:graph","basis":"PM-75 graph/MPD contract, derived from the raw FILE sequence: 136 unique FILE blocks, beginning `10030 - main.ldr` and ending `10030 - subModel-135.ldr`, with 2,450 type-1 references and stable root model identity `omr-10030-1` / instance `instance:omr-10030-1:0`.","decision":"Accepted as observation for this corpus row."},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:colour_state","basis":"No !COLOUR directive was found in the raw MPD; the initial colour state remains current.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; direct inspection found no !TEXMAP START, NEXT, FALLBACK, or STOP directive, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:steps","basis":"The authored record uses the canonical initial step marker for this graph-focused observation; STEP/ROTSTEP interpretation is outside the applied graph gate.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:limits","basis":"The raw artifact is below the PM-77 resource/line/command limits and contains no limit or cancellation marker; the authored limits list is empty.","decision":null},{"field":"provenance","authority":"observation","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:provenance","basis":"artifact-provenance.json entry `omr-10030-1`, the OMR catalogue/source URLs, CCAL 2.0 attribution, and the supplied exact SHA-256 bind this record to the verbatim download.","decision":"Accepted as observation for this corpus row."},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:outcome","basis":"The inventory declares the OMR observation under the compatibility profile and the graph projection is accepted without diagnostics.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/omr-10030-1.expected.json:profile","basis":"Inventory declaration selects the compatibility profile for this external observation fixture.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/path-contexts.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/path-contexts.expected.json index 7d4ce79..023ab31 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/path-contexts.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/path-contexts.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-path-contexts","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:path-contexts:0"],"lines":0,"model_id":"path-contexts","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:shadowed.dat","canonical_path":"shadowed.dat","colour_state":"current","limits":[],"root_identity":"pinned-official-library","steps":["step-0"],"target_identity":"shadowed.dat"},"syntax":[{"fields":["0","PM77","path","contexts;","each","row","is","an","authored","resolver-policy","vector"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 path contexts; each row is an authored resolver-policy vector\n","span":{"column":1,"end":69,"line":1,"start":0}},{"fields":["0","FILE","shadowed.dat"],"line_ending":"lf","line_type":0,"raw_tail":"FILE shadowed.dat\n","span":{"column":1,"end":89,"line":2,"start":69}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","parts/shadowed.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 parts/shadowed.dat\n","span":{"column":1,"end":137,"line":3,"start":89}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE\n","span":{"column":1,"end":146,"line":4,"start":137}},{"fields":["0","context=mpd","root=mpd-virtual","shadow=external","exact-case","target=shadowed.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=mpd root=mpd-virtual shadow=external exact-case target=shadowed.dat\n","span":{"column":1,"end":224,"line":5,"start":146}},{"fields":["0","context=mpd","collision=duplicate-name","forbidden=shadowed.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=mpd collision=duplicate-name forbidden=shadowed.dat\n","span":{"column":1,"end":286,"line":6,"start":224}},{"fields":["0","context=manifest","root=uploaded-manifest","directory=relative","duplicate-canonical-key","target=parts/part.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=manifest root=uploaded-manifest directory=relative duplicate-canonical-key target=parts/part.dat\n","span":{"column":1,"end":393,"line":7,"start":286}},{"fields":["0","context=manifest","forbidden=%25part.dat","out-of-root=../escape.dat","controls=\\tpart.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=manifest forbidden=%25part.dat out-of-root=../escape.dat controls=\\tpart.dat\n","span":{"column":1,"end":480,"line":8,"start":393}},{"fields":["0","context=uploaded-roots","root=models","explicit=s/","no-fallback","target=s/part.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=uploaded-roots root=models explicit=s/ no-fallback target=s/part.dat\n","span":{"column":1,"end":559,"line":9,"start":480}},{"fields":["0","context=uploaded-roots","explicit=8/","collision=PARTS/part.dat","ascii-fold=parts/PART.DAT"],"line_ending":"lf","line_type":0,"raw_tail":"context=uploaded-roots explicit=8/ collision=PARTS/part.dat ascii-fold=parts/PART.DAT\n","span":{"column":1,"end":647,"line":10,"start":559}},{"fields":["0","context=uploaded-roots","forbidden=\\\\part.dat","empty=.","dotdot=../part.dat","colon=C:part.dat","query=part.dat?x","fragment=part.dat#x"],"line_ending":"lf","line_type":0,"raw_tail":"context=uploaded-roots forbidden=\\\\part.dat empty=. dotdot=../part.dat colon=C:part.dat query=part.dat?x fragment=part.dat#x\n","span":{"column":1,"end":774,"line":11,"start":647}},{"fields":["0","context=official-library","root=pinned-official-library","target=parts/part.dat","canonical=PARTS/part.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=official-library root=pinned-official-library target=parts/part.dat canonical=PARTS/part.dat\n","span":{"column":1,"end":877,"line":12,"start":774}},{"fields":["0","context=official-library","explicit=48/","no-fallback","target=48/part.dat","ascii-fold-collision=Parts/PART.DAT"],"line_ending":"lf","line_type":0,"raw_tail":"context=official-library explicit=48/ no-fallback target=48/part.dat ascii-fold-collision=Parts/PART.DAT\n","span":{"column":1,"end":984,"line":13,"start":877}},{"fields":["0","context=official-library","ingestion-invalidation=revision-sha256"],"line_ending":"lf","line_type":0,"raw_tail":"context=official-library ingestion-invalidation=revision-sha256\n","span":{"column":1,"end":1050,"line":14,"start":984}}]},"outcome":"accepted","profile":"compatibility"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-path-contexts","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:path-contexts:0"],"lines":0,"model_id":"path-contexts","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:shadowed.dat","canonical_path":"shadowed.dat","colour_state":"current","limits":[],"root_identity":"pinned-official-library","steps":["step-0"],"target_identity":"shadowed.dat","texmap_events":[]},"syntax":[{"fields":["0","PM77","path","contexts;","each","row","is","an","authored","resolver-policy","vector"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 path contexts; each row is an authored resolver-policy vector\n","span":{"column":1,"end":69,"line":1,"start":0}},{"fields":["0","FILE","shadowed.dat"],"line_ending":"lf","line_type":0,"raw_tail":"FILE shadowed.dat\n","span":{"column":1,"end":89,"line":2,"start":69}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","parts/shadowed.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 parts/shadowed.dat\n","span":{"column":1,"end":137,"line":3,"start":89}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE\n","span":{"column":1,"end":146,"line":4,"start":137}},{"fields":["0","context=mpd","root=mpd-virtual","shadow=external","exact-case","target=shadowed.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=mpd root=mpd-virtual shadow=external exact-case target=shadowed.dat\n","span":{"column":1,"end":224,"line":5,"start":146}},{"fields":["0","context=mpd","collision=duplicate-name","forbidden=shadowed.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=mpd collision=duplicate-name forbidden=shadowed.dat\n","span":{"column":1,"end":286,"line":6,"start":224}},{"fields":["0","context=manifest","root=uploaded-manifest","directory=relative","duplicate-canonical-key","target=parts/part.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=manifest root=uploaded-manifest directory=relative duplicate-canonical-key target=parts/part.dat\n","span":{"column":1,"end":393,"line":7,"start":286}},{"fields":["0","context=manifest","forbidden=%25part.dat","out-of-root=../escape.dat","controls=\\tpart.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=manifest forbidden=%25part.dat out-of-root=../escape.dat controls=\\tpart.dat\n","span":{"column":1,"end":480,"line":8,"start":393}},{"fields":["0","context=uploaded-roots","root=models","explicit=s/","no-fallback","target=s/part.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=uploaded-roots root=models explicit=s/ no-fallback target=s/part.dat\n","span":{"column":1,"end":559,"line":9,"start":480}},{"fields":["0","context=uploaded-roots","explicit=8/","collision=PARTS/part.dat","ascii-fold=parts/PART.DAT"],"line_ending":"lf","line_type":0,"raw_tail":"context=uploaded-roots explicit=8/ collision=PARTS/part.dat ascii-fold=parts/PART.DAT\n","span":{"column":1,"end":647,"line":10,"start":559}},{"fields":["0","context=uploaded-roots","forbidden=\\\\part.dat","empty=.","dotdot=../part.dat","colon=C:part.dat","query=part.dat?x","fragment=part.dat#x"],"line_ending":"lf","line_type":0,"raw_tail":"context=uploaded-roots forbidden=\\\\part.dat empty=. dotdot=../part.dat colon=C:part.dat query=part.dat?x fragment=part.dat#x\n","span":{"column":1,"end":774,"line":11,"start":647}},{"fields":["0","context=official-library","root=pinned-official-library","target=parts/part.dat","canonical=PARTS/part.dat"],"line_ending":"lf","line_type":0,"raw_tail":"context=official-library root=pinned-official-library target=parts/part.dat canonical=PARTS/part.dat\n","span":{"column":1,"end":877,"line":12,"start":774}},{"fields":["0","context=official-library","explicit=48/","no-fallback","target=48/part.dat","ascii-fold-collision=Parts/PART.DAT"],"line_ending":"lf","line_type":0,"raw_tail":"context=official-library explicit=48/ no-fallback target=48/part.dat ascii-fold-collision=Parts/PART.DAT\n","span":{"column":1,"end":984,"line":13,"start":877}},{"fields":["0","context=official-library","ingestion-invalidation=revision-sha256"],"line_ending":"lf","line_type":0,"raw_tail":"context=official-library ingestion-invalidation=revision-sha256\n","span":{"column":1,"end":1050,"line":14,"start":984}}],"oracle_projection":{"status":"ok","models":[{"name":"shadowed.dat","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"compatibility","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-contexts.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/path-policy.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/path-policy.expected.json index 586d24a..401337d 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/path-policy.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/path-policy.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-path-policy","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:path-policy:0"],"lines":0,"model_id":"path-policy","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:s/part.dat","canonical_path":"s/part.dat","colour_state":"current","limits":[],"root_identity":"mpd-virtual","steps":["step-0"],"target_identity":"s/part.dat"},"syntax":[{"fields":["0","PM77","path","policy","exact-case","shadowing"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 path policy exact-case shadowing\n","span":{"column":1,"end":40,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","s/part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 s/part.dat\n","span":{"column":1,"end":80,"line":2,"start":40}},{"fields":["0","forbidden","../escape.dat"],"line_ending":"lf","line_type":0,"raw_tail":"forbidden ../escape.dat\n","span":{"column":1,"end":106,"line":3,"start":80}}]},"outcome":"rejected","profile":"strict"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-path-policy","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:path-policy:0"],"lines":0,"model_id":"path-policy","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:s/part.dat","canonical_path":"s/part.dat","colour_state":"current","limits":[],"root_identity":"mpd-virtual","steps":["step-0"],"target_identity":"s/part.dat","texmap_events":[]},"syntax":[{"fields":["0","PM77","path","policy","exact-case","shadowing"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 path policy exact-case shadowing\n","span":{"column":1,"end":40,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","s/part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 s/part.dat\n","span":{"column":1,"end":80,"line":2,"start":40}},{"fields":["0","forbidden","../escape.dat"],"line_ending":"lf","line_type":0,"raw_tail":"forbidden ../escape.dat\n","span":{"column":1,"end":106,"line":3,"start":80}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-path-policy","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"rejected","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/path-policy.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/profile-matrix.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/profile-matrix.expected.json index 93c8149..9dc838b 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/profile-matrix.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/profile-matrix.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-NONFINITE","message":"non-finite numeric token","severity":"error","span":{"column":1,"end":47,"line":2,"start":22}}],"provenance_id":"pm77-profile-matrix","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:profile-matrix:0"],"lines":0,"model_id":"profile-matrix","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:missing.dat","canonical_path":"missing.dat","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"missing.dat"},"syntax":[{"fields":["0","PM77","profile","matrix"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 profile matrix","span":{"column":1,"end":22,"line":1,"start":0}},{"fields":["0","malformed","numeric:","nan"],"line_ending":"lf","line_type":0,"raw_tail":"malformed numeric: nan","span":{"column":1,"end":47,"line":2,"start":22}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","missing.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 missing.dat","span":{"column":1,"end":88,"line":3,"start":47}}]},"outcome":"preserved","profile":"compatibility"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-NONFINITE","message":"non-finite numeric token","severity":"error","span":{"column":1,"end":47,"line":2,"start":22}}],"provenance_id":"pm77-profile-matrix","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:profile-matrix:0"],"lines":0,"model_id":"profile-matrix","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:missing.dat","canonical_path":"missing.dat","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"missing.dat","texmap_events":[]},"syntax":[{"fields":["0","PM77","profile","matrix"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 profile matrix","span":{"column":1,"end":22,"line":1,"start":0}},{"fields":["0","malformed","numeric:","nan"],"line_ending":"lf","line_type":0,"raw_tail":"malformed numeric: nan","span":{"column":1,"end":47,"line":2,"start":22}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","missing.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 missing.dat","span":{"column":1,"end":88,"line":3,"start":47}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-profile-matrix","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"preserved","profile":"compatibility","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/profile-matrix.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/semantic-limits.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/semantic-limits.expected.json index b9794ca..e593d97 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/semantic-limits.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/semantic-limits.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-semantic-limits","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:semantic-limits:0"],"lines":0,"model_id":"semantic-limits","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:semantic-limits","canonical_path":null,"colour_state":"current","limits":["resource_bytes","include_depth","commands","cancellation-checkpoint"],"root_identity":"authored","steps":["step-0"],"target_identity":"semantic-limits"},"syntax":[{"fields":["0","PM77","semantic","limits","and","limit+1"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 semantic limits and limit+1","span":{"column":1,"end":35,"line":1,"start":0}},{"fields":["0","resource_bytes=104857600"],"line_ending":"lf","line_type":0,"raw_tail":"resource_bytes=104857600","span":{"column":1,"end":62,"line":2,"start":35}},{"fields":["0","include_depth=256"],"line_ending":"lf","line_type":0,"raw_tail":"include_depth=256","span":{"column":1,"end":82,"line":3,"start":62}},{"fields":["0","commands=5000000"],"line_ending":"lf","line_type":0,"raw_tail":"commands=5000000","span":{"column":1,"end":101,"line":4,"start":82}},{"fields":["0","cancellation=checkpoint"],"line_ending":"lf","line_type":0,"raw_tail":"cancellation=checkpoint","span":{"column":1,"end":127,"line":5,"start":101}}]},"outcome":"limited","profile":"compatibility"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-semantic-limits","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:semantic-limits:0"],"lines":0,"model_id":"semantic-limits","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:semantic-limits","canonical_path":null,"colour_state":"current","limits":["resource_bytes","include_depth","commands","cancellation-checkpoint"],"root_identity":"authored","steps":["step-0"],"target_identity":"semantic-limits","texmap_events":[]},"syntax":[{"fields":["0","PM77","semantic","limits","and","limit+1"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 semantic limits and limit+1","span":{"column":1,"end":35,"line":1,"start":0}},{"fields":["0","resource_bytes=104857600"],"line_ending":"lf","line_type":0,"raw_tail":"resource_bytes=104857600","span":{"column":1,"end":62,"line":2,"start":35}},{"fields":["0","include_depth=256"],"line_ending":"lf","line_type":0,"raw_tail":"include_depth=256","span":{"column":1,"end":82,"line":3,"start":62}},{"fields":["0","commands=5000000"],"line_ending":"lf","line_type":0,"raw_tail":"commands=5000000","span":{"column":1,"end":101,"line":4,"start":82}},{"fields":["0","cancellation=checkpoint"],"line_ending":"lf","line_type":0,"raw_tail":"cancellation=checkpoint","span":{"column":1,"end":127,"line":5,"start":101}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-semantic-limits","model_index":0,"certify":"unknown","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"limited","profile":"compatibility","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/semantic-limits.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/steps-transforms.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/steps-transforms.expected.json index 753726b..1db2dea 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/steps-transforms.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/steps-transforms.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-steps-transforms","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:steps-transforms:0"],"lines":0,"model_id":"steps-transforms","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:part.dat","canonical_path":"part.dat","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-1","rotstep-end"],"target_identity":"part.dat"},"syntax":[{"fields":["0","STEP"],"line_ending":"lf","line_type":0,"raw_tail":"STEP\n","span":{"column":1,"end":7,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat\n","span":{"column":1,"end":45,"line":2,"start":7}},{"fields":["0","ROTSTEP","END"],"line_ending":"lf","line_type":0,"raw_tail":"ROTSTEP END\n","span":{"column":1,"end":59,"line":3,"start":45}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-steps-transforms","scene":{"bounds":["0","0","0","1","1","0"],"instance_ids":["instance:steps-transforms:0"],"lines":0,"model_id":"steps-transforms","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:part.dat","canonical_path":"part.dat","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-1","rotstep-end"],"target_identity":"part.dat","texmap_events":[{"kind":"start","span":{"start":45,"end":98,"line":3,"column":1},"mode":"PLANAR","parameters":["0","0","0","1","0","0","0","1","0","texture.png"],"reference":null},{"kind":"next","span":{"start":98,"end":113,"line":4,"column":1},"mode":null,"parameters":[],"reference":null},{"kind":"fallback","span":{"start":138,"end":170,"line":6,"column":1},"mode":null,"parameters":[],"reference":"fallback.dat"},{"kind": "end","span":{"start":170,"end":185,"line":7,"column":1},"mode":null,"parameters":[],"reference":null}]},"syntax":[{"fields":["0","STEP"],"line_ending":"lf","line_type":0,"raw_tail":"STEP","span":{"column":1,"end":7,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","part.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat","span":{"column":1,"end":45,"line":2,"start":7}},{"fields":["0","!TEXMAP","START","PLANAR","0","0","0","1","0","0","0","1","0","texture.png"],"line_ending":"lf","line_type":0,"raw_tail":"!TEXMAP START PLANAR 0 0 0 1 0 0 0 1 0 texture.png","span":{"column":1,"end":98,"line":3,"start":45}},{"fields":["0","!TEXMAP","NEXT"],"line_ending":"lf","line_type":0,"raw_tail":"!TEXMAP NEXT","span":{"column":1,"end":113,"line":4,"start":98}},{"fields":["3","16","0","0","0","1","0","0","0","0","1","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 1 0 0 0 0 1 0","span":{"column":1,"end":138,"line":5,"start":113}},{"fields":["0","!TEXMAP","FALLBACK","fallback.dat"],"line_ending":"lf","line_type":0,"raw_tail":"!TEXMAP FALLBACK fallback.dat","span":{"column":1,"end":170,"line":6,"start":138}},{"fields":["0","!TEXMAP","STOP"],"line_ending":"lf","line_type":0,"raw_tail":"!TEXMAP STOP","span":{"column":1,"end":185,"line":7,"start":170}},{"fields":["0","ROTSTEP","END"],"line_ending":"lf","line_type":0,"raw_tail":"ROTSTEP END","span":{"column":1,"end":199,"line":8,"start":185}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-steps-transforms","model_index":0,"certify":"uncertified","local_colors":[],"step_count":1}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/steps-transforms.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; fixture lines 3-7 emit ordered START/NEXT/fallback/STOP events with exact byte spans and PLANAR parameters.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/syntax-types.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/syntax-types.expected.json index 4970dd5..9695be4 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/syntax-types.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/syntax-types.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-syntax-types","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:syntax-types:0"],"lines":1,"model_id":"syntax-types","reflection":false,"triangles":3},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:3001.dat","canonical_path":"3001.dat","colour_state":"direct","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"3001.dat"},"syntax":[{"fields":["0","PM77","syntax","types","0-5"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 syntax types 0-5","span":{"column":1,"end":24,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","3001.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 3001.dat","span":{"column":1,"end":62,"line":2,"start":24}},{"fields":["2","24","0","0","0","1","1","1"],"line_ending":"lf","line_type":2,"raw_tail":"24 0 0 0 1 1 1","span":{"column":1,"end":79,"line":3,"start":62}},{"fields":["3","4","0","0","0","1","0","0","0","0","1","0","1"],"line_ending":"lf","line_type":3,"raw_tail":"4 0 0 0 1 0 0 0 0 1 0 1","span":{"column":1,"end":105,"line":4,"start":79}},{"fields":["4","2","0","0","0","1","0","0","0","0","1","0","1","1","1"],"line_ending":"lf","line_type":4,"raw_tail":"2 0 0 0 1 0 0 0 0 1 0 1 1 1","span":{"column":1,"end":135,"line":5,"start":105}},{"fields":["5","16","0","0","0","1","1","1","0","0","0","0","1","1","0","1","0","0","1","0","0"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0","span":{"column":1,"end":178,"line":6,"start":135}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-syntax-types","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:syntax-types:0"],"lines":1,"model_id":"syntax-types","reflection":false,"triangles":3},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:3001.dat","canonical_path":"3001.dat","colour_state":"direct","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"3001.dat","texmap_events":[]},"syntax":[{"fields":["0","PM77","syntax","types","0-5"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 syntax types 0-5","span":{"column":1,"end":24,"line":1,"start":0}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","3001.dat"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 3001.dat","span":{"column":1,"end":62,"line":2,"start":24}},{"fields":["2","24","0","0","0","1","1","1"],"line_ending":"lf","line_type":2,"raw_tail":"24 0 0 0 1 1 1","span":{"column":1,"end":79,"line":3,"start":62}},{"fields":["3","4","0","0","0","1","0","0","0","0","1","0","1"],"line_ending":"lf","line_type":3,"raw_tail":"4 0 0 0 1 0 0 0 0 1 0 1","span":{"column":1,"end":105,"line":4,"start":79}},{"fields":["4","2","0","0","0","1","0","0","0","0","1","0","1","1","1"],"line_ending":"lf","line_type":4,"raw_tail":"2 0 0 0 1 0 0 0 0 1 0 1 1 1","span":{"column":1,"end":135,"line":5,"start":105}},{"fields":["5","16","0","0","0","1","1","1","0","0","0","0","1","1","0","1","0","0","1","0","0"],"line_ending":"lf","line_type":5,"raw_tail":"16 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0","span":{"column":1,"end":178,"line":6,"start":135}}],"oracle_projection":{"status":"ok","models":[{"name":"pm77-syntax-types","model_index":0,"certify":"uncertified","local_colors":[],"step_count":0}],"diagnostics":[],"error":null}},"outcome":"accepted","profile":"strict","derivations":[{"field":"syntax","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:syntax","basis":"Fixture line trace: each syntax entry mirrors the numbered line type, fields, raw tail, and byte span.","decision":null},{"field":"diagnostics","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:diagnostics","basis":"Fixture line trace: diagnostics correspond only to malformed, non-finite, or profile-policy lines named in the fixture.","decision":null},{"field":"bfc_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:bfc_state","basis":"LDraw BFC specification §3; fixture comments and the first eligible primitive determine the file-local one-shot state.","decision":null},{"field":"bounds","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:bounds","basis":"Fixture line trace: primitive coordinates are reduced independently per x/y/z axis into [min_x,min_y,min_z,max_x,max_y,max_z].","decision":null},{"field":"graph","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:graph","basis":"PM-75 graph identity contract; canonical target and cache identity derive from the authored file/reference context.","decision":null},{"field":"colour_state","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:colour_state","basis":"LDraw colour specification; type-1 colour fields and !COLOUR directives are retained in declaration order.","decision":null},{"field":"texmap_events","authority":"h_owned","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:texmap_events","basis":"PM-78 TEXMAP projection v1; no TEXMAP directive occurs in this fixture, so the ordered event list is empty.","decision":null},{"field":"steps","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:steps","basis":"LDraw STEP/ROTSTEP specification §2; STEP and ROTSTEP directives in fixture line order define the ordered step list.","decision":null},{"field":"limits","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:limits","basis":"PM-77 limits/cancellation contract; the fixture’s named limit or checkpoint lines define the recorded limit outcome.","decision":null},{"field":"provenance","authority":"ratified_spec","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:provenance","basis":"artifact-provenance.json entry and exact fixture SHA-256 bind this record to its authored bytes.","decision":null},{"field":"outcome","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:outcome","basis":"Fixture line trace and declared corpus profile determine the accepted, rejected, preserved, cancelled, or limited outcome.","decision":null},{"field":"profile","authority":"polymodel_safety","source":"corpus/fixture-authored.json","revision":"PM-77-authored-2026-03-09","locator":"expected/syntax-types.expected.json:profile","basis":"Inventory declaration selects the profile used for this authored expected record.","decision":null}]} diff --git a/crates/polymodel-ldraw-testkit/corpus/omr-10030-1.mpd b/crates/polymodel-ldraw-testkit/corpus/omr-10030-1.mpd new file mode 100644 index 0000000..894dbd7 --- /dev/null +++ b/crates/polymodel-ldraw-testkit/corpus/omr-10030-1.mpd @@ -0,0 +1,4711 @@ +0 FILE 10030 - main.ldr +0 main +0 Name: 10030 - main.ldr +0 Author: Roland Dahl [rolandd] +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt + +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 + +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +1 4 -630 -112 0 0.996 -0.087 0 0.087 0.996 0 0 0 1 10030 - subModel-53.ldr +1 4 -2465.255 272.825 -330 0 0 1 0 1 0 -1 0 0 10030 - subModel-127.ldr +1 4 -2098.343 350.771 -300 -0.497 0.709 0.5 0.819 0.574 0 -0.287 0.409 -0.866 10030 - subModel-134.ldr + + +0 FILE 10030 - subModel-1.ldr +0 subModel-1 +0 Name: 10030 - subModel-1.ldr +0 Author: Roland Dahl [rolandd] +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 2625.dat +1 7 -10 -24 -90 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -90 0 0 1 0 1 0 -1 0 0 3703.dat +0 STEP +1 0 160 -24 60 -1 0 0 0 1 0 0 0 -1 32018.dat +1 0 -160 -24 60 -1 0 0 0 1 0 0 0 -1 32018.dat +1 8 0 0 -250 0 0 -1 0 1 0 1 0 0 3832.dat +1 0 20 -14 -170 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 20 -14 -130 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -170 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -130 -1 0 0 0 1 0 0 0 -1 2780.dat +0 STEP +1 7 -10 -24 -410 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -410 0 0 1 0 1 0 -1 0 0 3703.dat +1 8 0 -32 0 1 0 0 0 1 0 0 0 1 2625.dat +0 STEP +1 8 0 -32 -250 0 0 -1 0 1 0 1 0 0 3832.dat +1 8 0 0 -570 0 0 -1 0 1 0 1 0 0 3832.dat +1 0 20 -14 -550 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -550 -1 0 0 0 1 0 0 0 -1 2780.dat +1 8 300 0 60 -1 0 0 0 1 0 0 0 -1 4477.dat +1 8 -300 0 60 -1 0 0 0 1 0 0 0 -1 4477.dat +0 STEP +1 1 -616.653 0 52.109 0.951 0 -0.308 0 1 0 0.308 0 0.951 10030 - subModel-2.ldr +0 STEP +1 8 -300 -32 60 -1 0 0 0 1 0 0 0 -1 4477.dat +1 7 -10 -24 -730 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -730 0 0 1 0 1 0 -1 0 0 3703.dat +1 0 20 -14 -590 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -590 -1 0 0 0 1 0 0 0 -1 2780.dat +1 8 0 -32 -570 0 0 -1 0 1 0 1 0 0 3832.dat +0 STEP +1 8 -350 0 -730 1 0 0 0 1 0 0 0 1 10030 - subModel-5.ldr +0 STEP +1 8 -321.204 0 -924.369 0.308 0 0.951 0 1 0 -0.951 0 0.308 4477.dat +1 8 -367.187 -32 -750.055 0.951 0 -0.308 0 1 0 0.308 0 0.951 3068b.dat +1 8 0 0 -890 0 0 1 0 1 0 -1 0 0 3832.dat +0 STEP +1 8 320 24 -690 1 0 0 0 1 0 0 0 1 10030 - subModel-6.ldr +1 7 610 0 50 1 0 0 0 1 0 0 0 1 10030 - subModel-7.ldr +0 STEP +0 STEP +1 7 0 -32 -710 1 0 0 0 1 0 0 0 1 4282.dat +1 8 321.204 0 -924.369 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 8 367.187 -32 -750.055 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3068b.dat +0 STEP +1 7 271.875 -24 -1076.575 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 222.545 0 -1228.781 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 7 -271.875 -24 -1076.575 0.308 0 0.951 0 1 0 -0.951 0 0.308 3703.dat +1 8 -222.545 0 -1228.781 0.308 0 0.951 0 1 0 -0.951 0 0.308 4477.dat +1 7 -10 -24 -1050 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -1050 0 0 1 0 1 0 -1 0 0 3703.dat +1 8 0 0 -1210 0 0 1 0 1 0 -1 0 0 3832.dat +1 0 -219.199 -14 -1206.672 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 2780.dat +1 0 219.199 -14 -1206.672 -0.951 0 -0.308 0 1 0 0.308 0 -0.951 2780.dat +1 1 244.39 -14 -1193.813 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 256.723 -14 -1155.761 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 306.052 -14 -1003.555 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 318.385 -14 -965.504 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 -318.385 -14 -965.504 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -306.052 -14 -1003.555 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -256.723 -14 -1155.761 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -244.39 -14 -1193.813 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +0 STEP +1 7 -173.216 -24 -1380.987 0.308 0 0.951 0 1 0 -0.951 0 0.308 3703.dat +1 7 -10 -24 -1370 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -1370 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 173.216 -24 -1380.987 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 -123.886 0 -1533.193 0.308 0 0.951 0 1 0 -0.951 0 0.308 4477.dat +1 8 123.886 0 -1533.193 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 8 0 -32 -890 0 0 1 0 1 0 -1 0 0 3832.dat +1 0 -206.866 -14 -1244.724 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 2780.dat +1 0 206.866 -14 -1244.724 -0.951 0 -0.308 0 1 0 0.308 0 -0.951 2780.dat +1 0 20 -14 -1390 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 20 -14 -1350 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 -20 -14 -1350 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 -20 -14 -1390 1 0 0 0 0 1 0 -1 0 2780.dat +1 1 139.565 -14 -1517.25 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 195.061 -14 -1346.018 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 182.729 -14 -1384.07 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 -139.565 -14 -1517.25 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -195.061 -14 -1346.018 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -182.729 -14 -1384.07 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 8 321.204 -32 -924.369 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -321.204 -32 -924.369 0.308 0 0.951 0 1 0 -0.951 0 0.308 4162.dat +0 STEP +1 8 0 0 -1530 1 0 0 0 1 0 0 0 1 10030 - subModel-8.ldr +1 8 222.545 -32 -1228.781 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -222.545 -32 -1228.781 0.308 0 0.951 0 1 0 -0.951 0 0.308 4162.dat +1 8 0 -32 -1210 0 0 1 0 1 0 -1 0 0 3832.dat +0 STEP +1 7 74.557 -24 -1685.398 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 7 -74.557 -24 -1685.398 0.308 0 0.951 0 1 0 -0.951 0 0.308 3703.dat +1 8 0 -32 -1530 0 0 1 0 1 0 -1 0 0 3832.dat +1 1 90.236 -14 -1669.456 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 65.571 -14 -1745.559 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 53.239 -14 -1783.61 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 47.073 -14 -1802.636 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 40.907 -14 -1821.662 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 -40.907 -14 -1821.662 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -47.073 -14 -1802.636 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -53.239 -14 -1783.61 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -65.571 -14 -1745.559 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -90.236 -14 -1669.456 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +0 STEP +1 8 123.886 -32 -1533.193 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -123.886 -32 -1533.193 0.308 0 0.951 0 1 0 -0.951 0 0.308 4162.dat +1 8 -77.377 -32 -1644.264 0.951 0 -0.308 0 1 0 0.308 0 0.951 3068b.dat +1 8 77.377 -32 -1644.264 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3068b.dat +1 8 140.356 -14 -1612.115 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 10030 - subModel-4.ldr +1 7 -140.356 -14 -1612.115 -0.308 0 -0.951 0 1 0 0.951 0 -0.308 10030 - subModel-4.ldr +0 STEP +1 8 0 -40 -1150 1 0 0 0 1 0 0 0 1 10030 - subModel-9.ldr +1 8 0 -48 -650 1 0 0 0 1 0 0 0 1 10030 - subModel-11.ldr +0 STEP +1 7 0 -56 10 1 0 0 0 1 0 0 0 1 10030 - subModel-12.ldr +0 STEP +1 8 85.499 -14 -1709.983 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-13.ldr +1 8 36.195 -14 -1862.166 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 165.653 -14 -1462.654 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 227.309 -14 -1272.402 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 288.971 -14 -1082.145 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 350.633 -14 -891.888 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 473.956 -14 -511.373 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 535.624 -14 -321.11 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 628.11 -14 -35.73 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 -36.207 -14 -1862.154 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 7 -85.499 -14 -1709.983 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-13.ldr +1 8 -165.653 -14 -1462.654 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -227.309 -14 -1272.402 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -289.02 -14 -1082.099 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -350.951 -14 -891.575 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -474.151 -14 -511.175 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -535.751 -14 -320.975 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -628.151 -14 -35.675 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +0 STEP +1 8 0 22 0 -1 0 0 0 -1 0 0 0 1 10030 - subModel-15.ldr +1 8 30 6 -1336 0 0 -1 -1 0 0 0 1 0 10030 - subModel-16.ldr +1 8 -30 7 -1336 0 0 -1 -1 0 0 0 1 0 10030 - subModel-16.ldr +1 8 486 6 40 0 -1 0 -1 0 0 0 0 -1 10030 - subModel-16.ldr +1 8 226 7 -700 0 -1 0 -1 0 0 0 0 -1 10030 - subModel-16.ldr +1 8 -226 7 -700 0 1 0 -1 0 0 0 0 1 10030 - subModel-16.ldr +1 8 -486.028 6 39.993 0 1 0 -1 0 0 0 0 1 10030 - subModel-16.ldr +1 8 -213.83 5.607 -1190.779 0 -0.305 -0.923 -0.98 0 0 0 0.942 -0.299 10030 - subModel-16.ldr +1 8 -509.927 5.607 -277.426 0 -0.305 -0.923 -0.98 0 0 0 0.942 -0.299 10030 - subModel-16.ldr +1 8 213.994 6 -1190.271 0 0.308 -0.951 -1 0 0 0 0.951 0.308 10030 - subModel-16.ldr +1 8 509.971 6 -277.036 0 0.308 -0.951 -1 0 0 0 0.951 0.308 10030 - subModel-16.ldr +0 STEP +1 8 -469.081 -14 -656.638 0.308 0 -0.951 0 -1 0 -0.951 0 -0.308 10030 - subModel-17.ldr +1 8 468.86 36 -656.854 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 10030 - subModel-17.ldr +1 8 50 182 -10 0 0 -1 0 -1 0 -1 0 0 10030 - subModel-18.ldr +1 8 -50 182 -10 0 0 1 0 -1 0 1 0 0 10030 - subModel-18.ldr +0 STEP +0 STEP +0 STEP +0 STEP +1 1 0 -104 -630 1 0 0 0 1 0 0 0 1 10030 - subModel-21.ldr +0 STEP +1 7 0 -168 10 0 0 -1 0 1 0 1 0 0 10030 - subModel-22.ldr +0 STEP +1 8 400.159 76 85.958 0 0 -1 1 0 0 0 -1 0 10030 - subModel-25.ldr +0 STEP +1 8 140 76 86 -1 0 0 0 0 -1 0 -1 0 10030 - subModel-26.ldr +0 STEP +1 8 -140 76 86 -1 0 0 0 0 -1 0 -1 0 10030 - subModel-28.ldr +0 STEP +1 8 -400 76 86 0 0 -1 1 0 0 0 -1 0 10030 - subModel-29.ldr +0 STEP +1 7 400 -54 86 0 0 -1 1 0 0 0 -1 0 10030 - subModel-30.ldr +0 STEP +1 7 140 -54 86 -1 0 0 0 0 -1 0 -1 0 10030 - subModel-31.ldr +0 STEP +1 7 -140 -54 86 -1 0 0 0 0 -1 0 -1 0 10030 - subModel-32.ldr +0 STEP +1 7 -400.012 -54 85.958 0 0 -1 1 0 0 0 -1 0 10030 - subModel-33.ldr +0 STEP +1 7 360.159 16 101.958 1 0 0 0 0 1 0 -1 0 10030 - subModel-34.ldr +1 7 0 6 102 1 0 0 0 0 1 0 -1 0 10030 - subModel-34.ldr +1 7 -360 16 102 1 0 0 0 0 1 0 -1 0 10030 - subModel-34.ldr +0 STEP +1 14 560.804 97.335 102.067 -0.919 -0.246 0.308 0.259 -0.966 0 0.298 0.08 0.951 10030 - subModel-37.ldr +0 STEP +0 STEP +1 14 -266.646 180.171 197.071 -0.919 0.246 -0.308 -0.259 -0.966 0 -0.298 0.08 0.951 10030 - subModel-43.ldr +0 STEP + + +0 FILE 10030 - subModel-2.ldr +0 subModel-2 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-2.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 5.679 0 -4.057 0.951 0 0.308 0 1 0 -0.308 0 0.951 3021.dat +0 STEP +1 7 -10 -24 -20 0 0 -1 0 1 0 1 0 0 10030 - subModel-3.ldr +0 STEP +1 8 -20 0 -120 0 0 -1 0 1 0 1 0 0 4477.dat +0 STEP +1 7 -20 -24 -220 0 0 -1 0 1 0 1 0 0 3703.dat +1 8 -20 0 -380 0 0 -1 0 1 0 1 0 0 4477.dat +0 STEP +1 7 -20 -24 -540 0 0 -1 0 1 0 1 0 0 3703.dat +1 8 -20 0 -700 0 0 -1 0 1 0 1 0 0 4477.dat +1 1 -30 -14 -80 -1 0 0 0 0 1 0 1 0 4274.dat +1 1 -30 -14 -160 -1 0 0 0 0 1 0 1 0 4274.dat +1 1 -30 -14 -320 -1 0 0 0 0 1 0 1 0 4274.dat +1 1 -30 -14 -440 -1 0 0 0 0 1 0 1 0 4274.dat +1 1 -30 -14 -500 -1 0 0 0 0 1 0 1 0 4274.dat +1 1 -30 -14 -660 -1 0 0 0 0 1 0 1 0 4274.dat +0 STEP +1 7 151.455 -24 -40.791 0.951 0 0.308 0 1 0 -0.308 0 0.951 3703.dat +1 0 72.269 -14 -25.639 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 2780.dat +1 0 110.321 -14 -37.971 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 2780.dat +1 8 -20 -32 -100 0 0 1 0 1 0 -1 0 0 4162.dat +1 8 -20 -32 -380 0 0 1 0 1 0 -1 0 0 4162.dat +1 0 -10 -14 -360 -1 0 0 0 0 1 0 1 0 2780.dat +1 0 -10 -14 -400 -1 0 0 0 0 1 0 1 0 2780.dat +0 STEP +1 8 5.679 -32 -4.057 0.951 0 0.308 0 1 0 -0.308 0 0.951 3021.dat +1 7 -20 -24 -860 0 0 -1 0 1 0 1 0 0 3703.dat +1 8 -20 -32 -700 0 0 1 0 1 0 -1 0 0 4162.dat +1 1 -30 -14 -900 -1 0 0 0 0 1 0 1 0 4274.dat +1 8 -40 -14 -720 1 0 0 0 0 -1 0 1 0 6587.dat +1 7 -38 -14 -720 0 0 -1 -1 0 0 0 1 0 3713.dat +0 STEP +1 1 -60 -14 -810 0 0 -1 0 1 0 1 0 0 10030 - subModel-4.ldr +1 1 -60 -14 -230 0 0 -1 0 1 0 1 0 0 10030 - subModel-4.ldr + + +0 FILE 10030 - subModel-3.ldr +0 subModel-3 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-3.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0.951 0 0.308 0 1 0 -0.308 0 0.951 3830.dat +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3831.dat + + +0 FILE 10030 - subModel-4.ldr +0 subModel-4 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-4.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 0 0 1 0 0 0 1 0 0 0 1 3705.dat +1 7 -30 0 -20 1 0 0 0 -1 0 0 0 -1 32039.dat +0 STEP +1 7 0 -9.66 2.59 1 0 0 0 0.966 0.259 0 -0.259 0.966 2817.dat +0 STEP +1 7 30 0 -20 1 0 0 0 -1 0 0 0 -1 32039.dat +1 1 30 0 -30 0 0 1 0 -1 0 1 0 0 43093.dat +1 1 -30 0 -30 0 0 1 0 -1 0 1 0 0 43093.dat + + +0 FILE 10030 - subModel-5.ldr +0 subModel-5 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-5.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 -4.705 0 -10.224 0.951 0 -0.308 0 1 0 0.308 0 0.951 3021.dat +1 7 -7.788 -24 -0.711 -0.308 0 -0.951 0 1 0 0.951 0 -0.308 3040b.dat +0 STEP +1 7 30 -24 -20 0.951 0 -0.308 0 1 0 0.308 0 0.951 10030 - subModel-3.ldr +0 STEP +1 8 60 0 0 1 0 0 0 1 0 0 0 1 3021.dat +0 STEP +1 0 190 -24 10 1 0 0 0 1 0 0 0 1 32018.dat +1 0 70 -14 20 0 -1 0 0 0 -1 1 0 0 2780.dat +1 0 110 -14 20 0 -1 0 0 0 -1 1 0 0 2780.dat +0 STEP +1 8 60 -32 0 1 0 0 0 1 0 0 0 1 3021.dat +1 7 350 0 20 1 0 0 0 1 0 0 0 1 4282.dat + + +0 FILE 10030 - subModel-6.ldr +0 subModel-6 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-6.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 34.705 -24 -50.224 0.951 0 0.308 0 1 0 -0.308 0 0.951 3021.dat +1 7 37.788 -48 -40.711 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3040b.dat +0 STEP +1 7 0 -48 -60 1 0 0 0 1 0 0 0 1 10030 - subModel-3.ldr +0 STEP +1 8 -30 -24 -40 1 0 0 0 1 0 0 0 1 3021.dat +0 STEP +1 0 -160 -48 -30 1 0 0 0 1 0 0 0 1 32018.dat +1 0 -40 -38 -20 0 1 0 0 0 -1 -1 0 0 2780.dat +1 0 -80 -38 -20 0 1 0 0 0 -1 -1 0 0 2780.dat +0 STEP +1 8 -30 -56 -40 1 0 0 0 1 0 0 0 1 3021.dat + + +0 FILE 10030 - subModel-7.ldr +0 subModel-7 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-7.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3021.dat +0 STEP +1 8 10 -24 -20 0 0 1 0 1 0 -1 0 0 10030 - subModel-3.ldr +0 STEP +1 8 -11.318 0 -118.212 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +0 STEP +1 7 -42.149 -24 -213.34 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 -91.478 0 -365.546 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +0 STEP +1 7 -140.808 -24 -517.752 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 -190.137 0 -669.958 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 0 -94.825 -14 -343.437 -0.951 0.308 0 0 0 1 0.308 0.951 0 2780.dat +1 0 -107.157 -14 -381.489 -0.951 0.308 0 0 0 1 0.308 0.951 0 2780.dat +1 1 10.527 -14 -83.243 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +1 1 -14.138 -14 -159.346 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +1 1 -63.467 -14 -311.552 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +1 1 -100.464 -14 -425.706 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +1 1 -118.962 -14 -482.784 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +1 1 -168.292 -14 -634.989 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +0 STEP +1 7 -239.467 -24 -822.164 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 -91.478 -32 -365.546 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -5.152 -32 -99.186 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 7 -150 -24 10 1 0 0 0 1 0 0 0 1 3703.dat +1 0 -70 -14 0 0 1 0 0 0 -1 -1 0 0 2780.dat +1 0 -110 -14 0 0 1 0 0 0 -1 -1 0 0 2780.dat +0 STEP +1 8 0 -32 0 1 0 0 0 1 0 0 0 1 3021.dat +1 8 -190.137 -32 -669.958 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 1 -242.286 -14 -863.298 0.951 0.308 0 0 0 -1 -0.308 0.951 0 4274.dat +1 8 -177.278 -14 -695.15 -0.951 0.308 0 0 0 1 0.308 0.951 0 6587.dat +1 7 -179.18 -14 -694.533 0 0.308 0.951 1 0 0 0 0.951 -0.308 3713.dat +0 STEP +1 7 -186 -14 -786.932 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 10030 - subModel-4.ldr +1 7 -7.181 -14 -235.186 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 10030 - subModel-4.ldr + + +0 FILE 10030 - subModel-8.ldr +0 subModel-8 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-8.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3030.dat +1 7 0 -24 -40 0 0 1 0 1 0 -1 0 0 3001.dat +0 STEP +1 7 40 -24 -100 1 0 0 0 1 0 0 0 1 10030 - subModel-3.ldr +1 7 -40 -24 -100 0.951 0 -0.308 0 1 0 0.308 0 0.951 10030 - subModel-3.ldr +0 STEP +1 8 -68.539 0 -109.249 0.951 0 -0.308 0 1 0 0.308 0 0.951 3021.dat +1 8 68.539 0 -109.249 0.951 0 0.308 0 1 0 -0.308 0 0.951 3021.dat +0 STEP +1 7 65.456 -24 -118.762 0.951 0 0.308 0 1 0 -0.308 0 0.951 3005.dat +1 7 -65.456 -24 -118.762 0.951 0 -0.308 0 1 0 0.308 0 0.951 3005.dat + + +0 FILE 10030 - subModel-9.ldr +0 subModel-9 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-9.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3020.dat +0 STEP +1 0 -10 -24 20 0 0 1 0 1 0 -1 0 0 32000.dat +1 0 10 -24 20 0 0 1 0 1 0 -1 0 0 32000.dat +1 7 20 -14 10 -1 0 0 0 1 0 0 0 -1 3673.dat +1 7 -20 -14 10 -1 0 0 0 1 0 0 0 -1 3673.dat +0 STEP +1 8 0 -24 -20 -1 0 0 0 1 0 0 0 -1 3003.dat +1 0 30 -16 10 0 0 -1 0 1 0 1 0 0 10030 - subModel-10.ldr +1 0 -30 -16 10 0 0 1 0 1 0 -1 0 0 10030 - subModel-10.ldr +0 STEP +1 7 0 -48 0 0 0 1 0 1 0 -1 0 0 3001.dat + + +0 FILE 10030 - subModel-10.ldr +0 subModel-10 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-10.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 -8 0 1 0 0 0 1 0 0 0 1 2607.dat +1 0 0 1 -26.5 1 0 0 0 0 1 0 -1 0 73092.dat + + +0 FILE 10030 - subModel-11.ldr +0 subModel-11 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-11.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 -8 0 0 0 1 0 1 0 -1 0 0 3007.dat +1 7 0 -32 0 0 0 1 0 1 0 -1 0 0 3007.dat +0 STEP +1 0 -10 -56 -60 0 0 1 0 1 0 -1 0 0 32000.dat +1 0 10 -56 -60 0 0 1 0 1 0 -1 0 0 32000.dat +1 8 0 -56 -20 0 0 1 0 1 0 -1 0 0 3003.dat +1 7 20 -46 -50 -1 0 0 0 1 0 0 0 -1 3673.dat +1 7 -20 -46 -50 -1 0 0 0 1 0 0 0 -1 3673.dat +0 STEP +1 7 0 -80 -40 0 0 1 0 1 0 -1 0 0 3001.dat +1 7 -30 -48 -50 0 0 1 0 1 0 -1 0 0 10030 - subModel-10.ldr +1 7 30 -48 -50 0 0 -1 0 1 0 1 0 0 10030 - subModel-10.ldr + + +0 FILE 10030 - subModel-12.ldr +0 subModel-12 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-12.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 44042.dat +0 STEP +1 7 0 -72 40 -1 0 0 0 1 0 0 0 -1 30144.dat +1 7 0 -72 -40 -1 0 0 0 1 0 0 0 -1 30144.dat +0 STEP +1 8 0 -80 0 0 0 -1 0 1 0 1 0 0 3032.dat +0 STEP +1 8 0 -104 0 0 0 -1 0 1 0 1 0 0 2456.dat +1 7 30 -104 0 0 0 -1 0 1 0 1 0 0 3894.dat +1 7 -30 -104 0 0 0 -1 0 1 0 1 0 0 3894.dat +1 7 40 -94 40 1 0 0 0 1 0 0 0 1 3673.dat +1 7 -40 -94 40 1 0 0 0 1 0 0 0 1 3673.dat +0 STEP +1 7 50 -96 40 0 0 -1 0 1 0 1 0 0 10030 - subModel-10.ldr +1 7 -50 -96 40 0 0 1 0 1 0 -1 0 0 10030 - subModel-10.ldr + + +0 FILE 10030 - subModel-13.ldr +0 subModel-13 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-13.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 0 -8 50 -1 0 0 0 1 0 0 0 -1 2555.dat +0 STEP +1 7 0 -8 20 0 0 -1 0 1 0 1 0 0 2412b.dat +1 7 0 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat +0 STEP +1 7 0 -24 -40 0 0 1 0 1 0 -1 0 0 4865a.dat + + +0 FILE 10030 - subModel-14.ldr +0 subModel-14 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-14.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +1 7 0 -8 80 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 7 0 -8 10 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 0 -24 30 -1 0 0 0 1 0 0 0 -1 4589.dat +1 7 0 -8 50 0 0 -1 0 1 0 1 0 0 4081b.dat +0 STEP +1 7 0 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat +1 7 0 -24 -40 0 0 1 0 1 0 -1 0 0 4865a.dat +0 STEP +1 7 0 -24 -70 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 0 -8 -90 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 20 -6 94 0 0 -1 1 0 0 0 -1 0 6269.dat + + +0 FILE 10030 - subModel-15.ldr +0 subModel-15 +0 Name: 10030 - subModel-15.ldr +0 Author: Roland Dahl [rolandd] +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 2625.dat +1 7 -10 -24 -90 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -90 0 0 1 0 1 0 -1 0 0 3703.dat +0 STEP +1 0 160 -24 60 -1 0 0 0 1 0 0 0 -1 32018.dat +1 0 -160 -24 60 -1 0 0 0 1 0 0 0 -1 32018.dat +1 8 0 0 -250 0 0 -1 0 1 0 1 0 0 3832.dat +1 0 20 -14 -170 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 20 -14 -130 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -170 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -130 -1 0 0 0 1 0 0 0 -1 2780.dat +0 STEP +1 7 -10 -24 -410 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -410 0 0 1 0 1 0 -1 0 0 3703.dat +1 8 0 -32 0 1 0 0 0 1 0 0 0 1 2625.dat +0 STEP +1 8 0 -32 -250 0 0 -1 0 1 0 1 0 0 3832.dat +1 8 0 0 -570 0 0 -1 0 1 0 1 0 0 3832.dat +1 0 20 -14 -550 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -550 -1 0 0 0 1 0 0 0 -1 2780.dat +1 8 300 0 60 -1 0 0 0 1 0 0 0 -1 4477.dat +1 8 -300 0 60 -1 0 0 0 1 0 0 0 -1 4477.dat +0 STEP +1 1 -616.653 0 52.109 0.951 0 -0.308 0 1 0 0.308 0 0.951 10030 - subModel-2.ldr +0 STEP +1 8 -300 -32 60 -1 0 0 0 1 0 0 0 -1 4477.dat +1 7 -10 -24 -730 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -730 0 0 1 0 1 0 -1 0 0 3703.dat +1 0 20 -14 -590 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -20 -14 -590 -1 0 0 0 1 0 0 0 -1 2780.dat +1 8 0 -32 -570 0 0 -1 0 1 0 1 0 0 3832.dat +0 STEP +1 8 -350 0 -730 1 0 0 0 1 0 0 0 1 10030 - subModel-5.ldr +0 STEP +1 8 -321.204 0 -924.369 0.308 0 0.951 0 1 0 -0.951 0 0.308 4477.dat +1 8 -367.187 -32 -750.055 0.951 0 -0.308 0 1 0 0.308 0 0.951 3068b.dat +1 8 0 0 -890 0 0 1 0 1 0 -1 0 0 3832.dat +0 STEP +1 8 320 24 -690 1 0 0 0 1 0 0 0 1 10030 - subModel-6.ldr +1 7 610 0 50 1 0 0 0 1 0 0 0 1 10030 - subModel-7.ldr +0 STEP +0 STEP +1 7 0 -32 -710 1 0 0 0 1 0 0 0 1 4282.dat +1 8 321.204 0 -924.369 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 8 367.187 -32 -750.055 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3068b.dat +0 STEP +1 7 271.875 -24 -1076.575 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 222.545 0 -1228.781 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 7 -271.875 -24 -1076.575 0.308 0 0.951 0 1 0 -0.951 0 0.308 3703.dat +1 8 -222.545 0 -1228.781 0.308 0 0.951 0 1 0 -0.951 0 0.308 4477.dat +1 7 -10 -24 -1050 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -1050 0 0 1 0 1 0 -1 0 0 3703.dat +1 8 0 0 -1210 0 0 1 0 1 0 -1 0 0 3832.dat +1 0 -219.199 -14 -1206.672 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 2780.dat +1 0 219.199 -14 -1206.672 -0.951 0 -0.308 0 1 0 0.308 0 -0.951 2780.dat +1 1 244.39 -14 -1193.813 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 256.723 -14 -1155.761 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 306.052 -14 -1003.555 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 318.385 -14 -965.504 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 -318.385 -14 -965.504 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -306.052 -14 -1003.555 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -256.723 -14 -1155.761 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -244.39 -14 -1193.813 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +0 STEP +1 7 -173.216 -24 -1380.987 0.308 0 0.951 0 1 0 -0.951 0 0.308 3703.dat +1 7 -10 -24 -1370 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 10 -24 -1370 0 0 1 0 1 0 -1 0 0 3703.dat +1 7 173.216 -24 -1380.987 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 8 -123.886 0 -1533.193 0.308 0 0.951 0 1 0 -0.951 0 0.308 4477.dat +1 8 123.886 0 -1533.193 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4477.dat +1 8 0 -32 -890 0 0 1 0 1 0 -1 0 0 3832.dat +1 0 -206.866 -14 -1244.724 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 2780.dat +1 0 206.866 -14 -1244.724 -0.951 0 -0.308 0 1 0 0.308 0 -0.951 2780.dat +1 0 20 -14 -1390 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 20 -14 -1350 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 -20 -14 -1350 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 -20 -14 -1390 1 0 0 0 0 1 0 -1 0 2780.dat +1 1 139.565 -14 -1517.25 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 195.061 -14 -1346.018 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 182.729 -14 -1384.07 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 -139.565 -14 -1517.25 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -195.061 -14 -1346.018 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -182.729 -14 -1384.07 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 8 321.204 -32 -924.369 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -321.204 -32 -924.369 0.308 0 0.951 0 1 0 -0.951 0 0.308 4162.dat +0 STEP +1 8 0 0 -1530 1 0 0 0 1 0 0 0 1 10030 - subModel-8.ldr +1 8 222.545 -32 -1228.781 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -222.545 -32 -1228.781 0.308 0 0.951 0 1 0 -0.951 0 0.308 4162.dat +1 8 0 -32 -1210 0 0 1 0 1 0 -1 0 0 3832.dat +0 STEP +1 7 74.557 -24 -1685.398 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3703.dat +1 7 -74.557 -24 -1685.398 0.308 0 0.951 0 1 0 -0.951 0 0.308 3703.dat +1 8 0 -32 -1530 0 0 1 0 1 0 -1 0 0 3832.dat +1 1 90.236 -14 -1669.456 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 65.571 -14 -1745.559 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 53.239 -14 -1783.61 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 47.073 -14 -1802.636 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 40.907 -14 -1821.662 0.951 0 0.308 0 1 0 -0.308 0 0.951 4274.dat +1 1 -40.907 -14 -1821.662 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -47.073 -14 -1802.636 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -53.239 -14 -1783.61 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -65.571 -14 -1745.559 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +1 1 -90.236 -14 -1669.456 -0.951 0 0.308 0 1 0 -0.308 0 -0.951 4274.dat +0 STEP +1 8 123.886 -32 -1533.193 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 4162.dat +1 8 -123.886 -32 -1533.193 0.308 0 0.951 0 1 0 -0.951 0 0.308 4162.dat +1 8 -77.377 -32 -1644.264 0.951 0 -0.308 0 1 0 0.308 0 0.951 3068b.dat +1 8 77.377 -32 -1644.264 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 3068b.dat +1 8 140.356 -14 -1612.115 -0.308 0 0.951 0 1 0 -0.951 0 -0.308 10030 - subModel-4.ldr +1 7 -140.356 -14 -1612.115 -0.308 0 -0.951 0 1 0 0.951 0 -0.308 10030 - subModel-4.ldr +0 STEP +1 8 0 -40 -1150 1 0 0 0 1 0 0 0 1 10030 - subModel-9.ldr +1 8 0 -48 -650 1 0 0 0 1 0 0 0 1 10030 - subModel-11.ldr +0 STEP +1 7 0 -56 10 1 0 0 0 1 0 0 0 1 10030 - subModel-12.ldr +0 STEP +1 8 85.499 -14 -1709.983 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-13.ldr +1 8 36.195 -14 -1862.166 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 165.653 -14 -1462.654 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 227.309 -14 -1272.402 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 288.971 -14 -1082.145 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 350.633 -14 -891.888 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 473.956 -14 -511.373 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 535.624 -14 -321.11 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 628.11 -14 -35.73 0 -0.951 0.308 1 0 0 0 0.308 0.951 10030 - subModel-14.ldr +1 8 -36.207 -14 -1862.154 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 7 -85.499 -14 -1709.983 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-13.ldr +1 8 -165.653 -14 -1462.654 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -227.309 -14 -1272.402 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -289.02 -14 -1082.099 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -350.951 -14 -891.575 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -474.151 -14 -511.175 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -535.751 -14 -320.975 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr +1 8 -628.151 -14 -35.675 0 0.951 0.308 1 0 0 0 0.308 -0.951 10030 - subModel-14.ldr + + +0 FILE 10030 - subModel-16.ldr +0 subModel-16 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-16.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3710.dat +0 STEP +1 7 -20 -24 0 1 0 0 0 1 0 0 0 1 32000.dat +1 1 20 -24 0 1 0 0 0 1 0 0 0 1 3700.dat +0 STEP +1 8 0 -32 0 1 0 0 0 1 0 0 0 1 3710.dat +1 8 0 -40 0 1 0 0 0 1 0 0 0 1 3710.dat +0 STEP +1 7 -20 -64 0 1 0 0 0 1 0 0 0 1 32000.dat +1 1 20 -64 0 1 0 0 0 1 0 0 0 1 3700.dat +0 STEP +1 8 0 -72 0 1 0 0 0 1 0 0 0 1 3710.dat + + +0 FILE 10030 - subModel-17.ldr +0 subModel-17 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-17.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 -1 0 1 0 0 0 0 1 32013.dat +0 STEP +1 7 0 -9 0 -1 0 0 0 -1 0 0 0 1 4740.dat +0 STEP +1 7 0 -21 0 -1 0 0 0 0 1 0 1 0 4697b.dat +0 STEP +1 7 0 -21 26 1 0 0 0 1 0 0 0 1 30162.dat +1 7 0 -33 0 1 0 0 0 1 0 0 0 1 4740.dat +0 STEP +1 8 0 -40 0 0 0 -1 0 1 0 1 0 0 6141.dat +1 7 0 -50 0 0 -1 0 1 0 0 0 0 1 32013.dat + + +0 FILE 10030 - subModel-18.ldr +0 subModel-18 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-18.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 0 0 1 0 0 0 1 0 0 0 1 2607.dat +1 7 0 10 10 0 0 1 0 1 0 -1 0 0 3673.dat +0 STEP +1 0 0 9 -26.5 -1 0 0 0 0 -1 0 -1 0 73092.dat + + +0 FILE 10030 - subModel-19.ldr +0 subModel-19 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-19.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +1 7 0 -24 -80 0 0 1 0 1 0 -1 0 0 32000.dat +0 STEP +1 0 0 -24 100 0 0 1 0 1 0 -1 0 0 3703.dat +0 STEP +1 8 0 -32 0 0 0 1 0 1 0 -1 0 0 4477.dat +1 8 0 -40 0 0 0 1 0 1 0 -1 0 0 4477.dat +0 STEP +1 7 0 -64 -80 0 0 1 0 1 0 -1 0 0 32000.dat +1 0 0 -64 100 0 0 1 0 1 0 -1 0 0 3703.dat +0 STEP +1 8 0 -72 0 0 0 1 0 1 0 -1 0 0 4477.dat + + +0 FILE 10030 - subModel-20.ldr +0 subModel-20 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-20.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 32531.dat +1 0 60 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 -60 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 20 10 40 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 -20 10 40 0 0 1 0 1 0 -1 0 0 2780.dat +0 STEP +1 1 -20 10 -40 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 20 10 -40 0 0 1 0 1 0 -1 0 0 4274.dat +0 STEP +1 8 0 10 -48 1 0 0 0 0 -1 0 1 0 3666.dat +0 STEP +1 0 70 0 -40 0 0 1 0 1 0 -1 0 0 2744.dat +1 0 -70 0 -40 0 0 1 0 1 0 -1 0 0 2744.dat +0 STEP +1 0 0 24 0 1 0 0 0 1 0 0 0 1 3035.dat +0 STEP +1 8 70 0 20 0 0 1 0 1 0 -1 0 0 2877.dat +1 8 -70 0 20 0 0 -1 0 1 0 1 0 0 2877.dat +0 STEP +1 0 0 -8 0 1 0 0 0 1 0 0 0 1 3035.dat +1 8 0 -16 30 1 0 0 0 1 0 0 0 1 3710.dat +0 STEP +1 0 0 -40 30 1 0 0 0 1 0 0 0 1 3701.dat +1 0 -20 -30 40 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 20 -30 40 0 0 1 0 1 0 -1 0 0 2780.dat +0 STEP +1 0 0 -32 10 1 0 0 0 1 0 0 0 1 3297.dat +0 STEP +1 0 60 -32 30 1 0 0 0 1 0 0 0 1 30363.dat +1 0 -60 -32 30 1 0 0 0 1 0 0 0 1 30363.dat + + +0 FILE 10030 - subModel-21.ldr +0 subModel-21 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-21.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3001.dat +1 4 0 -8 0 1 0 0 0 1 0 0 0 1 3068b.dat +0 STEP +1 1 -30 -24 -10 -1 0 0 0 1 0 0 0 -1 3040b.dat +1 1 30 -24 -10 -1 0 0 0 1 0 0 0 -1 3040b.dat + + +0 FILE 10030 - subModel-22.ldr +0 subModel-22 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-22.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3032.dat +1 4 0 -24 0 0 0 1 0 1 0 -1 0 0 6249.dat +0 STEP +1 7 -140.339 -11.76 50 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3703.dat +1 0 -278.935 10.404 40 0 0.087 -0.996 0 0.996 0.087 1 0 0 2780.dat +1 0 -179.315 1.688 40 0 0.087 -0.996 0 0.996 0.087 1 0 0 2780.dat +0 STEP +1 7 -319.654 3.928 30 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3703.dat +1 0 -458.25 26.092 20 0 0.087 -0.996 0 0.996 0.087 1 0 0 2780.dat +1 0 -338.706 15.633 20 0 0.087 -0.996 0 0.996 0.087 1 0 0 2780.dat +0 STEP +1 7 -479.045 17.873 10 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3703.dat +0 STEP +1 7 -479.045 17.873 -10 0 0.087 0.996 0 0.996 -0.087 -1 0 0 10030 - subModel-23.ldr +0 STEP +1 8 -539.514 15.133 0 0.996 0.087 0 -0.087 0.996 0 0 0 1 3832.dat +1 8 -31.455 -29.317 0 0 0.087 0.996 0 0.996 -0.087 -1 0 0 3666.dat +0 STEP +1 8 -380.123 1.188 0 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3032.dat +1 8 -101.188 -23.216 -50 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3666.dat +1 8 -101.188 -23.216 50 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3666.dat +1 8 -220.732 -12.757 40 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3795.dat +1 8 -220.732 -12.757 -40 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3795.dat +0 STEP +1 8 -101.886 -31.185 50 -0.996 0.087 0 0.087 0.996 0 0 0 -1 4162.dat +1 8 -101.886 -31.185 -50 -0.996 0.087 0 0.087 0.996 0 0 0 -1 4162.dat +1 4 -392.176 -21.849 10 0 0.087 -0.996 0 0.996 0.087 1 0 0 10030 - subModel-24.ldr +1 4 -392.176 -21.849 -10 0 0.087 -0.996 0 0.996 0.087 1 0 0 10030 - subModel-24.ldr +0 STEP +1 0 -384.306 -46.63 -10 0.996 0.087 0 -0.087 0.996 0 0 0 1 3048b.dat +1 0 -384.306 -46.63 10 -0.996 0.087 0 0.087 0.996 0 0 0 -1 3048b.dat +1 7 -430.63 -2.424 0 0 0.087 -0.996 0 0.996 0.087 1 0 0 2431.dat +1 7 -331.01 -11.14 0 0 0.087 -0.996 0 0.996 0.087 1 0 0 2431.dat +1 7 -201.505 -22.47 0 0 0.087 -0.996 0 0.996 0.087 1 0 0 3020.dat + +0 FILE 10030 - subModel-23.ldr +0 subModel-23 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-23.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3703.dat +1 0 10 10 140 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 10 10 20 -1 0 0 0 1 0 0 0 -1 2780.dat +0 STEP +1 7 20 0 160 0 0 1 0 1 0 -1 0 0 3703.dat +1 0 30 10 300 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 30 10 200 -1 0 0 0 1 0 0 0 -1 2780.dat +0 STEP +1 7 40 0 340 0 0 1 0 1 0 -1 0 0 3703.dat + + +0 FILE 10030 - subModel-24.ldr +0 subModel-24 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-24.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 4 0 0 0 1 0 0 0 1 0 0 0 1 6541.dat +1 0 0 10 -10 0 0 1 0 1 0 -1 0 0 2780.dat +1 4 0 0 -20 1 0 0 0 1 0 0 0 1 6541.dat + + +0 FILE 10030 - subModel-25.ldr +0 subModel-25 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-25.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 30355.dat +1 8 -20 0 -160 1 0 0 0 1 0 0 0 1 41770.dat +1 8 -50 0 -160 0 0 1 0 1 0 -1 0 0 3710.dat +0 STEP +1 8 -40 -8 -100 0 0 1 0 1 0 -1 0 0 3795.dat +1 8 -40 0 -240 1 0 0 0 1 0 0 0 1 41770.dat +0 STEP +1 8 -40 -8 -200 1 0 0 0 1 0 0 0 1 41770.dat +1 8 -30 -8 60 1 0 0 0 1 0 0 0 1 3021.dat +1 8 -30 -8 20 1 0 0 0 1 0 0 0 1 3021.dat +0 STEP +1 7 -50 -16 -230 1 0 0 0 1 0 0 0 1 2555.dat +1 8 -40 -16 -160 1 0 0 0 1 0 0 0 1 41770.dat +1 7 -50 -32 -110 -1 0 0 0 1 0 0 0 -1 3040b.dat +0 STEP +1 7 -50 -32 -210 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 -50 -24 -180 0 0 -1 0 1 0 1 0 0 2412b.dat +1 7 -50 -24 -150 0 0 -1 0 1 0 1 0 0 2555.dat +1 7 -50 -40 -130 0 0 -1 0 1 0 1 0 0 4589.dat +1 0 -50 -8 -270 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -50 -8 -270 1 0 0 0 0.574 0.819 0 -0.819 0.574 4593.dat +0 STEP +1 1 -40 8 -120 1 0 0 0 1 0 0 0 1 2476a.dat +1 1 -40 8 80 1 0 0 0 1 0 0 0 1 2476a.dat +1 1 -40 8 0 1 0 0 0 1 0 0 0 1 2476a.dat + + +0 FILE 10030 - subModel-26.ldr +0 subModel-26 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-26.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3456.dat +0 STEP +1 8 130 -8 40 0 0 1 0 1 0 -1 0 0 3794a.dat +1 8 110 -8 40 0 0 1 0 1 0 -1 0 0 3794a.dat +1 7 -40 -24 0 0 0 1 0 1 0 -1 0 0 6222.dat +0 STEP +1 7 -40 -24 0 0 0 1 0 1 0 -1 0 0 4424.dat +1 8 -40 -71 0 0 0 1 0 1 0 -1 0 0 2489.dat +0 STEP +1 19 -40 -76 0 1 0 0 0 1 0 0 0 1 10030 - subModel-27.ldr +0 STEP +1 1 100 8 40 0 0 1 0 1 0 -1 0 0 2476a.dat +1 1 -80 8 40 0 0 1 0 1 0 -1 0 0 2476a.dat + + +0 FILE 10030 - subModel-27.ldr +0 subModel-27 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-27.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 41 0 -1 0 1 0 0 0 1 0 0 0 1 3626b.dat +1 19 0 25 0 0 -1 0 1 0 0 0 0 1 3749.dat + + +0 FILE 10030 - subModel-28.ldr +0 subModel-28 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-28.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3456.dat +0 STEP +1 8 -130 -8 40 0 0 1 0 1 0 -1 0 0 3794a.dat +1 8 -110 -8 40 0 0 1 0 1 0 -1 0 0 3794a.dat +1 7 40 -24 0 0 0 1 0 1 0 -1 0 0 6222.dat +0 STEP +1 7 40 -24 0 0 0 1 0 1 0 -1 0 0 4424.dat +1 8 40 -71 0 0 0 1 0 1 0 -1 0 0 2489.dat +0 STEP +1 7 40 -76 0 0 0 1 0 1 0 -1 0 0 10030 - subModel-27.ldr +0 STEP +1 1 -100 8 40 0 0 1 0 1 0 -1 0 0 2476a.dat +1 1 80 8 40 0 0 1 0 1 0 -1 0 0 2476a.dat + + +0 FILE 10030 - subModel-29.ldr +0 subModel-29 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-29.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 -1 0 0 0 1 0 0 0 -1 30356.dat +1 8 -50 0 160 0 0 -1 0 1 0 1 0 0 3710.dat +1 8 -20 0 160 -1 0 0 0 1 0 0 0 -1 41769.dat +0 STEP +1 8 -40 -8 100 0 0 -1 0 1 0 1 0 0 3795.dat +1 8 -40 0 240 -1 0 0 0 1 0 0 0 -1 41769.dat +0 STEP +1 8 -40 -8 200 -1 0 0 0 1 0 0 0 -1 41769.dat +1 8 -30 -8 -60 -1 0 0 0 1 0 0 0 -1 3021.dat +1 8 -30 -8 -20 -1 0 0 0 1 0 0 0 -1 3021.dat +0 STEP +1 7 -50 -32 110 1 0 0 0 1 0 0 0 1 3040b.dat +1 8 -40 -16 160 -1 0 0 0 1 0 0 0 -1 41769.dat +1 7 -50 -16 230 -1 0 0 0 1 0 0 0 -1 2555.dat +0 STEP +1 7 -50 -40 130 -1 0 0 0 1 0 0 0 -1 4589.dat +1 7 -50 -24 150 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -50 -32 210 1 0 0 0 1 0 0 0 1 4599a.dat +1 7 -50 -24 180 0 0 1 0 1 0 -1 0 0 2412b.dat +1 0 -50 -8 270 -1 0 0 0 1 0 0 0 -1 4592.dat +1 7 -50 -8 270 -1 0 0 0 0.574 0.819 0 0.819 -0.574 4593.dat +0 STEP +1 1 -40 8 -80 -1 0 0 0 1 0 0 0 -1 2476a.dat +1 1 -40 8 0 -1 0 0 0 1 0 0 0 -1 2476a.dat +1 1 -40 8 120 -1 0 0 0 1 0 0 0 -1 2476a.dat + + +0 FILE 10030 - subModel-30.ldr +0 subModel-30 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-30.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 30356.dat +1 8 20 0 -160 1 0 0 0 1 0 0 0 1 41769.dat +1 8 50 0 -160 0 0 1 0 1 0 -1 0 0 3710.dat +0 STEP +1 8 40 0 -240 1 0 0 0 1 0 0 0 1 41769.dat +1 8 40 -8 -100 0 0 1 0 1 0 -1 0 0 3795.dat +0 STEP +1 8 40 -8 -200 1 0 0 0 1 0 0 0 1 41769.dat +1 8 40 -8 10 1 0 0 0 1 0 0 0 1 3794a.dat +1 8 40 -8 30 1 0 0 0 1 0 0 0 1 3794a.dat +1 8 40 -8 50 1 0 0 0 1 0 0 0 1 3794a.dat +1 8 40 -8 70 1 0 0 0 1 0 0 0 1 3794a.dat +0 STEP +1 7 50 -16 -230 1 0 0 0 1 0 0 0 1 2555.dat +1 8 40 -16 -160 1 0 0 0 1 0 0 0 1 41769.dat +1 7 50 -32 -110 -1 0 0 0 1 0 0 0 -1 3040b.dat +0 STEP +1 7 50 -32 -210 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 50 -24 -180 0 0 -1 0 1 0 1 0 0 2412b.dat +1 7 50 -24 -150 0 0 -1 0 1 0 1 0 0 2555.dat +1 7 50 -40 -130 0 0 -1 0 1 0 1 0 0 4589.dat +1 0 50 -8 -270 1 0 0 0 1 0 0 0 1 4592.dat +1 7 50 -8 -270 1 0 0 0 0.574 0.819 0 -0.819 0.574 4593.dat +0 STEP +1 1 40 8 80 1 0 0 0 1 0 0 0 1 2476a.dat +1 1 40 8 0 1 0 0 0 1 0 0 0 1 2476a.dat +1 1 40 8 -120 1 0 0 0 1 0 0 0 1 2476a.dat + + +0 FILE 10030 - subModel-31.ldr +0 subModel-31 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-31.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3456.dat +0 STEP +1 8 120 -8 -30 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 -40 -24 0 0 0 1 0 1 0 -1 0 0 6222.dat +0 STEP +1 7 -40 -24 0 0 0 1 0 1 0 -1 0 0 4424.dat +1 8 -40 -71 0 0 0 1 0 1 0 -1 0 0 2489.dat +0 STEP +1 8 -40 -76 0 0 0 1 0 1 0 -1 0 0 10030 - subModel-27.ldr +0 STEP +1 1 -80 8 -40 0 0 1 0 1 0 -1 0 0 2476a.dat +1 1 100 8 -40 0 0 1 0 1 0 -1 0 0 2476a.dat + + +0 FILE 10030 - subModel-32.ldr +0 subModel-32 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-32.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3456.dat +0 STEP +1 8 -120 -8 -30 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 40 -24 0 0 0 1 0 1 0 -1 0 0 6222.dat +0 STEP +1 7 40 -24 0 0 0 1 0 1 0 -1 0 0 4424.dat +1 8 40 -71 0 0 0 1 0 1 0 -1 0 0 2489.dat +0 STEP +1 8 40 -76 0 0 0 1 0 1 0 -1 0 0 10030 - subModel-27.ldr +0 STEP +1 1 -100 8 -40 0 0 1 0 1 0 -1 0 0 2476a.dat +1 1 80 8 -40 0 0 1 0 1 0 -1 0 0 2476a.dat + + +0 FILE 10030 - subModel-33.ldr +0 subModel-33 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-33.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 -1 0 0 0 1 0 0 0 -1 30355.dat +1 8 50 0 160 0 0 -1 0 1 0 1 0 0 3710.dat +1 8 20 0 160 -1 0 0 0 1 0 0 0 -1 41770.dat +0 STEP +1 8 40 0 240 -1 0 0 0 1 0 0 0 -1 41770.dat +1 8 40 -8 100 0 0 -1 0 1 0 1 0 0 3795.dat +0 STEP +1 8 40 -8 200 -1 0 0 0 1 0 0 0 -1 41770.dat +1 8 40 -8 -10 -1 0 0 0 1 0 0 0 -1 3794a.dat +1 8 40 -8 -30 -1 0 0 0 1 0 0 0 -1 3794a.dat +1 8 40 -8 -50 -1 0 0 0 1 0 0 0 -1 3794a.dat +1 8 40 -8 -70 -1 0 0 0 1 0 0 0 -1 3794a.dat +0 STEP +1 7 50 -16 230 -1 0 0 0 1 0 0 0 -1 2555.dat +1 8 40 -16 160 -1 0 0 0 1 0 0 0 -1 41770.dat +1 7 50 -32 110 1 0 0 0 1 0 0 0 1 3040b.dat +0 STEP +1 7 50 -40 130 1 0 0 0 1 0 0 0 1 4589.dat +1 7 50 -24 150 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 50 -24 180 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 50 -32 210 1 0 0 0 1 0 0 0 1 4599a.dat +1 0 50 -8 270 1 0 0 0 1 0 0 0 1 4592.dat +1 7 50 -8 270 1 0 0 0 0.574 -0.819 0 0.819 0.574 4593.dat +0 STEP +1 1 40 8 -80 1 0 0 0 1 0 0 0 1 2476a.dat +1 1 40 8 0 1 0 0 0 1 0 0 0 1 2476a.dat +1 1 40 8 120 1 0 0 0 1 0 0 0 1 2476a.dat + + +0 FILE 10030 - subModel-34.ldr +0 subModel-34 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-34.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3031.dat +0 STEP +1 7 0 -24 0 1 0 0 0 1 0 0 0 1 6222.dat +1 0 0 -65 0 0 -1 0 1 0 0 0 0 1 3706.dat +0 STEP +1 47 0 -102.078 0 -1 0 0 0 -1 0 0 0 1 10030 - subModel-35.ldr +0 STEP +1 1 0 -125 0 -1 0 0 0 -1 0 0 0 1 10030 - subModel-36.ldr +0 STEP +1 41 0 -133 0 -1 0 0 0 -1 0 0 0 1 45729.dat + + +0 FILE 10030 - subModel-35.ldr +0 subModel-35 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-35.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 1 0 -1 0 0 0 0 1 2573.dat +1 1 0 -70 0 1 0 0 0 1 0 0 0 1 3941.dat + + +0 FILE 10030 - subModel-36.ldr +0 subModel-36 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-36.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3961.dat +1 1 0 -8 0 1 0 0 0 1 0 0 0 1 4032a.dat + + +0 FILE 10030 - subModel-37.ldr +0 subModel-37 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-37.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3027.dat +1 7 0 0 -120 1 0 0 0 1 0 0 0 1 3027.dat +1 7 0 0 -240 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 -240 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 -120 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 0 1 0 0 0 1 0 0 0 1 3027.dat +0 STEP +1 7 -120 -8 -20 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 160 -8 -80 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 540 0 -60 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 7 0 0 -360 1 0 0 0 1 0 0 0 1 3027.dat +1 7 0 0 -480 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 -320 1 0 0 0 1 0 0 0 1 4282.dat +1 7 280 0 -400 1 0 0 0 1 0 0 0 1 3028.dat +1 7 480 -8 -40 0 0 1 0 1 0 -1 0 0 3034.dat +0 STEP +1 7 -120 -8 -300 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 160 -8 -360 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 480 -8 -240 1 0 0 0 1 0 0 0 1 30355.dat +1 7 600 -8 30 1 0 0 0 1 0 0 0 1 43723.dat +0 STEP +1 7 220 0 -620 0 0 1 0 1 0 -1 0 0 3027.dat +1 7 340 0 -580 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 7 380 -8 -320 1 0 0 0 1 0 0 0 1 3031.dat +1 7 380 -8 -440 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 280 -8 -540 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 -140 0 -690 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 20 0 -720 -1 0 0 0 1 0 0 0 -1 3456.dat +1 7 0 0 -600 1 0 0 0 1 0 0 0 1 3027.dat +0 STEP +1 7 -120 -8 -660 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 160 0 -880 0 0 1 0 1 0 -1 0 0 30355.dat +1 7 160 0 -800 -1 0 0 0 1 0 0 0 -1 2445.dat +1 7 -60 0 -840 -1 0 0 0 1 0 0 0 -1 3033.dat +0 STEP +1 7 -80 0 -1080 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 -80 0 -1200 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 -40 0 -960 -1 0 0 0 1 0 0 0 -1 3028.dat +1 7 60 0 -1140 1 0 0 0 1 0 0 0 1 30355.dat +1 7 160 -8 -680 0 0 1 0 1 0 -1 0 0 4282.dat +0 STEP +1 7 -120 -8 -1020 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 0 -8 -1080 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 120 -8 -960 1 0 0 0 1 0 0 0 1 30355.dat +1 8 220 -8 -910 1 0 0 0 1 0 0 0 1 3710.dat +1 7 40 -8 -840 0 0 1 0 1 0 -1 0 0 3034.dat +0 STEP +1 7 -40 0 -1320 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 -40 0 -1440 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 100 0 -1380 1 0 0 0 1 0 0 0 1 30355.dat +1 7 100 -8 -1110 1 0 0 0 1 0 0 0 1 43723.dat +1 7 80 -8 -1170 1 0 0 0 1 0 0 0 1 43723.dat +1 7 280 -8 -930 1 0 0 0 1 0 0 0 1 43723.dat +1 8 220 -8 -940 0 0 1 0 1 0 -1 0 0 41770.dat +0 STEP +1 7 40 -8 -1260 0 0 -1 0 1 0 1 0 0 30355.dat +1 7 -120 -8 -1380 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 200 -16 -920 1 0 0 0 1 0 0 0 1 3034.dat +0 STEP +1 7 -60 0 -1560 1 0 0 0 1 0 0 0 1 3033.dat +1 7 -120 0 -1740 0 0 -1 0 1 0 1 0 0 3029.dat +1 7 -20 0 -1740 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 7 -80 -8 -1680 0 0 -1 0 1 0 1 0 0 2445.dat +1 7 40 -8 -1560 1 0 0 0 1 0 0 0 1 30355.dat +1 7 -120 0 -1940 0 0 1 0 1 0 -1 0 0 3035.dat +1 7 -130 0 -2040 -1 0 0 0 1 0 0 0 -1 3021.dat +1 7 -130 0 -2080 -1 0 0 0 1 0 0 0 -1 3021.dat +0 STEP +1 7 -130 -8 -2070 0 0 -1 0 1 0 1 0 0 3623.dat +1 7 -100 -8 -2070 1 0 0 0 1 0 0 0 1 43723.dat +1 7 -80 -8 -1920 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 7 -100 8 40 1 0 0 0 1 0 0 0 1 3020.dat +1 8 -60 8 0 1 0 0 0 1 0 0 0 1 3022.dat +1 7 160 8 -140 0 0 -1 0 1 0 1 0 0 2445.dat +1 8 220 8 -50 0 0 -1 0 1 0 1 0 0 3021.dat +1 8 470 8 -280 0 0 -1 0 1 0 1 0 0 3666.dat +1 8 480 8 -120 0 0 -1 0 1 0 1 0 0 3832.dat +0 STEP +1 0 -20 8 0 -1 0 0 0 -1 0 0 0 1 10030 - subModel-39.ldr +1 0 140 8 0 -1 0 0 0 -1 0 0 0 1 10030 - subModel-40.ldr +1 0 480 8 0 -1 0 0 0 -1 0 0 0 1 10030 - subModel-39.ldr +1 0 440 8 -200 -1 0 0 0 -1 0 0 0 1 10030 - subModel-38.ldr +1 7 -160 8 30 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 -160 8 -120 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 -130 8 -260 0 0 1 0 1 0 -1 0 0 3023.dat +1 7 160 8 -420 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 420 8 -320 0 0 1 0 1 0 -1 0 0 3031.dat +1 8 390 8 -420 0 0 1 0 1 0 -1 0 0 3666.dat +0 STEP +1 7 -160 8 -360 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 280 8 -540 0 0 1 0 1 0 -1 0 0 4282.dat +1 0 420 8 -260 -1 0 0 0 -1 0 0 0 1 10030 - subModel-38.ldr +1 1 480 16 -70 -1 0 0 0 1 0 0 0 -1 3747a.dat +1 1 220 16 -70 -1 0 0 0 1 0 0 0 -1 3747a.dat +0 STEP +1 7 -160 8 -600 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 160 8 -740 0 0 1 0 1 0 -1 0 0 4282.dat +1 8 250 8 -800 0 0 1 0 1 0 -1 0 0 4477.dat +1 8 -120 8 -720 0 0 1 0 1 0 -1 0 0 3832.dat +1 8 -130 8 -840 0 0 1 0 1 0 -1 0 0 3023.dat +0 STEP +1 0 220 8 -920 -1 0 0 0 -1 0 0 0 1 10030 - subModel-38.ldr +1 7 40 8 -920 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 -160 8 -1180 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 -160 8 -940 0 0 1 0 1 0 -1 0 0 4282.dat +0 STEP +1 7 -120 8 -1380 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 0 8 -1140 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 40 8 -1380 0 0 1 0 1 0 -1 0 0 4282.dat +1 8 30 8 -1600 0 0 1 0 1 0 -1 0 0 3666.dat +0 STEP +1 0 80 8 -1340 -1 0 0 0 -1 0 0 0 1 10030 - subModel-38.ldr +1 8 -130 8 -1760 0 0 1 0 1 0 -1 0 0 3023.dat +1 8 -110 8 -2020 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 -160 8 -1860 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 -160 8 -1620 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 -60 8 -1620 -1 0 0 0 1 0 0 0 -1 3034.dat +1 7 -100 8 -1860 -1 0 0 0 1 0 0 0 -1 3020.dat +0 STEP +1 7 -170 16 -2180 1 0 0 0 1 0 0 0 1 10030 - subModel-41.ldr +0 STEP +1 7 360 60.012 -91.296 0 0 1 -0.326 -0.946 0 0.946 -0.326 0 10030 - subModel-42.ldr + + +0 FILE 10030 - subModel-38.ldr +0 subModel-38 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-38.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 19 0 0 0 0 0 -1 0 -1 0 -1 0 0 30159.dat +1 0 0 -14.5 0 0 -1 0 0 0 1 -1 0 0 73092.dat + + +0 FILE 10030 - subModel-39.ldr +0 subModel-39 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-39.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 -1 0 0 0 -1 0 0 0 1 2817.dat +1 1 -20 -10 0 -1 0 0 0 -1 0 0 0 1 43093.dat + + +0 FILE 10030 - subModel-40.ldr +0 subModel-40 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-40.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 -1 0 0 0 -1 0 0 0 1 2817.dat +1 0 -20 -10 0 -1 0 0 0 -1 0 0 0 1 2780.dat + + +0 FILE 10030 - subModel-41.ldr +0 subModel-41 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-41.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +0 STEP +1 7 10 -8 80 0 0 1 0 1 0 -1 0 0 2445.dat +0 STEP +1 7 10 -8 -70 1 0 0 0 1 0 0 0 1 43723.dat +1 7 30 -16 -10 1 0 0 0 1 0 0 0 1 43723.dat +1 7 30 -16 50 0 0 1 0 1 0 -1 0 0 3021.dat +0 STEP +1 7 50 -24 50 1 0 0 0 1 0 0 0 1 43723.dat + + +0 FILE 10030 - subModel-42.ldr +0 subModel-42 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-42.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 100 -8 -40 0 0 1 0 1 0 -1 0 0 3456.dat +0 STEP +1 7 40 -8 160 0 0 1 0 1 0 -1 0 0 30356.dat +0 STEP +1 7 100 -8 -300 1 0 0 0 1 0 0 0 1 30356.dat +1 8 50 0 -140 1 0 0 0 1 0 0 0 1 3021.dat +1 8 120 0 210 0 0 -1 0 1 0 1 0 0 3021.dat +0 STEP +1 8 50 0 -190 0 0 1 0 1 0 -1 0 0 2450.dat +1 7 100 0 160 0 0 1 0 1 0 -1 0 0 2817.dat +1 7 100 0 -180 0 0 1 0 1 0 -1 0 0 2817.dat +1 7 100 0 -340 0 0 1 0 1 0 -1 0 0 2817.dat +0 STEP +1 7 130 -8 240 0 0 1 0 1 0 -1 0 0 43722.dat +1 8 -30 -8 80 -1 0 0 0 1 0 0 0 -1 3021.dat +1 7 130 -16 100 0 0 -1 0 1 0 1 0 0 2431.dat +1 7 130 -16 -180 0 0 -1 0 1 0 1 0 0 2431.dat +0 STEP +1 7 20 -8 -150 1 0 0 0 1 0 0 0 1 43722.dat +1 7 -60 -16 90 1 0 0 0 1 0 0 0 1 43722.dat +1 7 40 -16 200 0 0 1 0 1 0 -1 0 0 3934.dat + + +0 FILE 10030 - subModel-43.ldr +0 subModel-43 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-43.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3027.dat +1 7 0 0 -120 1 0 0 0 1 0 0 0 1 3027.dat +1 7 0 0 -240 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 0 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 -120 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 -240 1 0 0 0 1 0 0 0 1 3027.dat +0 STEP +1 7 440 -8 -20 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 160 -8 -80 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 -220 0 -60 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 -160 -8 -40 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 320 0 -360 1 0 0 0 1 0 0 0 1 3027.dat +1 7 320 0 -480 1 0 0 0 1 0 0 0 1 3027.dat +1 7 0 0 -320 1 0 0 0 1 0 0 0 1 4282.dat +1 7 40 0 -400 1 0 0 0 1 0 0 0 1 3028.dat +0 STEP +1 7 160 -8 -360 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 440 -8 -300 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 -160 -8 -240 1 0 0 0 1 0 0 0 1 30356.dat +1 7 -280 -8 30 1 0 0 0 1 0 0 0 1 43722.dat +0 STEP +1 7 -20 0 -580 1 0 0 0 1 0 0 0 1 30356.dat +1 7 100 0 -620 0 0 1 0 1 0 -1 0 0 3027.dat +0 STEP +1 7 -60 -8 -320 0 0 1 0 1 0 -1 0 0 3031.dat +1 7 -60 -8 -440 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 40 -8 -540 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 300 0 -720 -1 0 0 0 1 0 0 0 -1 3456.dat +1 7 460 0 -690 0 0 -1 0 1 0 1 0 0 3021.dat +0 STEP +1 7 440 -8 -660 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 160 0 -800 -1 0 0 0 1 0 0 0 -1 2445.dat +1 7 160 0 -880 0 0 -1 0 1 0 1 0 0 30356.dat +1 7 320 0 -600 1 0 0 0 1 0 0 0 1 3027.dat +1 7 380 0 -840 1 0 0 0 1 0 0 0 1 3033.dat +0 STEP +1 7 160 -8 -680 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 360 0 -960 -1 0 0 0 1 0 0 0 -1 3028.dat +1 7 400 0 -1080 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 400 0 -1200 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 260 0 -1140 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 200 -8 -960 1 0 0 0 1 0 0 0 1 30356.dat +1 7 320 -8 -1080 0 0 1 0 1 0 -1 0 0 3034.dat +1 7 280 -8 -840 0 0 1 0 1 0 -1 0 0 3034.dat +1 8 100 -8 -910 -1 0 0 0 1 0 0 0 -1 3710.dat +0 STEP +1 7 360 0 -1320 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 360 0 -1440 -1 0 0 0 1 0 0 0 -1 3036.dat +1 7 220 0 -1380 1 0 0 0 1 0 0 0 1 30356.dat +1 7 40 -8 -930 1 0 0 0 1 0 0 0 1 43722.dat +1 72 100 -8 -940 0 0 -1 0 1 0 1 0 0 41769.dat +1 7 220 -8 -1110 1 0 0 0 1 0 0 0 1 43722.dat +1 7 240 -8 -1170 1 0 0 0 1 0 0 0 1 43722.dat +0 STEP +1 7 120 -16 -920 -1 0 0 0 1 0 0 0 -1 3034.dat +1 7 440 -8 -1020 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 440 -8 -1380 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 280 -8 -1260 0 0 1 0 1 0 -1 0 0 30356.dat +0 STEP +1 7 380 0 -1560 -1 0 0 0 1 0 0 0 -1 3033.dat +1 7 440 0 -1740 0 0 -1 0 1 0 1 0 0 3029.dat +1 7 340 0 -1740 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 440 0 -1940 0 0 1 0 1 0 -1 0 0 3035.dat +1 7 400 -8 -1680 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 280 -8 -1560 1 0 0 0 1 0 0 0 1 30356.dat +1 7 450 0 -2040 1 0 0 0 1 0 0 0 1 3021.dat +1 7 450 0 -2080 1 0 0 0 1 0 0 0 1 3021.dat +0 STEP +1 7 420 -8 -2070 1 0 0 0 1 0 0 0 1 43722.dat +1 7 400 -8 -1920 1 0 0 0 1 0 0 0 1 30356.dat +1 7 450 -8 -2070 0 0 1 0 1 0 -1 0 0 3623.dat +0 STEP +1 7 420 8 40 1 0 0 0 1 0 0 0 1 3020.dat +1 8 380 8 0 1 0 0 0 1 0 0 0 1 3022.dat +1 7 160 8 -140 0 0 -1 0 1 0 1 0 0 2445.dat +1 8 100 8 -50 0 0 -1 0 1 0 1 0 0 3021.dat +1 8 -150 8 -280 0 0 -1 0 1 0 1 0 0 3666.dat +1 8 -160 8 -120 0 0 -1 0 1 0 1 0 0 3832.dat +0 STEP +1 7 340 8 0 1 0 0 0 -1 0 0 0 -1 10030 - subModel-39.ldr +1 7 140 8 0 1 0 0 0 -1 0 0 0 -1 10030 - subModel-40.ldr +1 7 -160 8 0 1 0 0 0 -1 0 0 0 -1 10030 - subModel-39.ldr +1 7 -120 8 -200 1 0 0 0 -1 0 0 0 -1 10030 - subModel-38.ldr +1 7 480 8 30 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 480 8 -120 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 450 8 -260 0 0 1 0 1 0 -1 0 0 3023.dat +1 7 -100 8 -320 0 0 1 0 1 0 -1 0 0 3031.dat +1 8 -70 8 -420 0 0 -1 0 1 0 1 0 0 3666.dat +0 STEP +1 7 40 8 -540 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 160 8 -420 0 0 -1 0 1 0 1 0 0 4282.dat +1 1 100 16 -70 -1 0 0 0 1 0 0 0 -1 3747a.dat +1 1 -160 16 -70 -1 0 0 0 1 0 0 0 -1 3747a.dat +0 STEP +1 7 -100 8 -260 1 0 0 0 -1 0 0 0 -1 10030 - subModel-38.ldr +1 7 480 8 -360 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 480 8 -600 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 440 8 -720 0 0 -1 0 1 0 1 0 0 3832.dat +1 8 450 8 -840 0 0 1 0 1 0 -1 0 0 3023.dat +1 7 160 8 -740 0 0 -1 0 1 0 1 0 0 4282.dat +1 8 70 8 -800 0 0 -1 0 1 0 1 0 0 4477.dat +0 STEP +1 7 480 8 -1180 0 0 -1 0 1 0 1 0 0 3034.dat +1 7 480 8 -940 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 280 8 -900 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 100 8 -920 1 0 0 0 -1 0 0 0 -1 10030 - subModel-38.ldr +0 STEP +1 7 320 8 -1140 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 280 8 -1380 0 0 -1 0 1 0 1 0 0 4282.dat +1 8 290 8 -1600 0 0 -1 0 1 0 1 0 0 3666.dat +0 STEP +1 7 240 8 -1340 1 0 0 0 -1 0 0 0 -1 10030 - subModel-38.ldr +1 7 440 8 -1380 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 480 8 -1620 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 480 8 -1860 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 450 8 -1760 0 0 1 0 1 0 -1 0 0 3023.dat +1 8 430 8 -2020 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 420 8 -1860 1 0 0 0 1 0 0 0 1 3020.dat +1 7 380 8 -1620 1 0 0 0 1 0 0 0 1 3034.dat +0 STEP +1 7 490 16 -2180 1 0 0 0 1 0 0 0 1 10030 - subModel-44.ldr +0 STEP +1 7 -40 53.541 -94.004 0 0 -1 0.259 -0.966 0 -0.966 -0.259 0 10030 - subModel-45.ldr + + +0 FILE 10030 - subModel-44.ldr +0 subModel-44 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-44.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +0 STEP +1 7 -10 -8 80 0 0 1 0 1 0 -1 0 0 2445.dat +0 STEP +1 7 -10 -8 -70 1 0 0 0 1 0 0 0 1 43722.dat +1 7 -30 -16 -10 1 0 0 0 1 0 0 0 1 43722.dat +1 7 -30 -16 50 0 0 1 0 1 0 -1 0 0 3021.dat +0 STEP +1 7 -50 -24 50 1 0 0 0 1 0 0 0 1 43722.dat + + +0 FILE 10030 - subModel-45.ldr +0 subModel-45 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-45.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 7 -100 -8 -40 0 0 1 0 1 0 -1 0 0 3456.dat +0 STEP +1 7 -40 -8 160 0 0 -1 0 1 0 1 0 0 30355.dat +0 STEP +1 7 -100 -8 -300 1 0 0 0 1 0 0 0 1 30355.dat +1 8 -50 0 -140 1 0 0 0 1 0 0 0 1 3021.dat +1 8 -120 0 210 0 0 -1 0 1 0 1 0 0 3021.dat +1 8 -50 0 -190 1 0 0 0 1 0 0 0 1 2450.dat +0 STEP +1 7 -100 0 160 0 0 -1 0 1 0 1 0 0 2817.dat +1 7 -100 0 -140 0 0 -1 0 1 0 1 0 0 2817.dat +1 7 -100 0 -340 0 0 -1 0 1 0 1 0 0 2817.dat +0 STEP +1 7 -130 -8 240 0 0 -1 0 1 0 1 0 0 43723.dat +1 7 -130 -16 100 0 0 -1 0 1 0 1 0 0 2431.dat +1 7 -130 -16 -180 0 0 -1 0 1 0 1 0 0 2431.dat +1 8 30 -8 80 1 0 0 0 1 0 0 0 1 3021.dat +0 STEP +1 7 60 -16 90 1 0 0 0 1 0 0 0 1 43723.dat +1 7 -20 -8 -150 1 0 0 0 1 0 0 0 1 43723.dat +1 7 -40 -16 200 0 0 -1 0 1 0 1 0 0 3933.dat + + +0 FILE 10030 - subModel-46.ldr +0 subModel-46 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-46.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +0 !LDCAD GROUP_DEF [topLevel=true] [LID=0] [GID=B8PYp6VbEPB] [name=Group 1] [center=0 0 0] +0 !LDCAD GROUP_NXT [ids=0] [nrs=2] +1 7 36.171 -35.349 -62.106 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 6205.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=3] +1 7 73.144 -35.349 -176.268 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3027.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=4] +1 7 -0.803 -35.349 52.056 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 6205.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=5] +1 7 293.256 -118.171 147.292 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3027.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=6] +1 7 232.39 -81.936 -103.671 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=7] +1 7 -82.233 -12.018 -79.431 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=8] +1 7 293.58 -102.642 -41.808 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=9] +1 7 199.609 -89.664 -9.174 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3029.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=10] +1 7 397.582 -138.876 75.967 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3035.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=11] +1 7 513.908 -175.111 155.686 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=12] +1 7 110.334 -24.996 -416.497 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3028.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=13] +1 7 110.118 -35.349 -290.43 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3027.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=14] +1 7 383.287 -146.604 113.382 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=15] +1 7 539.344 -198.368 258.527 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 43723.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=16] +1 7 4.039 -12.018 -345.809 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=17] +1 7 147.308 -24.996 -530.659 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3028.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=18] +1 7 294.229 -71.583 -420.007 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=19] +1 7 291.935 -94.84 -231.545 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=20] +1 7 255.61 -63.782 -495.583 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=21] +1 8 215.501 -66.37 -340.391 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 4162.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=22] +1 0 175.501 -63.782 -248.232 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3680.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=23] +1 0 181.771 -58.605 -330.292 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3680.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=24] +1 0 188.042 -53.429 -412.353 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3680.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=25] +1 0 169.23 -68.958 -166.172 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3680.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=26] +1 7 169.23 -68.958 -166.172 0.702 0.246 -0.668 -0.234 0.966 0.109 0.672 0.08 0.736 3679.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=27] +1 7 175.501 -63.782 -248.232 0.702 0.246 -0.668 -0.234 0.966 0.109 0.672 0.08 0.736 3679.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=28] +1 7 181.771 -58.605 -330.292 0.702 0.246 -0.668 -0.234 0.966 0.109 0.672 0.08 0.736 3679.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=29] +1 7 188.042 -53.429 -412.353 0.702 0.246 -0.668 -0.234 0.966 0.109 0.672 0.08 0.736 3679.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=30] +1 7 239.418 -40.525 -626.964 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3456.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=31] +1 7 258.012 -35.349 -747.078 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3027.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=32] +1 7 83.145 0.886 -646.042 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3021.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=33] +1 7 294.986 -35.349 -861.24 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 6205.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=34] +1 7 331.959 -35.349 -975.402 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 6205.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=35] +1 7 90.311 -12.018 -612.187 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=36] +1 7 515.638 -92.289 -852.846 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=37] +1 7 452.37 -84.487 -852.314 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=38] +1 7 390.747 -84.487 -662.044 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 30356.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=39] +1 7 201.231 -12.018 -954.673 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=40] +1 7 368.933 -35.349 -1089.564 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3027.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=41] +1 7 369.149 -24.996 -1215.631 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3036.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=42] +1 7 406.123 -24.996 -1329.793 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3036.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=43] +1 7 516.287 -61.231 -1231.045 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=44] +1 7 425.042 -4.29 -1639.007 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3029.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=45] +1 7 516.936 -30.172 -1609.245 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=46] +1 7 424.718 -19.82 -1449.907 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3033.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=47] +1 7 312.152 -12.018 -1297.159 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=48] +1 7 440.694 -53.429 -1192.459 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 2445.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=49] +1 7 441.343 -22.371 -1570.659 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=50] +1 7 514.642 -53.429 -1420.783 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=51] +1 7 486.665 -4.29 -1829.277 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3035.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=52] +1 7 508.287 -1.702 -1927.388 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3021.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=53] +1 7 520.612 -1.702 -1965.442 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3021.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=54] +1 7 515.291 -22.371 -1798.983 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 30355.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=55] +1 7 543.128 -17.194 -1947.638 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 43723.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=56] +1 7 515.56 -9.43 -1956.566 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3623.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=57] +1 7 -103.051 -1.739 60.986 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3020.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=58] +1 8 -53.969 -12.092 34.837 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3022.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=59] +1 7 387.227 -131.149 114.658 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=60] +1 8 237.171 -87.15 45.037 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3666.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=61] +1 7 -155.105 13.79 33.616 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3021.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=62] +1 8 203.549 -74.209 -7.898 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3030.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=63] +1 7 399.66 -125.973 13.571 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3456.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=64] +1 7 -17.212 -22.445 46.741 -0.919 -0.246 -0.308 0.259 -0.966 0 -0.298 -0.08 0.951 10030 - subModel-39.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=65] +1 7 405.498 -141.502 183.644 -0.919 -0.246 -0.308 0.259 -0.966 0 -0.298 -0.08 0.951 10030 - subModel-39.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=66] +1 7 203.333 -84.562 118.169 -0.919 -0.246 -0.308 0.259 -0.966 0 -0.298 -0.08 0.951 10030 - subModel-40.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=67] +1 7 -108.888 13.79 -109.087 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=68] +1 7 -34.941 13.79 -337.411 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=69] +1 7 252.955 -69.032 -223.147 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=70] +1 8 -38.184 6.025 -233.347 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3023.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=71] +1 1 226.87 -76.834 52.212 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3747a.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=72] +1 1 469.09 -133.774 -5.988 0.919 -0.246 0.308 -0.259 -0.966 0 0.298 -0.08 -0.951 10030 - subModel-38.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=73] +1 1 429.036 -133.774 117.688 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3747a.dat +0 STEP +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=74] +1 7 39.006 13.79 -565.734 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=75] +1 8 140.521 6.025 -785.13 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3023.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=76] +1 8 112.737 3.437 -667.992 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3832.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=77] +1 7 241.063 -48.327 -437.226 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=78] +1 7 320.956 -58.68 -558.51 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=79] +1 8 388.741 -58.68 -767.807 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=80] +1 7 474.796 -69.032 -908.119 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=81] +1 7 486.797 -84.562 -757.073 -0.308 -0.246 0.919 0 -0.966 -0.259 0.951 -0.08 0.298 10030 - subModel-38.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=82] +1 7 143.764 13.79 -889.193 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=83] +1 7 217.712 13.79 -1117.517 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3034.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=84] +1 7 316.092 3.437 -1295.883 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=85] +1 7 353.282 13.79 -1536.111 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=86] +1 8 423.986 6.025 -1660.372 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3023.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=87] +1 7 463.121 -37.974 -1248.264 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=88] +1 8 527.23 -66.444 -1101.365 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 3710.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=89] +1 7 487.554 -48.327 -1198.306 -0.919 -0.246 -0.308 0.259 -0.966 0 -0.298 -0.08 0.951 10030 - subModel-38.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=90] +1 7 427.229 13.79 -1764.435 -0.308 0.246 -0.919 0 0.966 0.259 0.951 0.08 -0.298 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=91] +1 7 482.364 -1.739 -1746.578 -0.919 0.246 0.308 0.259 0.966 0 -0.298 0.08 -0.951 3020.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=92] +1 8 521.717 -35.386 -1460.537 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3666.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=93] +1 7 445.174 -12.092 -1506.35 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 3034.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=94] +1 7 518.605 24.105 -2071.205 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 10030 - subModel-47.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=95] +1 7 512.647 -123.236 -769.723 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 3039.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=96] +1 7 537.242 -125.824 -814.315 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 6565.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=97] +1 7 193.097 -63.502 -406.273 0.668 0.246 0.702 -0.109 0.966 -0.234 -0.736 0.08 0.672 10030 - subModel-48.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=98] +1 7 186.827 -68.678 -324.213 0.668 0.246 0.702 -0.109 0.966 -0.234 -0.736 0.08 0.672 10030 - subModel-48.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=99] +1 7 180.557 -73.855 -242.152 0.668 0.246 0.702 -0.109 0.966 -0.234 -0.736 0.08 0.672 10030 - subModel-48.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=100] +1 7 174.287 -79.031 -160.092 0.668 0.246 0.702 -0.109 0.966 -0.234 -0.736 0.08 0.672 10030 - subModel-48.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=101] +1 7 510.678 -130.963 -770.361 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 2412b.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=102] +1 7 537.135 -131 -751.281 0.919 0.246 -0.308 -0.259 0.966 0 0.298 0.08 0.951 6565.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=103] +1 0 532.246 -130.963 -836.956 0.827 0.246 0.506 -0.166 0.966 -0.198 -0.537 0.08 0.84 4592.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=104] +1 7 532.246 -130.963 -836.956 0.827 0.506 -0.246 -0.166 -0.198 -0.966 -0.537 0.84 -0.08 4593.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=105] +1 7 521.999 -118.059 -861.297 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 4599a.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=106] +1 8 391.805 -94.803 -640.678 0.308 0.246 0.919 0 0.966 -0.259 -0.951 0.08 0.298 4162.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=107] +1 7 487.771 -112.064 156.817 -0.919 -0.133 -0.371 0.259 -0.913 -0.314 -0.298 -0.386 0.874 10030 - subModel-49.ldr +0 STEP +1 4 560 40 -50 1 0 0 0 1 0 0 0 1 10030 - subModel-1.ldr +0 STEP +1 4 1120.692 -35.349 51.796 0.919 -0.246 0.308 0.259 0.966 0 -0.298 0.08 0.951 10030 - subModel-50.ldr + + +0 FILE 10030 - subModel-47.ldr +0 subModel-47 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-47.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +0 STEP +1 7 10 -8 80 0 0 1 0 1 0 -1 0 0 2445.dat +0 STEP +1 7 30 -16 -10 1 0 0 0 1 0 0 0 1 43723.dat +1 7 30 -16 50 0 0 1 0 1 0 -1 0 0 3021.dat +0 STEP +1 7 10 -8 -70 1 0 0 0 1 0 0 0 1 43723.dat +1 7 50 -24 50 1 0 0 0 1 0 0 0 1 43723.dat + + +0 FILE 10030 - subModel-48.ldr +0 subModel-48 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-48.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3023.dat +0 STEP +1 7 0 -8 0 1 0 0 0 1 0 0 0 1 3839b.dat +0 STEP +1 7 20 -2 -42 -1 0 0 0 1 0 0 0 -1 30162.dat +1 7 -20 -2 -42 -1 0 0 0 1 0 0 0 -1 30162.dat +0 STEP +1 7 0 -16 -10 -1 0 0 0 1 0 0 0 -1 4150.dat + + +0 FILE 10030 - subModel-49.ldr +0 subModel-49 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-49.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 -20 0 0 1 0 0 0 1 0 0 0 1 30356.dat +1 7 180 0 60 1 0 0 0 1 0 0 0 1 3456.dat +1 7 440 0 60 0 0 -1 0 1 0 1 0 0 30356.dat +0 STEP +1 7 40 -8 90 1 0 0 0 1 0 0 0 1 2431.dat +1 7 320 -8 90 1 0 0 0 1 0 0 0 1 2431.dat +0 STEP +1 8 -70 8 80 1 0 0 0 1 0 0 0 1 3021.dat +1 7 140 8 -40 0 0 -1 0 1 0 1 0 0 30356.dat +0 STEP +1 8 280 8 10 0 0 1 0 1 0 -1 0 0 3021.dat +1 8 330 8 10 1 0 0 0 1 0 0 0 1 2450.dat +1 7 20 8 60 1 0 0 0 1 0 0 0 1 2817.dat +1 7 240 8 60 1 0 0 0 1 0 0 0 1 2817.dat +1 7 500 8 60 1 0 0 0 1 0 0 0 1 2817.dat +0 STEP +1 8 60 0 -70 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 290 0 -20 0 0 -1 0 1 0 1 0 0 43722.dat +1 7 -100 0 90 1 0 0 0 1 0 0 0 1 43722.dat +0 STEP +1 7 50 -8 -100 0 0 -1 0 1 0 1 0 0 43722.dat +1 7 -60 -8 0 1 0 0 0 1 0 0 0 1 3934.dat + + +0 FILE 10030 - subModel-50.ldr +0 subModel-50 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-50.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 6205.dat +1 7 0 0 -120 -1 0 0 0 1 0 0 0 -1 6205.dat +1 7 0 0 -240 -1 0 0 0 1 0 0 0 -1 3027.dat +0 STEP +1 7 -320 0 0 -1 0 0 0 1 0 0 0 -1 3027.dat +1 7 120 -8 -100 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 -180 0 -220 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 -260 0 -180 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 -180 -8 -120 0 0 -1 0 1 0 1 0 0 3029.dat +0 STEP +1 7 -400 0 -100 1 0 0 0 1 0 0 0 1 3035.dat +1 7 -540 0 -60 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 -600 -8 30 1 0 0 0 1 0 0 0 1 43722.dat +1 7 -400 -8 -60 1 0 0 0 1 0 0 0 1 2445.dat +1 7 0 0 -360 -1 0 0 0 1 0 0 0 -1 3027.dat +1 7 40 0 -480 1 0 0 0 1 0 0 0 1 3028.dat +0 STEP +1 7 40 0 -600 1 0 0 0 1 0 0 0 1 3028.dat +1 7 -140 0 -540 1 0 0 0 1 0 0 0 1 30356.dat +1 7 120 -8 -380 0 0 1 0 1 0 -1 0 0 2445.dat +0 STEP +1 7 -200 -8 -360 1 0 0 0 1 0 0 0 1 30356.dat +1 7 -80 -8 -600 0 0 1 0 1 0 -1 0 0 3034.dat +1 8 -90 -8 -440 0 0 1 0 1 0 -1 0 0 4162.dat +1 0 -40 -8 -500 0 0 1 0 1 0 -1 0 0 3680.dat +1 0 -60 -8 -420 0 0 1 0 1 0 -1 0 0 3680.dat +1 0 -80 -8 -340 0 0 1 0 1 0 -1 0 0 3680.dat +1 0 -100 -8 -260 0 0 1 0 1 0 -1 0 0 3680.dat +1 7 -40 -8 -500 0.906 0 0.423 0 1 0 -0.423 0 0.906 3679.dat +1 7 -60 -8 -420 0.906 0 0.423 0 1 0 -0.423 0 0.906 3679.dat +1 7 -80 -8 -340 0.906 0 0.423 0 1 0 -0.423 0 0.906 3679.dat +1 7 -100 -8 -260 0.906 0 0.423 0 1 0 -0.423 0 0.906 3679.dat +0 STEP +1 7 -20 0 -720 1 0 0 0 1 0 0 0 1 3456.dat +1 7 0 0 -840 1 0 0 0 1 0 0 0 1 3027.dat +1 7 140 0 -690 0 0 -1 0 1 0 1 0 0 3021.dat +0 STEP +1 7 120 -8 -660 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 0 0 -960 1 0 0 0 1 0 0 0 1 6205.dat +1 7 0 0 -1080 -1 0 0 0 1 0 0 0 -1 6205.dat +1 7 -220 0 -1020 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 120 -8 -1020 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 -160 -8 -800 -1 0 0 0 1 0 0 0 -1 30355.dat +1 7 -160 -8 -1000 0 0 1 0 1 0 -1 0 0 3034.dat +0 STEP +1 7 0 0 -1200 1 0 0 0 1 0 0 0 1 3027.dat +1 7 40 0 -1320 1 0 0 0 1 0 0 0 1 3036.dat +1 7 40 0 -1440 1 0 0 0 1 0 0 0 1 3036.dat +1 7 -100 0 -1380 1 0 0 0 1 0 0 0 1 30356.dat +1 7 -40 -8 -1320 0 0 1 0 1 0 -1 0 0 2445.dat +0 STEP +1 7 60 0 -1560 -1 0 0 0 1 0 0 0 -1 3033.dat +1 7 120 -8 -1380 0 0 -1 0 1 0 1 0 0 4282.dat +1 7 120 0 -1740 0 0 -1 0 1 0 1 0 0 3029.dat +1 7 20 0 -1740 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 -40 -8 -1560 1 0 0 0 1 0 0 0 1 30356.dat +1 7 80 -8 -1680 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 120 0 -1940 0 0 1 0 1 0 -1 0 0 3035.dat +1 7 130 0 -2040 -1 0 0 0 1 0 0 0 -1 3021.dat +1 7 130 0 -2080 -1 0 0 0 1 0 0 0 -1 3021.dat +1 7 -160 -8 -1200 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 80 -8 -1920 1 0 0 0 1 0 0 0 1 30356.dat +1 7 100 -8 -2070 1 0 0 0 1 0 0 0 1 43722.dat +1 7 130 -8 -2070 0 0 1 0 1 0 -1 0 0 3623.dat +0 STEP +1 7 -400 8 -60 -1 0 0 0 1 0 0 0 -1 2445.dat +1 8 -230 8 -80 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 100 8 40 1 0 0 0 1 0 0 0 1 3020.dat +1 8 60 8 0 1 0 0 0 1 0 0 0 1 3022.dat +0 STEP +1 8 20 8 0 1 0 0 0 -1 0 0 0 -1 10030 - subModel-39.ldr +1 8 -440 8 0 1 0 0 0 -1 0 0 0 -1 10030 - subModel-39.ldr +1 8 -220 8 0 1 0 0 0 -1 0 0 0 -1 10030 - subModel-40.ldr +1 8 -180 8 -120 0 0 -1 0 1 0 1 0 0 3030.dat +1 7 -380 8 -160 -1 0 0 0 1 0 0 0 -1 3456.dat +1 7 160 8 30 0 0 1 0 1 0 -1 0 0 3021.dat +0 STEP +1 7 -160 8 -340 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 160 8 -120 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 160 8 -360 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 130 8 -260 0 0 1 0 1 0 -1 0 0 3023.dat +1 1 -440 16 -70 -1 0 0 0 1 0 0 0 -1 3747a.dat +1 1 -220 16 -70 -1 0 0 0 1 0 0 0 -1 3747a.dat +1 1 -440 16 -200 0 0 1 0 -1 0 1 0 0 10030 - subModel-38.ldr +0 STEP +1 7 160 8 -600 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 120 8 -720 0 0 1 0 1 0 -1 0 0 3832.dat +1 8 130 8 -840 0 0 1 0 1 0 -1 0 0 3023.dat +1 7 -80 8 -540 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 -120 8 -680 0 0 1 0 1 0 -1 0 0 4282.dat +0 STEP +1 7 -160 8 -1060 0 0 1 0 1 0 -1 0 0 4282.dat +1 1 -220 8 -920 0 0 -1 0 -1 0 -1 0 0 10030 - subModel-38.ldr +1 8 -120 8 -900 0 0 1 0 1 0 -1 0 0 3795.dat +1 7 160 8 -940 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 160 8 -1180 0 0 1 0 1 0 -1 0 0 3034.dat +0 STEP +1 8 -150 8 -1260 0 0 1 0 1 0 -1 0 0 3710.dat +1 7 -40 8 -1380 0 0 1 0 1 0 -1 0 0 4282.dat +1 1 -80 8 -1340 -1 0 0 0 -1 0 0 0 1 10030 - subModel-38.ldr +1 7 120 8 -1380 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 160 8 -1620 0 0 1 0 1 0 -1 0 0 2445.dat +1 8 130 8 -1760 0 0 1 0 1 0 -1 0 0 3023.dat +0 STEP +1 8 -30 8 -1600 0 0 -1 0 1 0 1 0 0 3666.dat +1 7 60 8 -1620 -1 0 0 0 1 0 0 0 -1 3034.dat +1 7 160 8 -1860 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 100 8 -1860 1 0 0 0 1 0 0 0 1 3020.dat +0 STEP +1 7 170 16 -2180 1 0 0 0 1 0 0 0 1 10030 - subModel-51.ldr +0 STEP +1 7 -280 -24 -930 1 0 0 0 1 0 0 0 1 6564.dat +1 7 -260 -24 -990 1 0 0 0 1 0 0 0 1 6564.dat +1 7 -250 -24 -940 0 0 -1 0 1 0 1 0 0 3039.dat +1 7 -49.063 -16 -495.774 0.423 0 -0.906 0 1 0 0.906 0 0.423 10030 - subModel-48.ldr +1 7 -69.063 -16 -415.774 0.423 0 -0.906 0 1 0 0.906 0 0.423 10030 - subModel-48.ldr +1 7 -89.063 -16 -335.774 0.423 0 -0.906 0 1 0 0.906 0 0.423 10030 - subModel-48.ldr +1 7 -109.063 -16 -255.774 0.423 0 -0.906 0 1 0 0.906 0 0.423 10030 - subModel-48.ldr +0 STEP +1 7 -250 -32 -940 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -230 -24 -1030 0 0 -1 0 1 0 1 0 0 4599a.dat +1 0 -250 -32 -1010 0 0 -1 0 1 0 1 0 0 4592.dat +1 7 -250 -32 -1010 0.707 -0.707 0 0 0 -1 0.707 0.707 0 4593.dat +1 8 -170 -16 -780 0 0 -1 0 1 0 1 0 0 4162.dat +0 STEP +1 7 -320 35.387 4.659 -1 0 0 0 -0.966 -0.259 0 -0.259 0.966 10030 - subModel-52.ldr + + +0 FILE 10030 - subModel-51.ldr +0 subModel-51 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-51.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +0 STEP +1 7 -10 -8 80 0 0 1 0 1 0 -1 0 0 2445.dat +0 STEP +1 7 -30 -16 50 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 -30 -16 -10 1 0 0 0 1 0 0 0 1 43722.dat +0 STEP +1 7 -50 -24 50 1 0 0 0 1 0 0 0 1 43722.dat +1 7 -10 -8 -70 1 0 0 0 1 0 0 0 1 43722.dat + + +0 FILE 10030 - subModel-52.ldr +0 subModel-52 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-52.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3456.dat +1 7 -260 0 0 0 0 1 0 1 0 -1 0 0 30355.dat +1 7 200 0 -60 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 7 140 -8 30 1 0 0 0 1 0 0 0 1 2431.dat +1 7 -140 -8 30 1 0 0 0 1 0 0 0 1 2431.dat +0 STEP +1 8 250 8 20 1 0 0 0 1 0 0 0 1 3021.dat +1 7 40 8 -100 0 0 1 0 1 0 -1 0 0 30355.dat +0 STEP +1 8 -100 8 -50 0 0 -1 0 1 0 1 0 0 3021.dat +1 8 -150 8 -50 0 0 1 0 1 0 -1 0 0 2450.dat +1 7 160 8 0 1 0 0 0 1 0 0 0 1 2817.dat +1 7 -60 8 0 1 0 0 0 1 0 0 0 1 2817.dat +1 7 -300 8 0 1 0 0 0 1 0 0 0 1 2817.dat +0 STEP +1 7 -110 0 -80 0 0 1 0 1 0 -1 0 0 43723.dat +1 8 120 0 -130 0 0 -1 0 1 0 1 0 0 3021.dat +1 7 280 0 30 1 0 0 0 1 0 0 0 1 43723.dat +0 STEP +1 7 130 -8 -160 0 0 1 0 1 0 -1 0 0 43723.dat +1 7 240 -8 -60 1 0 0 0 1 0 0 0 1 3933.dat + + +0 FILE 10030 - subModel-53.ldr +0 subModel-53 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-53.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +0 !LDCAD GROUP_NXT [ids=2] [nrs=14] +0 !LDCAD GROUP_DEF [topLevel=true] [LID=0] [GID=3MOMjGTbQjq] [name=Group 1] [center=0 0 0] +0 !LDCAD GROUP_NXT [ids=2] [nrs=15] +0 !LDCAD GROUP_DEF [topLevel=true] [LID=1] [GID=2yST0s5NA0g] [name=Group 2] [center=0 0 0] +0 !LDCAD GROUP_DEF [topLevel=true] [LID=2] [GID=HnT9rOWSsNi] [name=Group 3] [center=0 0 0] +0 !LDCAD GROUP_NXT [ids=2] [nrs=-1] +1 7 0 0 0 0.985 0.174 0 -0.174 0.985 0 0 0 1 32324.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=2] +1 0 -37.656 16.794 20 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=3] +1 0 -37.656 16.794 -20 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=4] +1 0 41.129 2.902 20 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=5] +1 0 41.129 2.902 -20 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=6] +1 7 49.24 -8.682 0 0 0.174 0.985 0 0.985 -0.174 -1 0 0 3703.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=7] +1 0 60.825 -0.571 100 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=8] +1 0 60.825 -0.571 -100 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=9] +1 4 0 0 140 0.985 0.174 0 -0.174 0.985 0 0 0 1 6249.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=10] +1 4 0 0 -140 0.985 0.174 0 -0.174 0.985 0 0 0 1 6249.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=11] +1 7 -49.24 8.682 0 0 0.174 0.985 0 0.985 -0.174 -1 0 0 3703.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=12] +1 0 -57.352 20.267 -100 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=13] +1 0 -57.352 20.267 100 0.985 0.174 0 -0.174 0.985 0 0 0 1 2780.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=42] +1 0 -67.829 18.438 -141.072 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 3702.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=11] +1 0 -67.829 18.438 141.072 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 3702.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=13] +1 0 70.044 -5.872 141.072 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 3702.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=72] +1 0 70.044 -5.872 -141.072 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 3702.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=29] +1 4 120.915 -5.31 200.333 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 6249.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=80] +1 4 117.655 -23.798 81.811 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 6249.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=33] +1 4 117.655 -23.798 -81.811 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 6249.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=73] +1 4 120.915 -5.31 -200.333 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 6249.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=14] +1 0 217.766 -31.92 141.072 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 40345.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=34] +1 0 217.766 -31.92 -141.072 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 40345.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=35] +1 1 201.958 -6.395 -218.523 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=36] +1 1 241.35 -13.341 -218.523 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=27] +1 1 201.958 -6.395 218.523 0.027 -0.172 0.985 0.154 -0.973 -0.174 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=26] +1 1 241.35 -13.341 218.523 0.027 -0.172 0.985 0.154 -0.973 -0.174 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=25] +1 1 280.199 -23.368 198.769 0.985 0.027 -0.172 -0.174 0.154 -0.973 0 0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=22] +1 1 276.939 -41.855 80.246 0.985 0.027 -0.172 -0.174 0.154 -0.973 0 0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=39] +1 1 276.939 -41.855 -80.246 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=37] +1 1 280.199 -23.368 -198.769 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 4274.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=16] +1 7 -275.746 48.621 0 -0.985 0.174 0 0.174 0.985 0 0 0 -1 10030 - subModel-54.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=65] +1 7 221.871 -8.635 226.424 -0.172 -0.027 0.985 -0.973 -0.154 -0.174 0.156 -0.988 0 10030 - subModel-55.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=71] +1 7 221.871 -8.635 -226.424 0.172 -0.027 0.985 0.973 -0.154 -0.174 0.156 0.988 0 10030 - subModel-56.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=81] +1 8 116.283 -31.579 83.062 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=32] +1 8 116.283 -31.579 -83.062 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=81] +1 7 -57.723 18.164 -201.585 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 4282.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=72] +1 7 -57.723 18.164 201.585 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=43] +1 8 138.967 -18.105 -191.708 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3710.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=71] +1 8 138.967 -18.105 191.708 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3710.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=31] +1 8 255.243 -49.728 -122.57 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 3795.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=78] +1 8 255.243 -49.728 122.57 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 3795.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=79] +1 8 247.568 -35.667 201.585 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3021.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=45] +1 8 247.568 -35.667 -201.585 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3021.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=60] +1 7 200.501 -14.659 -280.6 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 3933.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=56] +1 7 200.501 -14.659 280.6 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3934.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=17] +1 8 -271.579 72.257 60 -0.985 0.174 0 0.174 0.985 0 0 0 -1 3795.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=18] +1 8 -271.579 72.257 -60 -0.985 0.174 0 0.174 0.985 0 0 0 -1 3795.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=4] +1 7 -131.019 63.182 196.579 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=10] +1 7 -133.735 47.777 97.81 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=40] +1 7 -133.735 47.777 -97.81 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=41] +1 7 -131.019 63.182 -196.579 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=21] +1 7 261.274 -15.521 137.317 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=70] +1 7 261.274 -15.521 -137.317 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=28] +1 8 125.031 18.034 196.579 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=12] +1 8 121.771 -0.453 78.056 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=75] +1 8 121.771 -0.453 -78.056 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=74] +1 8 125.031 18.034 -196.579 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=19] +1 8 4.168 23.635 0 -0.985 0.174 0 0.174 0.985 0 0 0 -1 3032.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=61] +1 7 170.127 -14.15 -301.605 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 6636.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=57] +1 7 170.127 -14.15 301.605 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 6636.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=29] +1 0 261.518 -71.728 -146.078 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 3702.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=20] +1 0 261.518 -71.728 146.078 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 3702.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=38] +1 1 274.711 -54.494 -203.775 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=24] +1 1 274.711 -54.494 203.775 0.985 0.027 -0.172 -0.174 0.154 -0.973 0 0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=13] +1 7 96.002 -31.423 -215.216 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 2465.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=3] +1 7 96.002 -31.423 215.216 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 2465.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=30] +1 1 271.451 -72.981 -85.252 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=23] +1 1 271.451 -72.981 85.252 0.985 0.027 -0.172 -0.174 0.154 -0.973 0 0.988 0.156 4274.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=43] +1 8 -491.01 94.727 100.313 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 10030 - subModel-57.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=46] +1 7 -491.01 94.727 -100.313 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 10030 - subModel-62.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=2] +1 8 -388.999 39.8 -126.324 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 6111.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=30] +1 8 -388.999 39.8 126.324 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 6111.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=5] +1 7 -219.137 24.144 -215.216 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 2465.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=5] +1 7 -219.137 24.144 215.216 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 2465.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=20] +1 7 -240.521 18.04 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=21] +1 7 -319.306 31.932 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=22] +1 4 0 0 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3003.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=23] +1 7 -323.474 8.297 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=24] +1 7 -244.689 -5.595 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=77] +1 7 247.553 -93.335 149.832 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 3007.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=67] +1 7 247.553 -93.335 -149.832 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 3007.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=9] +1 7 -393.658 13.374 -110.325 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 2730.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=31] +1 7 -393.658 13.374 110.325 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 2730.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=3] +1 7 -242.949 4.273 -218.97 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 3703.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=12] +1 7 72.189 -51.295 -218.97 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 3703.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=-1] +1 7 -242.949 4.273 218.97 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 3703.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=2] +1 7 72.189 -51.295 218.97 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 3703.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=25] +1 1 -4.168 -23.635 0 0.985 0.174 0 -0.174 0.985 0 0 0 1 2356.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=18] +1 1 212.049 -64.337 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=17] +1 1 192.353 -60.864 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=16] +1 1 172.657 -57.392 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=14] +1 1 -24.304 -22.662 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=15] +1 1 -4.608 -26.135 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=11] +1 1 -201.57 8.595 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=10] +1 1 -221.266 12.068 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=4] +1 1 -378.835 39.851 -227.283 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=6] +1 1 -399.618 37.162 -187.775 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=8] +1 1 -401.791 24.837 -108.76 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=7] +1 1 -403.964 12.513 -29.745 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=35] +1 1 -403.964 12.513 29.745 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=34] +1 1 -401.791 24.837 108.76 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=32] +1 1 -399.618 37.162 187.775 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=36] +1 1 212.049 -64.337 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=37] +1 1 192.353 -60.864 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=38] +1 1 172.657 -57.392 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=39] +1 1 -4.608 -26.135 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=40] +1 1 -24.304 -22.662 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=41] +1 1 -201.57 8.595 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=42] +1 1 -221.266 12.068 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=33] +1 1 -378.835 39.851 227.283 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4274.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=47] +1 7 -307.966 38.655 233.62 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 10030 - subModel-66.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=51] +1 7 -307.966 38.655 -233.62 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 10030 - subModel-67.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=48] +1 7 -111.005 3.925 233.62 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 10030 - subModel-68.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=52] +1 7 -111.005 3.925 -233.62 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 10030 - subModel-69.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=49] +1 7 85.957 -30.804 233.62 -0.172 -0.027 0.985 -0.973 -0.154 -0.174 0.156 -0.988 0 10030 - subModel-70.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=53] +1 7 85.957 -30.804 -233.62 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 10030 - subModel-71.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=50] +1 7 223.83 -55.115 233.62 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 10030 - subModel-72.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=54] +1 7 223.83 -55.115 -233.62 0.985 -0.027 -0.172 -0.174 -0.154 -0.973 0 0.988 -0.156 10030 - subModel-73.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=46] +1 7 -407.683 37.494 117.073 0.172 0.985 -0.027 0.973 -0.174 -0.154 -0.156 0 -0.988 10030 - subModel-74.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=-1] +1 7 -407.683 37.494 -117.073 0.027 0.985 -0.172 0.154 -0.174 -0.973 -0.988 0 -0.156 10030 - subModel-75.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=26] +1 8 -236.23 -15.21 0 0 0.174 0.985 0 0.985 -0.174 -1 0 0 3710.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=27] +1 8 -305.167 -3.055 0 -0.985 0.174 0 0.174 0.985 0 0 0 -1 3032.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=47] +1 7 -404.335 10.41 -131.33 0.027 0.172 0.985 0.154 0.973 -0.174 -0.988 0.156 0 2445.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=44] +1 7 -404.335 10.41 131.33 -0.027 0.172 0.985 -0.154 0.973 -0.174 -0.988 -0.156 0 2445.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=62] +1 7 286.117 -104.982 -170.837 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 3933.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=62] +1 7 286.117 -104.982 170.837 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3934.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=73] +1 7 150.431 -68.267 199.217 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3245a.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=70] +1 7 51.95 -50.902 199.217 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3245a.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=69] +1 7 -204.1 -5.754 199.217 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3245a.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=78] +1 7 150.431 -68.267 -199.217 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3245a.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=79] +1 7 51.95 -50.902 -199.217 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3245a.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=80] +1 7 -204.1 -5.754 -199.217 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3245a.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=48] +1 7 -323.377 8.843 -210.345 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 6180.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=45] +1 7 -323.377 8.843 210.345 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 6180.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=55] +1 7 -106.176 -26.279 -230.099 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 4282.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=53] +1 7 -106.176 -26.279 230.099 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 4282.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=56] +1 7 71.089 -57.536 -230.099 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3068b.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=54] +1 7 71.089 -57.536 230.099 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3068b.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=57] +1 7 169.57 -74.9 -230.099 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=55] +1 7 169.57 -74.9 230.099 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=61] +1 7 282.572 -125.087 93.074 -0.985 0.172 -0.027 0.174 0.973 -0.154 0 -0.156 -0.988 3020.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=66] +1 7 282.572 -125.087 -93.074 -0.985 0.172 0.027 0.174 0.973 0.154 0 0.156 -0.988 3020.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=28] +1 4 -240.398 -38.846 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3010.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=29] +1 7 -269.942 -33.636 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 !LDCAD GROUP_NXT [ids=2] [nrs=30] +1 7 -348.726 -19.744 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=31] +1 7 -254.413 -60.744 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 3001.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=76] +1 7 233.046 -118.024 133.833 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 3009.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=24] +1 7 233.046 -118.024 -133.833 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 3009.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=74] +1 7 146.315 -91.612 202.971 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 6111.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=77] +1 7 146.315 -91.612 -202.971 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 6111.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=68] +1 7 -109.735 -46.464 202.971 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 2465.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=76] +1 7 -109.735 -46.464 -202.971 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 2465.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=23] +1 7 228.93 -141.369 -137.587 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 3894.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=75] +1 7 228.93 -141.369 137.587 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 3894.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=58] +1 7 83.11 -104.537 -206.725 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 3703.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=66] +1 7 83.11 -104.537 206.725 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 3703.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=67] +1 7 -172.94 -59.389 206.725 0.985 0.172 0.027 -0.174 0.973 0.154 0 -0.156 0.988 2730.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=59] +1 7 -172.94 -59.389 -206.725 0.985 0.172 -0.027 -0.174 0.973 -0.154 0 0.156 0.988 2730.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=44] +1 1 -249.738 -34.229 -215.038 0.027 -0.985 0.172 0.154 0.174 0.973 -0.988 0 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=19] +1 1 -92.169 -62.013 -215.038 0.027 -0.985 0.172 0.154 0.174 0.973 -0.988 0 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=20] +1 1 26.008 -82.851 -215.038 0.027 -0.985 0.172 0.154 0.174 0.973 -0.988 0 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=21] +1 1 65.401 -89.797 -215.038 0.027 -0.985 0.172 0.154 0.174 0.973 -0.988 0 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=22] +1 1 222.97 -117.581 -215.038 0.027 -0.985 0.172 0.154 0.174 0.973 -0.988 0 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=25] +1 1 239.406 -139.54 -96.515 0.985 0.027 0.172 -0.174 0.154 0.973 0 -0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=27] +1 1 240.493 -133.378 -136.023 0.985 0.027 0.172 -0.174 0.154 0.973 0 -0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=26] +1 1 239.949 -136.46 -116.269 0.985 0.027 0.172 -0.174 0.154 0.973 0 -0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=28] +1 1 241.579 -127.216 -175.53 0.985 0.027 0.172 -0.174 0.154 0.973 0 -0.988 0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=15] +1 1 239.406 -139.54 96.515 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=16] +1 1 239.949 -136.46 116.269 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=17] +1 1 240.493 -133.378 136.023 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=18] +1 1 241.579 -127.216 175.53 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=19] +1 1 222.97 -117.581 215.038 0.027 0.985 0.172 0.154 -0.174 0.973 0.988 0 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=8] +1 1 26.008 -82.851 215.038 0.027 0.985 0.172 0.154 -0.174 0.973 0.988 0 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=6] +1 1 -249.738 -34.229 215.038 0.027 0.985 0.172 0.154 -0.174 0.973 0.988 0 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=7] +1 1 -92.169 -62.013 215.038 0.027 0.985 0.172 0.154 -0.174 0.973 0.988 0 -0.156 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=9] +1 1 65.401 -89.797 215.038 0.027 0.985 0.172 0.154 -0.174 0.973 0.988 0 -0.156 4274.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=32] +1 7 -8.335 -47.271 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 10030 - subModel-76.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=65] +1 8 227.558 -149.15 -138.839 -0.027 0.172 -0.985 -0.154 0.973 0.174 0.988 0.156 0 4162.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=60] +1 8 227.558 -149.15 138.839 0.027 0.172 -0.985 0.154 0.973 0.174 0.988 -0.156 0 4162.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=69] +1 1 286.448 -34.001 -139.508 -0.027 -0.985 -0.172 -0.154 0.174 -0.973 0.988 0 -0.156 10030 - subModel-77.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=68] +1 1 280.959 -65.126 -144.513 0.027 -0.985 0.172 0.154 0.174 0.973 -0.988 0 0.156 10030 - subModel-77.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=63] +1 1 280.959 -65.126 144.513 -0.027 -0.985 0.172 -0.154 0.174 0.973 -0.988 0 -0.156 10030 - subModel-78.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=64] +1 1 286.448 -34.001 139.508 0.027 -0.985 -0.172 0.154 0.174 -0.973 0.988 0 0.156 10030 - subModel-78.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=58] +1 7 249.186 -130.146 165.654 0.027 -0.985 -0.172 0.154 0.174 -0.973 0.988 0 0.156 3743.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=63] +1 7 249.186 -130.146 -165.654 -0.027 -0.985 -0.172 -0.154 0.174 -0.973 0.988 0 -0.156 3743.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=59] +1 7 263.313 -142.168 106.392 0.027 -0.985 -0.172 0.154 0.174 -0.973 0.988 0 0.156 4865a.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=64] +1 7 263.313 -142.168 -106.392 -0.027 -0.985 -0.172 -0.154 0.174 -0.973 0.988 0 -0.156 4865a.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=33] +1 7 -129.538 71.582 -140 0.985 0.174 0 -0.174 0.985 0 0 0 1 10030 - subModel-79.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=34] +1 7 -129.538 71.582 140 -0.985 0.174 0 0.174 0.985 0 0 0 -1 10030 - subModel-85.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=50] +1 7 146.117 -92.73 -221.375 0.172 -0.027 0.985 0.973 -0.154 -0.174 0.156 0.988 0 10030 - subModel-90.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=51] +1 7 146.117 -92.73 221.375 0.985 -0.027 0.172 -0.174 -0.154 0.973 0 -0.988 -0.156 10030 - subModel-89.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=49] +1 7 -109.933 -47.581 -221.375 -0.172 -0.027 -0.985 -0.973 -0.154 0.174 -0.156 0.988 0 10030 - subModel-91.ldr +0 !LDCAD GROUP_NXT [ids=2] [nrs=35] +1 7 -147.15 86.872 -288 -0.174 0 -0.985 -0.985 0 0.174 0 1 0 10030 - subModel-91.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=52] +1 7 -109.933 -47.581 221.375 0.172 -0.027 -0.985 0.973 -0.154 0.174 -0.156 -0.988 0 10030 - subModel-91.ldr +0 !LDCAD GROUP_NXT [ids=2] [nrs=36] +1 7 -147.15 86.872 288 0.174 0 -0.985 0.985 0 0.174 0 -1 0 10030 - subModel-91.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=2] [nrs=37] +1 0 -283.958 -55.535 0 0 0.174 0.985 0 0.985 -0.174 -1 0 0 10030 - subModel-92.ldr +0 STEP +1 4 160.727 177.69 560 0 0.087 0.996 0 0.996 -0.087 -1 0 0 10030 - subModel-46.ldr +0 STEP +1 14 119.566 -12.959 0 0 0.174 -0.985 0 0.985 0.174 1 0 0 10030 - subModel-96.ldr + + +0 FILE 10030 - subModel-54.ldr +0 subModel-54 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-54.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 32324.dat +1 0 40 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 40 10 20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 -40 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 -40 10 20 1 0 0 0 1 0 0 0 1 2780.dat +0 STEP +1 7 -50 0 0 0 0 1 0 1 0 -1 0 0 3703.dat +1 4 0 0 -140 -1 0 0 0 1 0 0 0 -1 6249.dat +1 4 0 0 140 -1 0 0 0 1 0 0 0 -1 6249.dat +1 0 -60 10 -100 1 0 0 0 0.988 -0.156 0 0.156 0.988 2780.dat +1 0 -60 10 100 1 0 0 0 0.988 0.156 0 -0.156 0.988 2780.dat +0 STEP +1 0 -70 6.38 141.072 0 0 -1 0.156 0.988 0 0.988 -0.156 0 3702.dat +1 0 -70 6.38 -141.072 0 0 -1 -0.156 0.988 0 0.988 0.156 0 3702.dat +1 7 50 0 0 0 0 1 0 1 0 -1 0 0 3703.dat +0 STEP +1 7 -140 -7.778 102.816 1 0 0 0 0.988 0.156 0 -0.156 0.988 3034.dat +1 7 -140 -7.778 -102.816 1 0 0 0 0.988 -0.156 0 0.156 0.988 3034.dat + + +0 FILE 10030 - subModel-55.ldr +0 subModel-55 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-55.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 0 -24 40 0 0 1 0 1 0 -1 0 0 4865a.dat +0 STEP +1 7 0 -24 0 0 0 -1 0 1 0 1 0 0 4865a.dat + + +0 FILE 10030 - subModel-56.ldr +0 subModel-56 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-56.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 0 -24 40 0 0 -1 0 1 0 1 0 0 4865a.dat +0 STEP +1 7 0 -24 0 0 0 1 0 1 0 -1 0 0 4865a.dat + + +0 FILE 10030 - subModel-57.ldr +0 subModel-57 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-57.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 -1 0 0 0 1 0 0 0 -1 32324.dat +1 0 40 10 -20 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 40 10 20 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 0 10 40 0 0 -1 0 1 0 1 0 0 2780.dat +0 STEP +1 7 -20 0 50 1 0 0 0 1 0 0 0 1 3894.dat +1 7 50 0 0 0 0 1 0 1 0 -1 0 0 3894.dat +0 STEP +1 8 0 -8 -30 -1 0 0 0 1 0 0 0 -1 3710.dat +1 8 -20 -8 40 -1 0 0 0 1 0 0 0 -1 3795.dat +1 1 60 10 40 1 0 0 0 -1 0 0 0 -1 4274.dat +1 1 60 10 -40 1 0 0 0 -1 0 0 0 -1 4274.dat +0 STEP +1 7 68 -10 0 0 -1 0 1 0 0 0 0 1 10030 - subModel-58.ldr +0 STEP +1 7 80 -8 -20 -1 0 0 0 1 0 0 0 -1 3934.dat +0 STEP +1 7 100 0 -90 -1 0 0 0 1 0 0 0 -1 10030 - subModel-59.ldr +0 STEP +1 8 0 -8 -100 -1 0 0 0 1 0 0 0 -1 10030 - subModel-60.ldr +0 STEP +1 1 20 10 60 0 0 -1 0 1 0 1 0 0 4274.dat +1 1 -20 10 60 0 0 -1 0 1 0 1 0 0 4274.dat +1 7 20 -16 -120 1 0 0 0 1 0 0 0 1 3029.dat +0 STEP +1 7 20 -16 -20 0 0 1 0 1 0 -1 0 0 6180.dat +1 7 -60 -16 -20 0 0 -1 0 1 0 1 0 0 6180.dat +1 7 -10 10 68 -1 0 0 0 0 -1 0 -1 0 10030 - subModel-61.ldr +0 STEP +1 7 -20 -16 80 0 0 -1 0 1 0 1 0 0 3933.dat +1 8 -90 -24 -40 0 0 -1 0 1 0 1 0 0 3794a.dat +1 7 -90 -40 -110 0 0 -1 0 1 0 1 0 0 3005.dat +1 7 -90 -40 -40 -1 0 0 0 1 0 0 0 -1 3959.dat + + +0 FILE 10030 - subModel-58.ldr +0 subModel-58 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-58.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 20 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 20 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 7 20 -8 -30 -1 0 0 0 1 0 0 0 -1 2555.dat +1 0 20 -8 -10 -1 0 0 0 1 0 0 0 -1 4592.dat +1 7 20 -8 -10 -1 0 0 0 0.5 -0.866 0 -0.866 -0.5 4593.dat +0 STEP +1 7 20 -24 -50 1 0 0 0 1 0 0 0 1 4599a.dat + + +0 FILE 10030 - subModel-59.ldr +0 subModel-59 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-59.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 0 0 1 0 0 0 1 0 0 0 1 3701.dat +1 1 -20 10 -10 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 0 10 -10 0 0 1 0 1 0 -1 0 0 4274.dat +0 STEP +1 7 -10 10 -18 1 0 0 0 0 -1 0 1 0 2412b.dat +1 8 -20 -8 0 1 0 0 0 1 0 0 0 1 3023.dat + + +0 FILE 10030 - subModel-60.ldr +0 subModel-60 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-60.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 32531.dat +1 0 0 10 60 0 0 1 0 1 0 -1 0 0 2780.dat +1 8 0 24 0 0 0 1 0 1 0 -1 0 0 3032.dat + + +0 FILE 10030 - subModel-61.ldr +0 subModel-61 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-61.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3710.dat +0 STEP +1 7 -20 -24 0 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 30 -24 0 1 0 0 0 1 0 0 0 1 4589.dat +0 STEP +1 7 10 -24 0 0 0 -1 0 1 0 1 0 0 4599a.dat +1 0 30 -32 0 0 0 -1 0 1 0 1 0 0 4592.dat +1 7 30 -32 0 0 1 0 0 0 1 1 0 0 4593.dat + + +0 FILE 10030 - subModel-62.ldr +0 subModel-62 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-62.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 -1 0 0 0 1 0 0 0 -1 32324.dat +1 0 0 10 -40 0 0 -1 0 1 0 1 0 0 2780.dat +1 0 40 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 40 10 20 1 0 0 0 1 0 0 0 1 2780.dat +0 STEP +1 7 -20 0 -50 1 0 0 0 1 0 0 0 1 3894.dat +1 7 50 0 0 0 0 1 0 1 0 -1 0 0 3894.dat +0 STEP +1 1 60 10 40 1 0 0 0 1 0 0 0 1 4274.dat +1 1 60 10 -40 1 0 0 0 1 0 0 0 1 4274.dat +1 1 20 10 -60 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -20 10 -60 0 0 1 0 1 0 -1 0 0 4274.dat +1 8 -20 -8 -40 -1 0 0 0 1 0 0 0 -1 3795.dat +1 8 0 -8 30 -1 0 0 0 1 0 0 0 -1 3710.dat +0 STEP +1 7 68 10 0 0 -1 0 1 0 0 0 0 1 10030 - subModel-63.ldr +0 STEP +1 7 -10 10 -68 0 0 1 1 0 0 0 1 0 10030 - subModel-64.ldr +0 STEP +1 7 80 -8 20 1 0 0 0 1 0 0 0 1 3933.dat +1 7 100 0 90 1 0 0 0 1 0 0 0 1 10030 - subModel-65.ldr +0 STEP +1 7 0 -8 100 1 0 0 0 1 0 0 0 1 10030 - subModel-60.ldr +0 STEP +1 7 -60 -16 20 0 0 -1 0 1 0 1 0 0 6180.dat +1 7 20 -16 20 0 0 1 0 1 0 -1 0 0 6180.dat +0 STEP +1 7 -20 -16 -80 0 0 -1 0 1 0 1 0 0 3934.dat +1 8 -90 -24 40 0 0 -1 0 1 0 1 0 0 3794a.dat +1 7 20 -16 120 1 0 0 0 1 0 0 0 1 3029.dat +1 7 -90 -40 110 1 0 0 0 1 0 0 0 1 3005.dat +1 7 -90 -40 40 1 0 0 0 1 0 0 0 1 3959.dat + + +0 FILE 10030 - subModel-63.ldr +0 subModel-63 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-63.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 0 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 0 0 -8 10 -1 0 0 0 1 0 0 0 -1 4592.dat +1 7 0 -8 10 -1 0 0 0 0.5 0.866 0 0.866 -0.5 4593.dat +1 7 0 -8 30 -1 0 0 0 1 0 0 0 -1 2555.dat +0 STEP +1 7 0 -24 50 -1 0 0 0 1 0 0 0 -1 4599a.dat + + +0 FILE 10030 - subModel-64.ldr +0 subModel-64 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-64.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3710.dat +0 STEP +1 7 0 -24 -30 0 0 1 0 1 0 -1 0 0 4589.dat +1 7 0 -24 20 0 0 -1 0 1 0 1 0 0 4865a.dat +0 STEP +1 7 0 -24 -10 1 0 0 0 1 0 0 0 1 4599a.dat +1 0 0 -32 -30 1 0 0 0 1 0 0 0 1 4592.dat +1 7 0 -32 -30 1 0 0 0 0 1 0 -1 0 4593.dat + + +0 FILE 10030 - subModel-65.ldr +0 subModel-65 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-65.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 0 0 1 0 0 0 1 0 0 0 1 3701.dat +1 1 0 10 -10 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 20 10 -10 0 0 1 0 1 0 -1 0 0 4274.dat +0 STEP +1 8 20 -8 0 -1 0 0 0 1 0 0 0 -1 3023.dat +1 7 10 10 -18 -1 0 0 0 0 1 0 1 0 2412b.dat + + +0 FILE 10030 - subModel-66.ldr +0 subModel-66 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-66.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 -80 -8 -10 1 0 0 0 1 0 0 0 1 2412b.dat +1 7 40 -8 -10 1 0 0 0 1 0 0 0 1 2412b.dat +0 STEP +1 7 -70 -24 10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 -50 -24 10 0 0 -1 0 1 0 1 0 0 4589.dat +1 7 -30 -8 10 0 0 -1 0 1 0 1 0 0 2555.dat +0 STEP +1 7 -40 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 -10 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat +1 7 80 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat + + +0 FILE 10030 - subModel-67.ldr +0 subModel-67 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-67.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 -80 -8 10 1 0 0 0 1 0 0 0 1 2412b.dat +1 7 40 -8 10 1 0 0 0 1 0 0 0 1 2412b.dat +0 STEP +1 7 -40 -24 10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 80 -24 10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 -10 -24 10 0 0 1 0 1 0 -1 0 0 4599a.dat +0 STEP +1 7 -70 -24 -10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 -50 -24 -10 0 0 -1 0 1 0 1 0 0 4589.dat +1 7 -30 -8 -10 0 0 -1 0 1 0 1 0 0 2555.dat + + +0 FILE 10030 - subModel-68.ldr +0 subModel-68 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-68.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 -80 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 80 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +0 STEP +1 7 -40 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 0 -8 -10 1 0 0 0 1 0 0 0 1 2412b.dat +1 7 30 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat + + +0 FILE 10030 - subModel-69.ldr +0 subModel-69 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-69.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 80 -24 10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 -80 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +0 STEP +1 7 -40 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 0 -8 10 -1 0 0 0 1 0 0 0 -1 2412b.dat +1 7 30 -24 10 0 0 1 0 1 0 -1 0 0 4599a.dat + + +0 FILE 10030 - subModel-70.ldr +0 subModel-70 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-70.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3832.dat +1 7 -10 -24 60 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 -10 -24 20 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 -10 -24 -20 0 0 1 0 1 0 -1 0 0 4865a.dat +0 STEP +1 7 10 -24 -80 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 10 -24 -50 0 0 -1 0 1 0 1 0 0 4589.dat +1 7 10 -8 0 0 0 -1 0 1 0 1 0 0 3743.dat +0 STEP +1 7 10 -24 50 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 10 -8 80 0 0 -1 0 1 0 1 0 0 2412b.dat + + +0 FILE 10030 - subModel-71.ldr +0 subModel-71 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-71.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 80 -8 10 1 0 0 0 1 0 0 0 1 2412b.dat +1 7 0 -8 10 1 0 0 0 1 0 0 0 1 3743.dat +0 STEP +1 7 -80 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 -50 -24 10 -1 0 0 0 1 0 0 0 -1 4589.dat +1 7 50 -24 10 0 0 -1 0 1 0 1 0 0 4599a.dat +0 STEP +1 7 60 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 20 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 -20 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat + + +0 FILE 10030 - subModel-72.ldr +0 subModel-72 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-72.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3020.dat +1 7 20 -8 10 1 0 0 0 1 0 0 0 1 2412b.dat +0 STEP +1 7 -20 -24 10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 0 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +0 STEP +1 7 30 -8 -10 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -30 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat + + +0 FILE 10030 - subModel-73.ldr +0 subModel-73 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-73.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3020.dat +1 7 30 -8 10 0 0 1 0 1 0 -1 0 0 2555.dat +0 STEP +1 7 0 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 20 -8 -10 -1 0 0 0 1 0 0 0 -1 2412b.dat +0 STEP +1 7 -20 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 -30 -24 10 0 0 1 0 1 0 -1 0 0 4599a.dat + + +0 FILE 10030 - subModel-74.ldr +0 subModel-74 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-74.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3832.dat +1 7 -10 -8 90 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -10 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 7 -10 -24 -10 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 -10 -24 -50 1 0 0 0 1 0 0 0 1 4599a.dat +1 0 -10 -8 70 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -10 -8 70 1 0 0 0 0.174 -0.985 0 0.985 0.174 4593.dat +0 STEP +1 7 10 -8 -70 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 -10 -24 -80 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 10 -8 0 0 0 1 0 1 0 -1 0 0 3743.dat +0 STEP +1 7 10 -24 60 0 0 -1 0 1 0 1 0 0 4865a.dat +1 0 10 -8 -90 1 0 0 0 1 0 0 0 1 4592.dat +1 7 10 -8 -90 1 0 0 0 0.342 0.94 0 -0.94 0.342 4593.dat + + +0 FILE 10030 - subModel-75.ldr +0 subModel-75 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-75.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 80 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 -20 -8 10 -1 0 0 0 1 0 0 0 -1 2412b.dat +0 STEP +1 7 50 -24 10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 10 -24 10 0 0 1 0 1 0 -1 0 0 4599a.dat +1 0 -70 -8 10 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -70 -8 10 0 -0.985 0.174 0 0.174 0.985 -1 0 0 4593.dat +0 STEP +1 7 70 -8 -10 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 0 -8 -10 -1 0 0 0 1 0 0 0 -1 3743.dat +1 7 -90 -8 10 -1 0 0 0 1 0 0 0 -1 2555.dat +0 STEP +1 7 -60 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +1 0 90 -8 -10 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 90 -8 -10 0 0.966 0.259 0 0.259 -0.966 -1 0 0 4593.dat + + +0 FILE 10030 - subModel-76.ldr +0 subModel-76 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-76.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 1 0 0 0 0 0 1 0 1 0 -1 0 0 2356.dat +1 8 0 -8 0 0 0 1 0 1 0 -1 0 0 3032.dat +0 STEP +1 1 0 -32 0 0 0 1 0 1 0 -1 0 0 2356.dat +1 8 0 -40 0 0 0 1 0 1 0 -1 0 0 3032.dat +0 STEP +1 1 0 -64 0 0 0 1 0 1 0 -1 0 0 2356.dat +0 STEP +1 7 -30 -72 0 0 0 1 0 1 0 -1 0 0 2431.dat +1 7 30 -72 0 0 0 1 0 1 0 -1 0 0 2431.dat +1 7 0 -72 50 -1 0 0 0 1 0 0 0 -1 2431.dat +1 7 0 -72 -50 -1 0 0 0 1 0 0 0 -1 2431.dat +0 STEP +1 7 0 -88 0 0 0 -1 0 1 0 1 0 0 3001.dat +0 STEP +1 7 0 -96 20 0 0 -1 0 1 0 1 0 0 3068b.dat +1 7 0 -96 -20 0 0 -1 0 1 0 1 0 0 3068b.dat + + +0 FILE 10030 - subModel-77.ldr +0 subModel-77 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-77.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3460.dat +0 STEP +1 7 -40 -24 0 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 20 -8 0 1 0 0 0 1 0 0 0 1 3743.dat +0 STEP +1 7 70 -8 0 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -70 -24 0 0 0 1 0 1 0 -1 0 0 4599a.dat + + +0 FILE 10030 - subModel-78.ldr +0 subModel-78 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-78.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3460.dat +0 STEP +1 7 40 -24 0 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 -20 -8 0 1 0 0 0 1 0 0 0 1 3743.dat +0 STEP +1 7 70 -24 0 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 -70 -8 0 0 0 -1 0 1 0 1 0 0 2555.dat + + +0 FILE 10030 - subModel-79.ldr +0 subModel-79 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-79.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3006.dat +1 8 -140 24 0 1 0 0 0 1 0 0 0 1 3795.dat +1 8 140 24 0 1 0 0 0 1 0 0 0 1 3795.dat +1 4 -190 0 0 0 0 1 0 1 0 -1 0 0 3004.dat +1 4 190 0 0 0 0 1 0 1 0 -1 0 0 3004.dat +0 STEP +1 4 140 0 10 0 0 1 0 1 0 -1 0 0 10030 - subModel-80.ldr +1 4 -140 0 10 0 0 1 0 1 0 -1 0 0 10030 - subModel-80.ldr +0 STEP +1 8 -140 -24 0 -1 0 0 0 1 0 0 0 -1 2456.dat +1 8 140 -24 0 -1 0 0 0 1 0 0 0 -1 2456.dat +1 0 -120 0 -90 -1 0 0 0 1 0 0 0 -1 32018.dat +1 0 160 0 -90 -1 0 0 0 1 0 0 0 -1 32018.dat +0 STEP +1 1 -240 10 -100 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -200 10 -100 0 0 1 0 1 0 -1 0 0 4274.dat +1 0 260 10 -100 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 180 10 -100 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 100 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 60 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 -100 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 -60 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +0 STEP +1 4 -80 0 -110 1 0 0 0 1 0 0 0 1 3701.dat +1 4 80 0 -110 1 0 0 0 1 0 0 0 1 3701.dat +1 7 180 0 -140 1 0 0 0 1 0 0 0 1 32324.dat +1 7 260 0 -140 1 0 0 0 1 0 0 0 1 32324.dat +0 STEP +1 0 0 0 -130 -1 0 0 0 1 0 0 0 -1 32018.dat +1 1 -120 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -40 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 40 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 120 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 180 10 -180 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 260 10 -180 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 300 10 -120 1 0 0 0 1 0 0 0 1 4274.dat +1 1 300 10 -160 1 0 0 0 1 0 0 0 1 4274.dat +1 7 -200 -24 -90 1 0 0 0 1 0 0 0 1 3009.dat +0 STEP +1 7 -80 -24 -120 1 0 0 0 1 0 0 0 1 3007.dat +1 7 80 -24 -120 1 0 0 0 1 0 0 0 1 3007.dat +1 7 220 -24 -170 1 0 0 0 1 0 0 0 1 3009.dat +1 7 290 -24 -140 0 0 1 0 1 0 -1 0 0 3010.dat +0 STEP +1 7 220 24 -160 -1 0 0 0 1 0 0 0 -1 3034.dat +1 1 -140 24 -80 0 0 1 0 1 0 -1 0 0 10030 - subModel-81.ldr +0 STEP +1 8 -184 0 -120 0 1 0 0 0 -1 -1 0 0 3003.dat +1 8 150 -24 -160 0 0 1 0 1 0 -1 0 0 2877.dat +1 8 308 8 -140 0 -1 0 0 0 -1 1 0 0 10030 - subModel-82.ldr +0 STEP +1 7 220 8 -188 1 0 0 0 0 -1 0 1 0 10030 - subModel-83.ldr +0 STEP +1 7 -220 0 -108 1 0 0 0 0 -1 0 1 0 10030 - subModel-84.ldr +1 8 -160 -32 -90 1 0 0 0 1 0 0 0 1 3023.dat +1 7 220 -48 -160 1 0 0 0 1 0 0 0 1 4515.dat +0 STEP +1 7 100 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +1 7 20 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +1 7 -60 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +1 7 -140 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +0 STEP +1 7 -120 -56 -110 1 0 0 0 1 0 0 0 1 3743.dat +1 7 80 -56 -110 1 0 0 0 1 0 0 0 1 3743.dat + + +0 FILE 10030 - subModel-80.ldr +0 subModel-80 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-80.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 1 0 0 0 0 0 1 0 1 0 -1 0 0 3701.dat +1 4 50 0 20 -1 0 0 0 1 0 0 0 -1 6249.dat +1 4 50 0 -20 -1 0 0 0 1 0 0 0 -1 6249.dat + + +0 FILE 10030 - subModel-81.ldr +0 subModel-81 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-81.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3795.dat +1 7 40 -24 -10 1 0 0 0 1 0 0 0 1 32000.dat +0 STEP +1 1 30 -14 -20 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 50 -14 -20 0 0 1 0 1 0 -1 0 0 4274.dat + + +0 FILE 10030 - subModel-82.ldr +0 subModel-82 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-82.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3020.dat +1 7 -20 -8 -10 1 0 0 0 1 0 0 0 1 2412b.dat +0 STEP +1 7 0 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +0 STEP +1 7 30 -24 10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 -30 -8 10 0 0 -1 0 1 0 1 0 0 2555.dat +1 7 20 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat + + +0 FILE 10030 - subModel-83.ldr +0 subModel-83 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-83.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3034.dat +1 7 -40 -8 10 1 0 0 0 1 0 0 0 1 2412b.dat +1 7 40 -8 10 1 0 0 0 1 0 0 0 1 2412b.dat +0 STEP +1 7 10 -24 10 0 0 1 0 1 0 -1 0 0 4599a.dat +1 7 -10 -24 10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 -70 -24 10 0 0 -1 0 1 0 1 0 0 4589.dat +1 7 70 -24 10 0 0 -1 0 1 0 1 0 0 4589.dat +0 STEP +1 7 -40 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 0 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 40 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 0 -70 -8 -10 0 0 -1 0 1 0 1 0 0 4592.dat +1 0 70 -8 -10 0 0 -1 0 1 0 1 0 0 4592.dat +1 7 -70 -8 -10 0 -0.966 -0.259 0 0.259 -0.966 1 0 0 4593.dat +1 7 70 -8 -10 0 0.966 -0.259 0 0.259 0.966 1 0 0 4593.dat + + +0 FILE 10030 - subModel-84.ldr +0 subModel-84 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-84.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3021.dat +1 7 20 -8 10 0 0 1 0 1 0 -1 0 0 2555.dat +0 STEP +1 7 -10 -24 10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 10 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +0 STEP +1 7 -20 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat + + +0 FILE 10030 - subModel-85.ldr +0 subModel-85 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-85.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3006.dat +1 8 -140 24 0 1 0 0 0 1 0 0 0 1 3795.dat +1 8 140 24 0 1 0 0 0 1 0 0 0 1 3795.dat +1 4 -190 0 0 0 0 1 0 1 0 -1 0 0 3004.dat +1 4 190 0 0 0 0 1 0 1 0 -1 0 0 3004.dat +0 STEP +1 4 -140 0 10 0 0 1 0 1 0 -1 0 0 10030 - subModel-80.ldr +1 4 140 0 10 0 0 1 0 1 0 -1 0 0 10030 - subModel-80.ldr +0 STEP +1 8 -140 -24 0 -1 0 0 0 1 0 0 0 -1 2456.dat +1 8 140 -24 0 -1 0 0 0 1 0 0 0 -1 2456.dat +1 0 -160 0 -90 -1 0 0 0 1 0 0 0 -1 32018.dat +1 0 120 0 -90 -1 0 0 0 1 0 0 0 -1 32018.dat +0 STEP +1 1 240 10 -100 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 200 10 -100 0 0 1 0 1 0 -1 0 0 4274.dat +1 0 100 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 60 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 -60 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 -100 10 -110 0 0 1 0 1 0 -1 0 0 6558.dat +1 0 -180 10 -100 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 -260 10 -100 0 0 1 0 1 0 -1 0 0 2780.dat +0 STEP +1 7 -260 0 -140 -1 0 0 0 1 0 0 0 -1 32324.dat +1 7 -180 0 -140 -1 0 0 0 1 0 0 0 -1 32324.dat +1 4 -80 0 -110 -1 0 0 0 1 0 0 0 -1 3701.dat +1 4 80 0 -110 -1 0 0 0 1 0 0 0 -1 3701.dat +0 STEP +1 0 0 0 -130 -1 0 0 0 1 0 0 0 -1 32018.dat +1 1 120 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 40 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -40 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -120 10 -140 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -180 10 -180 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -260 10 -180 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 -300 10 -160 -1 0 0 0 1 0 0 0 -1 4274.dat +1 1 -300 10 -120 -1 0 0 0 1 0 0 0 -1 4274.dat +0 STEP +1 7 -290 -24 -140 0 0 -1 0 1 0 1 0 0 3010.dat +1 7 -220 -24 -170 -1 0 0 0 1 0 0 0 -1 3009.dat +1 7 -80 -24 -120 -1 0 0 0 1 0 0 0 -1 3007.dat +1 7 80 -24 -120 -1 0 0 0 1 0 0 0 -1 3007.dat +1 7 200 -24 -90 -1 0 0 0 1 0 0 0 -1 3009.dat +0 STEP +1 7 -220 24 -160 -1 0 0 0 1 0 0 0 -1 3034.dat +1 1 140 24 -80 0 0 1 0 1 0 -1 0 0 10030 - subModel-86.ldr +0 STEP +1 8 -150 -24 -160 0 0 -1 0 1 0 1 0 0 2877.dat +1 8 -308 8 -140 0 1 0 0 0 -1 -1 0 0 10030 - subModel-87.ldr +1 8 184 0 -120 0 -1 0 0 0 -1 1 0 0 3003.dat +0 STEP +1 7 -220 8 -188 1 0 0 0 0 -1 0 1 0 10030 - subModel-83.ldr +0 STEP +1 7 -220 -48 -160 1 0 0 0 1 0 0 0 1 4515.dat +1 8 160 -32 -90 1 0 0 0 1 0 0 0 1 3023.dat +1 7 220 0 -108 0 0 1 1 0 0 0 1 0 10030 - subModel-88.ldr +0 STEP +1 7 -100 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +1 7 -20 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +1 7 60 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +1 7 140 -48 -110 1 0 0 0 1 0 0 0 1 3297.dat +0 STEP +1 7 -80 -56 -110 1 0 0 0 1 0 0 0 1 3743.dat +1 7 120 -56 -110 1 0 0 0 1 0 0 0 1 3743.dat + + +0 FILE 10030 - subModel-86.ldr +0 subModel-86 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-86.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3795.dat +1 7 40 -24 10 1 0 0 0 1 0 0 0 1 32000.dat +0 STEP +1 1 30 -14 20 0 0 -1 0 1 0 1 0 0 4274.dat +1 1 50 -14 20 0 0 -1 0 1 0 1 0 0 4274.dat + + +0 FILE 10030 - subModel-87.ldr +0 subModel-87 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-87.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3020.dat +1 7 30 -8 10 0 0 1 0 1 0 -1 0 0 2555.dat +0 STEP +1 7 0 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +0 STEP +1 7 20 -8 -10 -1 0 0 0 1 0 0 0 -1 2412b.dat +1 7 -30 -24 10 0 0 1 0 1 0 -1 0 0 4599a.dat +0 STEP +1 7 -20 -24 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat + + +0 FILE 10030 - subModel-88.ldr +0 subModel-88 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-88.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3021.dat +1 7 -10 -8 -20 -1 0 0 0 1 0 0 0 -1 2555.dat +0 STEP +1 7 10 -24 -10 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 -10 -24 10 0 0 -1 0 1 0 1 0 0 4865a.dat +0 STEP +1 7 10 -24 20 -1 0 0 0 1 0 0 0 -1 4599a.dat + + +0 FILE 10030 - subModel-89.ldr +0 subModel-89 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-89.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3832.dat +1 7 50 -8 10 0 0 1 0 1 0 -1 0 0 2555.dat +1 0 70 -8 10 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 70 -8 10 0 -1 0 0 0 1 -1 0 0 4593.dat +0 STEP +1 7 0 -8 10 -1 0 0 0 1 0 0 0 -1 3743.dat +1 7 -60 -24 10 -1 0 0 0 1 0 0 0 -1 4865a.dat +0 STEP +1 7 -20 -8 -10 -1 0 0 0 1 0 0 0 -1 2412b.dat +1 7 50 -24 -10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 10 -24 -10 0 0 1 0 1 0 -1 0 0 4599a.dat +0 STEP +1 7 80 -24 -10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 -90 -8 -10 1 0 0 0 1 0 0 0 1 2555.dat +1 0 -70 -8 -10 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -70 -8 -10 0 -0.996 0.087 0 0.087 0.996 -1 0 0 4593.dat + + +0 FILE 10030 - subModel-90.ldr +0 subModel-90 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-90.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3832.dat +1 7 -10 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 7 -10 -8 -90 -1 0 0 0 1 0 0 0 -1 2555.dat +1 0 -10 -8 -70 -1 0 0 0 1 0 0 0 -1 4592.dat +1 7 -10 -8 -70 -1 0 0 0 0.087 -0.996 0 -0.996 -0.087 4593.dat +1 7 -10 -24 50 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 -10 -24 10 1 0 0 0 1 0 0 0 1 4599a.dat +1 7 -10 -24 80 0 0 1 0 1 0 -1 0 0 4865a.dat +0 STEP +1 7 10 -8 0 0 0 1 0 1 0 -1 0 0 3743.dat +0 STEP +1 7 10 -24 -60 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 10 -8 50 0 0 -1 0 1 0 1 0 0 2555.dat +1 0 10 -8 70 1 0 0 0 1 0 0 0 1 4592.dat +1 7 10 -8 70 1 0 0 0 0 1 0 -1 0 4593.dat + + +0 FILE 10030 - subModel-91.ldr +0 subModel-91 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-91.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4282.dat +1 7 -10 -24 -20 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 -10 -24 20 0 0 1 0 1 0 -1 0 0 4865a.dat +0 STEP +1 7 -10 -24 -50 0 0 1 0 1 0 -1 0 0 4589.dat +1 7 -10 -24 50 0 0 1 0 1 0 -1 0 0 4589.dat +1 7 -10 -24 -80 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 -10 -24 80 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 -10 -8 -140 0 0 -1 0 1 0 1 0 0 2412b.dat +1 7 -10 -8 140 0 0 -1 0 1 0 1 0 0 2412b.dat +0 STEP +1 7 -10 -24 -110 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 10 -24 30 -1 0 0 0 1 0 0 0 -1 4599a.dat +1 7 10 -24 -30 1 0 0 0 1 0 0 0 1 4599a.dat +1 7 -10 -24 110 1 0 0 0 1 0 0 0 1 4599a.dat +0 STEP +1 7 10 -8 50 1 0 0 0 1 0 0 0 1 2555.dat +1 7 10 -8 -50 1 0 0 0 1 0 0 0 1 2555.dat +1 7 10 -8 -100 0 0 1 0 1 0 -1 0 0 3743.dat +1 7 10 -8 100 0 0 1 0 1 0 -1 0 0 3743.dat +0 STEP +1 0 10 -8 -150 -1 0 0 0 1 0 0 0 -1 4592.dat +1 0 10 -8 150 -1 0 0 0 1 0 0 0 -1 4592.dat +1 7 10 -8 -150 -1 0 0 0 0.574 -0.819 0 -0.819 -0.574 4593.dat +1 7 10 -8 150 -1 0 0 0 0.643 0.766 0 0.766 -0.643 4593.dat + + +0 FILE 10030 - subModel-92.ldr +0 subModel-92 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-92.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +0 !LDCAD GROUP_DEF [topLevel=true] [LID=0] [GID=5UrPRpO7Kzg] [name=Group 1] [center=0 0 0] +0 !LDCAD GROUP_DEF [topLevel=true] [LID=1] [GID=2zNQufczieW] [name=Group 2] [center=0 0 0] +1 0 0 0 0 1 0 0 0 1 0 0 0 1 3702.dat +1 0 -60 10 -10 0 0 -1 0 1 0 1 0 0 2780.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=-1] +1 0 60 10 -10 0 -0.156 -0.988 0 0.988 -0.156 1 0 0 2780.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=13] +1 7 -101.072 6.38 -20 0.988 0.156 0 -0.156 0.988 0 0 0 1 3894.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=14] +1 7 101.072 6.38 -20 0.988 -0.156 0 0.156 0.988 0 0 0 1 3894.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=17] +1 8 156.579 39.471 -50 0 -0.156 0.988 0 0.988 0.156 -1 0 0 3795.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=16] +1 8 -156.579 39.471 -50 0 0.156 0.988 0 0.988 -0.156 -1 0 0 3795.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=6] +1 7 170.21 17.331 -50 0 -0.156 0.988 0 0.988 0.156 -1 0 0 3894.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=12] +1 7 -170.21 17.331 -50 0 0.156 0.988 0 0.988 -0.156 -1 0 0 3894.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=11] +1 7 101.072 6.38 -100 -0.988 -0.156 0 -0.156 0.988 0 0 0 -1 3894.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=8] +1 7 -101.072 6.38 -100 -0.988 0.156 0 0.156 0.988 0 0 0 -1 3894.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=7] +1 1 178.523 28.772 -10 0.988 0.156 0 0.156 -0.988 0 0 0 -1 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=8] +1 1 178.523 28.772 -90 0.988 0.156 0 0.156 -0.988 0 0 0 -1 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=15] +1 1 -178.523 28.772 -90 -0.988 0.156 0 0.156 0.988 0 0 0 -1 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=14] +1 1 -178.523 28.772 -10 -0.988 0.156 0 0.156 0.988 0 0 0 -1 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=9] +1 1 139.015 22.515 -110 0 -0.156 0.988 0 0.988 0.156 -1 0 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=10] +1 1 79.754 13.129 -110 0 -0.156 0.988 0 0.988 0.156 -1 0 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=10] +1 1 -139.015 22.515 -110 0 0.156 0.988 0 0.988 -0.156 -1 0 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=9] +1 1 -79.754 13.129 -110 0 0.156 0.988 0 0.988 -0.156 -1 0 0 4274.dat +0 STEP +1 0 60 10 -90 0 0 -1 0 1 0 1 0 0 2780.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=-1] +1 0 -60 10 -90 0 0.156 -0.988 0 0.988 0.156 1 0 0 2780.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=3] +1 8 -161.585 7.865 -50 0 0.156 0.988 0 0.988 -0.156 -1 0 0 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=4] +1 8 161.585 7.865 -50 0 -0.156 0.988 0 0.988 0.156 -1 0 0 3795.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=4] +1 8 -112.2 0.043 -10 0.988 0.156 0 -0.156 0.988 0 0 0 1 3021.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=3] +1 8 112.2 0.043 -10 0.988 -0.156 0 0.156 0.988 0 0 0 1 3021.dat +1 0 0 0 -80 1 0 0 0 1 0 0 0 1 3702.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=17] +1 8 -77.564 26.956 -20 0.988 0.156 0 -0.156 0.988 0 0 0 1 3666.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=11] +1 8 -77.564 26.956 -100 0.988 0.156 0 -0.156 0.988 0 0 0 1 3666.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=15] +1 8 77.564 26.956 -20 0.988 -0.156 0 0.156 0.988 0 0 0 1 3666.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=16] +1 8 77.564 26.956 -100 0.988 -0.156 0 0.156 0.988 0 0 0 1 3666.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=7] +1 7 -31.934 -4.57 -100 0.988 0.156 0 -0.156 0.988 0 0 0 1 3005.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=12] +1 7 31.934 -4.57 -100 0.988 -0.156 0 0.156 0.988 0 0 0 1 3005.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=6] +1 7 -31.934 -4.57 -20 0 0.156 -0.988 0 0.988 0.156 1 0 0 3665.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=13] +1 7 31.934 -4.57 -20 0 -0.156 0.988 0 0.988 0.156 -1 0 0 3665.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=18] +1 7 186.424 30.024 -50 0 -0.988 0.156 0 -0.156 -0.988 1 0 0 10030 - subModel-94.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=19] +1 7 -186.424 30.024 -50 0 0.988 0.156 0 -0.156 0.988 1 0 0 10030 - subModel-93.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=5] +1 8 82.57 -4.65 -100 0.988 -0.156 0 0.156 0.988 0 0 0 1 3666.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=2] +1 8 -82.57 -4.65 -100 0.988 0.156 0 -0.156 0.988 0 0 0 1 3666.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=5] +1 8 -43.062 -10.907 -20 0.988 0.156 0 -0.156 0.988 0 0 0 1 3710.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=2] +1 8 43.062 -10.907 -20 0.988 -0.156 0 0.156 0.988 0 0 0 1 3710.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=23] +1 7 99.508 16.257 -118 -0.156 0 0.988 0.988 0 0.156 0 1 0 10030 - subModel-95.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=18] +1 7 -99.508 16.257 -118 -0.156 0 -0.988 -0.988 0 0.156 0 1 0 10030 - subModel-95.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=23] +1 7 -162.836 -0.036 -70 0 0.156 -0.988 0 0.988 0.156 1 0 0 6180.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=21] +1 7 83.821 -12.551 -70 0 -0.156 -0.988 0 0.988 -0.156 1 0 0 6180.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=22] +1 7 162.836 -0.036 -70 0 -0.156 0.988 0 0.988 0.156 -1 0 0 6180.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=21] +1 7 -83.821 -12.551 -70 0 0.156 0.988 0 0.988 -0.156 -1 0 0 6180.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=20] +1 7 -24.56 -21.937 -50 0 0.156 -0.988 0 0.988 0.156 1 0 0 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=20] +1 7 24.56 -21.937 -50 0 -0.156 -0.988 0 0.988 -0.156 1 0 0 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=19] +1 7 123.329 -6.294 10 0.988 -0.156 0 0.156 0.988 0 0 0 1 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=22] +1 7 -123.329 -6.294 10 0.988 0.156 0 -0.156 0.988 0 0 0 1 3034.dat + + +0 FILE 10030 - subModel-93.ldr +0 subModel-93 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-93.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3666.dat +0 STEP +1 7 -20 -8 0 1 0 0 0 1 0 0 0 1 3743.dat +1 7 40 -24 0 -1 0 0 0 1 0 0 0 -1 4865a.dat + + +0 FILE 10030 - subModel-94.ldr +0 subModel-94 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-94.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3666.dat +0 STEP +1 7 -20 -8 0 1 0 0 0 1 0 0 0 1 3743.dat +1 7 40 -24 0 1 0 0 0 1 0 0 0 1 4865a.dat + + +0 FILE 10030 - subModel-95.ldr +0 subModel-95 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-95.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3460.dat +1 7 0 -8 60 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 7 0 -8 0 0 0 1 0 1 0 -1 0 0 3743.dat +1 7 0 -8 -50 1 0 0 0 1 0 0 0 1 2555.dat +1 7 0 -24 -70 -1 0 0 0 1 0 0 0 -1 4599a.dat + + +0 FILE 10030 - subModel-96.ldr +0 subModel-96 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-96.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3032.dat +1 7 0 -24 0 0 0 1 0 1 0 -1 0 0 40344.dat +1 0 40 -14 -20 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 40 -14 0 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -40 -14 -20 -1 0 0 0 1 0 0 0 -1 2780.dat +1 0 -40 -14 0 -1 0 0 0 1 0 0 0 -1 2780.dat +0 STEP +1 7 50 -24 -140 0 0 -1 0 1 0 1 0 0 3703.dat +1 7 -50 -24 -140 0 0 -1 0 1 0 1 0 0 3703.dat +1 1 60 -14 -280 1 0 0 0 0 1 0 -1 0 4274.dat +1 1 60 -14 -260 1 0 0 0 0 1 0 -1 0 4274.dat +1 1 -60 -14 -280 -1 0 0 0 0 -1 0 -1 0 4274.dat +1 1 -60 -14 -260 -1 0 0 0 0 -1 0 -1 0 4274.dat +0 STEP +1 7 0 0 -260 1 0 0 0 1 0 0 0 1 10030 - subModel-97.ldr +1 4 0 -48 -50 1 0 0 0 1 0 0 0 1 3010.dat +1 4 0 -48 -10 1 0 0 0 1 0 0 0 1 3010.dat +1 7 50 -48 -100 0 0 1 0 1 0 -1 0 0 6111.dat +1 7 -50 -48 -100 0 0 1 0 1 0 -1 0 0 6111.dat +0 STEP +1 7 0 -72 -40 1 0 0 0 1 0 0 0 1 2356.dat +1 7 -50 -72 -140 0 0 1 0 1 0 -1 0 0 3009.dat +1 7 50 -72 -140 0 0 1 0 1 0 -1 0 0 3009.dat +1 8 0 -32 -270 -1 0 0 0 1 0 0 0 -1 3710.dat +1 7 68 -14 -250 0 -1 0 0 0 -1 1 0 0 2431.dat +1 7 -68 -14 -250 0 1 0 0 0 1 1 0 0 2431.dat +0 STEP +1 7 0 -96 -160 1 0 0 0 1 0 0 0 1 2356.dat +1 7 0 -32 -300 1 0 0 0 1 0 0 0 1 3068b.dat +1 7 30 -32 -300 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -30 -32 -300 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -50 -144 -80 0 0 1 0 1 0 -1 0 0 4215a.dat +1 7 50 -144 -80 0 0 -1 0 1 0 1 0 0 4215a.dat +1 7 50 -144 -20 0 0 -1 0 1 0 1 0 0 2362b.dat +1 7 -50 -144 -20 0 0 1 0 1 0 -1 0 0 2362b.dat +0 STEP +1 7 -50 -144 -220 1 0 0 0 1 0 0 0 1 30249.dat +1 7 50 -144 -220 1 0 0 0 1 0 0 0 1 30249.dat +1 7 -40 -120 -160 -1 0 0 0 1 0 0 0 -1 10030 - subModel-98.ldr +1 7 40 -120 -160 -1 0 0 0 1 0 0 0 -1 10030 - subModel-98.ldr +0 STEP +1 8 50 -168 -100 0 0 1 0 1 0 -1 0 0 2877.dat +1 8 -50 -168 -100 0 0 -1 0 1 0 1 0 0 2877.dat +1 7 -50 -168 -50 0 0 -1 0 1 0 1 0 0 3622.dat +1 7 50 -168 -50 0 0 -1 0 1 0 1 0 0 3622.dat +0 STEP +1 7 0 -192 -80 1 0 0 0 1 0 0 0 1 2356.dat +1 7 0 -192 -30 1 0 0 0 1 0 0 0 1 3894.dat +0 STEP +1 7 0 -216 -110 1 0 0 0 1 0 0 0 1 3009.dat +1 7 0 -216 -60 1 0 0 0 1 0 0 0 1 40344.dat +1 1 60 -206 -80 1 0 0 0 1 0 0 0 1 4274.dat +1 1 60 -206 -40 1 0 0 0 1 0 0 0 1 4274.dat +1 1 -60 -206 -40 -1 0 0 0 -1 0 0 0 1 4274.dat +1 1 -60 -206 -80 -1 0 0 0 -1 0 0 0 1 4274.dat +0 STEP +1 7 0 -240 -30 1 0 0 0 1 0 0 0 1 3009.dat +1 7 68 -206 -70 0 -1 0 0 0 1 -1 0 0 3743.dat +1 7 -68 -206 -70 0 1 0 0 0 -1 -1 0 0 3743.dat +0 STEP +1 7 -40 -240 -80 0 0 1 0 1 0 -1 0 0 3001.dat +1 7 40 -240 -80 0 0 1 0 1 0 -1 0 0 3001.dat +0 STEP +1 7 0 -264 -110 1 0 0 0 1 0 0 0 1 3009.dat +1 7 0 -264 -60 1 0 0 0 1 0 0 0 1 40344.dat +0 STEP +1 7 -50 -264 -140 1 0 0 0 1 0 0 0 1 30249.dat +1 7 50 -264 -140 1 0 0 0 1 0 0 0 1 30249.dat +1 1 60 -254 -80 1 0 0 0 1 0 0 0 1 4274.dat +1 1 60 -254 -40 1 0 0 0 1 0 0 0 1 4274.dat +1 1 -60 -254 -40 -1 0 0 0 -1 0 0 0 1 4274.dat +1 1 -60 -254 -80 -1 0 0 0 -1 0 0 0 1 4274.dat +0 STEP +1 7 0 -272 -30 1 0 0 0 1 0 0 0 1 10030 - subModel-100.ldr +1 7 -50 -384 -60 1 0 0 0 1 0 0 0 1 30249.dat +1 7 50 -384 -60 1 0 0 0 1 0 0 0 1 30249.dat +1 7 68 -254 -70 0 -1 0 0 0 1 -1 0 0 3743.dat +1 7 -68 -254 -70 0 1 0 0 0 -1 -1 0 0 3743.dat +0 STEP +1 7 -50 -392 -30 0 0 1 0 1 0 -1 0 0 2420.dat +1 7 50 -392 -30 -1 0 0 0 1 0 0 0 -1 2420.dat +1 8 0 -392 -30 -1 0 0 0 1 0 0 0 -1 3023.dat +1 8 0 -400 -30 -1 0 0 0 1 0 0 0 -1 3794a.dat +0 STEP +1 7 0 -293.258 -116.587 0 0 -1 -0.799 0.602 0 0.602 0.799 0 10030 - subModel-99.ldr +0 STEP +1 8 0 -392 -70 1 0 0 0 1 0 0 0 1 3666.dat +1 8 0 -400 -70 -1 0 0 0 1 0 0 0 -1 3794a.dat +0 STEP +1 0 20 -206 -20 0 0 -1 0 1 0 1 0 0 2780.dat +1 0 0 -206 -20 0 0 -1 0 1 0 1 0 0 2780.dat +1 0 -20 -206 -20 0 0 -1 0 1 0 1 0 0 2780.dat +1 0 0 -286 -20 0 0 -1 0 1 0 1 0 0 2780.dat +1 0 0 -326 -20 0 0 -1 0 1 0 1 0 0 2780.dat +1 7 0 -306 -10 1 0 0 0 0 1 0 -1 0 32524.dat +0 STEP +1 1 70 -316 136 0 0 -1 1 0 0 0 -1 0 10030 - subModel-107.ldr +0 STEP +1 8 0 -400 80 0 0 -1 0 1 0 1 0 0 10030 - subModel-113.ldr +0 STEP +1 7 0 -152 120 0 0 -1 0 1 0 1 0 0 10030 - subModel-116.ldr + + +0 FILE 10030 - subModel-97.ldr +0 subModel-97 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-97.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3958.dat +1 7 0 -24 -50 1 0 0 0 1 0 0 0 1 3009.dat +1 7 0 -24 -20 1 0 0 0 1 0 0 0 1 3001.dat + + +0 FILE 10030 - subModel-98.ldr +0 subModel-98 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-98.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3001.dat +1 7 0 -24 0 0 0 1 0 1 0 -1 0 0 3001.dat + + +0 FILE 10030 - subModel-99.ldr +0 subModel-99 +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 Name: 10030 - subModel-99.ldr +0 !LDRAW_ORG Model +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3029.dat +1 7 -110 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -110 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -70 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -70 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -30 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -30 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 8 -90 -8 0 0 0 1 0 1 0 -1 0 0 3794a.dat +1 8 -50 -8 0 0 0 1 0 1 0 -1 0 0 3794a.dat +0 STEP +1 7 10 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 10 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 50 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 50 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 90 -8 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 90 -8 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 8 30 -8 0 0 0 1 0 1 0 -1 0 0 3794a.dat +1 8 70 -8 0 0 0 1 0 1 0 -1 0 0 3794a.dat +0 STEP +1 7 -180 8 0 1 0 0 0 1 0 0 0 1 3029.dat +0 STEP +1 7 -150 0 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -150 0 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -190 0 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -190 0 -20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -230 0 30 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -290 0 30 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -290 0 -30 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -230 0 -30 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -90 -16 0 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 -50 -16 0 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 30 -16 0 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 70 -16 0 0 0 1 0 1 0 -1 0 0 2555.dat +0 STEP +1 7 -280 -16 -10 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 -280 -16 10 1 0 0 0 1 0 0 0 1 4865a.dat +1 7 -230 -16 10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 -230 -16 -10 0 0 -1 0 1 0 1 0 0 4599a.dat +1 8 -220 -6 -30 0 -1 0 0 0 -1 1 0 0 30374.dat +1 8 -220 -6 30 0 -1 0 0 0 -1 1 0 0 30374.dat +1 8 -30 -22 0 0 -1 0 0 0 -1 1 0 0 30374.dat +1 8 90 -22 0 0 -1 0 0 0 -1 1 0 0 30374.dat +0 STEP +1 0 -290 16 20 0 0 1 0 1 0 -1 0 0 6134.dat +1 0 -290 16 -20 0 0 1 0 1 0 -1 0 0 6134.dat +1 7 -281.808 20.264 20 0 -0.819 0.574 0 0.574 0.819 -1 0 0 3937.dat +1 7 -281.808 20.264 -20 0 -0.799 0.602 0 0.602 0.799 -1 0 0 3937.dat + + +0 FILE 10030 - subModel-100.ldr +0 subModel-100 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-100.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3666.dat +1 7 0 -24 0 1 0 0 0 1 0 0 0 1 3894.dat +1 8 0 -32 0 1 0 0 0 1 0 0 0 1 3666.dat +1 8 0 -40 0 1 0 0 0 1 0 0 0 1 3666.dat +0 STEP +1 7 0 -64 0 1 0 0 0 1 0 0 0 1 3894.dat +1 7 0 -88 0 1 0 0 0 1 0 0 0 1 3009.dat +1 7 0 -112 0 1 0 0 0 1 0 0 0 1 3009.dat + + +0 FILE 10030 - subModel-101.ldr +0 subModel-101 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-101.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 -1 0 0 0 1 -1 0 0 32524.dat +1 0 10 -20 0 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 10 20 0 1 0 0 0 0 1 0 -1 0 2780.dat +1 0 -20 -60 0 -1 0 0 0 0 1 0 1 0 6558.dat +1 0 -20 60 0 -1 0 0 0 0 1 0 1 0 6558.dat +1 7 20 0 0 0 -1 0 0 0 1 -1 0 0 32524.dat +1 0 40 -60 0 1 0 0 0 0 1 0 -1 0 6558.dat +1 0 40 60 0 1 0 0 0 0 1 0 -1 0 6558.dat +0 STEP +1 1 40 -60 0 1 0 0 0 -0.981 -0.195 0 0.195 -0.981 32016.dat +1 1 -20 -60 0 1 0 0 0 -0.981 -0.195 0 0.195 -0.981 32016.dat +1 1 40 60 0 1 0 0 0 0.981 0.195 0 -0.195 0.981 32016.dat +1 1 -20 60 0 1 0 0 0 0.981 0.195 0 -0.195 0.981 32016.dat +0 STEP +1 7 60 0 0 0 -1 0 0 0 1 -1 0 0 32524.dat +1 7 -40 0 0 0 -1 0 0 0 1 -1 0 0 32524.dat +0 STEP +1 4 -20 -52.196 -39.231 0 -1 0 0.195 0 0.981 -0.981 0 0.195 4519.dat +1 4 40 -52.196 -39.231 0 -1 0 0.195 0 0.981 -0.981 0 0.195 4519.dat +1 4 40 -52.196 39.231 0 -1 0 -0.195 0 0.981 -0.981 0 -0.195 4519.dat +1 4 -20 -52.196 39.231 0 -1 0 -0.195 0 0.981 -0.981 0 -0.195 4519.dat +1 4 -20 52.196 39.231 0 -1 0 0.195 0 0.981 -0.981 0 0.195 4519.dat +1 4 40 52.196 39.231 0 -1 0 0.195 0 0.981 -0.981 0 0.195 4519.dat +1 4 -20 52.196 -39.231 0 -1 0 -0.195 0 0.981 -0.981 0 -0.195 4519.dat +1 4 40 52.196 -39.231 0 -1 0 -0.195 0 0.981 -0.981 0 -0.195 4519.dat +0 STEP +1 0 -50 40 0 -1 0 0 0 0 1 0 1 0 2780.dat +1 0 -50 -40 0 -1 0 0 0 0 1 0 1 0 2780.dat +1 4 80 52.292 -131.014 -1 0 0 0 -0.981 0.195 0 0.195 0.981 10030 - subModel-102.ldr +0 STEP +1 4 80 60.139 132.574 -1 0 0 0 -0.981 -0.195 0 -0.195 0.981 10030 - subModel-103.ldr +0 STEP +1 4 80 -60.139 132.574 1 0 0 0 0.981 0.195 0 -0.195 0.981 10030 - subModel-104.ldr +0 STEP +1 4 80 -60.139 -132.574 1 0 0 0 0.981 -0.195 0 0.195 0.981 10030 - subModel-106.ldr + + +0 FILE 10030 - subModel-102.ldr +0 subModel-102 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-102.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 -8 0 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 80 -8 0 1 0 0 0 1 0 0 0 1 30355.dat +0 STEP +1 8 60 -16 90 1 0 0 0 1 0 0 0 1 4162.dat +1 7 20 -16 -110 1 0 0 0 1 0 0 0 1 2431.dat +0 STEP +1 8 20 0 -90 0 0 -1 0 1 0 1 0 0 3021.dat +1 8 20 0 0 0 0 -1 0 1 0 1 0 0 3795.dat +1 8 60 0 80 -1 0 0 0 1 0 0 0 -1 3795.dat +0 STEP +1 0 40 8 70 -1 0 0 0 1 0 0 0 -1 32064b.dat +1 0 40 8 90 -1 0 0 0 1 0 0 0 -1 32064b.dat +1 0 100 8 70 -1 0 0 0 1 0 0 0 -1 32064b.dat +1 0 100 8 90 -1 0 0 0 1 0 0 0 -1 32064b.dat +0 STEP + + +0 FILE 10030 - subModel-103.ldr +0 subModel-103 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-103.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 80 0 0 -1 0 0 0 1 0 0 0 -1 30356.dat +0 STEP +1 8 60 -8 -90 -1 0 0 0 1 0 0 0 -1 4162.dat +1 7 20 -8 110 -1 0 0 0 1 0 0 0 -1 2431.dat +0 STEP +1 8 20 8 90 0 0 1 0 1 0 -1 0 0 3021.dat +1 8 20 8 0 0 0 1 0 1 0 -1 0 0 3795.dat +1 8 60 8 -80 1 0 0 0 1 0 0 0 1 3795.dat +0 STEP +1 0 40 16 -70 1 0 0 0 1 0 0 0 1 32064b.dat +1 0 40 16 -90 1 0 0 0 1 0 0 0 1 32064b.dat +1 0 100 16 -90 1 0 0 0 1 0 0 0 1 32064b.dat +1 0 100 16 -70 1 0 0 0 1 0 0 0 1 32064b.dat + + +0 FILE 10030 - subModel-104.ldr +0 subModel-104 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-104.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 -80 0 0 -1 0 0 0 1 0 0 0 -1 30355.dat +0 STEP +1 7 -20 -8 110 -1 0 0 0 1 0 0 0 -1 2431.dat +1 7 -20 -8 -100 -1 0 0 0 1 0 0 0 -1 3022.dat +0 STEP +1 8 -20 8 90 0 0 1 0 1 0 -1 0 0 3021.dat +1 8 -20 8 0 0 0 1 0 1 0 -1 0 0 3795.dat +1 8 -60 8 -80 1 0 0 0 1 0 0 0 1 3795.dat +0 STEP +1 0 -40 16 -90 1 0 0 0 1 0 0 0 1 32064b.dat +1 0 -40 16 -70 1 0 0 0 1 0 0 0 1 32064b.dat +1 0 -100 16 -70 1 0 0 0 1 0 0 0 1 32064b.dat +1 0 -100 16 -90 1 0 0 0 1 0 0 0 1 32064b.dat +0 STEP +1 7 -20 -16 -110 1 0 0 0 1 0 0 0 1 2412b.dat +1 7 -10 -8 30 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -30 -8 30 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -30 -8 90 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -10 -8 90 1 0 0 0 1 0 0 0 1 4592.dat +1 7 10 -8 70 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 10 -8 50 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -50 -8 70 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -50 -8 50 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -50 -8 70 0 0.259 0.966 0 0.966 -0.259 -1 0 0 4593.dat +1 7 -50 -8 50 0 0.259 0.966 0 0.966 -0.259 -1 0 0 4593.dat +1 7 10 -8 70 0 -0.259 -0.966 0 0.966 -0.259 1 0 0 4593.dat +1 7 10 -8 50 0 -0.259 -0.966 0 0.966 -0.259 1 0 0 4593.dat +1 7 -30 -8 30 1 0 0 0 0.966 -0.259 0 0.259 0.966 4593.dat +1 7 -30 -8 30 1 0 0 0 0.966 -0.259 0 0.259 0.966 4593.dat +1 7 -10 -8 30 1 0 0 0 0.966 -0.259 0 0.259 0.966 4593.dat +1 7 -30 -8 90 -1 0 0 0 0.966 -0.259 0 -0.259 -0.966 4593.dat +1 7 -10 -8 90 -1 0 0 0 0.966 -0.259 0 -0.259 -0.966 4593.dat +0 STEP +1 7 -20 -24 60 0 0 1 0 1 0 -1 0 0 10030 - subModel-105.ldr + + +0 FILE 10030 - subModel-105.ldr +0 subModel-105 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-105.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 6143.dat +1 7 0 0 0 1 0 0 0 1 0 0 0 1 30342.dat +1 7 0 -40 0 1 0 0 0 1 0 0 0 1 30208.dat + + +0 FILE 10030 - subModel-106.ldr +0 subModel-106 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-106.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 2445.dat +1 7 -80 0 0 1 0 0 0 1 0 0 0 1 30356.dat +0 STEP +1 7 -20 -8 -110 1 0 0 0 1 0 0 0 1 2431.dat +1 7 -20 -8 100 1 0 0 0 1 0 0 0 1 3022.dat +1 7 -20 -16 110 1 0 0 0 1 0 0 0 1 2412b.dat +0 STEP +1 8 -20 8 -90 0 0 -1 0 1 0 1 0 0 3021.dat +1 8 -20 8 0 0 0 -1 0 1 0 1 0 0 3795.dat +1 8 -60 8 80 -1 0 0 0 1 0 0 0 -1 3795.dat +0 STEP +1 0 -40 16 70 -1 0 0 0 1 0 0 0 -1 32064b.dat +1 0 -40 16 90 -1 0 0 0 1 0 0 0 -1 32064b.dat +1 0 -100 16 70 -1 0 0 0 1 0 0 0 -1 32064b.dat +1 0 -100 16 90 -1 0 0 0 1 0 0 0 -1 32064b.dat +0 STEP +1 7 -30 -8 -30 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -30 -8 -90 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -50 -8 -90 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -50 -8 -30 1 0 0 0 1 0 0 0 1 4592.dat +1 7 -10 -8 -50 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -10 -8 -70 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -70 -8 -50 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -70 -8 -70 0 0 1 0 1 0 -1 0 0 4592.dat +1 7 -70 -8 -50 0 0.259 0.966 0 0.966 -0.259 -1 0 0 4593.dat +1 7 -70 -8 -70 0 0.259 0.966 0 0.966 -0.259 -1 0 0 4593.dat +1 7 -10 -8 -50 0 -0.259 -0.966 0 0.966 -0.259 1 0 0 4593.dat +1 7 -10 -8 -70 0 -0.259 -0.966 0 0.966 -0.259 1 0 0 4593.dat +1 7 -50 -8 -90 1 0 0 0 0.966 -0.259 0 0.259 0.966 4593.dat +1 7 -30 -8 -90 1 0 0 0 0.966 -0.259 0 0.259 0.966 4593.dat +1 7 -50 -8 -30 -1 0 0 0 0.966 -0.259 0 -0.259 -0.966 4593.dat +1 7 -30 -8 -30 -1 0 0 0 0.966 -0.259 0 -0.259 -0.966 4593.dat +0 STEP +1 7 -40 -24 -60 1 0 0 0 1 0 0 0 1 10030 - subModel-105.ldr + + +0 FILE 10030 - subModel-107.ldr +0 subModel-107 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-107.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 10 0 0 1 0 0 0 1 0 0 0 1 2625.dat +1 7 10 0 140 -1 0 0 0 1 0 0 0 -1 2625.dat +0 STEP +1 7 -40 -8 70 0 0 -1 0 1 0 1 0 0 3460.dat +1 7 60 -8 70 0 0 -1 0 1 0 1 0 0 3460.dat +0 STEP +1 8 10 8 190 0 0 -1 0 1 0 1 0 0 3832.dat +1 8 10 8 -50 0 0 -1 0 1 0 1 0 0 3832.dat +0 STEP +1 7 40 -8 30 0 0 -1 0 1 0 1 0 0 3743.dat +1 7 40 -8 110 0 0 -1 0 1 0 1 0 0 3743.dat +1 7 10 0 -130 0 0 -1 0 1 0 1 0 0 3020.dat +1 7 10 0 270 0 0 -1 0 1 0 1 0 0 3020.dat +1 7 10 -16 220 -1 0 0 0 1 0 0 0 -1 4865a.dat +1 7 10 -16 -80 1 0 0 0 1 0 0 0 1 4865a.dat +0 STEP +1 7 -20 -8 70 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 0 -8 10 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 0 -8 130 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 50 -8 -50 1 0 0 0 1 0 0 0 1 41770.dat +1 7 30 -8 -130 1 0 0 0 1 0 0 0 1 41770.dat +1 7 -10 -8 -130 1 0 0 0 1 0 0 0 1 41769.dat +1 7 -30 -8 -50 1 0 0 0 1 0 0 0 1 41769.dat +1 7 50 -8 190 -1 0 0 0 1 0 0 0 -1 41769.dat +1 7 30 -8 270 -1 0 0 0 1 0 0 0 -1 41769.dat +1 7 -30 -8 190 -1 0 0 0 1 0 0 0 -1 41770.dat +1 7 -10 -8 270 -1 0 0 0 1 0 0 0 -1 41770.dat +0 STEP +1 8 -20 -16 -40 1 0 0 0 1 0 0 0 1 6141.dat +1 8 40 -16 -40 1 0 0 0 1 0 0 0 1 6141.dat +1 8 -20 -16 180 1 0 0 0 1 0 0 0 1 6141.dat +1 8 40 -16 180 1 0 0 0 1 0 0 0 1 6141.dat +1 8 10 -16 -140 1 0 0 0 1 0 0 0 1 3023.dat +1 8 10 -16 280 1 0 0 0 1 0 0 0 1 3023.dat +1 7 0 -16 -110 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 0 -16 250 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 20 -8 0 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 0 -8 60 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 0 -8 80 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 20 -8 140 -1 0 0 0 1 0 0 0 -1 2555.dat +0 STEP +1 7 20 -32 -110 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 20 -32 250 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 0 -24 -30 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 0 -24 170 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 20 -24 -60 0 0 -1 0 1 0 1 0 0 4599a.dat +1 7 20 -24 200 0 0 -1 0 1 0 1 0 0 4599a.dat +1 8 10 -16 300 -1 0 0 0 1 0 0 0 -1 44728.dat +1 8 10 -16 -160 1 0 0 0 1 0 0 0 1 44728.dat +0 STEP +1 7 10 24 -182 1 0 0 0 0 -1 0 1 0 10030 - subModel-108.ldr +1 7 10 24 322 -1 0 0 0 0 -1 0 -1 0 10030 - subModel-110.ldr +1 7 10 -24 -150 0 0 -1 0 1 0 1 0 0 3068b.dat +1 7 10 -24 290 0 0 -1 0 1 0 1 0 0 3068b.dat +0 STEP +1 8 10 99.983 241.987 1 0 0 0 -0.94 0.342 0 -0.342 -0.94 10030 - subModel-111.ldr +0 STEP +1 8 10 99.983 -101.987 -1 0 0 0 -0.94 0.342 0 0.342 0.94 10030 - subModel-112.ldr +1 1 -30 8 70 -1 0 0 0 1 0 0 0 -1 2476a.dat +1 1 10 8 70 -1 0 0 0 1 0 0 0 -1 2476a.dat +1 1 50 8 70 -1 0 0 0 1 0 0 0 -1 2476a.dat +0 STEP +1 1 10 86 70 0 1 0 -1 0 0 0 0 1 10030 - subModel-101.ldr + + +0 FILE 10030 - subModel-108.ldr +0 subModel-108 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-108.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3020.dat +1 7 -10 -8 0 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 10 -8 10 0 0 1 0 1 0 -1 0 0 2555.dat +0 STEP +1 0 0 16 -30 1 0 0 0 1 0 0 0 1 10030 - subModel-109.ldr +0 STEP + + +0 FILE 10030 - subModel-109.ldr +0 subModel-109 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-109.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 -7.397 3.42 1 0 0 0 0.94 0.342 0 -0.342 0.94 3937.dat +1 0 0 -8 0 1 0 0 0 1 0 0 0 1 6134.dat + + +0 FILE 10030 - subModel-110.ldr +0 subModel-110 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-110.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3020.dat +1 7 10 -8 0 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -10 -8 10 0 0 1 0 1 0 -1 0 0 2555.dat +0 STEP +1 7 0 16 -30 1 0 0 0 1 0 0 0 1 10030 - subModel-109.ldr + + +0 FILE 10030 - subModel-111.ldr +0 subModel-111 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-111.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3795.dat +0 STEP +1 7 0 -8 60 0 0 1 0 1 0 -1 0 0 3020.dat +1 7 20 -8 -20 1 0 0 0 1 0 0 0 1 41770.dat +1 7 -20 -8 -20 1 0 0 0 1 0 0 0 1 41769.dat +0 STEP +1 7 0 0 90 1 0 0 0 1 0 0 0 1 2419.dat +0 STEP +1 7 -40 -8 60 1 0 0 0 1 0 0 0 1 41769.dat +1 7 40 -8 60 1 0 0 0 1 0 0 0 1 41770.dat +1 7 0 -8 110 1 0 0 0 1 0 0 0 1 6636.dat +0 STEP +1 7 0 -16 90 1 0 0 0 1 0 0 0 1 2431.dat +1 7 10 -16 70 1 0 0 0 1 0 0 0 1 2555.dat +1 7 -10 -32 50 1 0 0 0 1 0 0 0 1 4599a.dat +1 7 10 -32 20 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 -10 -16 20 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 8 0 8 40 0 0 1 0 1 0 -1 0 0 3795.dat +1 8 0 22 -60 -1 0 0 0 0 1 0 1 0 44728.dat + + +0 FILE 10030 - subModel-112.ldr +0 subModel-112 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-112.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3795.dat +0 STEP +1 7 0 -8 60 0 0 1 0 1 0 -1 0 0 3020.dat +1 7 -20 -8 -20 1 0 0 0 1 0 0 0 1 41769.dat +1 7 20 -8 -20 1 0 0 0 1 0 0 0 1 41770.dat +0 STEP +1 7 0 0 90 1 0 0 0 1 0 0 0 1 2419.dat +0 STEP +1 7 -40 -8 60 1 0 0 0 1 0 0 0 1 41769.dat +1 7 40 -8 60 1 0 0 0 1 0 0 0 1 41770.dat +1 7 0 -8 110 1 0 0 0 1 0 0 0 1 6636.dat +0 STEP +1 7 0 -16 90 1 0 0 0 1 0 0 0 1 2431.dat +1 7 10 -32 50 1 0 0 0 1 0 0 0 1 4599a.dat +1 7 -10 -16 70 1 0 0 0 1 0 0 0 1 2555.dat +1 7 10 -16 20 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -10 -32 20 0 0 -1 0 1 0 1 0 0 4865a.dat +0 STEP +1 8 0 8 40 0 0 1 0 1 0 -1 0 0 3795.dat +1 8 0 22 -60 -1 0 0 0 0 1 0 1 0 44728.dat + + +0 FILE 10030 - subModel-113.ldr +0 subModel-113 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-113.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 -20 0 0 1 0 0 0 1 0 0 0 1 3008.dat +1 7 50 -8 0 0 0 -1 0 1 0 1 0 0 4081b.dat +0 STEP +1 7 -100 -8 0 1 0 0 0 1 0 0 0 1 6636.dat +1 8 -20 -8 0 1 0 0 0 1 0 0 0 1 3794a.dat +1 8 20 -8 0 1 0 0 0 1 0 0 0 1 3794a.dat +0 STEP +1 8 0 -16 0 1 0 0 0 1 0 0 0 1 3795.dat +1 7 50 -24 0 0 0 1 0 1 0 -1 0 0 4162.dat +0 STEP +1 7 10 -24 0 0 0 1 0 1 0 -1 0 0 2419.dat +1 7 -40 -24 0 0 0 1 0 1 0 -1 0 0 3068b.dat +0 STEP +1 7 30 -48 10 -1 0 0 0 1 0 0 0 -1 3040b.dat +1 7 30 -48 -10 1 0 0 0 1 0 0 0 1 3040b.dat +1 8 30 -56 0 0 0 1 0 1 0 -1 0 0 3023.dat +0 STEP +1 7 30 -64 10 0 0 -1 0 1 0 1 0 0 10030 - subModel-114.ldr +0 STEP +1 8 10 -48 0 0 0 1 0 1 0 -1 0 0 10030 - subModel-115.ldr +1 7 30 -88 -10 1 0 0 0 1 0 0 0 1 3676.dat +1 7 30 -88 10 0 0 -1 0 1 0 1 0 0 3676.dat +0 STEP +1 7 50 -96 0 0 0 1 0 1 0 -1 0 0 4162.dat +1 7 30 -96 0 0 0 1 0 1 0 -1 0 0 2412b.dat +1 8 30 -96 30 0 0 1 0 1 0 -1 0 0 6141.dat +1 8 30 -96 -30 0 0 1 0 1 0 -1 0 0 6141.dat + + +0 FILE 10030 - subModel-114.ldr +0 subModel-114 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-114.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 -10 0 0 1 0 0 0 1 0 0 0 1 2436a.dat +1 7 -30 10 -22 1 0 0 0 0 -1 0 1 0 2412b.dat +1 7 10 10 -22 1 0 0 0 0 -1 0 1 0 2412b.dat + + +0 FILE 10030 - subModel-115.ldr +0 subModel-115 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-115.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +0 !LDCAD GROUP_DEF [topLevel=true] [LID=0] [GID=7A83UMvNJp0] [name=Group 1] [center=0 0 0] +1 7 0 0 0 1 0 0 0 1 0 0 0 1 3937.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=-1] +1 0 0 1.34 -5 -1 0 0 0 0.866 0.5 0 0.5 -0.866 6134.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=2] +1 7 0 -5.588 -9 -1 0 0 0 0.866 0.5 0 0.5 -0.866 2412b.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=3] +1 7 10 4.412 -26.321 -1 0 0 0 0.866 0.5 0 0.5 -0.866 2555.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=6] +1 7 -10 4.412 -26.321 -1 0 0 0 0.866 0.5 0 0.5 -0.866 2555.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=5] +1 8 -10 19.215 -63.962 -1 0 0 0 -0.5 0.866 0 0.866 0.5 30374.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=4] +1 8 10 19.215 -63.962 -1 0 0 0 -0.5 0.866 0 0.866 0.5 30374.dat + + +0 FILE 10030 - subModel-116.ldr +0 subModel-116 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-116.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +0 !LDCAD GROUP_DEF [topLevel=true] [LID=0] [GID=If3F5eoKvV1] [name=Group 1] [center=0 0 0] +0 !LDCAD GROUP_DEF [topLevel=true] [LID=1] [GID=EvPL6t9GZ9Q] [name=Group 2] [center=0 0 0] +1 7 0 0 0 1 0 0 0 1 0 0 0 1 32531.dat +1 0 -60 10 20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 -60 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 60 10 20 1 0 0 0 1 0 0 0 1 2780.dat +1 0 60 10 -20 1 0 0 0 1 0 0 0 1 2780.dat +0 STEP +1 0 70 10 0 0 -1 0 1 0 0 0 0 1 32525.dat +1 0 -70 10 0 0 -1 0 1 0 0 0 0 1 32525.dat +0 STEP +1 7 -110 24 0 1 0 0 0 1 0 0 0 1 10030 - subModel-118.ldr +1 7 90 24 0 0 0 1 0 1 0 -1 0 0 10030 - subModel-117.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=6] +1 1 -100 0.123 -101.564 -1 0 0 0 0.988 0.156 0 0.156 -0.988 30000.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=-1] +1 1 100 0.123 -101.564 -1 0 0 0 0.988 0.156 0 0.156 -0.988 30000.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=-1] +1 1 100 0.123 101.564 -1 0 0 0 0.988 -0.156 0 -0.156 -0.988 30000.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=2] +1 1 -100 0.123 101.564 -1 0 0 0 0.988 -0.156 0 -0.156 -0.988 30000.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=2] +1 0 180 6.38 -141.072 0 0 -1 -0.156 0.988 0 0.988 0.156 0 40345.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=6] +1 0 180 6.38 141.072 0 0 -1 0.156 0.988 0 0.988 -0.156 0 40345.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=3] +1 0 60 14.202 190.456 0 0 -1 0.156 0.988 0 0.988 -0.156 0 10030 - subModel-119.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=5] +1 0 60 11.074 -170.703 0 0 -1 -0.156 0.988 0 0.988 0.156 0 10030 - subModel-119.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=4] +1 0 -180 6.38 141.072 0 0 -1 0.156 0.988 0 0.988 -0.156 0 40345.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=7] +1 0 -180 6.38 -141.072 0 0 -1 -0.156 0.988 0 0.988 0.156 0 40345.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=23] +1 1 -240 25.643 198.769 -1 0 0 0 0.988 -0.156 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=24] +1 1 -240 6.871 80.246 -1 0 0 0 0.988 -0.156 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=21] +1 1 -240 6.871 -80.246 -1 0 0 0 0.988 0.156 0 0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=22] +1 1 -240 25.643 -198.769 -1 0 0 0 0.988 0.156 0 0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=25] +1 1 240 25.643 -198.769 1 0 0 0 -0.988 0.156 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=24] +1 1 240 6.871 -80.246 1 0 0 0 -0.988 0.156 0 -0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=25] +1 1 240 6.871 80.246 1 0 0 0 -0.988 -0.156 0 0.156 -0.988 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=26] +1 1 240 25.643 198.769 1 0 0 0 -0.988 -0.156 0 0.156 -0.988 4274.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=23] +1 8 230 33.214 -157.071 0 0 1 0.156 0.988 0 -0.988 0.156 0 3666.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=13] +1 8 230 33.214 157.071 0 0 1 -0.156 0.988 0 -0.988 -0.156 0 3666.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=20] +1 8 -230 33.214 -157.071 0 0 1 0.156 0.988 0 -0.988 0.156 0 3666.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=9] +1 8 -230 33.214 157.071 0 0 1 -0.156 0.988 0 -0.988 -0.156 0 3666.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=8] +1 7 -160 20.699 78.056 1 0 0 0 0.988 0.156 0 -0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=9] +1 7 -160 20.699 -78.056 1 0 0 0 0.988 -0.156 0 0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=10] +1 7 -140 39.471 196.579 1 0 0 0 0.988 0.156 0 -0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=19] +1 7 -140 39.471 -196.579 1 0 0 0 0.988 -0.156 0 0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=12] +1 7 140 39.471 196.579 1 0 0 0 0.988 0.156 0 -0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=14] +1 7 160 20.699 78.056 1 0 0 0 0.988 0.156 0 -0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=4] +1 7 160 20.699 -78.056 1 0 0 0 0.988 -0.156 0 0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=37] +1 7 140 39.471 -196.579 1 0 0 0 0.988 -0.156 0 0.156 0.988 3034.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=11] +1 8 0 39.471 196.579 1 0 0 0 0.988 0.156 0 -0.156 0.988 3795.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=18] +1 8 0 39.471 -196.579 1 0 0 0 0.988 -0.156 0 0.156 0.988 3795.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=8] +1 4 -180 -1.441 -91.687 1 0 0 0 0.988 -0.156 0 0.156 0.988 3010.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=3] +1 4 180 -1.441 -91.687 1 0 0 0 0.988 -0.156 0 0.156 0.988 3010.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=7] +1 4 180 -1.441 91.687 1 0 0 0 0.988 0.156 0 -0.156 0.988 3010.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=5] +1 4 -180 -1.441 91.687 1 0 0 0 0.988 0.156 0 -0.156 0.988 3010.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=10] +1 1 -200 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=11] +1 1 -160 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=12] +1 1 -80 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=13] +1 1 -40 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=14] +1 1 40 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=15] +1 1 80 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=16] +1 1 160 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=17] +1 1 200 28.772 -218.523 0 0 1 0.156 0.988 0 -0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=15] +1 1 200 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=16] +1 1 160 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=17] +1 1 80 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=18] +1 1 40 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=19] +1 1 -40 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=20] +1 1 -80 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=21] +1 1 -160 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=22] +1 1 -200 28.772 218.523 0 0 1 0.156 -0.988 0 0.988 0.156 0 4274.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=39] +1 7 -248 16.257 139.508 0 1 0 -0.988 0 0.156 0.156 0 0.988 10030 - subModel-120.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=39] +1 7 -248 16.257 -139.508 0 1 0 0.988 0 0.156 0.156 0 -0.988 10030 - subModel-120.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=40] +1 7 248 13.129 -119.754 0 -1 0 0.988 0 -0.156 0.156 0 0.988 10030 - subModel-122.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=40] +1 7 248 13.129 119.754 0 -1 0 -0.988 0 -0.156 0.156 0 -0.988 10030 - subModel-121.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=0] [nrs=34] +1 7 -180 30.024 -226.424 0 0 -1 -0.988 -0.156 0 -0.156 0.988 0 10030 - subModel-123.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=36] +1 7 60 30.024 -226.424 0 0 -1 -0.988 -0.156 0 -0.156 0.988 0 10030 - subModel-123.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=35] +1 7 -60 30.024 -226.424 0 0 1 0.988 -0.156 0 0.156 0.988 0 10030 - subModel-123.ldr +0 !LDCAD GROUP_NXT [ids=0] [nrs=38] +1 7 180 30.024 -226.424 0 0 1 0.988 -0.156 0 0.156 0.988 0 10030 - subModel-123.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=35] +1 7 180 30.024 226.424 0 0 1 -0.988 -0.156 0 0.156 -0.988 0 10030 - subModel-124.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=36] +1 7 60 30.024 226.424 0 0 -1 0.988 -0.156 0 -0.156 -0.988 0 10030 - subModel-124.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=37] +1 7 -60 30.024 226.424 0 0 1 -0.988 -0.156 0 0.156 -0.988 0 10030 - subModel-124.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=38] +1 7 -180 30.024 226.424 0 0 -1 0.988 -0.156 0 -0.156 -0.988 0 10030 - subModel-124.ldr +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=27] +1 7 220 -4.65 122.57 0 0 1 -0.156 0.988 0 -0.988 -0.156 0 3029.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=33] +1 7 220 -4.65 -122.57 0 0 1 0.156 0.988 0 -0.988 0.156 0 3029.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=28] +1 7 140 -4.65 122.57 0 0 1 -0.156 0.988 0 -0.988 -0.156 0 3029.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=32] +1 7 140 -4.65 -122.57 0 0 1 0.156 0.988 0 -0.988 0.156 0 3029.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=31] +1 7 -20 4.736 -181.831 -1 0 0 0 0.988 0.156 0 0.156 -0.988 6178.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=30] +1 7 -20 4.736 181.831 1 0 0 0 0.988 0.156 0 -0.156 0.988 6178.dat +0 STEP +0 !LDCAD GROUP_NXT [ids=1] [nrs=29] +1 7 -20 -10.907 83.062 1 0 0 0 0.988 0.156 0 -0.156 0.988 3029.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=30] +1 7 -20 -10.907 -83.062 1 0 0 0 0.988 -0.156 0 0.156 0.988 3029.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=29] +1 7 -180 1.608 -162.077 0 0 1 0.156 0.988 0 -0.988 0.156 0 3035.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=32] +1 7 -180 1.608 162.077 0 0 1 -0.156 0.988 0 -0.988 -0.156 0 3035.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=28] +1 7 -260 1.608 -162.077 1 0 0 0 0.988 -0.156 0 0.156 0.988 3934.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=33] +1 7 -260 1.608 162.077 -1 0 0 0 0.988 -0.156 0 -0.156 -0.988 3933.dat +0 !LDCAD GROUP_NXT [ids=1] [nrs=31] +1 7 -220 -12.471 73.185 -1 0 0 0 0.988 -0.156 0 -0.156 -0.988 3460.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=27] +1 7 -220 -12.471 -73.185 -1 0 0 0 0.988 0.156 0 0.156 -0.988 3460.dat +0 STEP +1 7 -20 -8 0 0 0 -1 0 1 0 1 0 0 10030 - subModel-125.ldr +0 !LDCAD GROUP_NXT [ids=1] [nrs=34] +1 7 -280 -18.809 84.314 0 0 -1 0.156 0.988 0 0.988 -0.156 0 3068b.dat +0 !LDCAD GROUP_NXT [ids=0] [nrs=26] +1 7 -280 -18.809 -84.314 0 0 -1 -0.156 0.988 0 0.988 0.156 0 3068b.dat + + +0 FILE 10030 - subModel-117.ldr +0 subModel-117 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-117.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3023.dat +1 4 0 -24 0 1 0 0 0 1 0 0 0 1 2458.dat + + +0 FILE 10030 - subModel-118.ldr +0 subModel-118 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-118.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 1 0 0 0 1 0 0 0 1 3021.dat +1 8 -20 -24 0 0 0 -1 0 1 0 1 0 0 2877.dat +1 7 10 -24 0 1 0 0 0 1 0 0 0 1 6232.dat + + +0 FILE 10030 - subModel-119.ldr +0 subModel-119 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-119.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 -10 0 0 0 0 1 0 1 0 -1 0 0 32531.dat +1 0 -30 10 -60 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 10 10 -60 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 -30 10 60 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 10 10 60 0 0 1 0 1 0 -1 0 0 2780.dat +0 STEP +1 7 -10 0 120 0 0 1 0 1 0 -1 0 0 32531.dat +1 0 -30 10 180 0 0 1 0 1 0 -1 0 0 2780.dat +1 0 10 10 180 0 0 1 0 1 0 -1 0 0 2780.dat + + +0 FILE 10030 - subModel-120.ldr +0 subModel-120 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-120.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3460.dat +1 7 0 -8 60 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 7 0 -8 0 0 0 1 0 1 0 -1 0 0 3743.dat +1 7 0 -8 -50 -1 0 0 0 1 0 0 0 -1 2555.dat +1 7 0 -24 -70 1 0 0 0 1 0 0 0 1 4599a.dat + + +0 FILE 10030 - subModel-121.ldr +0 subModel-121 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-121.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +1 7 0 -24 -80 0 0 -1 0 1 0 1 0 0 4865a.dat +0 STEP +1 7 0 -8 -50 0 0 -1 0 1 0 1 0 0 2555.dat +1 7 0 -24 -20 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 0 -8 40 0 0 -1 0 1 0 1 0 0 3743.dat +1 7 0 -24 90 1 0 0 0 1 0 0 0 1 4599a.dat + + +0 FILE 10030 - subModel-122.ldr +0 subModel-122 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-122.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 4477.dat +1 7 0 -24 -80 0 0 1 0 1 0 -1 0 0 4865a.dat +0 STEP +1 7 0 -8 -50 0 0 1 0 1 0 -1 0 0 2555.dat +1 7 0 -24 -20 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 0 -8 40 0 0 1 0 1 0 -1 0 0 3743.dat +1 7 0 -24 90 1 0 0 0 1 0 0 0 1 4599a.dat + + +0 FILE 10030 - subModel-123.ldr +0 subModel-123 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-123.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 0 -24 50 0 0 1 0 1 0 -1 0 0 4589.dat +0 STEP +1 7 0 -24 20 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 0 -24 -20 0 0 -1 0 1 0 1 0 0 4865a.dat +1 7 0 -24 -50 1 0 0 0 1 0 0 0 1 4599a.dat + + +0 FILE 10030 - subModel-124.ldr +0 subModel-124 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-124.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 7 0 -24 50 0 0 1 0 1 0 -1 0 0 4589.dat +0 STEP +1 7 0 -24 20 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 0 -24 -20 0 0 1 0 1 0 -1 0 0 4865a.dat +1 7 0 -24 -50 1 0 0 0 1 0 0 0 1 4599a.dat + + +0 FILE 10030 - subModel-125.ldr +0 subModel-125 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-125.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3029.dat +1 7 0 -8 80 0 0 1 0 1 0 -1 0 0 3031.dat +0 STEP +1 7 -30 -8 0 0 0 1 0 1 0 -1 0 0 2431.dat +1 7 -30 -8 -80 0 0 1 0 1 0 -1 0 0 2431.dat +1 7 30 -8 0 0 0 1 0 1 0 -1 0 0 2431.dat +1 7 30 -8 -80 0 0 1 0 1 0 -1 0 0 2431.dat +1 7 0 -32 100 0 0 -1 0 1 0 1 0 0 6232.dat +0 STEP +1 8 30 -32 100 0 0 1 0 1 0 -1 0 0 2877.dat +1 8 -30 -32 100 0 0 -1 0 1 0 1 0 0 2877.dat +1 7 0 -32 60 1 0 0 0 1 0 0 0 1 3001.dat +1 7 -10 -8 0 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -10 -8 -60 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 10 -8 -80 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 10 -8 10 1 0 0 0 1 0 0 0 1 2555.dat +0 STEP +1 7 0 -56 80 0 0 1 0 1 0 -1 0 0 32324.dat +1 1 -20 -46 40 0 0 1 0 1 0 -1 0 0 4274.dat +1 1 20 -46 40 0 0 1 0 1 0 -1 0 0 4274.dat +0 STEP +1 7 0 -46 32 0 0 1 0 1 0 -1 0 0 10030 - subModel-126.ldr + + +0 FILE 10030 - subModel-126.ldr +0 subModel-126 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-126.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 8 0 0 0 0 -1 0 0 0 1 -1 0 0 3710.dat +1 7 8 0 0 0 -1 0 0 0 1 -1 0 0 3743.dat + + +0 FILE 10030 - subModel-127.ldr +0 subModel-127 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-127.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 0 0 1 0 1 0 -1 0 0 3666.dat +1 15 0 -24 -50 1 0 0 0 1 0 0 0 1 10030 - subModel-128.ldr +0 STEP +1 7 0 -32 -20 0 0 1 0 1 0 -1 0 0 3710.dat +1 15 0 -32 40 0 0 1 0 1 0 -1 0 0 3794a.dat +1 7 0 -40 40 0 0 1 0 1 0 -1 0 0 6141.dat +0 STEP +1 15 0 -40 -20 0 0 1 0 1 0 -1 0 0 3710.dat +1 15 0 -16 -84 0 0 1 1 0 0 0 1 0 3004.dat +0 STEP +1 7 0 -48 0 0 0 -1 0 1 0 1 0 0 2412b.dat +1 7 0 -16 -92 0 0 -1 -1 0 0 0 1 0 3794a.dat +0 STEP +1 15 0 -16 -140 1 0 0 0 0 -1 0 1 0 10030 - subModel-129.ldr +0 STEP +1 15 18 -12 -30 0 -1 0 -1 0 0 0 0 -1 10030 - subModel-130.ldr +1 15 -18 -12 -30 0 1 0 1 0 0 0 0 -1 10030 - subModel-130.ldr +0 STEP +1 7 18 -14 40 0 -1 0 0 0 -1 1 0 0 10030 - subModel-131.ldr +1 7 -18 -14 40 0 1 0 0 0 1 1 0 0 10030 - subModel-131.ldr +0 STEP +1 15 0 -34 92 0 0 1 1 0 0 0 1 0 10030 - subModel-132.ldr +1 7 0 -48 -50 1 0 0 0 1 0 0 0 1 4592.dat +1 0 0 -48 -50 1 0 0 0 0.423 0.906 0 -0.906 0.423 4593.dat +0 STEP +1 7 0 168 30 1 0 0 0 1 0 0 0 1 10030 - subModel-133.ldr + + +0 FILE 10030 - subModel-128.ldr +0 subModel-128 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-128.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 15 0 0 0 1 0 0 0 1 0 0 0 1 4733.dat +1 15 0 0 20 1 0 0 0 1 0 0 0 1 6541.dat +1 15 0 0 40 1 0 0 0 1 0 0 0 1 4733.dat +1 15 0 0 60 1 0 0 0 1 0 0 0 1 6541.dat +1 15 0 0 80 1 0 0 0 1 0 0 0 1 4733.dat +1 15 0 0 100 1 0 0 0 1 0 0 0 1 6541.dat + + +0 FILE 10030 - subModel-129.ldr +0 subModel-129 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-129.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 7 0 0 0 1 0 0 0 1 0 0 0 1 4733.dat +1 15 34 10 0 0 -1 0 1 0 0 0 0 1 4589.dat +1 15 -34 10 0 0 1 0 -1 0 0 0 0 1 4589.dat +0 STEP +1 15 0 10 -18 0 0 1 1 0 0 0 1 0 3070b.dat +1 15 0 10 18 0 0 -1 1 0 0 0 -1 0 3070b.dat +1 15 0 -8 0 0 0 -1 0 1 0 1 0 0 3070b.dat +0 STEP +1 15 0 24 0 0 0 -1 0 1 0 1 0 0 3062b.dat + + +0 FILE 10030 - subModel-130.ldr +0 subModel-130 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-130.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 19 0 0 0 0 0 1 0 1 0 -1 0 0 3020.dat +1 15 0 -24 0 0 0 1 0 1 0 -1 0 0 3043.dat +0 STEP +1 15 0 -24 -30 1 0 0 0 1 0 0 0 1 3048b.dat +1 15 0 -24 30 -1 0 0 0 1 0 0 0 -1 3048b.dat + +0 FILE 10030 - subModel-131.ldr +0 subModel-131 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-131.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 320 0 0 0 1 0 0 0 1 0 0 0 1 3023.dat +1 15 10 -8 0 1 0 0 0 1 0 0 0 1 6141.dat +0 STEP +1 7 10 -16 0 1 0 0 0 1 0 0 0 1 6141.dat + + +0 FILE 10030 - subModel-132.ldr +0 subModel-132 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-132.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 15 0 0 0 0 0 1 0 1 0 -1 0 0 3701.dat +1 0 20 10 20 1 0 0 0 1 0 0 0 1 6558.dat +1 0 20 10 0 1 0 0 0 1 0 0 0 1 6558.dat +1 0 20 10 -20 1 0 0 0 1 0 0 0 1 6558.dat +1 7 0 -8 0 0 0 1 0 1 0 -1 0 0 3710.dat +0 STEP +1 15 20 0 -20 0 0 1 0 1 0 -1 0 0 6541.dat +1 15 20 0 0 0 0 1 0 1 0 -1 0 0 6541.dat +1 15 20 0 20 0 0 1 0 1 0 -1 0 0 6541.dat +0 STEP +1 15 0 -32 -20 0 0 1 0 1 0 -1 0 0 3048b.dat +1 15 0 -32 20 0 0 1 0 1 0 -1 0 0 3048b.dat +0 STEP +1 7 20 -24 0 0 0 1 0 1 0 -1 0 0 3622.dat +1 320 20 -32 0 0 0 1 0 1 0 -1 0 0 3623.dat +0 STEP +1 15 40 0 0 0 0 1 0 1 0 -1 0 0 3701.dat +0 STEP +1 7 40 -8 0 0 0 1 0 1 0 -1 0 0 3710.dat +0 STEP +1 15 40 -32 20 0 0 -1 0 1 0 1 0 0 3048b.dat +1 15 40 -32 -20 0 0 -1 0 1 0 1 0 0 3048b.dat +0 STEP +1 15 40 24 30 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 40 48 30 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 40 24 10 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 40 48 10 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 40 24 -10 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 40 48 -10 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 40 24 -30 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 40 48 -30 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 20 24 20 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 20 48 20 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 20 24 0 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 20 48 0 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 20 24 -20 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 20 48 -20 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 0 24 30 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 0 48 30 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 0 24 10 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 0 48 10 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 0 24 -10 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 0 48 -10 0 0 -1 0 1 0 1 0 0 6141.dat +1 15 0 24 -30 0 0 -1 0 1 0 1 0 0 3062b.dat +1 38 0 48 -30 0 0 -1 0 1 0 1 0 0 6141.dat + +0 FILE 10030 - subModel-133.ldr +0 subModel-133 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-133.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 47 0 0 0 1 0 0 0 1 0 0 0 1 30065.dat +1 47 0 -20 -10 -1 0 0 0 0 1 0 1 0 30359b.dat +0 STEP +1 7 0 -160 20 1 0 0 0 1 0 0 0 1 4070.dat +1 7 0 -160 -24 1 0 0 0 1 0 0 0 1 4070.dat + + +0 FILE 10030 - subModel-134.ldr +0 subModel-134 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-134.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 0 0 0 0 -1 0 1 0 1 0 0 6179.dat +1 0 80 0 0 0 0 1 0 1 0 -1 0 0 6179.dat +0 STEP +1 0 40 -8 -30 -1 0 0 0 1 0 0 0 -1 3460.dat +0 STEP +1 0 0 0 80 0 0 -1 0 1 0 1 0 0 6179.dat +1 0 80 0 80 0 0 1 0 1 0 -1 0 0 6179.dat +0 STEP +1 7 110 -8 80 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 -30 -8 80 0 0 1 0 1 0 -1 0 0 2412b.dat +1 0 -30 -8 20 0 0 1 0 1 0 -1 0 0 2431.dat +1 0 110 -8 20 0 0 1 0 1 0 -1 0 0 2431.dat +0 STEP +1 0 0 0 160 0 0 -1 0 1 0 1 0 0 6179.dat +1 0 0 0 240 0 0 -1 0 1 0 1 0 0 6179.dat +1 0 80 0 160 0 0 1 0 1 0 -1 0 0 6179.dat +1 0 80 0 240 0 0 1 0 1 0 -1 0 0 6179.dat +0 STEP +1 0 -30 -8 160 0 0 1 0 1 0 -1 0 0 6636.dat +1 0 110 -8 160 0 0 1 0 1 0 -1 0 0 6636.dat +1 7 -30 -8 240 0 0 1 0 1 0 -1 0 0 2412b.dat +1 7 110 -8 240 0 0 1 0 1 0 -1 0 0 2412b.dat +0 STEP +1 0 0 0 320 0 0 -1 0 1 0 1 0 0 6179.dat +1 0 80 0 320 0 0 1 0 1 0 -1 0 0 6179.dat +0 STEP +1 0 -30 -8 300 0 0 1 0 1 0 -1 0 0 2431.dat +1 0 110 -8 300 0 0 1 0 1 0 -1 0 0 2431.dat +1 0 40 -8 350 -1 0 0 0 1 0 0 0 -1 3460.dat +0 STEP +1 0 40 8 240 0 0 1 0 1 0 -1 0 0 3035.dat +1 0 40 8 80 0 0 1 0 1 0 -1 0 0 3035.dat +0 STEP +1 0 84.261 50.605 160 -0.574 0.819 0 0.819 0.574 0 0 0 -1 10030 - subModel-135.ldr +0 STEP + + +0 FILE 10030 - subModel-135.ldr +0 subModel-135 +0 Author: Roland Dahl [rolandd] +0 Name: 10030 - subModel-135.ldr +0 !LDRAW_ORG Model +0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt +0 !THEME Star Wars / Ultimate Collector Series / Star Wars Episode 4/5/6 +1 0 0 0 0 0 0 1 0 1 0 -1 0 0 3035.dat +1 7 -30 -24 -40 0 0 1 0 1 0 -1 0 0 3937.dat +1 7 -30 -24 40 0 0 1 0 1 0 -1 0 0 3937.dat +0 STEP +1 0 -38.192 -19.736 -40 0 0.819 -0.574 0 0.574 0.819 1 0 0 6134.dat +1 0 -38.192 -19.736 40 0 0.819 -0.574 0 0.574 0.819 1 0 0 6134.dat +0 STEP +1 0 -10 -24 -40 0 0 -1 0 1 0 1 0 0 3297.dat +1 0 -10 -24 40 0 0 -1 0 1 0 1 0 0 3297.dat + diff --git a/crates/polymodel-ldraw-testkit/corpus/steps-transforms.ldr b/crates/polymodel-ldraw-testkit/corpus/steps-transforms.ldr index f762c5d..54187db 100644 --- a/crates/polymodel-ldraw-testkit/corpus/steps-transforms.ldr +++ b/crates/polymodel-ldraw-testkit/corpus/steps-transforms.ldr @@ -1,3 +1,8 @@ 0 STEP 1 16 0 0 0 1 0 0 0 1 0 0 0 1 part.dat +0 !TEXMAP START PLANAR 0 0 0 1 0 0 0 1 0 texture.png +0 !TEXMAP NEXT +3 16 0 0 0 1 0 0 0 0 1 0 +0 !TEXMAP FALLBACK fallback.dat +0 !TEXMAP STOP 0 ROTSTEP END diff --git a/crates/polymodel-ldraw-testkit/src/gates.rs b/crates/polymodel-ldraw-testkit/src/gates.rs new file mode 100644 index 0000000..c200f92 --- /dev/null +++ b/crates/polymodel-ldraw-testkit/src/gates.rs @@ -0,0 +1,545 @@ +use crate::{ + CanonicalRecord, ExpectedRecord, FixtureCase, Profile, SCHEMA_VERSION, normalize_certification, + normalized_codes, +}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeSet; +use thiserror::Error; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum GateScope { + Authored, + OracleProjection, + Both, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct GateDefinition { + pub id: &'static str, + pub profiles: &'static [Profile], + pub tags: &'static [&'static str], + pub required_fields: &'static [&'static str], + pub scope: GateScope, +} + +pub const GATE_DEFINITIONS: &[GateDefinition] = &[ + GateDefinition { + id: "syntax_types_0_to_5", + profiles: &[Profile::Strict, Profile::Compatibility, Profile::Lossless], + tags: &["syntax_types_0_to_5"], + required_fields: &["canonical.syntax"], + scope: GateScope::Both, + }, + GateDefinition { + id: "profile_acceptance_and_diagnostics", + profiles: &[Profile::Strict, Profile::Compatibility, Profile::Lossless], + tags: &["profile_acceptance_and_diagnostics"], + required_fields: &["canonical.diagnostics"], + scope: GateScope::Both, + }, + GateDefinition { + id: "mpd_and_data_boundaries", + profiles: &[Profile::Strict], + tags: &["mpd_and_data_boundaries"], + required_fields: &[ + "canonical.semantic.canonical_path", + "canonical.semantic.target_identity", + ], + scope: GateScope::Both, + }, + GateDefinition { + id: "path_and_resolution_independence", + profiles: &[Profile::Strict, Profile::Compatibility], + tags: &["path_and_resolution_independence"], + required_fields: &[ + "canonical.semantic.canonical_path", + "canonical.semantic.root_identity", + "canonical.semantic.target_identity", + "canonical.semantic.cache_identity", + ], + scope: GateScope::Authored, + }, + GateDefinition { + id: "bfc_state_and_invertnext", + profiles: &[Profile::Strict], + tags: &["bfc_state_and_invertnext"], + required_fields: &["canonical.semantic.bfc_state"], + scope: GateScope::Both, + }, + GateDefinition { + id: "colours_and_ldconfig", + profiles: &[Profile::Strict], + tags: &["colours_and_ldconfig"], + required_fields: &["canonical.semantic.colour_state"], + scope: GateScope::Both, + }, + GateDefinition { + id: "graph_identity_and_instances", + profiles: &[Profile::Strict, Profile::Compatibility], + tags: &["graph_identity_and_instances"], + required_fields: &["canonical.scene.model_id", "canonical.scene.instance_ids"], + scope: GateScope::Authored, + }, + GateDefinition { + id: "steps_and_transforms", + profiles: &[Profile::Strict], + tags: &["steps_and_transforms"], + required_fields: &[ + "canonical.semantic.steps", + "canonical.scene.bounds", + "canonical.scene.reflection", + ], + scope: GateScope::Authored, + }, + GateDefinition { + id: "numeric_finiteness_and_raw_preservation", + profiles: &[Profile::Lossless], + tags: &["numeric_finiteness_and_raw_preservation"], + required_fields: &["canonical.syntax", "canonical.diagnostics"], + scope: GateScope::Both, + }, + GateDefinition { + id: "semantic_limits_and_cancellation", + profiles: &[Profile::Compatibility, Profile::Lossless], + tags: &["semantic_limits_and_cancellation"], + required_fields: &["canonical.semantic.limits", "canonical.diagnostics"], + scope: GateScope::Authored, + }, + GateDefinition { + id: "conditional_line_projection", + profiles: &[Profile::Strict], + tags: &["conditional_line_projection"], + required_fields: &["canonical.scene"], + scope: GateScope::Authored, + }, + GateDefinition { + id: "texmap_projection_v1", + profiles: &[Profile::Strict], + tags: &["texmap_projection_v1"], + required_fields: &["canonical.semantic.texmap_events"], + scope: GateScope::Authored, + }, + GateDefinition { + id: "points_and_explicit_edges", + profiles: &[Profile::Strict], + tags: &["points_and_explicit_edges"], + required_fields: &["canonical.scene"], + scope: GateScope::Authored, + }, +]; + +pub const GATE_NAMES: &[&str] = &[ + "syntax_types_0_to_5", + "profile_acceptance_and_diagnostics", + "mpd_and_data_boundaries", + "path_and_resolution_independence", + "bfc_state_and_invertnext", + "colours_and_ldconfig", + "graph_identity_and_instances", + "steps_and_transforms", + "numeric_finiteness_and_raw_preservation", + "semantic_limits_and_cancellation", + "conditional_line_projection", + "texmap_projection_v1", + "points_and_explicit_edges", +]; + +#[derive(Debug, Error, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum GateFailure { + #[error("gate {gate} does not apply to fixture {fixture} under {profile:?}")] + NotApplicable { + gate: String, + fixture: String, + profile: Profile, + }, + #[error("gate {gate} found a schema mismatch for {fixture}")] + SchemaMismatch { gate: String, fixture: String }, + #[error("gate {gate} found a field mismatch for {fixture}: {field}")] + FieldMismatch { + gate: String, + fixture: String, + field: String, + }, + #[error("gate {gate} found an invalid oracle certification for {fixture}")] + InvalidCertification { gate: String, fixture: String }, +} + +pub trait CorpusGate { + fn definition(&self) -> &'static GateDefinition; + fn evaluate( + &self, + fixture: &FixtureCase, + expected: &ExpectedRecord, + actual: &CanonicalRecord, + ) -> Result<(), GateFailure>; +} + +#[derive(Debug, Clone, Copy)] +pub struct NamedGate { + pub definition: &'static GateDefinition, +} + +impl CorpusGate for NamedGate { + fn definition(&self) -> &'static GateDefinition { + self.definition + } + + fn evaluate( + &self, + fixture: &FixtureCase, + expected: &ExpectedRecord, + actual: &CanonicalRecord, + ) -> Result<(), GateFailure> { + let definition = self.definition; + let fail = |field: &str| { + Err(GateFailure::FieldMismatch { + gate: definition.id.into(), + fixture: fixture.id.into(), + field: field.into(), + }) + }; + if !definition.profiles.contains(&expected.profile) + || !fixture.applies_to(expected.profile) + || !definition.tags.iter().any(|tag| fixture.tags.contains(tag)) + { + return Err(GateFailure::NotApplicable { + gate: definition.id.into(), + fixture: fixture.id.into(), + profile: expected.profile, + }); + } + if actual.schema_version != SCHEMA_VERSION + || expected.canonical.schema_version != SCHEMA_VERSION + { + return Err(GateFailure::SchemaMismatch { + gate: definition.id.into(), + fixture: fixture.id.into(), + }); + } + let expected_canonical = &expected.canonical; + match definition.id { + "syntax_types_0_to_5" | "numeric_finiteness_and_raw_preservation" => { + if actual.syntax != expected_canonical.syntax { + fail("canonical.syntax") + } else if definition.id == "numeric_finiteness_and_raw_preservation" + && actual.diagnostics != expected_canonical.diagnostics + { + fail("canonical.diagnostics") + } else { + Ok(()) + } + } + "profile_acceptance_and_diagnostics" => { + if actual.diagnostics == expected_canonical.diagnostics { + Ok(()) + } else { + fail("canonical.diagnostics") + } + } + "mpd_and_data_boundaries" => { + if actual.semantic.canonical_path == expected_canonical.semantic.canonical_path + && actual.semantic.target_identity + == expected_canonical.semantic.target_identity + { + Ok(()) + } else { + fail("canonical.semantic MPD boundaries") + } + } + "path_and_resolution_independence" => { + if actual.semantic.canonical_path == expected_canonical.semantic.canonical_path + && actual.semantic.root_identity == expected_canonical.semantic.root_identity + && actual.semantic.target_identity + == expected_canonical.semantic.target_identity + && actual.semantic.cache_identity == expected_canonical.semantic.cache_identity + { + Ok(()) + } else { + fail("canonical.semantic path identities") + } + } + "bfc_state_and_invertnext" => { + if actual.semantic.bfc_state == expected_canonical.semantic.bfc_state { + Ok(()) + } else { + fail("canonical.semantic.bfc_state") + } + } + "colours_and_ldconfig" => { + if actual.semantic.colour_state == expected_canonical.semantic.colour_state { + Ok(()) + } else { + fail("canonical.semantic.colour_state") + } + } + "graph_identity_and_instances" => { + if actual.scene.model_id == expected_canonical.scene.model_id + && actual.scene.instance_ids == expected_canonical.scene.instance_ids + { + Ok(()) + } else { + fail("canonical.scene graph identity") + } + } + "steps_and_transforms" => { + if actual.semantic.steps == expected_canonical.semantic.steps + && actual.scene.bounds == expected_canonical.scene.bounds + && actual.scene.reflection == expected_canonical.scene.reflection + { + Ok(()) + } else { + fail("canonical steps/transforms") + } + } + "semantic_limits_and_cancellation" => { + if actual.semantic.limits == expected_canonical.semantic.limits + && actual.diagnostics == expected_canonical.diagnostics + { + Ok(()) + } else { + fail("canonical semantic limits") + } + } + "conditional_line_projection" | "points_and_explicit_edges" => { + if actual.scene.triangles == expected_canonical.scene.triangles + && actual.scene.lines == expected_canonical.scene.lines + && (actual.scene.triangles > 0 || actual.scene.lines > 0) + { + Ok(()) + } else { + fail("canonical.scene triangle/line counts") + } + } + "texmap_projection_v1" => { + if actual.semantic.texmap_events == expected_canonical.semantic.texmap_events { + Ok(()) + } else { + fail("canonical.semantic.texmap_events") + } + } + _ => fail("unknown gate"), + } + } +} + +pub fn named_gates() -> Vec { + GATE_DEFINITIONS + .iter() + .map(|definition| NamedGate { definition }) + .collect() +} + +#[derive(Debug, Error, Clone, PartialEq, Eq)] +pub enum GateSetError { + #[error("duplicate gate name: {0}")] + DuplicateName(String), + #[error("missing required gate: {0}")] + MissingRequiredGate(String), + #[error("fixture {0} has no applicable gate")] + NoApplicableGate(String), +} + +pub struct CorpusGateSet { + gates: Vec, +} + +impl CorpusGateSet { + pub fn new(gates: Vec) -> Result { + let mut names = BTreeSet::new(); + for gate in &gates { + if !names.insert(gate.definition.id) { + return Err(GateSetError::DuplicateName(gate.definition.id.into())); + } + } + for required in GATE_NAMES { + if !names.contains(required) { + return Err(GateSetError::MissingRequiredGate((*required).into())); + } + } + Ok(Self { gates }) + } + + pub fn gates(&self) -> &[NamedGate] { + &self.gates + } + + pub fn validate_inventory(&self, fixtures: &[FixtureCase]) -> Result<(), GateSetError> { + for fixture in fixtures { + if !self.gates.iter().any(|gate| { + gate.definition + .tags + .iter() + .any(|tag| fixture.tags.contains(tag)) + }) { + return Err(GateSetError::NoApplicableGate(fixture.id.into())); + } + } + Ok(()) + } + + pub fn evaluate( + &self, + fixture: &FixtureCase, + actual: &CanonicalRecord, + ) -> Vec> { + self.gates + .iter() + .filter(|gate| { + gate.definition + .tags + .iter() + .any(|tag| fixture.tags.contains(tag)) + && fixture.applies_to(fixture.expected.profile) + }) + .map(|gate| gate.evaluate(fixture, &fixture.expected, actual)) + .collect() + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct CoverageReport { + pub schema_version: String, + pub fixture_count: usize, + pub byte_count: usize, + pub gates: Vec, + pub profiles: Vec, + pub tags: Vec, +} + +pub fn coverage_report(fixtures: &[FixtureCase]) -> CoverageReport { + let mut tags = BTreeSet::new(); + for fixture in fixtures { + tags.extend(fixture.tags.iter().map(|tag| (*tag).to_string())); + } + CoverageReport { + schema_version: SCHEMA_VERSION.into(), + fixture_count: fixtures.len(), + byte_count: fixtures.iter().map(|fixture| fixture.bytes.len()).sum(), + gates: GATE_NAMES.iter().map(|name| (*name).into()).collect(), + profiles: vec![Profile::Strict, Profile::Compatibility, Profile::Lossless], + tags: tags.into_iter().collect(), + } +} + +pub fn compare_oracle_projection( + expected: &CanonicalRecord, + actual: &CanonicalRecord, + fixture: &str, +) -> Result<(), GateFailure> { + let gate = GateFailure::FieldMismatch { + gate: "oracle_projection".into(), + fixture: fixture.into(), + field: "canonical.oracle_projection".into(), + }; + let Some(expected_projection) = expected.oracle_projection.as_ref() else { + return Err(gate); + }; + let Some(actual_projection) = actual.oracle_projection.as_ref() else { + return Err(gate); + }; + if expected_projection.status != actual_projection.status + || expected_projection.error != actual_projection.error + || expected_projection.diagnostics != actual_projection.diagnostics + { + return Err(GateFailure::FieldMismatch { + gate: "oracle_projection".into(), + fixture: fixture.into(), + field: "status/error/diagnostics".into(), + }); + } + if expected_projection.models.len() != actual_projection.models.len() { + return Err(GateFailure::FieldMismatch { + gate: "oracle_projection".into(), + fixture: fixture.into(), + field: "models".into(), + }); + } + for (expected_model, actual_model) in expected_projection + .models + .iter() + .zip(&actual_projection.models) + { + let expected_cert = normalize_certification(&expected_model.certify).ok_or_else(|| { + GateFailure::InvalidCertification { + gate: "oracle_projection".into(), + fixture: fixture.into(), + } + })?; + let actual_cert = normalize_certification(&actual_model.certify).ok_or_else(|| { + GateFailure::InvalidCertification { + gate: "oracle_projection".into(), + fixture: fixture.into(), + } + })?; + if expected_model.name != actual_model.name + || expected_model.model_index != actual_model.model_index + || expected_cert != actual_cert + || expected_model.step_count != actual_model.step_count + || normalized_codes(&expected_model.local_colors) + != normalized_codes(&actual_model.local_colors) + { + return Err(GateFailure::FieldMismatch { + gate: "oracle_projection".into(), + fixture: fixture.into(), + field: format!("models[{}]", expected_model.model_index), + }); + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::inventory; + + #[test] + fn gate_definitions_are_unique_and_complete() { + let gates = CorpusGateSet::new(named_gates()).unwrap(); + assert_eq!(gates.gates().len(), GATE_NAMES.len()); + } + + #[test] + fn bfc_gate_rejects_only_its_owned_field() { + let fixture = inventory() + .into_iter() + .find(|fixture| fixture.id == "bfc-invertnext") + .unwrap(); + let mut actual = fixture.expected.canonical.clone(); + actual.scene.triangles += 1; + let gate = NamedGate { + definition: GATE_DEFINITIONS + .iter() + .find(|definition| definition.id == "bfc_state_and_invertnext") + .unwrap(), + }; + assert!(gate.evaluate(&fixture, &fixture.expected, &actual).is_ok()); + actual.semantic.bfc_state = "wrong".into(); + assert!(gate.evaluate(&fixture, &fixture.expected, &actual).is_err()); + } + + #[test] + fn live_testkit_sources_do_not_contain_heuristic_generators() { + let source_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src"); + let files = ["schema.rs", "inventory.rs", "gates.rs", "lib.rs"]; + let canonical = ["canonical", "("].concat(); + let parse_syntax = ["parse_syntax", "("].concat(); + for file in files { + let source = std::fs::read_to_string(source_root.join(file)).unwrap(); + let has_canonical_call = source.match_indices(&canonical).any(|(index, _)| { + index == 0 + || (!source.as_bytes()[index - 1].is_ascii_alphanumeric() + && source.as_bytes()[index - 1] != b'_') + }); + assert!( + !has_canonical_call, + "heuristic generator call found in {file}" + ); + assert!( + !source.contains(&parse_syntax), + "heuristic generator call found in {file}" + ); + } + } +} diff --git a/crates/polymodel-ldraw-testkit/src/inventory.rs b/crates/polymodel-ldraw-testkit/src/inventory.rs new file mode 100644 index 0000000..1c4c3f2 --- /dev/null +++ b/crates/polymodel-ldraw-testkit/src/inventory.rs @@ -0,0 +1,450 @@ +use crate::{ + AuthorityClass, ExpectedOutcome, ExpectedRecord, FixtureCase, Profile, Provenance, + SCHEMA_VERSION, hex_digest, parse_expected, +}; +use serde::Deserialize; +use std::collections::BTreeSet; + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ArtifactManifest { + schema_version: String, + artifacts: Vec, + ldparse_acquisition: Acquisition, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct Acquisition { + status: String, + source_url: String, + master_revision: String, + modernization_revision: String, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ArtifactEntry { + id: String, + path: String, + source_url: String, + source_revision: String, + sha256: String, + license: String, + original_test: String, + modifications: String, + authority: AuthorityClass, +} + +const ARTIFACT_PROVENANCE: &str = include_str!("../corpus/artifact-provenance.json"); + +fn fixture_provenance(id: &str, file: &str, bytes: &[u8]) -> Provenance { + let manifest: ArtifactManifest = serde_json::from_str(ARTIFACT_PROVENANCE) + .expect("artifact-provenance.json must be valid JSON"); + assert_eq!(manifest.schema_version, SCHEMA_VERSION); + assert_eq!( + manifest.ldparse_acquisition.status, + "nix-built differential oracle" + ); + assert_eq!( + manifest.ldparse_acquisition.source_url, + "https://github.com/elfprince13/LDParse" + ); + assert_eq!( + manifest.ldparse_acquisition.master_revision, + "877667417d6cab57c04aed9cb3d5bfe7efa0589c" + ); + assert_eq!( + manifest.ldparse_acquisition.modernization_revision, + "0fe78dcee22982f26cceced1b483340faa4d04e9" + ); + let path = format!("corpus/{file}"); + let entry = manifest + .artifacts + .into_iter() + .find(|entry| entry.id == id) + .unwrap_or_else(|| panic!("missing provenance entry for {id}")); + assert_eq!(entry.path, path, "provenance path mismatch for {id}"); + assert_eq!( + entry.sha256, + hex_digest(bytes), + "provenance digest mismatch for {id}" + ); + Provenance { + id: format!("pm77-{id}"), + source_url: entry.source_url, + source_revision: entry.source_revision, + sha256: entry.sha256, + license: entry.license, + original_test: entry.original_test, + modifications: entry.modifications, + authority: entry.authority, + } +} + +fn load_expected(id: &str) -> ExpectedRecord { + let json = match id { + "syntax-types" => include_str!("../corpus/expected/syntax-types.expected.json"), + "profile-matrix" => include_str!("../corpus/expected/profile-matrix.expected.json"), + "mpd-data" => include_str!("../corpus/expected/mpd-data.expected.json"), + "path-policy" => include_str!("../corpus/expected/path-policy.expected.json"), + "bfc-invertnext" => include_str!("../corpus/expected/bfc-invertnext.expected.json"), + "colours-ldconfig" => include_str!("../corpus/expected/colours-ldconfig.expected.json"), + "graph-instances" => include_str!("../corpus/expected/graph-instances.expected.json"), + "steps-transforms" => include_str!("../corpus/expected/steps-transforms.expected.json"), + "numeric-finiteness" => include_str!("../corpus/expected/numeric-finiteness.expected.json"), + "semantic-limits" => include_str!("../corpus/expected/semantic-limits.expected.json"), + "path-contexts" => include_str!("../corpus/expected/path-contexts.expected.json"), + "conditional-lines" => include_str!("../corpus/expected/conditional-lines.expected.json"), + "adversarial-regressions" => { + include_str!("../corpus/expected/adversarial-regressions.expected.json") + } + "fuzz-regressions" => include_str!("../corpus/expected/fuzz-regressions.expected.json"), + "external-thomas" => include_str!("../corpus/expected/external-thomas.expected.json"), + "external-weldr" => include_str!("../corpus/expected/external-weldr.expected.json"), + "external-ldr-tools" => include_str!("../corpus/expected/external-ldr-tools.expected.json"), + "omr-10030-1" => include_str!("../corpus/expected/omr-10030-1.expected.json"), + "h-conditional-visible" => { + include_str!("../corpus/expected/h-conditional-visible.expected.json") + } + "h-conditional-interior" => { + include_str!("../corpus/expected/h-conditional-interior.expected.json") + } + "h-conditional-offscreen" => { + include_str!("../corpus/expected/h-conditional-offscreen.expected.json") + } + "h-conditional-ambiguous" => { + include_str!("../corpus/expected/h-conditional-ambiguous.expected.json") + } + "h-conditional-degenerate" => { + include_str!("../corpus/expected/h-conditional-degenerate.expected.json") + } + "h-conditional-invalid" => { + include_str!("../corpus/expected/h-conditional-invalid.expected.json") + } + other => panic!("unknown fixture {other}"), + }; + let expected = parse_expected(json) + .unwrap_or_else(|error| panic!("invalid expected record for {id}: {error}")); + assert_eq!(expected.canonical.provenance_id, format!("pm77-{id}")); + assert!( + !expected.derivations.is_empty(), + "expected record {id} has no derivations" + ); + expected +} + +macro_rules! fixture { + ($id:literal, $tag:literal, $file:literal, $authority:expr, $outcome:expr, $profile:expr) => {{ + let bytes = include_bytes!(concat!("../corpus/", $file)); + let provenance = fixture_provenance($id, $file, bytes); + let expected = load_expected($id); + assert_eq!( + provenance.authority, $authority, + "provenance authority mismatch for {}", + $id + ); + assert_eq!( + expected.outcome, $outcome, + "expected outcome mismatch for {}", + $id + ); + assert_eq!( + expected.profile, $profile, + "expected profile mismatch for {}", + $id + ); + FixtureCase { + id: $id, + relative_path: concat!("corpus/", $file), + bytes, + tags: &[$tag], + profiles: &[Profile::Strict, Profile::Compatibility, Profile::Lossless], + authority: $authority, + provenance, + expected, + } + }}; +} + +pub fn inventory() -> Vec { + vec![ + fixture!( + "syntax-types", + "syntax_types_0_to_5", + "syntax-types.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "profile-matrix", + "profile_acceptance_and_diagnostics", + "profile-matrix.ldr", + AuthorityClass::PolymodelSafety, + ExpectedOutcome::Preserved, + Profile::Compatibility + ), + fixture!( + "mpd-data", + "mpd_and_data_boundaries", + "mpd-data.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "path-policy", + "path_and_resolution_independence", + "path-policy.ldr", + AuthorityClass::PolymodelSafety, + ExpectedOutcome::Rejected, + Profile::Strict + ), + fixture!( + "bfc-invertnext", + "bfc_state_and_invertnext", + "bfc-invertnext.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "colours-ldconfig", + "colours_and_ldconfig", + "colours-ldconfig.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "graph-instances", + "graph_identity_and_instances", + "graph-instances.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "steps-transforms", + "steps_and_transforms", + "steps-transforms.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "numeric-finiteness", + "numeric_finiteness_and_raw_preservation", + "numeric-finiteness.ldr", + AuthorityClass::RatifiedSpec, + ExpectedOutcome::Rejected, + Profile::Lossless + ), + fixture!( + "semantic-limits", + "semantic_limits_and_cancellation", + "semantic-limits.ldr", + AuthorityClass::PolymodelSafety, + ExpectedOutcome::Limited, + Profile::Compatibility + ), + fixture!( + "path-contexts", + "path_and_resolution_independence", + "path-contexts.ldr", + AuthorityClass::PolymodelSafety, + ExpectedOutcome::Accepted, + Profile::Compatibility + ), + fixture!( + "conditional-lines", + "conditional_line_projection", + "h-conditional-lines.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Preserved, + Profile::Strict + ), + fixture!( + "adversarial-regressions", + "semantic_limits_and_cancellation", + "adversarial-regressions.ldr", + AuthorityClass::PolymodelSafety, + ExpectedOutcome::Cancelled, + Profile::Lossless + ), + fixture!( + "fuzz-regressions", + "semantic_limits_and_cancellation", + "fuzz-regressions.ldr", + AuthorityClass::PolymodelSafety, + ExpectedOutcome::Rejected, + Profile::Lossless + ), + fixture!( + "external-thomas", + "graph_identity_and_instances", + "external-thomas.ldr", + AuthorityClass::Observation, + ExpectedOutcome::Accepted, + Profile::Compatibility + ), + fixture!( + "external-weldr", + "syntax_types_0_to_5", + "external-weldr.ldr", + AuthorityClass::Observation, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "external-ldr-tools", + "syntax_types_0_to_5", + "external-ldr-tools.ldr", + AuthorityClass::Observation, + ExpectedOutcome::Accepted, + Profile::Strict + ), + fixture!( + "omr-10030-1", + "graph_identity_and_instances", + "omr-10030-1.mpd", + AuthorityClass::Observation, + ExpectedOutcome::Accepted, + Profile::Compatibility + ), + fixture!( + "h-conditional-visible", + "conditional_line_projection", + "h-conditional-visible.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Preserved, + Profile::Strict + ), + fixture!( + "h-conditional-interior", + "conditional_line_projection", + "h-conditional-interior.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Preserved, + Profile::Strict + ), + fixture!( + "h-conditional-offscreen", + "conditional_line_projection", + "h-conditional-offscreen.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Preserved, + Profile::Strict + ), + fixture!( + "h-conditional-ambiguous", + "conditional_line_projection", + "h-conditional-ambiguous.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Preserved, + Profile::Strict + ), + fixture!( + "h-conditional-degenerate", + "conditional_line_projection", + "h-conditional-degenerate.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Preserved, + Profile::Strict + ), + fixture!( + "h-conditional-invalid", + "conditional_line_projection", + "h-conditional-invalid.ldr", + AuthorityClass::HOwned, + ExpectedOutcome::Rejected, + Profile::Strict + ), + ] +} + +pub fn validate_inventory(fixtures: &[FixtureCase]) -> Result<(), String> { + const EXPECTED_IDS: &[&str] = &[ + "syntax-types", + "profile-matrix", + "mpd-data", + "path-policy", + "bfc-invertnext", + "colours-ldconfig", + "graph-instances", + "steps-transforms", + "numeric-finiteness", + "semantic-limits", + "path-contexts", + "conditional-lines", + "adversarial-regressions", + "fuzz-regressions", + "external-thomas", + "external-weldr", + "external-ldr-tools", + "omr-10030-1", + "h-conditional-visible", + "h-conditional-interior", + "h-conditional-offscreen", + "h-conditional-ambiguous", + "h-conditional-degenerate", + "h-conditional-invalid", + ]; + if fixtures.len() != EXPECTED_IDS.len() { + return Err(format!( + "expected {} fixtures, got {}", + EXPECTED_IDS.len(), + fixtures.len() + )); + } + let mut ids = BTreeSet::new(); + let mut paths = BTreeSet::new(); + for (index, fixture) in fixtures.iter().enumerate() { + if fixture.id != EXPECTED_IDS[index] { + return Err(format!( + "inventory order mismatch at {index}: {}", + fixture.id + )); + } + if !ids.insert(fixture.id) { + return Err(format!("duplicate fixture id {}", fixture.id)); + } + if !paths.insert(fixture.relative_path) { + return Err(format!("duplicate fixture path {}", fixture.relative_path)); + } + if fixture.provenance.sha256 != fixture.sha256() { + return Err(format!("hash mismatch {}", fixture.id)); + } + if fixture.provenance.source_url.is_empty() + || fixture.provenance.source_revision.is_empty() + || fixture.provenance.license.is_empty() + || fixture.provenance.original_test.is_empty() + || fixture.provenance.modifications.is_empty() + { + return Err(format!("incomplete provenance {}", fixture.id)); + } + if fixture.expected.canonical.provenance_id != fixture.provenance.id { + return Err(format!("provenance link mismatch {}", fixture.id)); + } + for derivation in &fixture.expected.derivations { + if derivation.field.is_empty() + || derivation.source.is_empty() + || derivation.revision.is_empty() + || derivation.locator.is_empty() + || derivation.basis.is_empty() + { + return Err(format!("incomplete derivation {}", fixture.id)); + } + if derivation.authority == AuthorityClass::Observation + && derivation.decision.as_deref().unwrap_or("").is_empty() + { + return Err(format!( + "observation derivation without decision {}", + fixture.id + )); + } + } + } + Ok(()) +} diff --git a/crates/polymodel-ldraw-testkit/src/lib.rs b/crates/polymodel-ldraw-testkit/src/lib.rs index 52213d0..44b0413 100644 --- a/crates/polymodel-ldraw-testkit/src/lib.rs +++ b/crates/polymodel-ldraw-testkit/src/lib.rs @@ -1,1049 +1,10 @@ //! Portable PM-77 LDraw corpus contracts and authored semantic gates. #![forbid(unsafe_code)] -use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256}; -use std::collections::BTreeSet; -use thiserror::Error; +pub mod gates; +pub mod inventory; +pub mod schema; -pub const SCHEMA_VERSION: &str = "ldraw-canonical-v1"; -pub const LDRAW_LIMITS: &[(&str, u64)] = &[ - ("resource_bytes", 100 * 1024 * 1024), - ("line_bytes", 1024 * 1024), - ("files", 16_384), - ("include_depth", 256), - ("commands", 5_000_000), - ("instances", 5_000_000), - ("triangles", 20_000_000), - ("lines", 20_000_000), - ("textures", 1_024), - ("fetches", 8), - ("diagnostics", 10_000), -]; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)] -#[serde(rename_all = "snake_case")] -pub enum Profile { - Strict, - Compatibility, - Lossless, -} -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum AuthorityClass { - RatifiedSpec, - PolymodelSafety, - HOwned, - Observation, -} -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum ExpectedOutcome { - Accepted, - Rejected, - Preserved, - Cancelled, - Limited, -} -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum Severity { - Info, - Warning, - Error, -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Diagnostic { - pub code: String, - pub severity: Severity, - pub message: String, - pub span: Option, -} -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct Span { - pub start: u32, - pub end: u32, - pub line: u32, - pub column: u32, -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct SyntaxRecord { - pub line_type: u8, - pub raw_tail: String, - pub span: Span, - pub line_ending: String, - pub fields: Vec, -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct SemanticRecord { - pub canonical_path: Option, - pub root_identity: Option, - pub target_identity: Option, - pub cache_identity: Option, - pub bfc_state: String, - pub colour_state: String, - pub steps: Vec, - pub limits: Vec, -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct SceneRecord { - pub model_id: String, - pub instance_ids: Vec, - pub triangles: u64, - pub lines: u64, - pub bounds: [String; 6], - pub reflection: bool, -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Provenance { - pub id: String, - pub source_url: String, - pub source_revision: String, - pub sha256: String, - pub license: String, - pub original_test: String, - pub modifications: String, - pub authority: AuthorityClass, -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct CanonicalRecord { - pub schema_version: String, - pub syntax: Vec, - pub semantic: SemanticRecord, - pub scene: SceneRecord, - pub diagnostics: Vec, - pub provenance_id: String, -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ExpectedRecord { - pub outcome: ExpectedOutcome, - pub profile: Profile, - pub canonical: CanonicalRecord, -} -#[derive(Debug, Clone)] -pub struct FixtureCase { - pub id: &'static str, - pub relative_path: &'static str, - pub bytes: &'static [u8], - pub tags: &'static [&'static str], - pub profiles: &'static [Profile], - pub authority: AuthorityClass, - pub provenance: Provenance, - pub expected: ExpectedRecord, -} -impl FixtureCase { - pub fn sha256(&self) -> String { - hex_digest(self.bytes) - } - pub fn applies_to(&self, p: Profile) -> bool { - self.profiles.contains(&p) - } -} - -#[derive(Debug, Error, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum GateFailure { - #[error("gate {gate} does not apply to fixture {fixture} under {profile:?}")] - NotApplicable { - gate: String, - fixture: String, - profile: Profile, - }, - #[error("gate {gate} expected {fixture} to have tag {tag}")] - MissingTag { - gate: String, - fixture: String, - tag: String, - }, - #[error("gate {gate} found a canonical-record mismatch for {fixture}: {field}")] - RecordMismatch { - gate: String, - fixture: String, - field: String, - }, - #[error("gate {gate} found a schema mismatch for {fixture}")] - SchemaMismatch { gate: String, fixture: String }, - #[error("gate {gate} found a non-canonical digest for {fixture}")] - NonCanonicalDigest { gate: String, fixture: String }, -} -pub trait CorpusGate { - fn name(&self) -> &'static str; - fn profile(&self) -> Profile; - fn assert_case( - &self, - fixture: &FixtureCase, - expected: &ExpectedRecord, - actual: &CanonicalRecord, - ) -> Result<(), GateFailure>; -} -#[derive(Debug, Clone, Copy)] -pub struct NamedGate { - pub id: &'static str, - pub profile: Profile, - pub tag: &'static str, -} -impl CorpusGate for NamedGate { - fn name(&self) -> &'static str { - self.id - } - fn profile(&self) -> Profile { - self.profile - } - fn assert_case( - &self, - fixture: &FixtureCase, - expected: &ExpectedRecord, - actual: &CanonicalRecord, - ) -> Result<(), GateFailure> { - let fail = |field: &str| { - Err(GateFailure::RecordMismatch { - gate: self.id.into(), - fixture: fixture.id.into(), - field: field.into(), - }) - }; - if !fixture.applies_to(self.profile) { - return Err(GateFailure::NotApplicable { - gate: self.id.into(), - fixture: fixture.id.into(), - profile: self.profile, - }); - } - if !fixture.tags.contains(&self.tag) { - return Err(GateFailure::MissingTag { - gate: self.id.into(), - fixture: fixture.id.into(), - tag: self.tag.into(), - }); - } - if actual.schema_version != SCHEMA_VERSION - || expected.canonical.schema_version != SCHEMA_VERSION - { - return Err(GateFailure::SchemaMismatch { - gate: self.id.into(), - fixture: fixture.id.into(), - }); - } - if hex_digest(fixture.bytes) != fixture.provenance.sha256 { - return Err(GateFailure::NonCanonicalDigest { - gate: self.id.into(), - fixture: fixture.id.into(), - }); - } - let e = &expected.canonical; - match self.id { - "syntax_types_0_to_5" => { - if actual.syntax != e.syntax { - return fail("syntax classification, raw tails, spans, or line endings"); - } - } - "profile_acceptance_and_diagnostics" => { - if actual.diagnostics != e.diagnostics { - return fail("diagnostics"); - } - } - "mpd_and_data_boundaries" => { - if actual.semantic.canonical_path != e.semantic.canonical_path - || actual.semantic.target_identity != e.semantic.target_identity - { - return fail("MPD identity/boundaries"); - } - } - "path_and_resolution_independence" => { - if actual.semantic.canonical_path != e.semantic.canonical_path - || actual.semantic.root_identity != e.semantic.root_identity - || actual.semantic.target_identity != e.semantic.target_identity - || actual.semantic.cache_identity != e.semantic.cache_identity - { - return fail("path identities"); - } - } - "bfc_state_and_invertnext" => { - if actual.semantic.bfc_state != e.semantic.bfc_state { - return fail("BFC winding/INVERTNEXT state"); - } - } - "colours_and_ldconfig" => { - if actual.semantic.colour_state != e.semantic.colour_state { - return fail("colour state"); - } - } - "graph_identity_and_instances" => { - if actual.scene.model_id != e.scene.model_id - || actual.scene.instance_ids != e.scene.instance_ids - { - return fail("graph identity/instances"); - } - } - "steps_and_transforms" => { - if actual.semantic.steps != e.semantic.steps - || actual.scene.bounds != e.scene.bounds - || actual.scene.reflection != e.scene.reflection - { - return fail("steps/transforms/bounds"); - } - } - "numeric_finiteness_and_raw_preservation" => { - if actual.syntax != e.syntax || actual.diagnostics != e.diagnostics { - return fail("numeric spelling/finiteness diagnostics"); - } - } - "semantic_limits_and_cancellation" => { - if actual.semantic.limits != e.semantic.limits - || actual.diagnostics != e.diagnostics - { - return fail("limit/cancellation outcomes"); - } - } - _ => return fail("unknown gate"), - } - Ok(()) - } -} -pub const GATE_NAMES: &[&str] = &[ - "syntax_types_0_to_5", - "profile_acceptance_and_diagnostics", - "mpd_and_data_boundaries", - "path_and_resolution_independence", - "bfc_state_and_invertnext", - "colours_and_ldconfig", - "graph_identity_and_instances", - "steps_and_transforms", - "numeric_finiteness_and_raw_preservation", - "semantic_limits_and_cancellation", -]; -pub fn named_gates() -> Vec { - GATE_NAMES - .iter() - .enumerate() - .map(|(i, id)| NamedGate { - id, - profile: [Profile::Strict, Profile::Compatibility, Profile::Lossless][i % 3], - tag: id, - }) - .collect() -} -#[derive(Debug, Error, Clone, PartialEq, Eq)] -pub enum GateSetError { - #[error("duplicate gate name: {0}")] - DuplicateName(String), - #[error("gate set has no gate for profile {0:?}")] - MissingProfile(Profile), - #[error("fixture {0} has no applicable gate")] - NoApplicableGate(String), - #[error("missing required gate: {0}")] - MissingRequiredGate(String), -} -pub struct CorpusGateSet { - gates: Vec>, -} -impl CorpusGateSet { - pub fn new(gates: Vec>) -> Result { - let mut names = BTreeSet::new(); - for g in &gates { - if !names.insert(g.name()) { - return Err(GateSetError::DuplicateName(g.name().into())); - } - } - for p in [Profile::Strict, Profile::Compatibility, Profile::Lossless] { - if !gates.iter().any(|g| g.profile() == p) { - return Err(GateSetError::MissingProfile(p)); - } - } - for req in GATE_NAMES { - if !gates.iter().any(|g| g.name() == *req) { - return Err(GateSetError::MissingRequiredGate((*req).into())); - } - } - Ok(Self { gates }) - } - pub fn gates(&self) -> &[Box] { - &self.gates - } - pub fn validate_inventory(&self, fixtures: &[FixtureCase]) -> Result<(), GateSetError> { - for f in fixtures { - if !self - .gates - .iter() - .any(|g| f.tags.contains(&g.name()) && f.applies_to(g.profile())) - { - return Err(GateSetError::NoApplicableGate(f.id.into())); - } - } - Ok(()) - } - pub fn evaluate( - &self, - fixture: &FixtureCase, - actual: &CanonicalRecord, - ) -> Vec> { - self.gates - .iter() - .filter(|g| fixture.tags.contains(&g.name()) && fixture.applies_to(g.profile())) - .map(|g| g.assert_case(fixture, &fixture.expected, actual)) - .collect() - } -} -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct CoverageReport { - pub schema_version: String, - pub fixture_count: usize, - pub byte_count: usize, - pub gates: Vec, - pub profiles: Vec, - pub tags: Vec, -} -pub fn coverage_report(fixtures: &[FixtureCase]) -> CoverageReport { - let mut tags = BTreeSet::new(); - for f in fixtures { - tags.extend(f.tags.iter().map(|x| (*x).to_string())); - } - CoverageReport { - schema_version: SCHEMA_VERSION.into(), - fixture_count: fixtures.len(), - byte_count: fixtures.iter().map(|f| f.bytes.len()).sum(), - gates: GATE_NAMES.iter().map(|x| (*x).into()).collect(), - profiles: vec![Profile::Strict, Profile::Compatibility, Profile::Lossless], - tags: tags.into_iter().collect(), - } -} -pub fn serialize_canonical(record: &CanonicalRecord) -> Result, serde_json::Error> { - serde_json::to_vec(record) -} -pub fn hex_digest(bytes: &[u8]) -> String { - Sha256::digest(bytes) - .iter() - .map(|b| format!("{b:02x}")) - .collect() -} - -fn diagnostic(code: &str, severity: Severity, message: &str, span: Option) -> Diagnostic { - Diagnostic { - code: code.into(), - severity, - message: message.into(), - span, - } -} -fn parse_syntax(bytes: &[u8]) -> (Vec, Vec, u64, u64, [String; 6]) { - let mut syntax = Vec::new(); - let mut diagnostics = Vec::new(); - let mut triangles = 0; - let mut lines = 0; - let mut bounds = [ - f64::INFINITY, - f64::INFINITY, - f64::INFINITY, - f64::NEG_INFINITY, - f64::NEG_INFINITY, - f64::NEG_INFINITY, - ]; - let mut offset = 0u32; - for (line_no, raw) in bytes.split_inclusive(|b| *b == b'\n').enumerate() { - let ending = if raw.ends_with(b"\r\n") { - "crlf" - } else if raw.ends_with(b"\n") { - "lf" - } else { - "none" - }; - let body = raw - .strip_suffix(b"\r\n") - .or_else(|| raw.strip_suffix(b"\n")) - .or_else(|| raw.strip_suffix(b"\r")) - .unwrap_or(raw); - let text = String::from_utf8_lossy(body).into_owned(); - let fields = text - .split_whitespace() - .map(str::to_string) - .collect::>(); - let ty = fields - .first() - .and_then(|x| x.parse::().ok()) - .unwrap_or(0); - let tail = text - .split_once(char::is_whitespace) - .map(|(_, x)| x.trim_start()) - .unwrap_or("") - .to_string(); - let span = Span { - start: offset, - end: offset + raw.len() as u32, - line: (line_no + 1) as u32, - column: 1, - }; - offset += raw.len() as u32; - syntax.push(SyntaxRecord { - line_type: ty, - raw_tail: tail, - line_ending: ending.into(), - span, - fields: fields.clone(), - }); - if ty >= 2 && ty <= 5 { - let required = match ty { - 2 => 8, - 3 => 11, - 4 => 14, - 5 => 14, - _ => 0, - }; - if fields.len() < required { - diagnostics.push(diagnostic( - "E-LDRAW-FIELD-COUNT", - Severity::Error, - "primitive has too few fields", - Some(span), - )); - } - } - if fields.iter().any(|f| { - f.eq_ignore_ascii_case("nan") - || f.eq_ignore_ascii_case("inf") - || f.eq_ignore_ascii_case("infinity") - }) { - diagnostics.push(diagnostic( - "E-LDRAW-NONFINITE", - Severity::Error, - "non-finite numeric token", - Some(span), - )); - } - if ty == 3 { - triangles += 1; - } else if ty == 4 { - triangles += 2; - } else if ty == 5 { - lines += 1; - } - if ty >= 2 && ty <= 5 { - for f in fields.iter().skip(2) { - if let Ok(v) = f.parse::() { - if v.is_finite() { - bounds[0] = bounds[0].min(v); - bounds[1] = bounds[1].min(v); - bounds[2] = bounds[2].min(v); - bounds[3] = bounds[3].max(v); - bounds[4] = bounds[4].max(v); - bounds[5] = bounds[5].max(v); - } - } - } - } - } - if !bytes.is_empty() && !bytes.ends_with(b"\n") { - diagnostics.push(diagnostic( - "W-LDRAW-UNTERMINATED-LINE", - Severity::Warning, - "final line has no line ending", - None, - )); - } - let bounds = if bounds[0].is_finite() { - bounds.map(|x| if x == 0.0 { "0".into() } else { x.to_string() }) - } else { - [ - "0".into(), - "0".into(), - "0".into(), - "0".into(), - "0".into(), - "0".into(), - ] - }; - (syntax, diagnostics, triangles, lines, bounds) -} -pub fn canonical(id: &str, bytes: &[u8], tag: &str, _authority: AuthorityClass) -> CanonicalRecord { - let (syntax, mut diagnostics, triangles, lines, bounds) = parse_syntax(bytes); - let text = String::from_utf8_lossy(bytes); - let bfc = if text.contains("NOCERTIFY") { - "uncertified" - } else if text.contains("INVERTNEXT") { - "certified_ccw_invertnext" - } else if text.contains("CERTIFY CW") { - "certified_cw" - } else if text.contains("CERTIFY CCW") { - "certified_ccw" - } else { - "uncertified" - }; - let colour = if text.contains("!COLOUR") { - "ldconfig:PMBlue#300;direct:24" - } else if text.contains(" 24 ") { - "direct" - } else { - "current" - }; - let path = text - .lines() - .find_map(|l| l.strip_prefix("0 FILE ").map(|x| x.trim().to_string())) - .or_else(|| { - text.lines().find_map(|l| { - l.split_whitespace() - .last() - .filter(|x| x.contains('.')) - .map(str::to_string) - }) - }); - let root = if tag == "path_and_resolution_independence" { - Some( - if text.contains("official-library") { - "pinned-official-library" - } else if text.contains("manifest") { - "uploaded-manifest" - } else if text.contains("uploaded-roots") { - "uploaded-ldraw-roots" - } else { - "mpd-virtual" - } - .into(), - ) - } else { - Some("authored".into()) - }; - let target = path.clone().or_else(|| Some(id.into())); - let cache = target.as_ref().map(|x| format!("cache:{x}")); - let mut steps = Vec::new(); - if text.contains("STEP") { - steps.push("step-1".into()); - } - if text.contains("ROTSTEP") { - steps.push("rotstep-end".into()); - } - if steps.is_empty() { - steps.push("step-0".into()); - } - let mut limits = Vec::new(); - for (name, _) in LDRAW_LIMITS { - if text.contains(name) { - limits.push((*name).into()); - } - } - if text.contains("cancellation") { - limits.push("cancellation-checkpoint".into()); - } - if text.contains("../") { - diagnostics.push(diagnostic( - "E-LDRAW-PATH-OUT-OF-ROOT", - Severity::Error, - "path escapes resolver root", - None, - )); - } - CanonicalRecord { - schema_version: SCHEMA_VERSION.into(), - syntax, - semantic: SemanticRecord { - canonical_path: path, - root_identity: root, - target_identity: target, - cache_identity: cache, - bfc_state: bfc.into(), - colour_state: colour.into(), - steps, - limits, - }, - scene: SceneRecord { - model_id: id.into(), - instance_ids: vec![format!("instance:{id}:0")], - triangles, - lines, - bounds, - reflection: text.contains("reflection") || text.contains("determinant=-"), - }, - diagnostics, - provenance_id: format!("pm77-{id}"), - } -} -#[derive(Debug, Deserialize)] -struct ArtifactManifest { - artifacts: Vec, -} -#[derive(Debug, Deserialize)] -struct ArtifactEntry { - id: String, - path: String, - source_url: String, - source_revision: String, - sha256: String, - license: String, - original_test: String, - modifications: String, - authority: AuthorityClass, -} -const ARTIFACT_PROVENANCE: &str = include_str!("../corpus/artifact-provenance.json"); -fn fixture_provenance(id: &str, file: &str, bytes: &[u8]) -> Provenance { - let manifest: ArtifactManifest = serde_json::from_str(ARTIFACT_PROVENANCE) - .expect("artifact-provenance.json must be valid JSON"); - let path = format!("corpus/{file}"); - let entry = manifest - .artifacts - .into_iter() - .find(|entry| entry.id == id) - .unwrap_or_else(|| panic!("missing provenance entry for fixture {id}")); - assert_eq!(entry.path, path, "provenance path mismatch for {id}"); - assert_eq!( - entry.sha256, - hex_digest(bytes), - "provenance digest mismatch for {id}" - ); - Provenance { - id: format!("pm77-{id}"), - source_url: entry.source_url, - source_revision: entry.source_revision, - sha256: entry.sha256, - license: entry.license, - original_test: entry.original_test, - modifications: entry.modifications, - authority: entry.authority, - } -} -fn load_expected(json: &str, id: &str) -> ExpectedRecord { - let expected: ExpectedRecord = serde_json::from_str(json) - .unwrap_or_else(|error| panic!("invalid expected record for {id}: {error}")); - assert_eq!(expected.canonical.provenance_id, format!("pm77-{id}")); - expected -} -macro_rules! fixture { - ($id:literal,$tag:literal,$file:literal,$authority:expr,$outcome:expr,$profile:expr) => {{ - let bytes = include_bytes!(concat!("../corpus/", $file)); - let provenance = fixture_provenance($id, $file, bytes); - let expected = load_expected( - include_str!(concat!("../corpus/expected/", $id, ".expected.json")), - $id, - ); - assert_eq!( - provenance.authority, $authority, - "provenance authority mismatch for {}", - $id - ); - assert_eq!( - expected.outcome, $outcome, - "expected outcome mismatch for {}", - $id - ); - assert_eq!( - expected.profile, $profile, - "expected profile mismatch for {}", - $id - ); - FixtureCase { - id: $id, - relative_path: concat!("corpus/", $file), - bytes, - tags: &[$tag], - profiles: &[Profile::Strict, Profile::Compatibility, Profile::Lossless], - authority: $authority, - provenance, - expected, - } - }}; -} -pub fn inventory() -> Vec { - vec![ - fixture!( - "syntax-types", - "syntax_types_0_to_5", - "syntax-types.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "profile-matrix", - "profile_acceptance_and_diagnostics", - "profile-matrix.ldr", - AuthorityClass::PolymodelSafety, - ExpectedOutcome::Preserved, - Profile::Compatibility - ), - fixture!( - "mpd-data", - "mpd_and_data_boundaries", - "mpd-data.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "path-policy", - "path_and_resolution_independence", - "path-policy.ldr", - AuthorityClass::PolymodelSafety, - ExpectedOutcome::Rejected, - Profile::Strict - ), - fixture!( - "bfc-invertnext", - "bfc_state_and_invertnext", - "bfc-invertnext.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "colours-ldconfig", - "colours_and_ldconfig", - "colours-ldconfig.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "graph-instances", - "graph_identity_and_instances", - "graph-instances.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "steps-transforms", - "steps_and_transforms", - "steps-transforms.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "numeric-finiteness", - "numeric_finiteness_and_raw_preservation", - "numeric-finiteness.ldr", - AuthorityClass::RatifiedSpec, - ExpectedOutcome::Rejected, - Profile::Lossless - ), - fixture!( - "semantic-limits", - "semantic_limits_and_cancellation", - "semantic-limits.ldr", - AuthorityClass::PolymodelSafety, - ExpectedOutcome::Limited, - Profile::Compatibility - ), - fixture!( - "path-contexts", - "path_and_resolution_independence", - "path-contexts.ldr", - AuthorityClass::PolymodelSafety, - ExpectedOutcome::Accepted, - Profile::Compatibility - ), - fixture!( - "conditional-lines", - "steps_and_transforms", - "h-conditional-lines.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Preserved, - Profile::Strict - ), - fixture!( - "adversarial-regressions", - "semantic_limits_and_cancellation", - "adversarial-regressions.ldr", - AuthorityClass::PolymodelSafety, - ExpectedOutcome::Cancelled, - Profile::Lossless - ), - fixture!( - "fuzz-regressions", - "semantic_limits_and_cancellation", - "fuzz-regressions.ldr", - AuthorityClass::PolymodelSafety, - ExpectedOutcome::Rejected, - Profile::Lossless - ), - fixture!( - "external-thomas", - "graph_identity_and_instances", - "external-thomas.ldr", - AuthorityClass::Observation, - ExpectedOutcome::Accepted, - Profile::Compatibility - ), - fixture!( - "external-weldr", - "syntax_types_0_to_5", - "external-weldr.ldr", - AuthorityClass::Observation, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "external-ldr-tools", - "syntax_types_0_to_5", - "external-ldr-tools.ldr", - AuthorityClass::Observation, - ExpectedOutcome::Accepted, - Profile::Strict - ), - fixture!( - "h-conditional-visible", - "steps_and_transforms", - "h-conditional-visible.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Preserved, - Profile::Strict - ), - fixture!( - "h-conditional-interior", - "steps_and_transforms", - "h-conditional-interior.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Preserved, - Profile::Strict - ), - fixture!( - "h-conditional-offscreen", - "steps_and_transforms", - "h-conditional-offscreen.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Preserved, - Profile::Strict - ), - fixture!( - "h-conditional-ambiguous", - "steps_and_transforms", - "h-conditional-ambiguous.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Preserved, - Profile::Strict - ), - fixture!( - "h-conditional-degenerate", - "steps_and_transforms", - "h-conditional-degenerate.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Preserved, - Profile::Strict - ), - fixture!( - "h-conditional-invalid", - "steps_and_transforms", - "h-conditional-invalid.ldr", - AuthorityClass::HOwned, - ExpectedOutcome::Rejected, - Profile::Strict - ), - ] -} -pub fn validate_inventory(fixtures: &[FixtureCase]) -> Result<(), String> { - let mut ids = BTreeSet::new(); - let mut paths = BTreeSet::new(); - for f in fixtures { - if !ids.insert(f.id) { - return Err(format!("duplicate fixture id {}", f.id)); - } - if !paths.insert(f.relative_path) { - return Err(format!("duplicate fixture path {}", f.relative_path)); - } - if f.provenance.sha256 != f.sha256() { - return Err(format!("hash mismatch {}", f.id)); - } - if f.provenance.source_url.is_empty() - || f.provenance.source_revision.is_empty() - || f.provenance.license.is_empty() - || f.provenance.original_test.is_empty() - { - return Err(format!("incomplete provenance {}", f.id)); - } - if f.expected.canonical.provenance_id != f.provenance.id { - return Err(format!("provenance link mismatch {}", f.id)); - } - } - Ok(()) -} -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn corpus_gate_set_validates_and_evaluates_every_fixture() { - let fixtures = inventory(); - let gates = CorpusGateSet::new( - named_gates() - .into_iter() - .map(|gate| Box::new(gate) as Box) - .collect(), - ) - .unwrap(); - gates.validate_inventory(&fixtures).unwrap(); - - for fixture in &fixtures { - let results = gates.evaluate(fixture, &fixture.expected.canonical); - assert!(!results.is_empty(), "no gate evaluated for {}", fixture.id); - assert!( - results.iter().all(Result::is_ok), - "gate failure for {}: {results:?}", - fixture.id - ); - } - } - #[test] - fn embedded_inventory_is_unique_and_attributed() { - let c = inventory(); - validate_inventory(&c).unwrap(); - assert!(c.len() >= 22); - assert!(c.iter().all(|x| !x.bytes.is_empty())); - assert!( - c.iter() - .map(|x| x.expected.canonical.syntax.len()) - .collect::>() - .len() - > 1 - ); - } - #[test] - fn all_gate_families_have_named_rows() { - let r = coverage_report(&inventory()); - for g in GATE_NAMES { - assert!(r.tags.iter().any(|x| x == g), "missing {g}"); - } - } - #[test] - fn canonical_serialization_is_repeatable_and_ordered() { - let r = &inventory()[0].expected.canonical; - assert_eq!( - serialize_canonical(r).unwrap(), - serialize_canonical(r).unwrap() - ); - assert!( - String::from_utf8(serialize_canonical(r).unwrap()) - .unwrap() - .starts_with("{\"schema_version\":\"ldraw-canonical-v1\"") - ); - } - #[test] - fn differentiated_gates_check_their_owned_fields() { - let c = inventory(); - let gate = NamedGate { - id: "bfc_state_and_invertnext", - profile: Profile::Strict, - tag: "bfc_state_and_invertnext", - }; - let mut actual = c - .iter() - .find(|x| x.id == "bfc-invertnext") - .unwrap() - .expected - .canonical - .clone(); - actual.scene.triangles += 9; - assert!( - gate.assert_case( - c.iter().find(|x| x.id == "bfc-invertnext").unwrap(), - &c[4].expected, - &actual - ) - .is_ok() - ); - actual.semantic.bfc_state = "wrong".into(); - assert!( - gate.assert_case( - c.iter().find(|x| x.id == "bfc-invertnext").unwrap(), - &c[4].expected, - &actual - ) - .is_err() - ); - } -} +pub use gates::*; +pub use inventory::*; +pub use schema::*; diff --git a/crates/polymodel-ldraw-testkit/src/schema.rs b/crates/polymodel-ldraw-testkit/src/schema.rs new file mode 100644 index 0000000..ee0b977 --- /dev/null +++ b/crates/polymodel-ldraw-testkit/src/schema.rs @@ -0,0 +1,279 @@ +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use std::collections::BTreeSet; + +pub const SCHEMA_VERSION: &str = "ldraw-canonical-v1"; +pub const ORACLE_SCHEMA_VERSION: &str = "ldraw-oracle-v1"; +pub const LDRAW_LIMITS: &[(&str, u64)] = &[ + ("resource_bytes", 100 * 1024 * 1024), + ("line_bytes", 1024 * 1024), + ("files", 16_384), + ("include_depth", 256), + ("commands", 5_000_000), + ("instances", 5_000_000), + ("triangles", 20_000_000), + ("lines", 20_000_000), + ("textures", 1_024), + ("fetches", 8), + ("diagnostics", 10_000), +]; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)] +#[serde(rename_all = "snake_case")] +pub enum Profile { + Strict, + Compatibility, + Lossless, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum AuthorityClass { + RatifiedSpec, + PolymodelSafety, + HOwned, + Observation, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ExpectedOutcome { + Accepted, + Rejected, + Preserved, + Cancelled, + Limited, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum Severity { + Info, + Warning, + Error, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Diagnostic { + pub code: String, + pub severity: Severity, + pub message: String, + pub span: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Span { + pub start: u32, + pub end: u32, + pub line: u32, + pub column: u32, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct SyntaxRecord { + pub line_type: u8, + pub raw_tail: String, + pub span: Span, + pub line_ending: String, + pub fields: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum TexmapKind { + Start, + Next, + Fallback, + End, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TexmapEvent { + pub kind: TexmapKind, + pub span: Span, + pub mode: Option, + pub parameters: Vec, + pub reference: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct SemanticRecord { + pub canonical_path: Option, + pub root_identity: Option, + pub target_identity: Option, + pub cache_identity: Option, + pub bfc_state: String, + pub colour_state: String, + pub steps: Vec, + pub limits: Vec, + #[serde(default)] + pub texmap_events: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct SceneRecord { + pub model_id: String, + pub instance_ids: Vec, + pub triangles: u64, + pub lines: u64, + pub bounds: [String; 6], + pub reflection: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct OracleModel { + pub name: String, + pub model_index: u32, + pub certify: String, + pub local_colors: Vec, + pub step_count: usize, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct OracleColor { + pub code: u16, + pub slot: u16, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct OracleDiagnostic { + pub message: String, + pub token: String, + pub fatal: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct OracleError { + pub kind: String, + pub message: String, + pub diagnostics: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct OracleProjection { + pub status: String, + pub models: Vec, + pub diagnostics: Vec, + pub error: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CanonicalRecord { + pub schema_version: String, + pub syntax: Vec, + pub semantic: SemanticRecord, + pub scene: SceneRecord, + pub diagnostics: Vec, + pub provenance_id: String, + #[serde(default)] + pub oracle_projection: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct DerivationRef { + pub field: String, + pub authority: AuthorityClass, + pub source: String, + pub revision: String, + pub locator: String, + pub basis: String, + pub decision: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ExpectedRecord { + pub outcome: ExpectedOutcome, + pub profile: Profile, + pub canonical: CanonicalRecord, + pub derivations: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Provenance { + pub id: String, + pub source_url: String, + pub source_revision: String, + pub sha256: String, + pub license: String, + pub original_test: String, + pub modifications: String, + pub authority: AuthorityClass, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FixtureCase { + pub id: &'static str, + pub relative_path: &'static str, + pub bytes: &'static [u8], + pub tags: &'static [&'static str], + pub profiles: &'static [Profile], + pub authority: AuthorityClass, + pub provenance: Provenance, + pub expected: ExpectedRecord, +} + +impl FixtureCase { + pub fn sha256(&self) -> String { + hex_digest(self.bytes) + } + + pub fn applies_to(&self, profile: Profile) -> bool { + self.profiles.contains(&profile) + } +} + +pub fn serialize_canonical(record: &CanonicalRecord) -> Result, serde_json::Error> { + serde_json::to_vec(record) +} + +pub fn serialize_expected(record: &ExpectedRecord) -> Result, serde_json::Error> { + serde_json::to_vec(record) +} + +pub fn parse_expected(json: &str) -> Result { + serde_json::from_str(json) +} + +pub fn hex_digest(bytes: &[u8]) -> String { + Sha256::digest(bytes) + .iter() + .map(|byte| format!("{byte:02x}")) + .collect() +} + +pub fn normalize_certification(value: &str) -> Option<&'static str> { + match value { + "indeterminate" => Some("unknown"), + "true" | "certified" => Some("certified"), + "false" | "uncertified" => Some("uncertified"), + "unknown" => Some("unknown"), + _ => None, + } +} + +pub fn normalized_codes(colors: &[OracleColor]) -> Vec { + let mut codes = colors.iter().map(|color| color.code).collect::>(); + codes.sort_unstable(); + codes.dedup(); + codes +} + +pub fn unique_strings(values: impl IntoIterator) -> bool { + let values = values.into_iter().collect::>(); + values.len() == values.iter().collect::>().len() +} diff --git a/crates/polymodel-renderer-ledger/src/lib.rs b/crates/polymodel-renderer-ledger/src/lib.rs index 73b143f..f8b34a6 100644 --- a/crates/polymodel-renderer-ledger/src/lib.rs +++ b/crates/polymodel-renderer-ledger/src/lib.rs @@ -817,10 +817,7 @@ fn apply( state.class_totals[class as usize] += bytes; state.domain_totals[class.domain() as usize] += bytes; *state.owner_totals.entry(bucket).or_default() += bytes; - *state - .owner_class_totals - .entry((owner, class)) - .or_default() += bytes; + *state.owner_class_totals.entry((owner, class)).or_default() += bytes; *state .owner_domain_totals .entry((owner, class.domain())) @@ -924,9 +921,18 @@ fn check_policy( let unified_owner_breach = prospective_unified > state.limits.unified_per_owner; let unified_global_breach = prospective_global > state.limits.unified_global; - let classes = class_breach.then_some(class).into_iter().collect::>(); - let domains = domain_breach.then_some(domain).into_iter().collect::>(); - let owners = owner_breach.then_some(bucket).into_iter().collect::>(); + let classes = class_breach + .then_some(class) + .into_iter() + .collect::>(); + let domains = domain_breach + .then_some(domain) + .into_iter() + .collect::>(); + let owners = owner_breach + .then_some(bucket) + .into_iter() + .collect::>(); let global_classes = global_class_breach .then_some(class) .into_iter() diff --git a/crates/polymodel-renderer-protocol/src/load_state.rs b/crates/polymodel-renderer-protocol/src/load_state.rs index 1782896..c86fc28 100644 --- a/crates/polymodel-renderer-protocol/src/load_state.rs +++ b/crates/polymodel-renderer-protocol/src/load_state.rs @@ -237,10 +237,7 @@ impl LoadReducer { } LoadEvent::LoadFailed { error, candidate, .. - } if matches!( - self.state, - LoadState::Loading(_) | LoadState::Installing(_) - ) => { + } if matches!(self.state, LoadState::Loading(_) | LoadState::Installing(_)) => { let disposed = self.take_resources(candidate); self.state = LoadState::Failed(identity.load_epoch, error.code); TransitionResult::committed(self.state.clone(), disposed) @@ -248,9 +245,7 @@ impl LoadReducer { LoadEvent::Cancel { candidate, .. } if matches!( self.state, - LoadState::Loading(_) - | LoadState::Installing(_) - | LoadState::Ready(_) + LoadState::Loading(_) | LoadState::Installing(_) | LoadState::Ready(_) ) => { let disposed = self.take_resources(candidate); @@ -474,7 +469,10 @@ mod tests { }); assert_eq!(result.outcome, TransitionOutcome::Committed); assert_eq!(result.disposed, vec![ResourceToken(7)]); - assert!(matches!(r.state(), LoadState::Failed(1, LoadErrorCode::Install))); + assert!(matches!( + r.state(), + LoadState::Failed(1, LoadErrorCode::Install) + )); } fn installing_reducer() -> LoadReducer { diff --git a/flake.nix b/flake.nix index 65e1f70..a1b5fee 100644 --- a/flake.nix +++ b/flake.nix @@ -40,7 +40,83 @@ "rustfmt" ]; }); + + ldparseRev = "0fe78dcee22982f26cceced1b483340faa4d04e9"; + immerRev = "141af37e46a75fce48318b13bf2bf71f51950de8"; + coroutinesRev = "a26a43912319fd2c40823dc96755990da765bc8f"; + ldparse = pkgs.fetchFromGitHub { + owner = "elfprince13"; + repo = "LDParse"; + rev = ldparseRev; + sha256 = "04frdxpb6kvrzggvbfq66cb95w7g6lf7yzyqaw3qyqvsnqbyw7r0"; + }; + immerSrc = pkgs.fetchFromGitHub { + owner = "arximboldi"; + repo = "immer"; + rev = immerRev; + sha256 = "10drhxqgr6pp4bih9kbcdk0x39gdz8r85zryfydisqq7gwp4ibfz"; + }; + coroutinesSrc = pkgs.fetchFromGitHub { + owner = "Geopipe"; + repo = "CxxBidirectionalCoroutines"; + rev = coroutinesRev; + sha256 = "10bdz6l5i1qgniysgm7fmrds76yh9kj59wfv7zk9kzvj76qqkdpq"; + }; + ldrawOracle = pkgs.stdenv.mkDerivation { + pname = "ldraw-oracle"; + version = ldparseRev; + src = ldparse; + nativeBuildInputs = [ pkgs.cmake pkgs.pkg-config pkgs.makeWrapper ]; + buildInputs = [ pkgs.boost pkgs.glm pkgs.fmt ]; + patches = [ ./patches/ldparse-oracle-access.patch ]; + cmakeFlags = [ "-DCMAKE_POLICY_VERSION_MINIMUM=3.5" ]; + postPatch = '' + test "${ldparseRev}" = "0fe78dcee22982f26cceced1b483340faa4d04e9" + # Place separately-fetched submodules into deps/ + rm -rf deps/immer deps/CxxBidirectionalCoroutines + cp -r ${immerSrc} deps/immer + cp -r ${coroutinesSrc} deps/CxxBidirectionalCoroutines + # Disable face-unwrapper (not needed for oracle) and fix case mismatch: + # GitHub archive has ParseTest/ but CMakeLists references lowercase parsetest + sed -i '/add_subdirectory(face-unwrapper)/d' CMakeLists.txt + sed -i 's/add_subdirectory(parsetest)/add_subdirectory(ParseTest)/' CMakeLists.txt + # GCC 15 requires explicit include for std::unique_ptr in Cache.hpp + sed -i '1i #include ' include/LDParse/Cache.hpp + # GCC 15 requires explicit lambda capture for offset in Geom.hpp + sed -i 's/\[\](uint32_t &index){ index += offset; }/[offset](uint32_t \&index){ index += offset; }/' include/LDParse/Geom.hpp + cp ${./tools/ldraw-oracle/oracle.cpp} oracle.cpp + ''; + buildPhase = '' + runHook preBuild + cmake --build . --parallel "$NIX_BUILD_CORES" + ldparse_lib=$(find . -type f -name 'libLDParse.so*' -print -quit) + test -n "$ldparse_lib" + ldparse_lib_dir=$(dirname "$ldparse_lib") + c++ -std=c++17 -I../include -I../deps/immer -I../deps/CxxBidirectionalCoroutines/include -I${pkgs.boost.dev}/include -I${pkgs.glm}/include -I${pkgs.fmt.dev}/include ${./tools/ldraw-oracle/oracle.cpp} -L"$ldparse_lib_dir" -Wl,-rpath,"\$$ORIGIN/../lib" -lLDParse -lboost_filesystem -o ldraw-oracle + runHook postBuild + ''; + installPhase = '' + runHook preInstall + ldparse_lib=$(find . -type f -name 'libLDParse.so*' -print -quit) + test -n "$ldparse_lib" + install -Dm755 "$ldparse_lib" "$out/lib/$(basename "$ldparse_lib")" + install -Dm755 ldraw-oracle $out/bin/ldraw-oracle + install -Dm644 ${./tools/ldraw-oracle/oracle.cpp} $out/share/ldraw-oracle/oracle.cpp + install -Dm644 ${./patches/ldparse-oracle-access.patch} $out/share/ldraw-oracle/ldparse-oracle-access.patch + cat > $out/share/ldraw-oracle/provenance.txt </dev/null 2>&1 || { echo "FAIL: nix is required for PM-77 oracle gates"; exit 1; } + # Run the offline native LDParse compatibility boundary. -ldraw-differential: +ldraw-differential: require-nix cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- differential -# Run all local validation expected before review. -test-all: fix check lint test test-server test-renderer-ledger test-renderer ldraw-corpus ldraw-wasm-check ldraw-fuzz-smoke ldraw-differential +# Run all local validation expected before review. Keep the PM-77 recipes explicit +# so corpus, WASM, fuzz, and Nix-backed differential gates remain visible. +test-all: require-nix fix check lint test test-server test-renderer-ledger test-renderer ldraw-corpus ldraw-wasm-check ldraw-fuzz-smoke ldraw-differential # Run browser end-to-end tests. e2e: cd e2e && npm test diff --git a/patches/ldparse-gcc15.patch b/patches/ldparse-gcc15.patch new file mode 100644 index 0000000..4ceb3fc --- /dev/null +++ b/patches/ldparse-gcc15.patch @@ -0,0 +1,10 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -34,7 +34,6 @@ + add_library(LDParse SHARED ${LDPARSE_SOURCE}) + target_link_libraries(LDParse Boost::filesystem) + +-add_subdirectory(face-unwrapper) +-add_subdirectory(parsetest) ++add_subdirectory(ParseTest) diff --git a/patches/ldparse-oracle-access.patch b/patches/ldparse-oracle-access.patch new file mode 100644 index 0000000..cadd681 --- /dev/null +++ b/patches/ldparse-oracle-access.patch @@ -0,0 +1,13 @@ +diff --git a/include/LDParse/Model.hpp b/include/LDParse/Model.hpp +--- a/include/LDParse/Model.hpp ++++ b/include/LDParse/Model.hpp +@@ -59,5 +59,9 @@ + Model(std::string name, std::string srcLoc, SrcType srcType, ColorTable& colorTable, const std::shared_ptr subModelNames = nullptr, std::shared_ptr subModels = nullptr); + + std::shared_ptr getSubFileCache() const { return mSubModels; } ++ const std::string& name() const { return mName; } ++ boost::logic::tribool certify() const { return mCertify; } ++ const std::vector& stepEnds() const { return mStepEnds; } ++ const std::unordered_map& localColors() const { return mLocalColors; } + const std::string& getPath() const { return mSrcLoc; } + }; diff --git a/src/viewer.rs b/src/viewer.rs index 79ded62..586c6be 100644 --- a/src/viewer.rs +++ b/src/viewer.rs @@ -1178,11 +1178,12 @@ impl WorkerBridgeState { namespace, identity, } => { - let result = reducer_msg.borrow_mut().reduce(LoadEvent::LoadSucceeded { - namespace, - identity, - candidate: None, - }); + let result = + reducer_msg.borrow_mut().reduce(LoadEvent::LoadSucceeded { + namespace, + identity, + candidate: None, + }); if matches!( result.outcome, polymodel_renderer_protocol::TransitionOutcome::Committed @@ -1197,11 +1198,14 @@ impl WorkerBridgeState { identity, stats, } => { - let result = reducer_msg.borrow_mut().reduce(LoadEvent::InstallSucceeded { - namespace, - identity, - scene: None, - }); + let result = + reducer_msg + .borrow_mut() + .reduce(LoadEvent::InstallSucceeded { + namespace, + identity, + scene: None, + }); if matches!( result.outcome, polymodel_renderer_protocol::TransitionOutcome::Committed diff --git a/tools/ldraw-compat-harness/.python-version b/tools/ldraw-compat-harness/.python-version deleted file mode 100644 index 04e2079..0000000 --- a/tools/ldraw-compat-harness/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12.8 diff --git a/tools/ldraw-compat-harness/README.md b/tools/ldraw-compat-harness/README.md index 06acfdc..27de346 100644 --- a/tools/ldraw-compat-harness/README.md +++ b/tools/ldraw-compat-harness/README.md @@ -1,18 +1,33 @@ # PM-77 native LDraw compatibility harness -This directory is the native-only process boundary. The reusable `polymodel-ldraw-testkit` crate has no filesystem, process, archive, or parser dependencies and is wasm-checkable. +This directory is the native-only process boundary. The reusable +`polymodel-ldraw-testkit` crate has no filesystem, process, archive, parser, or +native dependencies and is wasm-checkable. -## Offline commands +## Commands ```sh -uv sync --locked --offline +cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- validate cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- inventory -cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- differential +cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- corpus cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- fuzz +cargo run --manifest-path tools/ldraw-compat-harness/Cargo.toml -- differential ``` -The expected interpreter is CPython **3.12.8**. LDParse is a Python library and is represented only by the pinned driver boundary; the PM-75 revisions are `877667417d6cab57c04aed9cb3d5bfe7efa0589c` (master) and `0fe78dcee22982f26cceced1b483340faa4d04e9` (modernization). The driver refuses wrong revisions, interpreter drift, network acquisition, timeout/crash, malformed output, and unsupported surfaces. +`differential` is deliberately fail-closed: it requires Nix, builds the +pinned `.#ldraw-oracle` package, resolves that output with `nix path-info`, and +runs the C++17 oracle over all 24 committed fixtures. It never invokes the E +Rust parser. The oracle emits `ldraw-oracle-v1`, and the harness compares only +the fields declared by each fixture's authored oracle projection. -The minimum oracle surface is line types 0–5, raw tails/spans, MPD FILE/NOFILE, graph/cache/instance identity, BFC/INVERTNEXT, STEP boundaries, finite numeric diagnostics, and deterministic acceptance/rejection. TEXMAP, conditional-line classification, colour resolution, and renderer batches are explicitly observational/unsupported-by-ldparse and remain authored or separately owned corpus contracts; they are not silently treated as oracle coverage. +The D phase is C++ oracle versus independently authored expected records. The +E phase is separate: E must run its real in-process Rust adapter and compare +its projection to the saved/current C++ oracle JSON using the same +normalization rules. Geometry, instances, transforms, winding, TEXMAP, points, +explicit edges, and H-owned conditional-line classification remain authored or +owned by their respective contracts because the pinned LDParse reference does +not expose those populated surfaces. -Expected records are authored from ratified requirements or Polymodel safety decisions. Upstream output is an observation until a compatibility-ledger decision adopts it. +Expected records are authored from ratified requirements, Polymodel safety +decisions, LDraw source rules, or explicitly marked observations. They are not +generated from fixture bytes or oracle output. diff --git a/tools/ldraw-compat-harness/ldparse_driver.py b/tools/ldraw-compat-harness/ldparse_driver.py deleted file mode 100644 index cac0733..0000000 --- a/tools/ldraw-compat-harness/ldparse_driver.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python3 -"""Deterministic LDParse observation driver. - -The real LDParse package is imported only from the pinned vendor checkout in a -fully provisioned environment. This driver owns the process protocol and the -small ratified line-record surface used by the offline corpus: it never copies -expected records from the Rust testkit. -""" -from __future__ import annotations -import argparse, hashlib, json, math, sys - -MASTER = "877667417d6cab57c04aed9cb3d5bfe7efa0589c" -MODERNIZATION = "0fe78dcee22982f26cceced1b483340faa4d04e9" -PYTHON = "3.12.8" - - -def diagnostic(code: str, severity: str, message: str, span: dict | None = None) -> dict: - return {"code": code, "severity": severity, "message": message, "span": span} - - -def parse(raw: bytes, fixture: str, revision: str) -> dict: - syntax = [] - diagnostics = [] - triangles = lines = 0 - bfc = "uncertified" - steps = [] - offset = 0 - for number, line in enumerate(raw.splitlines(keepends=True), 1): - body = line.rstrip(b"\r\n") - ending = "crlf" if line.endswith(b"\r\n") else "lf" if line.endswith(b"\n") else "none" - text = body.decode("utf-8", errors="replace") - fields = text.split() - try: - line_type = int(fields[0]) if fields else 0 - except ValueError: - line_type = 0 - tail = text.split(None, 1)[1] if len(fields) > 1 else "" - span = {"start": offset, "end": offset + len(line), "line": number, "column": 1} - offset += len(line) - syntax.append({"line_type": line_type, "raw_tail": tail, "span": span, "line_ending": ending, "fields": fields}) - if line_type in (2, 3, 4, 5): - required = {2: 8, 3: 11, 4: 14, 5: 14}[line_type] - if len(fields) < required: - diagnostics.append(diagnostic("E-LDRAW-FIELD-COUNT", "error", "primitive has too few fields", span)) - if line_type == 3: - triangles += 1 - elif line_type == 4: - triangles += 2 - elif line_type == 5: - lines += 1 - for token in fields[2:]: - lowered = token.lower() - if lowered in {"nan", "+nan", "-nan", "inf", "+inf", "-inf", "infinity", "+infinity", "-infinity"}: - diagnostics.append(diagnostic("E-LDRAW-NONFINITE", "error", "non-finite numeric token", span)) - elif line_type in (2, 3, 4, 5): - try: - float(token) - except ValueError: - if any(c in token for c in ".eE"): - diagnostics.append(diagnostic("E-LDRAW-NUMERIC", "error", "malformed numeric token", span)) - if text.startswith("0 BFC "): - if "NOCERTIFY" in text: - bfc = "uncertified" - elif "INVERTNEXT" in text: - bfc = "certified_ccw_invertnext" - elif "CERTIFY CW" in text: - bfc = "certified_cw" - elif "CERTIFY CCW" in text: - bfc = "certified_ccw" - if text.startswith("0 STEP"): - steps.append("step-1") - if text.startswith("0 ROTSTEP"): - steps.append("rotstep-end") - if b"../" in raw: - diagnostics.append(diagnostic("E-LDRAW-PATH-OUT-OF-ROOT", "error", "path escapes resolver root")) - if raw and not raw.endswith(b"\n"): - diagnostics.append(diagnostic("W-LDRAW-UNTERMINATED-LINE", "warning", "final line has no line ending")) - if not steps: - steps = ["step-0"] - return { - "schema_version": "ldraw-canonical-v1", "fixture": fixture, "revision": revision, - "sha256": hashlib.sha256(raw).hexdigest(), "syntax": syntax, - "triangles": triangles, "lines": lines, "bfc_state": bfc, - "steps": steps, "diagnostics": diagnostics, - } - - -def main() -> int: - parser = argparse.ArgumentParser() - parser.add_argument("--revision", required=True) - parser.add_argument("--fixture", required=True) - parser.add_argument("--bytes", required=True) - args = parser.parse_args() - if sys.version_info[:3] != (3, 12, 8): - raise SystemExit(f"wrong interpreter: {sys.version.split()[0]} != {PYTHON}") - if args.revision not in (MASTER, MODERNIZATION): - raise SystemExit("wrong LDParse revision") - # Rust supplies the exact fixture bytes as a UTF-8-preserving argument. - raw = args.bytes.encode("utf-8", errors="surrogateescape") - print(json.dumps(parse(raw, args.fixture, args.revision), sort_keys=True, separators=(",", ":"))) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/tools/ldraw-compat-harness/pyproject.toml b/tools/ldraw-compat-harness/pyproject.toml deleted file mode 100644 index 6545a50..0000000 --- a/tools/ldraw-compat-harness/pyproject.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -name = "pm77-ldraw-compat-harness" -version = "0.1.0" -requires-python = "==3.12.8" -dependencies = [] - -[tool.uv] -package = false diff --git a/tools/ldraw-compat-harness/src/main.rs b/tools/ldraw-compat-harness/src/main.rs index a287cdb..b7e20d8 100644 --- a/tools/ldraw-compat-harness/src/main.rs +++ b/tools/ldraw-compat-harness/src/main.rs @@ -1,200 +1,70 @@ -//! Native PM-77 compatibility and bounded smoke harness. +//! Native PM-77 corpus validator and D-phase LDParse oracle harness. use polymodel_ldraw_testkit::{ - CanonicalRecord, FixtureCase, GATE_NAMES, LDRAW_LIMITS, SCHEMA_VERSION, coverage_report, - hex_digest, inventory, validate_inventory, + coverage_report, inventory, named_gates, validate_inventory, CanonicalRecord, FixtureCase, + CorpusGateSet, Diagnostic, OracleDiagnostic, OracleError, OracleModel, OracleProjection, + SCHEMA_VERSION, ORACLE_SCHEMA_VERSION, GATE_NAMES, LDRAW_LIMITS, }; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::{ env, - process::{Command, ExitCode, Stdio}, + fs, + io, + path::{Path, PathBuf}, + process::{Child, Command, ExitCode, Output, Stdio}, thread, time::{Duration, Instant}, }; const LD_PARSE_MASTER: &str = "877667417d6cab57c04aed9cb3d5bfe7efa0589c"; -const LD_PARSE_MODERNIZATION: &str = "0fe78dcee22982f26cceced1b483340faa4d04e9"; -const PYTHON_VERSION: &str = "3.12.8"; +const LD_PARSE_REVISION: &str = "0fe78dcee22982f26cceced1b483340faa4d04e9"; +const FUZZ_SEED: u64 = 0x504d3737_4435; +const FUZZ_ITERATIONS: usize = 128; +const MAX_MUTATED_BYTES: usize = 1024 * 1024; +const ORACLE_TIMEOUT: Duration = Duration::from_secs(2); +const FUZZ_BUDGET: Duration = Duration::from_secs(30); -#[derive(Debug, Clone, Serialize)] -struct HarnessReport { +#[derive(Debug, Serialize)] +struct Report<'a> { schema_version: &'static str, - command: String, + command: &'a str, + status: &'static str, fixtures: usize, bytes: usize, gates: usize, profiles: usize, - seeds: Vec, - iterations: u32, - adapter: AdapterEvidence, - status: &'static str, + oracle_revision: &'static str, + oracle_schema: &'static str, + seed: Option, + mutations: usize, } -#[derive(Debug, Clone, Serialize)] -struct AdapterEvidence { - kind: &'static str, - interpreter: &'static str, - master_revision: &'static str, - modernization_revision: &'static str, - network: bool, - timeout_ms: u64, -} -#[derive(Debug, Clone, Deserialize)] -struct DriverOutput { +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct OracleDocument { schema_version: String, - fixture: String, - #[serde(rename = "revision")] - revision: String, - sha256: String, - syntax: Vec, - triangles: u64, - lines: u64, - bfc_state: String, - steps: Vec, - diagnostics: Vec, -} - -pub trait InProcessRustAdapter { - fn identity(&self) -> &'static str; - fn parse(&self, fixture: &FixtureCase) -> Result; -} -pub trait OutOfProcessAdapter { - fn identity(&self) -> &str; - fn run(&self, fixture: &FixtureCase, timeout_ms: u64) -> Result, HarnessError>; -} - -#[derive(Debug, Clone)] -pub struct LDParseAdapter { - pub revision: String, - pub python: String, - pub network: bool, -} - -#[derive(Debug, thiserror::Error)] -pub enum HarnessError { - #[error("wrong LDParse revision: {0}")] - WrongRevision(String), - #[error("wrong interpreter: {0}")] - WrongInterpreter(String), - #[error("network acquisition is forbidden")] - NetworkEnabled, - #[error("adapter timed out after {0}ms")] - Timeout(u64), - #[error("adapter crashed: {0}")] - Crash(String), - #[error("unsupported LDParse surface: {0}")] - UnsupportedSurface(String), - #[error("malformed driver output: {0}")] - MalformedOutput(String), - #[error("driver failed with status {status}: {stderr}")] - Exit { status: String, stderr: String }, - #[error("driver could not be started: {0}")] - Spawn(String), -} - -impl LDParseAdapter { - fn validate(&self) -> Result<(), HarnessError> { - if self.revision != LD_PARSE_MASTER && self.revision != LD_PARSE_MODERNIZATION { - return Err(HarnessError::WrongRevision(self.revision.clone())); - } - if self.python != PYTHON_VERSION { - return Err(HarnessError::WrongInterpreter(self.python.clone())); - } - if self.network { - return Err(HarnessError::NetworkEnabled); - } - Ok(()) - } -} -impl OutOfProcessAdapter for LDParseAdapter { - fn identity(&self) -> &str { - &self.revision - } - fn run(&self, fixture: &FixtureCase, timeout_ms: u64) -> Result, HarnessError> { - self.validate()?; - if timeout_ms == 0 { - return Err(HarnessError::Timeout(timeout_ms)); - } - if fixture.tags.iter().any(|tag| { - *tag == "colours_and_ldconfig" - || *tag == "path_and_resolution_independence" - || *tag == "steps_and_transforms" - }) { - return Err(HarnessError::UnsupportedSurface(fixture.id.into())); - } - let driver = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("ldparse_driver.py"); - let mut child = Command::new("uv") - .current_dir(env!("CARGO_MANIFEST_DIR")) - .args([ - "run", - "--offline", - "python", - driver.to_str().unwrap(), - "--revision", - &self.revision, - "--fixture", - fixture.id, - "--bytes", - ]) - .arg(String::from_utf8_lossy(fixture.bytes).as_ref()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .map_err(|e| HarnessError::Spawn(e.to_string()))?; - let deadline = Instant::now() + Duration::from_millis(timeout_ms); - loop { - match child - .try_wait() - .map_err(|e| HarnessError::Crash(e.to_string()))? - { - Some(status) => { - let output = child - .wait_with_output() - .map_err(|e| HarnessError::Crash(e.to_string()))?; - if !status.success() { - return Err(HarnessError::Exit { - status: status.to_string(), - stderr: String::from_utf8_lossy(&output.stderr).into_owned(), - }); - } - let value: serde_json::Value = serde_json::from_slice(&output.stdout) - .map_err(|e| HarnessError::MalformedOutput(e.to_string()))?; - if value["schema_version"] != SCHEMA_VERSION - || value["fixture"] != fixture.id - || value["revision"] != self.revision - { - return Err(HarnessError::MalformedOutput( - "driver identity/schema mismatch".into(), - )); - } - return Ok(output.stdout); - } - None if Instant::now() >= deadline => { - let _ = child.kill(); - let _ = child.wait(); - return Err(HarnessError::Timeout(timeout_ms)); - } - None => thread::sleep(Duration::from_millis(5)), - } - } - } + fixture_path: String, + status: String, + models: Vec, + diagnostics: Vec, + error: Option, } fn main() -> ExitCode { - let command = env::args().nth(1).unwrap_or_else(|| "inventory".into()); + let command = env::args().nth(1).unwrap_or_else(|| "inventory".to_owned()); let result = match command.as_str() { - "inventory" | "corpus" => corpus_report(), - "fuzz" => fuzz_report(), - "differential" => differential_report(), "validate" => validate(), - "dump-expected" => dump_expected(), + "inventory" => report("inventory"), + "corpus" => report("corpus"), + "fuzz" => fuzz(), + "differential" => differential(), other => Err(format!( - "unknown command {other}; use inventory, fuzz, differential, or validate" + "unknown command {other}; use validate, inventory, corpus, fuzz, or differential" )), }; match result { - Ok(json) => { - println!("{json}"); + Ok(value) => { + println!("{value}"); ExitCode::SUCCESS } Err(error) => { @@ -204,364 +74,322 @@ fn main() -> ExitCode { } } -fn corpus_report() -> Result { +fn root_dir() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .and_then(Path::parent) + .expect("harness is nested below the repository root") + .to_owned() +} + +fn report(command: &'static str) -> Result { let fixtures = inventory(); validate_inventory(&fixtures)?; + CorpusGateSet::new(named_gates()) + .map_err(|error| error.to_string())? + .validate_inventory(&fixtures) + .map_err(|error| error.to_string())?; let coverage = coverage_report(&fixtures); - let report = HarnessReport { + serde_json::to_string_pretty(&Report { schema_version: SCHEMA_VERSION, - command: "inventory".into(), + command, + status: "pass", fixtures: coverage.fixture_count, bytes: coverage.byte_count, gates: GATE_NAMES.len(), profiles: coverage.profiles.len(), - seeds: Vec::new(), - iterations: 0, - adapter: evidence(), - status: "pass", - }; - serde_json::to_string_pretty(&report).map_err(|e| e.to_string()) + oracle_revision: LD_PARSE_REVISION, + oracle_schema: ORACLE_SCHEMA_VERSION, + seed: None, + mutations: 0, + }) + .map_err(|error| error.to_string()) } + fn validate() -> Result { let fixtures = inventory(); validate_inventory(&fixtures)?; - if LDRAW_LIMITS - .iter() - .any(|(name, limit)| *limit == 0 || name.is_empty()) - { - return Err("invalid semantic limit".into()); + CorpusGateSet::new(named_gates()) + .map_err(|error| error.to_string())? + .validate_inventory(&fixtures) + .map_err(|error| error.to_string())?; + if LDRAW_LIMITS.iter().any(|(name, limit)| name.is_empty() || *limit == 0) { + return Err("invalid LDraw semantic limit".to_owned()); } - let adapter = LDParseAdapter { - revision: LD_PARSE_MASTER.into(), - python: PYTHON_VERSION.into(), - network: false, - }; - adapter.validate().map_err(|e| e.to_string())?; - Ok("{\"status\":\"pass\",\"provenance\":\"inventory hashes checked; vendor source not verified\",\"pins\":\"configuration checked; vendor source not verified\"}".into()) + for fixture in &fixtures { + let encoded = serde_json::to_vec(&fixture.expected).map_err(|error| error.to_string())?; + let second = serde_json::to_vec(&fixture.expected).map_err(|error| error.to_string())?; + if encoded != second { + return Err(format!("non-deterministic expected serialization: {}", fixture.id)); + } + if fixture.expected.canonical.oracle_projection.is_none() { + return Err(format!("missing authored oracle projection: {}", fixture.id)); + } + } + Ok(serde_json::json!({ + "schema_version": SCHEMA_VERSION, + "oracle_schema": ORACLE_SCHEMA_VERSION, + "oracle_revision": LD_PARSE_REVISION, + "ldparse_master": LD_PARSE_MASTER, + "status": "pass", + "fixtures": fixtures.len(), + "provenance": "embedded rows and SHA-256 values checked", + "independence": "expected records load only from committed JSON" + }) + .to_string()) } -fn dump_expected() -> Result { - let mut output = serde_json::Map::new(); - for fixture in inventory() { - output.insert( - fixture.id.into(), - serde_json::to_value(&fixture.expected).map_err(|e| e.to_string())?, - ); + +fn run_checked(program: &str, args: &[&str], cwd: &Path) -> Result { + let output = Command::new(program) + .args(args) + .current_dir(cwd) + .output() + .map_err(|error| format!("could not start {program}: {error}"))?; + if !output.status.success() { + return Err(format!( + "{program} {} failed with {}:\n{}", + args.join(" "), + output.status, + String::from_utf8_lossy(&output.stderr) + )); } - serde_json::to_string_pretty(&output).map_err(|e| e.to_string()) + Ok(output) } -fn fuzz_report() -> Result { - let fixtures = inventory(); - validate_inventory(&fixtures)?; - let seeds = [0xD0_u64, 0x77_u64, 0x86_u64]; - let iterations = 128; - for seed in seeds { - deterministic_smoke(seed, iterations, &fixtures)?; + +fn oracle_binary(root: &Path) -> Result { + if !Command::new("nix").arg("--version").status().map_err(|error| format!("could not start nix: {error}"))?.success() { + return Err("nix is required for the LDParse differential oracle".to_owned()); } - let report = HarnessReport { - schema_version: SCHEMA_VERSION, - command: "fuzz".into(), - fixtures: fixtures.len(), - bytes: fixtures.iter().map(|f| f.bytes.len()).sum(), - gates: GATE_NAMES.len(), - profiles: 3, - seeds: seeds.to_vec(), - iterations, - adapter: evidence(), - status: "pass", - }; - serde_json::to_string_pretty(&report).map_err(|e| e.to_string()) + run_checked("nix", &["build", ".#ldraw-oracle"], root)?; + let output = run_checked("nix", &["path-info", ".#ldraw-oracle"], root)?; + let store_output = String::from_utf8(output.stdout) + .map_err(|error| format!("nix path-info returned non-UTF-8 output: {error}"))?; + let store_path = store_output + .lines() + .next() + .ok_or_else(|| "nix path-info returned no output".to_owned())?; + let binary = Path::new(store_path.trim()).join("bin/ldraw-oracle"); + if !binary.is_file() { + return Err(format!("oracle binary is missing from successful Nix output: {}", binary.display())); + } + Ok(binary) } -fn deterministic_smoke(seed: u64, iterations: u32, fixtures: &[FixtureCase]) -> Result<(), String> { - let mut state = seed; - for step in 0..iterations { - state = state.wrapping_mul(6364136223846793005).wrapping_add(1); - let fixture = &fixtures[(state as usize) % fixtures.len()]; - let mut mutated = fixture.bytes.to_vec(); - match step % 6 { - 0 => { - mutated.extend_from_slice(b" \r\n"); - } - 1 => { - mutated = mutated - .iter() - .enumerate() - .map(|(i, b)| if i % 7 == 0 { b'\t' } else { *b }) - .collect(); - } - 2 => { - mutated.extend_from_slice(b"3 16 nan 0 0 1 0 0 0 0 1 0\n"); - } - 3 => { - mutated.extend_from_slice(b"0 FILE ../escape.ldr\n"); - } - 4 => { - mutated.extend_from_slice( - b"0 FILE cycle.ldr\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 cycle.ldr\n0 NOFILE\n", - ); - } - _ => { - mutated.extend(std::iter::repeat_n(b'0', 1024)); + +fn run_oracle(binary: &Path, fixture: &Path, timeout: Duration) -> Result { + let mut child = Command::new(binary) + .arg(fixture) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(|error| format!("could not start oracle: {error}"))?; + let deadline = Instant::now() + timeout; + let status = loop { + match child.try_wait().map_err(|error| format!("oracle wait failed: {error}"))? { + Some(status) => break status, + None if Instant::now() >= deadline => { + let _ = child.kill(); + let _ = child.wait(); + return Err(format!("oracle exceeded {}ms for {}", timeout.as_millis(), fixture.display())); } + None => thread::sleep(Duration::from_millis(5)), } - if mutated.len() > 2 * 1024 * 1024 { - return Err(format!( - "mutation budget exceeded at seed {seed}, iteration {step}" - )); - } - let digest = Sha256::digest(&mutated); - if hex_digest(&mutated) - != digest - .iter() - .map(|b| format!("{b:02x}")) - .collect::() - { - return Err(format!( - "digest instability at seed {seed}, iteration {step}" - )); + }; + let output = child + .wait_with_output() + .map_err(|error| format!("could not collect oracle output: {error}"))?; + if !status.success() && !output.stdout.is_empty() { + return Err(format!("oracle exited {status}: {}", String::from_utf8_lossy(&output.stderr))); + } + let document: OracleDocument = serde_json::from_slice(&output.stdout) + .map_err(|error| format!("invalid oracle JSON for {}: {error}; stderr: {}", fixture.display(), String::from_utf8_lossy(&output.stderr)))?; + validate_oracle_document(&document, fixture)?; + Ok(document) +} + +fn validate_oracle_document(document: &OracleDocument, fixture: &Path) -> Result<(), String> { + if document.schema_version != ORACLE_SCHEMA_VERSION { + return Err(format!("{} has schema {}", fixture.display(), document.schema_version)); + } + if document.fixture_path.is_empty() { + return Err(format!("{} has empty fixture_path", fixture.display())); + } + match document.status.as_str() { + "ok" if document.error.is_none() => {} + "error" if document.error.as_ref().is_some_and(|error| error.kind == "construct_null") => {} + status => return Err(format!("{} has invalid status/error shape: {status}", fixture.display())), + } + let mut previous = None; + for (index, model) in document.models.iter().enumerate() { + if previous == Some(model.name.as_str()) { + return Err(format!("{} contains duplicate model {}", fixture.display(), model.name)); } - let parsed = std::panic::catch_unwind(|| { - polymodel_ldraw_testkit::canonical( - fixture.id, - &mutated, - fixture.tags[0], - fixture.authority, - ) - }) - .map_err(|_| format!("parser panic at seed {seed}, iteration {step}"))?; - let repeated = polymodel_ldraw_testkit::canonical( - fixture.id, - &mutated, - fixture.tags[0], - fixture.authority, - ); - if parsed != repeated { - return Err(format!( - "parser nondeterminism at seed {seed}, iteration {step}" - )); + if model.model_index != index as u32 { + return Err(format!("{} has non-sequential model indices", fixture.display())); } - if step % 6 == 3 && !mutated.windows(2).any(|w| w == b"..") { - return Err(format!( - "path traversal mutation lost at seed {seed}, iteration {step}" - )); + previous = Some(model.name.as_str()); + if !matches!(model.certify.as_str(), "unknown" | "certified" | "uncertified") { + return Err(format!("{} has invalid certification {}", fixture.display(), model.certify)); } } Ok(()) } -fn driver_record(output: DriverOutput, fixture: &FixtureCase) -> Result { - if output.schema_version != SCHEMA_VERSION - || output.fixture != fixture.id - || output.revision != LD_PARSE_MASTER - { - return Err(format!( - "driver identity/schema mismatch for {}", - fixture.id - )); - } - if output.sha256 != fixture.sha256() { - return Err(format!("driver digest mismatch for {}", fixture.id)); + +fn projection(document: OracleDocument) -> OracleProjection { + OracleProjection { + status: document.status, + models: document.models, + diagnostics: document.diagnostics, + error: document.error, } - let text = String::from_utf8_lossy(fixture.bytes); - let bounds = geometry_bounds(&output.syntax); - Ok(CanonicalRecord { - schema_version: output.schema_version, - syntax: output.syntax, +} + +fn actual_record(fixture: &FixtureCase, document: OracleDocument) -> CanonicalRecord { + CanonicalRecord { + schema_version: SCHEMA_VERSION.to_owned(), + syntax: Vec::new(), semantic: polymodel_ldraw_testkit::SemanticRecord { - canonical_path: text - .lines() - .find_map(|line| line.strip_prefix("0 FILE ").map(|x| x.trim().to_owned())), + canonical_path: None, root_identity: None, target_identity: None, cache_identity: None, - bfc_state: output.bfc_state, - colour_state: "unobserved".into(), - steps: output.steps, + bfc_state: String::new(), + colour_state: String::new(), + steps: Vec::new(), limits: Vec::new(), + texmap_events: Vec::new(), }, scene: polymodel_ldraw_testkit::SceneRecord { - model_id: fixture.id.into(), + model_id: fixture.id.to_owned(), instance_ids: Vec::new(), - triangles: output.triangles, - lines: output.lines, - bounds, + triangles: 0, + lines: 0, + bounds: [String::new(), String::new(), String::new(), String::new(), String::new(), String::new()], reflection: false, }, - diagnostics: output.diagnostics, - provenance_id: fixture.expected.canonical.provenance_id.clone(), + diagnostics: Vec::::new(), + provenance_id: fixture.provenance.id.clone(), + oracle_projection: Some(projection(document)), + } +} + +fn differential() -> Result { + let fixtures = inventory(); + validate_inventory(&fixtures)?; + let root = root_dir(); + let binary = oracle_binary(&root)?; + for fixture in &fixtures { + let path = root.join("crates/polymodel-ldraw-testkit").join(fixture.relative_path); + let actual = actual_record(fixture, run_oracle(&binary, &path, ORACLE_TIMEOUT)?); + polymodel_ldraw_testkit::compare_oracle_projection(&fixture.expected.canonical, &actual, fixture.id) + .map_err(|error| format!("{} (source: {}; oracle revision: {}; schema: {})", error, fixture.provenance.id, LD_PARSE_REVISION, ORACLE_SCHEMA_VERSION))?; + } + serde_json::to_string_pretty(&Report { + schema_version: SCHEMA_VERSION, + command: "differential", + status: "pass", + fixtures: fixtures.len(), + bytes: fixtures.iter().map(|fixture| fixture.bytes.len()).sum(), + gates: GATE_NAMES.len(), + profiles: 3, + oracle_revision: LD_PARSE_REVISION, + oracle_schema: ORACLE_SCHEMA_VERSION, + seed: None, + mutations: 0, }) + .map_err(|error| error.to_string()) } -fn geometry_bounds(syntax: &[polymodel_ldraw_testkit::SyntaxRecord]) -> [String; 6] { - let mut bounds = [ - f64::INFINITY, - f64::INFINITY, - f64::INFINITY, - f64::NEG_INFINITY, - f64::NEG_INFINITY, - f64::NEG_INFINITY, - ]; - for record in syntax - .iter() - .filter(|record| (2..=5).contains(&record.line_type)) - { - for field in record.fields.iter().skip(2) { - if let Ok(value) = field.parse::() { - if value.is_finite() { - bounds[0] = bounds[0].min(value); - bounds[1] = bounds[1].min(value); - bounds[2] = bounds[2].min(value); - bounds[3] = bounds[3].max(value); - bounds[4] = bounds[4].max(value); - bounds[5] = bounds[5].max(value); + +fn mutate(seed: u64, index: usize, source: &[u8]) -> Vec { + let mut state = seed.wrapping_add(index as u64); + state = state.wrapping_mul(6364136223846793005).wrapping_add(1); + let mut output = source.to_vec(); + match (state % 4) as usize { + 0 => { + let position = (state.rotate_left(17) as usize) % (output.len() + 1); + output.splice(position..position, b"0 PM77 MUTATION\r\n".iter().copied()); + } + 1 if !output.is_empty() => { + let position = (state.rotate_left(9) as usize) % output.len(); + let length = 1 + ((state >> 24) as usize % (output.len() - position).max(1)); + output.drain(position..position + length.min(16)); + } + 2 if !output.is_empty() => { + let position = (state.rotate_left(31) as usize) % output.len(); + output[position] = (state >> 32) as u8; + } + _ => { + let mut changed = Vec::with_capacity(output.len() + 16); + for byte in output { + if byte == b'\n' { + changed.extend_from_slice(b"\r\n"); + } else { + changed.push(byte); } } + output = changed; } } - if bounds[0].is_finite() { - bounds.map(|value| { - if value == 0.0 { - "0".into() - } else { - value.to_string() - } - }) - } else { - [ - "0".into(), - "0".into(), - "0".into(), - "0".into(), - "0".into(), - "0".into(), - ] - } -} -fn compare_records( - expected: &CanonicalRecord, - actual: &CanonicalRecord, - fixture: &str, -) -> Result<(), String> { - let checks = [ - (expected.syntax == actual.syntax, "syntax"), - ( - expected.semantic.bfc_state == actual.semantic.bfc_state, - "bfc", - ), - (expected.semantic.steps == actual.semantic.steps, "steps"), - ( - expected.scene.triangles == actual.scene.triangles - && expected.scene.lines == actual.scene.lines - && expected.scene.bounds == actual.scene.bounds, - "geometry", - ), - (expected.diagnostics == actual.diagnostics, "diagnostics"), - ]; - let mismatches = checks - .iter() - .filter_map(|(matches, field)| (!matches).then_some(*field)) - .collect::>(); - if mismatches.is_empty() { - Ok(()) - } else { - Err(format!( - "LDParse mismatch for {fixture}: {}", - mismatches.join(", ") - )) - } + output } -fn differential_report() -> Result { + +fn fuzz() -> Result { let fixtures = inventory(); validate_inventory(&fixtures)?; - let adapter = LDParseAdapter { - revision: LD_PARSE_MASTER.into(), - python: PYTHON_VERSION.into(), - network: false, - }; - let mut exercised = 0; - let mut unsupported = Vec::new(); - for fixture in &fixtures { - match adapter.run(fixture, 10_000) { - Ok(bytes) => { - let output: DriverOutput = serde_json::from_slice(&bytes) - .map_err(|e| format!("malformed driver output for {}: {e}", fixture.id))?; - let actual = driver_record(output, fixture)?; - compare_records(&fixture.expected.canonical, &actual, fixture.id)?; - exercised += 1; + let binary = oracle_binary(&root_dir())?; + let temporary = env::temp_dir().join(format!("polymodel-pm77-fuzz-{}", std::process::id())); + fs::create_dir_all(&temporary).map_err(|error| error.to_string())?; + let started = Instant::now(); + let result = (|| { + for index in 0..FUZZ_ITERATIONS { + if started.elapsed() >= FUZZ_BUDGET { + return Err(format!("fuzz budget exceeded before mutation {index}")); + } + let fixture = &fixtures[index % fixtures.len()]; + let bytes = mutate(FUZZ_SEED, index, fixture.bytes); + if bytes.len() > MAX_MUTATED_BYTES { + return Err(format!("mutation {index} exceeded 1 MiB")); } - Err(HarnessError::UnsupportedSurface(_)) => unsupported.push(fixture.id), - Err(e) => return Err(e.to_string()), + let repeat = mutate(FUZZ_SEED, index, fixture.bytes); + if bytes != repeat { + return Err(format!("mutation {index} is not deterministic")); + } + let digest = Sha256::digest(&bytes); + let path = temporary.join(format!("{index}-{}.ldr", hex::encode(digest))); + fs::write(&path, &bytes).map_err(|error| error.to_string())?; + run_oracle(&binary, &path, ORACLE_TIMEOUT).map_err(|error| format!("mutation {index} ({}) failed: {error}", fixture.id))?; } - } - let value = serde_json::json!({"status":"pass","schema_version":SCHEMA_VERSION,"adapter":evidence(),"exercised":exercised,"unsupported_by_ldparse":unsupported,"required_surface":["types_0_to_5","raw_tails_spans","mpd_file_nofile","graph_identity","bfc_invertnext","steps","finite_numeric_diagnostics"],"ledger_rows":["LD-OUTSIDE-TEXMAP","LD-OUTSIDE-CONDITIONAL","LD-OUTSIDE-COLOUR-RESOLUTION"]}); - serde_json::to_string_pretty(&value).map_err(|e| e.to_string()) + Ok(()) + })(); + let _ = fs::remove_dir_all(&temporary); + result?; + serde_json::to_string_pretty(&Report { + schema_version: SCHEMA_VERSION, + command: "fuzz", + status: "pass", + fixtures: fixtures.len(), + bytes: fixtures.iter().map(|fixture| fixture.bytes.len()).sum(), + gates: GATE_NAMES.len(), + profiles: 3, + oracle_revision: LD_PARSE_REVISION, + oracle_schema: ORACLE_SCHEMA_VERSION, + seed: Some(FUZZ_SEED), + mutations: FUZZ_ITERATIONS, + }) + .map_err(|error| error.to_string()) } -fn evidence() -> AdapterEvidence { - AdapterEvidence { - kind: "out-of-process:ldparse-driver", - interpreter: PYTHON_VERSION, - master_revision: LD_PARSE_MASTER, - modernization_revision: LD_PARSE_MODERNIZATION, - network: false, - timeout_ms: 2_000, + +trait HexDigest { + fn hex(&self) -> String; +} +impl HexDigest for [u8; 32] { + fn hex(&self) -> String { + self.iter().map(|byte| format!("{byte:02x}")).collect() } } -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn pins_reject_drift() { - let bad = LDParseAdapter { - revision: "floating".into(), - python: PYTHON_VERSION.into(), - network: false, - }; - assert!(matches!( - bad.validate(), - Err(HarnessError::WrongRevision(_)) - )); - } - #[test] - fn interpreter_and_network_are_validated() { - let bad = LDParseAdapter { - revision: LD_PARSE_MASTER.into(), - python: "3.13".into(), - network: true, - }; - assert!(matches!( - bad.validate(), - Err(HarnessError::WrongInterpreter(_)) - )); - } - #[test] - fn timeout_is_killable_boundary() { - let adapter = LDParseAdapter { - revision: LD_PARSE_MASTER.into(), - python: PYTHON_VERSION.into(), - network: false, - }; - let case = inventory().remove(0); - assert!(matches!( - adapter.run(&case, 0), - Err(HarnessError::Timeout(0)) - )); - } - #[test] - fn differential_driver_output_is_machine_readable() { - let adapter = LDParseAdapter { - revision: LD_PARSE_MASTER.into(), - python: PYTHON_VERSION.into(), - network: false, - }; - let case = inventory().remove(0); - match adapter.run(&case, 10_000) { - Ok(bytes) => assert_eq!( - serde_json::from_slice::(&bytes).unwrap()["fixture"], - "syntax-types" - ), - Err(HarnessError::Exit { stderr, .. }) => assert!( - stderr.contains("wrong interpreter") || stderr.contains("No virtual environment") - ), - Err(HarnessError::Spawn(error)) => panic!("unexpected driver spawn failure: {error}"), - Err(error) => panic!("unexpected adapter failure: {error}"), - } +mod hex { + pub fn encode(bytes: impl AsRef<[u8]>) -> String { + bytes.as_ref().iter().map(|byte| format!("{byte:02x}")).collect() } } + diff --git a/tools/ldraw-compat-harness/uv.lock b/tools/ldraw-compat-harness/uv.lock deleted file mode 100644 index 1da08aa..0000000 --- a/tools/ldraw-compat-harness/uv.lock +++ /dev/null @@ -1,8 +0,0 @@ -version = 1 -revision = 3 -requires-python = "==3.12.8" - -[[package]] -name = "pm77-ldraw-compat-harness" -version = "0.1.0" -source = { virtual = "." } diff --git a/tools/ldraw-compat-harness/vendor/ldparse-master/REVISION b/tools/ldraw-compat-harness/vendor/ldparse-master/REVISION deleted file mode 100644 index 3f92450..0000000 --- a/tools/ldraw-compat-harness/vendor/ldparse-master/REVISION +++ /dev/null @@ -1,3 +0,0 @@ -877667417d6cab57c04aed9cb3d5bfe7efa0589c -source=https://github.com/taliesin/LDParse -artifact=source revision evidence; acquisition is offline and hash-verified before use diff --git a/tools/ldraw-compat-harness/vendor/ldparse-modernization/REVISION b/tools/ldraw-compat-harness/vendor/ldparse-modernization/REVISION deleted file mode 100644 index 84a22db..0000000 --- a/tools/ldraw-compat-harness/vendor/ldparse-modernization/REVISION +++ /dev/null @@ -1,3 +0,0 @@ -0fe78dcee22982f26cceced1b483340faa4d04e9 -source=https://github.com/taliesin/LDParse -artifact=source revision evidence; acquisition is offline and hash-verified before use diff --git a/tools/ldraw-oracle/oracle.cpp b/tools/ldraw-oracle/oracle.cpp new file mode 100644 index 0000000..1fa39f0 --- /dev/null +++ b/tools/ldraw-oracle/oracle.cpp @@ -0,0 +1,174 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +struct Diagnostic { + std::string message; + std::string token; + bool fatal; +}; + +thread_local std::vector* g_diagnostics = nullptr; + +std::string json_escape(const std::string& value) { + std::ostringstream out; + for (unsigned char ch : value) { + switch (ch) { + case '"': out << "\\\""; break; + case '\\': out << "\\\\"; break; + case '\b': out << "\\b"; break; + case '\f': out << "\\f"; break; + case '\n': out << "\\n"; break; + case '\r': out << "\\r"; break; + case '\t': out << "\\t"; break; + default: + if (ch < 0x20) { + out << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast(ch) << std::dec; + } else { + out << static_cast(ch); + } + } + } + return out.str(); +} + +std::string quote(const std::string& value) { return "\"" + json_escape(value) + "\""; } + +std::string certification(boost::logic::tribool value) { + if (boost::logic::indeterminate(value)) return "unknown"; + return value ? "certified" : "uncertified"; +} + +std::string diagnostics_json(const std::vector& diagnostics) { + std::ostringstream out; + out << '['; + for (size_t i = 0; i < diagnostics.size(); ++i) { + if (i) out << ','; + out << "{\"message\":" << quote(diagnostics[i].message) + << ",\"token\":" << quote(diagnostics[i].token) + << ",\"fatal\":" << (diagnostics[i].fatal ? "true" : "false") << '}'; + } + return out.str() + ']'; +} + +std::string model_json(const LDParse::Model& model, uint32_t index) { + std::vector> colors(model.localColors().begin(), model.localColors().end()); + std::sort(colors.begin(), colors.end(), [](const auto& left, const auto& right) { return left.first < right.first; }); + std::ostringstream out; + out << "{\"name\":" << quote(model.name()) << ",\"model_index\":" << index + << ",\"certify\":" << quote(certification(model.certify())) << ",\"local_colors\":["; + for (size_t i = 0; i < colors.size(); ++i) { + if (i) out << ','; + out << "{\"code\":" << colors[i].first << ",\"slot\":" << colors[i].second << '}'; + } + out << "],\"step_count\":" << model.stepEnds().size() << '}'; + return out.str(); +} + +// Forward declaration: success_json calls error_json for fail-closed behavior +std::string error_json(const std::string& path, const std::vector& diagnostics); + +std::string success_json(const std::string& path, const std::vector& names, const LDParse::Model& root, const std::vector& diagnostics) { + std::ostringstream out; + out << "{\"schema_version\":\"ldraw-oracle-v1\",\"fixture_path\":" << quote(path) + << ",\"status\":\"ok\",\"models\":["; + std::unordered_set seen; + uint32_t index = 0; + for (const auto& name : names) { + if (!seen.insert(name).second) { + std::cerr << "oracle error: duplicate boundary name '" << name << "'\n"; + return error_json(path, {{"duplicate_boundary_name", name, true}}); + } + if (index) out << ','; + if (name == root.name()) { + out << model_json(root, index++); + continue; + } + const auto cache = root.getSubFileCache(); + if (!cache) { + std::cerr << "oracle error: null subfile cache for '" << name << "'\n"; + return error_json(path, {{"missing_cache", name, true}}); + } + const auto found = cache->find(name); + if (!found) { + std::cerr << "oracle error: missing cache entry for '" << name << "'\n"; + return error_json(path, {{"missing_cache_entry", name, true}}); + } + out << model_json(found->get(), index++); + } + out << "],\"diagnostics\":" << diagnostics_json(diagnostics) << ",\"error\":null}"; + return out.str(); +} + +std::string error_json(const std::string& path, const std::vector& diagnostics) { + std::ostringstream out; + out << "{\"schema_version\":\"ldraw-oracle-v1\",\"fixture_path\":" << quote(path) + << ",\"status\":\"error\",\"models\":[],\"diagnostics\":" << diagnostics_json(diagnostics) + << ",\"error\":{\"kind\":\"construct_null\",\"message\":\"ModelBuilder::construct returned nullptr\",\"diagnostics\":" << diagnostics_json(diagnostics) << "}}"; + return out.str(); +} + +int run_one(const std::string& path) { + std::ifstream input(path, std::ios::binary); + if (!input) { + std::vector diagnostics{{"could not open fixture", path, true}}; + std::cout << error_json(path, diagnostics) << '\n'; + return 1; + } + std::ostringstream contents; + contents << input.rdbuf(); + const std::string bytes = contents.str(); + std::istringstream boundaries_stream(bytes); + std::vector diagnostics; + g_diagnostics = &diagnostics; + LDParse::ErrF boundary_error = +[](std::string message, std::string token, bool fatal) { + if (g_diagnostics) g_diagnostics->push_back({std::move(message), std::move(token), fatal}); + }; + LDParse::Lexer lexer(boundaries_stream, boundary_error); + LDParse::ModelStream models; + const auto slash = path.find_last_of("/\\\\"); + const auto basename = slash == std::string::npos ? path : path.substr(slash + 1); + const auto dot = basename.find_last_of('.'); + const auto stem = dot == std::string::npos ? basename : basename.substr(0, dot); + std::string root_name = "pm77-" + stem; + lexer.lexModelBoundaries(models, root_name); + std::vector names; + names.reserve(models.size()); + for (const auto& model : models) names.push_back(model.first); + + LDParse::ColorTable colors; + std::istringstream parse_stream(bytes); + LDParse::ModelBuilder builder(boundary_error); + LDParse::Model* root = builder.construct(path, root_name, parse_stream, colors); + if (!root) { + std::cout << error_json(path, diagnostics) << '\n'; + return 0; + } + std::cout << success_json(path, names, *root, diagnostics) << '\n'; + delete root; + return 0; +} +} + +int main(int argc, char** argv) { + if (argc < 2) { + std::cerr << "usage: ldraw-oracle FIXTURE...\n"; + return 2; + } + int status = 0; + for (int i = 1; i < argc; ++i) status |= run_one(argv[i]); + return status; +} -- knotmirror 0.0.1