UNPKG

@itwin/core-frontend

Version:
192 lines • 8.84 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. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.ViewCreator3d = void 0; /** @packageDocumentation * @module Views */ const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const core_geometry_1 = require("@itwin/core-geometry"); const SpatialViewState_1 = require("./SpatialViewState"); /** * API for creating a 3D default [[ViewState3d]] for an iModel. @see [[ViewCreator2d]] to create a view for a 2d model. * Example usage: * ```ts * const viewCreator = new ViewCreator3d(imodel); * const defaultView = await viewCreator.createDefaultView({skyboxOn: true}); * ``` * @public * @extensions */ class ViewCreator3d { _imodel; /** * Constructs a ViewCreator3d using an [[IModelConnection]]. * @param _imodel [[IModelConnection]] to query for categories and/or models. */ constructor(_imodel) { this._imodel = _imodel; } /** * Creates a default [[ViewState3d]] based on the model ids passed in. If no model ids are passed in, all 3D models in the iModel are used. * @param [options] Options for creating the view. * @param [modelIds] Ids of models to display in the view. * @throws [IModelError]($common) If no 3d models are found in the iModel. */ async createDefaultView(options, modelIds) { const rpcOptions = modelIds ? { modelIds: core_bentley_1.CompressedId64Set.sortAndCompress(modelIds) } : {}; const rpc = core_common_1.IModelReadRpcInterface.getClientForRouting(this._imodel.routingContext.token); const serializedProps = await rpc.getCustomViewState3dData(this._imodel.getRpcProps(), rpcOptions); const baseExtents = core_geometry_1.Range3d.fromJSON(serializedProps.modelExtents); const props = await this._createViewStateProps(core_bentley_1.CompressedId64Set.decompressArray(serializedProps.modelIds), core_bentley_1.CompressedId64Set.decompressArray(serializedProps.categoryIds), baseExtents, options); const viewState = SpatialViewState_1.SpatialViewState.createFromProps(props, this._imodel); try { await viewState.iModel.subcategories.loadAllUsedSpatialSubCategories(); await viewState.load(); } catch { } if (options?.standardViewId) viewState.setStandardRotation(options.standardViewId); if (options?.allSubCategoriesVisible) viewState.displayStyle.enableAllLoadedSubCategories(viewState.categorySelector.categories); const range = viewState.computeFitRange({ baseExtents }); viewState.lookAtVolume(range, options?.vpAspect); return viewState; } /** * Generates a view state props object for creating a view. Merges display styles with a seed view if the options.useSeedView is true * @param models Models to put in view props * @param options view creation options like camera On and skybox On */ async _createViewStateProps(models, categories, modelExtents, options) { // Use dictionary model in all props const dictionaryId = core_common_1.IModel.dictionaryId; if (modelExtents.isNull) modelExtents.setFrom(this._imodel.projectExtents); let originX = modelExtents.low.x; let originY = modelExtents.low.y; const originZ = modelExtents.low.z; let deltaX = modelExtents.xLength(); let deltaY = modelExtents.yLength(); const deltaZ = modelExtents.zLength(); // if vp aspect given, update model extents to fit view if (options?.vpAspect) { const modelAspect = deltaY / deltaX; if (modelAspect > options.vpAspect) { const xFix = deltaY / options.vpAspect; originX = originX - xFix / 2; deltaX = deltaX + xFix; } else if (modelAspect < options.vpAspect) { const yFix = deltaX * options.vpAspect; originY = originY - yFix / 2; deltaY = deltaY + yFix; } } const categorySelectorProps = { categories, code: core_common_1.Code.createEmpty(), model: dictionaryId, classFullName: "BisCore:CategorySelector", }; const modelSelectorProps = { models, code: core_common_1.Code.createEmpty(), model: dictionaryId, classFullName: "BisCore:ModelSelector", }; const cameraData = new core_common_1.Camera(); const cameraOn = options?.cameraOn !== false; const viewDefinitionProps = { categorySelectorId: "", displayStyleId: "", code: core_common_1.Code.createEmpty(), model: dictionaryId, origin: { x: originX, y: originY, z: originZ }, extents: { x: deltaX, y: deltaY, z: deltaZ }, classFullName: "BisCore:SpatialViewDefinition", cameraOn, camera: { lens: cameraData.lens.toJSON(), focusDist: cameraData.focusDist, eye: cameraData.eye.toJSON(), }, }; const displayStyleProps = { code: core_common_1.Code.createEmpty(), model: dictionaryId, classFullName: "BisCore:DisplayStyle3d", jsonProperties: { styles: { viewflags: { renderMode: core_common_1.RenderMode.SmoothShade, noSourceLights: false, noCameraLights: false, noSolarLight: false, noConstruct: true, noTransp: false, visEdges: false, backgroundMap: this._imodel.isGeoLocated, }, environment: options !== undefined && options.skyboxOn !== undefined && options.skyboxOn ? core_common_1.Environment.defaults.withDisplay({ sky: true }).toJSON() : undefined, }, }, }; const viewStateProps = { displayStyleProps, categorySelectorProps, modelSelectorProps, viewDefinitionProps, }; // merge seed view props if needed return options?.useSeedView ? this._mergeSeedView(viewStateProps) : viewStateProps; } /** * Merges a seed view in the iModel with the passed view state props. It will be a no-op if there are no default 3D views in the iModel * @param viewStateProps Input view props to be merged */ async _mergeSeedView(viewStateProps) { const viewId = await this._getDefaultViewId(); // Handle iModels without any default view id if (viewId === undefined) return viewStateProps; const seedViewState = await this._imodel.views.load(viewId); const seedViewStateProps = { categorySelectorProps: seedViewState.categorySelector.toJSON(), modelSelectorProps: seedViewState.modelSelector.toJSON(), viewDefinitionProps: seedViewState.toJSON(), displayStyleProps: seedViewState.displayStyle.toJSON(), }; const mergedDisplayProps = seedViewStateProps.displayStyleProps; if (mergedDisplayProps.jsonProperties !== undefined) { mergedDisplayProps.jsonProperties.styles = { ...mergedDisplayProps.jsonProperties.styles, ...viewStateProps.displayStyleProps.jsonProperties.styles, }; } return { ...seedViewStateProps, ...viewStateProps, displayStyleProps: mergedDisplayProps }; } /** * Get the Id of the default view. */ async _getDefaultViewId() { // eslint-disable-next-line @typescript-eslint/no-deprecated const viewId = await this._imodel.views.queryDefaultViewId(); if (viewId !== core_bentley_1.Id64.invalid) return viewId; // Return the first spatial view const viewList = await this._imodel.views.getViewList({ wantPrivate: false, limit: 1, from: SpatialViewState_1.SpatialViewState.classFullName }); return viewList.length === 0 ? undefined : viewList[0].id; } } exports.ViewCreator3d = ViewCreator3d; //# sourceMappingURL=ViewCreator3d.js.map