mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
ifcviewer: rename sidecar transfer/record types; drop unused element hierarchy (sidecar v17)
Rename the streamer/sidecar transfer and record types to describe what they are rather than how they move: MeshChunk -> StreamedMesh InstanceChunk -> StreamedInstance InstanceCpu -> InstanceInfo PackedElementInfo -> ElementTableRecord uploadMeshChunk -> uploadStreamedMesh uploadInstanceChunk -> uploadStreamedInstance buildMeshChunk -> buildStreamedMesh and the two post-index sidecar metadata blocks: "critical" metadata -> "geometry" metadata (meshes/instances/georef/TOC) "deferred" metadata -> "element" metadata (elements + string table) parseSidecarCritical -> parseSidecarGeometryMetadata parseSidecarDeferred -> parseSidecarElementMetadata The one behavioural change: the element hierarchy (parent_id) was carried through ElementInfo, ElementTableRecord, and the sidecar element table but never consumed, so drop it and bump SIDECAR_VERSION 16 -> 17. No back-compat: regenerate sidecars. sample.ifcview is regenerated at v17. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -84,7 +84,6 @@ SidecarData buildFixture() {
|
||||
sd.elements[i].object_id = uint32_t(100 + i);
|
||||
sd.elements[i].model_id = 1;
|
||||
sd.elements[i].ifc_id = int32_t(1000 + i);
|
||||
sd.elements[i].parent_id = (i == 0) ? -1 : int32_t(100);
|
||||
}
|
||||
// v16 stores geometry per-chunk (compressed); a fixture with geometry needs
|
||||
// a chunk TOC covering its meshes (one chunk per mesh here).
|
||||
@@ -113,8 +112,8 @@ TEST_CASE("readSidecarMetadataOnly returns metadata, skips bulk geometry",
|
||||
// Chunk TOC carries compressed blob locators for each chunk.
|
||||
REQUIRE(meta->meta.chunks.size() == sd.chunks.size());
|
||||
REQUIRE(meta->meta.chunks[0].v_comp_size > 0);
|
||||
// The deferred (property) block locator is recorded for on-demand fetch.
|
||||
REQUIRE(meta->deferred_comp_size > 0);
|
||||
// The element metadata block locator is recorded for on-demand fetch.
|
||||
REQUIRE(meta->element_metadata_comp_size > 0);
|
||||
|
||||
// Metadata round-trips.
|
||||
REQUIRE(meta->meta.meshes.size() == sd.meshes.size());
|
||||
@@ -197,37 +196,37 @@ TEST_CASE("parseSidecarHead validates magic / version, reads geom length", "[str
|
||||
REQUIRE_FALSE(parseSidecarHead(bad, sizeof(bad), got));
|
||||
}
|
||||
|
||||
TEST_CASE("v16 deferred block: fetch via locator, decompress, parse", "[streaming]") {
|
||||
fs::path dir = makeScratchDir("v16def");
|
||||
TEST_CASE("v16 element metadata block: fetch via locator, decompress, parse", "[streaming]") {
|
||||
fs::path dir = makeScratchDir("v16element");
|
||||
fs::path ifc = dir / "model.ifc";
|
||||
SidecarData sd = buildFixture();
|
||||
REQUIRE(writeSidecar(ifc.string(), sd));
|
||||
|
||||
auto meta = readSidecarMetadataOnly(ifc.string());
|
||||
REQUIRE(meta.has_value());
|
||||
REQUIRE(meta->meta.meshes.size() == sd.meshes.size()); // critical
|
||||
REQUIRE(meta->meta.meshes.size() == sd.meshes.size()); // geometry metadata
|
||||
REQUIRE(meta->meta.chunks.size() == sd.chunks.size());
|
||||
REQUIRE(meta->meta.elements.size() == sd.elements.size()); // desktop reads deferred too
|
||||
REQUIRE(meta->deferred_comp_size > 0);
|
||||
REQUIRE(meta->meta.elements.size() == sd.elements.size()); // desktop reads element metadata too
|
||||
REQUIRE(meta->element_metadata_comp_size > 0);
|
||||
|
||||
// The on-demand path (web) fetches the compressed deferred frame via the
|
||||
// The on-demand path (web) fetches the compressed element metadata frame via the
|
||||
// recorded locator and decompresses it — verify that round-trips.
|
||||
FILE* f = std::fopen((dir / "model.ifcview").string().c_str(), "rb");
|
||||
REQUIRE(f);
|
||||
std::vector<uint8_t> cz(size_t(meta->deferred_comp_size));
|
||||
std::fseek(f, long(meta->deferred_comp_offset), SEEK_SET);
|
||||
std::vector<uint8_t> cz(size_t(meta->element_metadata_comp_size));
|
||||
std::fseek(f, long(meta->element_metadata_comp_offset), SEEK_SET);
|
||||
REQUIRE(std::fread(cz.data(), 1, cz.size(), f) == cz.size());
|
||||
std::fclose(f);
|
||||
|
||||
std::vector<uint8_t> raw(size_t(meta->deferred_raw_size));
|
||||
std::vector<uint8_t> raw(size_t(meta->element_metadata_raw_size));
|
||||
REQUIRE(SidecarCompress::decompress(cz.data(), cz.size(), raw.data(), raw.size()));
|
||||
SidecarData d;
|
||||
REQUIRE(parseSidecarDeferred(raw.data(), raw.size(), d));
|
||||
REQUIRE(parseSidecarElementMetadata(raw.data(), raw.size(), d));
|
||||
REQUIRE(d.elements.size() == sd.elements.size());
|
||||
REQUIRE(d.string_table == sd.string_table);
|
||||
|
||||
SidecarData chopped;
|
||||
REQUIRE_FALSE(parseSidecarDeferred(raw.data(), raw.size() - 1, chopped));
|
||||
REQUIRE_FALSE(parseSidecarElementMetadata(raw.data(), raw.size() - 1, chopped));
|
||||
}
|
||||
|
||||
TEST_CASE("planSidecarReadRanges coalesces adjacent ranges, keeps far ones split",
|
||||
|
||||
Reference in New Issue
Block a user