UNPKG

@itwin/core-backend

Version:
196 lines • 10.2 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { assert, ByteStream, utf8ToString } from "@itwin/core-bentley"; import { CurrentImdlVersion, ElementGeometry, FeatureTableHeader, GeometryStreamIterator, GltfHeader, ImdlHeader, } from "@itwin/core-common"; import { _nativeDb, GeometricElement3d } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; import { LineSegment3d } from "@itwin/core-geometry"; describe("ElementGraphics", () => { let imodel; before(() => { imodel = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("ElementGraphics", "mirukuru.ibim"), IModelTestUtils.resolveAssetFile("mirukuru.ibim")); }); after(() => { if (imodel && imodel.isOpen) imodel.close(); }); it("obtains graphics for elements", async () => { const elementId = "0x29"; const element = imodel.elements.tryGetElement(elementId); expect(element).not.to.be.undefined; expect(element).instanceof(GeometricElement3d); const request = { id: "test", elementId, toleranceLog10: -2, formatVersion: CurrentImdlVersion.Major, }; const result = await imodel[_nativeDb].generateElementGraphics(request); expect(result.status).to.equal(0 /* ElementGraphicsStatus.Success */); assert(result.status === 0 /* ElementGraphicsStatus.Success */); const content = result.content; expect(content).not.to.be.undefined; expect(content instanceof Uint8Array).to.be.true; expect(content.length).least(40); }); it("obtains graphics for dynamics from json format geometry stream", async () => { const elementId = "0x29"; const element = imodel.elements.tryGetElement({ id: elementId, wantGeometry: true }); expect(element).not.to.be.undefined; expect(element).instanceof(GeometricElement3d); expect(element?.geom).not.to.be.undefined; expect(element?.placement).not.to.be.undefined; const request = { id: "test", elementId, toleranceLog10: -2, formatVersion: CurrentImdlVersion.Major, type: "3d", placement: element.placement, categoryId: element.category, geometry: { format: "json", data: element.geom }, }; const result = await imodel[_nativeDb].generateElementGraphics(request); expect(result.status).to.equal(0 /* ElementGraphicsStatus.Success */); assert(result.status === 0 /* ElementGraphicsStatus.Success */); const content = result.content; expect(content).not.to.be.undefined; expect(content instanceof Uint8Array).to.be.true; expect(content.length).least(40); }); it("obtains graphics for dynamics from flatbuffers format geometry stream", async () => { const elementId = "0x29"; const element = imodel.elements.tryGetElement({ id: elementId, wantGeometry: true }); expect(element).not.to.be.undefined; expect(element).instanceof(GeometricElement3d); expect(element?.geom).not.to.be.undefined; expect(element?.placement).not.to.be.undefined; const entries = []; const it = new GeometryStreamIterator(element.geom, element.category); for (const entry of it) { if ("geometryQuery" !== entry.primitive.type) continue; if (!ElementGeometry.appendGeometryParams(entry.geomParams, entries)) continue; const geomEntry = ElementGeometry.fromGeometryQuery(entry.primitive.geometry); expect(geomEntry).not.to.be.undefined; entries.push(geomEntry); } const request = { id: "test", elementId, toleranceLog10: -2, formatVersion: CurrentImdlVersion.Major, type: "3d", placement: element.placement, categoryId: element.category, geometry: { format: "flatbuffer", data: entries }, }; const result = await imodel[_nativeDb].generateElementGraphics(request); expect(result.status).to.equal(0 /* ElementGraphicsStatus.Success */); assert(result.status === 0 /* ElementGraphicsStatus.Success */); const content = result.content; expect(content).not.to.be.undefined; expect(content instanceof Uint8Array).to.be.true; expect(content.length).least(40); }); it("supports an unlimited number of flatbuffer geometry stream entries", async () => { async function getElementGraphics(numCopies) { const elementId = "0x29"; const element = imodel.elements.tryGetElement({ id: elementId, wantGeometry: true }); expect(element).not.to.be.undefined; expect(element).instanceof(GeometricElement3d); expect(element?.geom).not.to.be.undefined; expect(element?.placement).not.to.be.undefined; const entries = []; const it = new GeometryStreamIterator(element.geom, element.category); for (const entry of it) { if ("geometryQuery" !== entry.primitive.type) continue; for (let i = 0; i < numCopies; i++) { const segment = LineSegment3d.createXYXY(i, i, i + 1, i); const geomEntry = ElementGeometry.fromGeometryQuery(segment); expect(geomEntry).not.to.be.undefined; entries.push(geomEntry); } break; } const request = { id: "test", elementId, toleranceLog10: -2, formatVersion: CurrentImdlVersion.Major, type: "3d", placement: element.placement, categoryId: element.category, geometry: { format: "flatbuffer", data: entries }, }; const result = await imodel[_nativeDb].generateElementGraphics(request); expect(result.status).to.equal(0 /* ElementGraphicsStatus.Success */); assert(result.status === 0 /* ElementGraphicsStatus.Success */); const content = result.content; expect(content).not.to.be.undefined; expect(content instanceof Uint8Array).to.be.true; expect(content.length).least(40); return content; } let prevGraphics = []; let prevRangeDiagonalMagnitude = 0; for (const numCopies of [1, 2, 3, 10, 100, 1000, 2000, 2047, 2048, 2049, 2050, 2500, 2501, 2600, 3000, 10000]) { const tileBytes = await getElementGraphics(numCopies); const newGraphics = Array.from(tileBytes); expect(newGraphics).not.to.deep.equal(prevGraphics); // Extract metadata from the tile graphics. const stream = ByteStream.fromUint8Array(tileBytes); const header = new ImdlHeader(stream); const featureTableStartPos = stream.curPos; const featureTableHeader = FeatureTableHeader.readFrom(stream); expect(featureTableHeader).not.to.be.undefined; stream.curPos = featureTableStartPos + featureTableHeader.length; const gltfHeader = new GltfHeader(stream); expect(gltfHeader.isValid).to.be.true; stream.curPos = gltfHeader.scenePosition; const sceneStrData = stream.nextBytes(gltfHeader.sceneStrLength); const sceneStr = utf8ToString(sceneStrData); expect(sceneStr).not.to.be.undefined; const json = JSON.parse(sceneStr); // The tile should have two unique vertices per line segment in the input geometry stream. expect(json.meshes.Mesh_Root.primitives[0].vertices.count).to.equal(numCopies * 2); expect(header.contentRange.diagonal().magnitude()).greaterThan(prevRangeDiagonalMagnitude); prevRangeDiagonalMagnitude = header.contentRange.diagonal().magnitude(); expect(newGraphics.length).greaterThan(prevGraphics.length); prevGraphics = newGraphics; } }); it("produces expected errors", async () => { const testCases = [ [5 /* ElementGraphicsStatus.ElementNotFound */, { elementId: "0" }], [5 /* ElementGraphicsStatus.ElementNotFound */, { elementId: "0x12345678" }], [5 /* ElementGraphicsStatus.ElementNotFound */, { elementId: undefined }], [3 /* ElementGraphicsStatus.InvalidJson */, { id: undefined }], [3 /* ElementGraphicsStatus.InvalidJson */, { toleranceLog10: undefined }], [3 /* ElementGraphicsStatus.InvalidJson */, { toleranceLog10: 12.5 }], [3 /* ElementGraphicsStatus.InvalidJson */, { toleranceLog10: "tol" }], [0 /* ElementGraphicsStatus.Success */, { formatVersion: undefined }], [4 /* ElementGraphicsStatus.UnknownMajorFormatVersion */, { formatVersion: CurrentImdlVersion.Major + 1 }], [4 /* ElementGraphicsStatus.UnknownMajorFormatVersion */, { formatVersion: "latest" }], ]; for (const testCase of testCases) { const request = { id: "test", elementId: "0x29", toleranceLog10: -2, formatVersion: CurrentImdlVersion.Major, ...testCase[1], }; const result = await imodel[_nativeDb].generateElementGraphics(request); expect(result.status).to.equal(testCase[0]); if (result.status === 0 /* ElementGraphicsStatus.Success */) expect(result.content).not.to.be.undefined; } }); }); //# sourceMappingURL=ElementGraphics.test.js.map