UNPKG

@itwin/core-frontend

Version:
197 lines • 9 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Rendering */ Object.defineProperty(exports, "__esModule", { value: true }); exports.tesselatePolylineList = tesselatePolylineList; exports.tesselatePolyline = tesselatePolyline; exports.createPolylineParams = createPolylineParams; exports.wantJointTriangles = wantJointTriangles; const core_common_1 = require("@itwin/core-common"); const VertexIndices_1 = require("./VertexIndices"); const core_geometry_1 = require("@itwin/core-geometry"); const core_bentley_1 = require("@itwin/core-bentley"); const VertexTableBuilder_1 = require("./VertexTableBuilder"); function tesselatePolylineList(args) { const tesselator = PolylineTesselator.create(args); return tesselator.tesselate(); } class PolylineVertex { isSegmentStart = false; isPolylineStartOrEnd = false; vertexIndex = 0; prevIndex = 0; nextIndex = 0; constructor() { } init(isSegmentStart, isPolylineStartOrEnd, vertexIndex, prevIndex, nextIndex) { this.isSegmentStart = isSegmentStart; this.isPolylineStartOrEnd = isPolylineStartOrEnd; this.vertexIndex = vertexIndex; this.prevIndex = prevIndex; this.nextIndex = nextIndex; } computeParam(negatePerp, adjacentToJoint = false, joint = false, noDisplacement = false) { if (joint) return 12 /* PolylineParam.kJointBase */; let param; if (noDisplacement) param = 96 /* PolylineParam.kNoneAdjustWeight */; // prevent getting tossed before width adjustment else if (adjacentToJoint) param = 9 /* PolylineParam.kMiterInsideOnly */; else param = this.isPolylineStartOrEnd ? 3 /* PolylineParam.kSquare */ : 6 /* PolylineParam.kMiter */; let adjust = 0; if (negatePerp) adjust = 24 /* PolylineParam.kNegatePerp */; if (!this.isSegmentStart) adjust += 48 /* PolylineParam.kNegateAlong */; return param + adjust; } } class PolylineTesselator { _polylines; _doJoints; _numIndices = 0; _vertIndex = []; _prevIndex = []; _nextIndex = []; _nextParam = []; _position = []; constructor(polylines, points, doJointTriangles) { this._polylines = polylines; if (points instanceof core_common_1.QPoint3dList) { for (const p of points.list) this._position.push(p.unquantize(points.params)); } else { this._position = points; } this._doJoints = doJointTriangles; } static fromPolyline(args) { return new PolylineTesselator(args.polylines, args.points, wantJointTriangles(args.width, !!args.flags.is2d)); } static create(args) { return new PolylineTesselator(args.polylines.map((x) => x.indices), args.points, wantJointTriangles(args.width, args.is2d)); } tesselate() { this._tesselate(); const vertIndex = VertexIndices_1.VertexIndices.fromArray(this._vertIndex); const prevIndex = VertexIndices_1.VertexIndices.fromArray(this._prevIndex); const nextIndexAndParam = new Uint8Array(this._numIndices * 4); for (let i = 0; i < this._numIndices; i++) { const index = this._nextIndex[i]; const j = i * 4; VertexIndices_1.VertexIndices.encodeIndex(index, nextIndexAndParam, j); nextIndexAndParam[j + 3] = this._nextParam[i] & 0x000000ff; } return { indices: vertIndex, prevIndices: prevIndex, nextIndicesAndParams: nextIndexAndParam, }; } _tesselate() { const v0 = new PolylineVertex(), v1 = new PolylineVertex(); const maxJointDot = -0.7; for (const line of this._polylines) { if (line.length < 2) continue; const last = line.length - 1; const isClosed = line[0] === line[last]; for (let i = 0; i < last; ++i) { const idx0 = line[i]; const idx1 = line[i + 1]; const isStart = (0 === i); const isEnd = (last - 1 === i); const prevIdx0 = isStart ? (isClosed ? line[last - 1] : idx0) : line[i - 1]; const nextIdx1 = isEnd ? (isClosed ? line[1] : idx1) : line[i + 2]; v0.init(true, isStart && !isClosed, idx0, prevIdx0, idx1); v1.init(false, isEnd && !isClosed, idx1, nextIdx1, idx0); const jointAt0 = this._doJoints && (isClosed || !isStart) && this._dotProduct(v0) > maxJointDot; const jointAt1 = this._doJoints && (isClosed || !isEnd) && this._dotProduct(v1) > maxJointDot; if (jointAt0 || jointAt1) { this._addVertex(v0, v0.computeParam(true, jointAt0, false, false)); this._addVertex(v1, v1.computeParam(false, jointAt1, false, false)); this._addVertex(v0, v0.computeParam(false, jointAt0, false, true)); this._addVertex(v0, v0.computeParam(false, jointAt0, false, true)); this._addVertex(v1, v1.computeParam(false, jointAt1, false, false)); this._addVertex(v1, v1.computeParam(false, jointAt1, false, true)); this._addVertex(v0, v0.computeParam(false, jointAt0, false, true)); this._addVertex(v1, v1.computeParam(false, jointAt1, false, true)); this._addVertex(v0, v0.computeParam(false, jointAt0, false, false)); this._addVertex(v0, v0.computeParam(false, jointAt0, false, false)); this._addVertex(v1, v1.computeParam(false, jointAt1, false, true)); this._addVertex(v1, v1.computeParam(true, jointAt1, false, false)); if (jointAt0) this.addJointTriangles(v0, v0.computeParam(false, true, false, true), v0); if (jointAt1) this.addJointTriangles(v1, v1.computeParam(false, true, false, true), v1); } else { this._addVertex(v0, v0.computeParam(true)); this._addVertex(v1, v1.computeParam(false)); this._addVertex(v0, v0.computeParam(false)); this._addVertex(v0, v0.computeParam(false)); this._addVertex(v1, v1.computeParam(false)); this._addVertex(v1, v1.computeParam(true)); } } } } addJointTriangles(v0, p0, v1) { const param = v1.computeParam(false, false, true); for (let i = 0; i < 3; i++) { this._addVertex(v0, p0); this._addVertex(v1, param + i + 1); this._addVertex(v1, param + i); } } _dotProduct(v) { const pos = this._position[v.vertexIndex]; const prevDir = core_geometry_1.Vector3d.createStartEnd(this._position[v.prevIndex], pos); const nextDir = core_geometry_1.Vector3d.createStartEnd(this._position[v.nextIndex], pos); return prevDir.dotProduct(nextDir); } _addVertex(vertex, param) { this._vertIndex[this._numIndices] = vertex.vertexIndex; this._prevIndex[this._numIndices] = vertex.prevIndex; this._nextIndex[this._numIndices] = vertex.nextIndex; this._nextParam[this._numIndices] = param; this._numIndices++; } } /** Strictly for tests. @internal */ function tesselatePolyline(polylines, points, doJointTriangles) { const tesselator = new PolylineTesselator(polylines, points, doJointTriangles); return tesselator.tesselate(); } /** @internal */ function createPolylineParams(args, maxDimension) { (0, core_bentley_1.assert)(!args.flags.isDisjoint); const vertices = VertexTableBuilder_1.VertexTableBuilder.buildFromPolylines(args, maxDimension); if (undefined === vertices) return undefined; const tesselator = PolylineTesselator.fromPolyline(args); if (undefined === tesselator) return undefined; return { vertices, polyline: tesselator.tesselate(), isPlanar: !!args.flags.isPlanar, type: args.flags.type ?? core_common_1.PolylineTypeFlags.Normal, weight: args.width, linePixels: args.linePixels, }; } /** @internal */ function wantJointTriangles(weight, is2d) { // Joints are incredibly expensive. In 3d, only generate them if the line is sufficiently wide for them to be noticeable. const jointWidthThreshold = 3; return is2d || weight >= jointWidthThreshold; } //# sourceMappingURL=PolylineParams.js.map