/
ElementMesh.ts
96 lines (84 loc) · 3.35 KB
/
ElementMesh.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Geometry
*/
import { ByteStream, Id64String } from "@itwin/core-bentley";
import { BentleyGeometryFlatBuffer, IndexedPolyface } from "@itwin/core-geometry";
/** Options used to control how [Polyface]($core-geometry)s are produced from elements by [IModelConnection.generateElementMeshes]($frontend).
* @beta
*/
export interface ElementMeshOptions {
/** Maximum distance from a face to the original geometry.
* If not supplied, defaults to zero and [[angleTolerance]] will control the quality of the resulting mesh instead.
* @see [StrokeOptions.chordTol]($core-geometry).
*/
chordTolerance?: number;
/** Maximum angle difference in radians for an approximated face.
* If not supplied, defaults to PI/12 (15 degrees).
* @see [StrokeOptions.angleTol]($core-geometry).
*/
angleTolerance?: number;
/** BRep features with bounding boxes smaller than this size will not generate graphics.
* This option can be used to ignore expensive details from [BRepEntity.DataProps]($core-common)
* like screws and screw holes.
*/
minBRepFeatureSize?: number;
// ###TODO? decimationTolerance?: number;
}
/** Describes a request to generate [Polyface]($core-geometry)s from an element.
* @see [IModelConnection.generateElementMeshes]($frontend).
* @beta
*/
export interface ElementMeshRequestProps extends ElementMeshOptions {
/** The Id of the [GeometricElement]($backend) from which to obtain meshes. */
source: Id64String;
}
interface Chunk {
type: string;
data?: Uint8Array;
}
function nextChunk(stream: ByteStream): Chunk | undefined {
if (stream.remainingLength < 8) {
// Consume remaining bytes.
stream.curPos = stream.length;
return undefined;
}
// Type codes are a sequence of four uppercase ASCII letters.
const chars = [stream.readUint8(), stream.readUint8(), stream.readUint8(), stream.readUint8()];
if (chars.some((c) => c < 65 || c > 90))
return undefined;
const dataLength = stream.readUint32();
const data = dataLength > 0 ? stream.nextBytes(dataLength) : undefined;
return {
type: String.fromCharCode(...chars),
data,
};
}
/** Convert the output of [IModelConnection.generateElementMeshes]($frontend) into an array of [Polyface]($core-geometry)s.
* @param data Encoded polyfaces obtained from [IModelConnection.generateElementMeshes]($frontend).
* @returns a list of decoded polyfaces.
* @beta
*/
export function readElementMeshes(data: Uint8Array): IndexedPolyface[] {
const polyfaces: IndexedPolyface[] = [];
const stream = ByteStream.fromUint8Array(data);
const firstChunk = nextChunk(stream);
if (!firstChunk || "LMSH" !== firstChunk.type)
return polyfaces;
while (stream.remainingLength > 0) {
const chunk = nextChunk(stream);
if (!chunk || chunk.type !== "PLFC" || !chunk.data)
continue;
try {
const geom = BentleyGeometryFlatBuffer.bytesToGeometry(chunk.data, true);
if (geom instanceof IndexedPolyface)
polyfaces.push(geom);
} catch (_) {
//
}
}
return polyfaces;
}