-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
translate saved view into view state and display; currently depends o…
…n saved views utilities package
- Loading branch information
1 parent
de41663
commit 4a034f9
Showing
9 changed files
with
1,589 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
240 changes: 240 additions & 0 deletions
240
packages/saved-views-react/src/api/utilities/translation/SavedViewTranslation.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
import { IModelReadRpcInterface, ViewQueryParams, ViewStateProps } from "@itwin/core-common"; | ||
import { DrawingViewState, IModelConnection, SheetViewState, SpatialViewState, ViewState } from "@itwin/core-frontend"; | ||
import { Extension, SavedViewWithDataRepresentation, ViewData, ViewDataITwinDrawing, ViewDataITwinSheet, ViewDataItwin3d } from "@itwin/saved-views-client"; | ||
import { cleanLegacyViewModelSelectorPropsModels, savedViewITwin3dToLegacy3dSavedView, savedViewItwinDrawingToLegacyDrawingView, savedViewItwinSheetToLegacySheetSavedView } from "./viewExtractorSavedViewToLegacySavedView.js"; | ||
import { ViewTypes } from "../../../SavedViewTypes.js"; | ||
import { SavedView as LegacySavedView, SavedView2d as LegacySavedView2d, SavedViewBase as LegacySavedViewBase } from "../SavedViewTypes.js"; | ||
import { isDrawingSavedView, isSheetSavedView, isSpatialSavedView } from "../../clients/ISavedViewsClient.js"; | ||
|
||
export async function translateSavedViewIntoITwinJsViewState(savedView: SavedViewWithDataRepresentation, iModelConnection: IModelConnection): Promise<ViewState | undefined> { | ||
|
||
// Doesn't have to be done this way, but for now... | ||
// Converts views into legacy views, then converts the legacy view into an iTwin.js-style ViewState | ||
|
||
// Translate into legacy view | ||
const legacySavedView: LegacySavedView | LegacySavedView2d = await translateSavedViewToLegacySavedView(savedView, iModelConnection); | ||
|
||
// Translate into iTwin.js-style ViewState | ||
const viewState = await translateLegacySavedViewToITwinJsViewState(legacySavedView, iModelConnection); | ||
|
||
return viewState; | ||
} | ||
|
||
declare const isSavedViewItwin3d: (savedViewData: ViewData) => savedViewData is ViewDataItwin3d; | ||
declare const isSavedViewItwinSheet: (savedViewData: ViewData) => savedViewData is ViewDataITwinSheet; | ||
declare const isSavedViewItwinDrawing: (savedViewData: ViewData) => savedViewData is ViewDataITwinDrawing; | ||
|
||
/** | ||
* Convert the saved view response recieved from the itwin-saved-views API into a SavedViewBaseSetting | ||
* @param id | ||
* @param savedView | ||
* @returns Promise<SavedViewBase> | ||
*/ | ||
async function translateSavedViewToLegacySavedView( | ||
savedView: SavedViewWithDataRepresentation, | ||
iModelConnection: IModelConnection, | ||
): Promise<LegacySavedView | LegacySavedView2d> { | ||
const savedViewData = savedView.savedViewData; | ||
// If the legacy view already exists, use that; otherwise, use extraction code to get the legacy view | ||
let legacySavedView: LegacySavedView | LegacySavedView2d; | ||
if (savedViewData.legacyView) { | ||
savedView = cleanLegacyViewModelSelectorPropsModels(savedView); | ||
legacySavedView = savedViewData.legacyView as any; | ||
// legacySavedView.id = savedView.id; // Change legacy sv id to comboId | ||
|
||
} else if (isSavedViewItwin3d(savedViewData)) { | ||
const iModelViewData = await fetchIModelViewData( | ||
ViewTypes.ViewDefinition3d, | ||
iModelConnection, | ||
); | ||
|
||
const actual = savedViewITwin3dToLegacy3dSavedView( | ||
savedView, | ||
iModelViewData as SpatialViewState | ||
); | ||
legacySavedView = actual; | ||
} else if (isSavedViewItwinDrawing(savedViewData)) { | ||
const iModelViewData = await fetchIModelViewData( | ||
ViewTypes.DrawingViewDefinition, | ||
iModelConnection, | ||
); | ||
const actual = savedViewItwinDrawingToLegacyDrawingView( | ||
savedView, | ||
iModelViewData as DrawingViewState | ||
); | ||
legacySavedView = actual; | ||
} else if (isSavedViewItwinSheet(savedViewData)) { | ||
const iModelViewData = await fetchIModelViewData( | ||
ViewTypes.SheetViewDefinition, | ||
iModelConnection, | ||
); | ||
const actual = savedViewItwinSheetToLegacySheetSavedView( | ||
savedView, | ||
iModelViewData as SheetViewState | ||
); | ||
legacySavedView = actual; | ||
} else { | ||
throw new Error( | ||
"Could not translate itwin-saved-views API response to a SavedViewBaseSetting" | ||
); | ||
} | ||
|
||
// Append all extensions to the saved view | ||
legacySavedView.extensions = new Map<string, string>(); | ||
for (const ext of savedView.extensions as Extension[]) { | ||
if (ext.extensionName && ext.data) { | ||
legacySavedView.extensions.set(ext.extensionName, ext.data); | ||
} | ||
} | ||
|
||
return legacySavedView; | ||
} | ||
|
||
|
||
/** | ||
* Grabs Seeded SavedView From IModel | ||
* @throws if iModel Connection of App is invalid | ||
* @returns iModelViewData | ||
*/ | ||
async function fetchIModelViewData(viewClassName: ViewTypes, iModelConnection: IModelConnection) { | ||
// let seedViewState = this._seedViewStates.get(viewClassName); | ||
// if (seedViewState) { | ||
// return seedViewState; | ||
// } | ||
// const iModelConnection = UiFramework.getIModelConnection(); | ||
// if (!iModelConnection) { | ||
// throw new Error("IModel Connection is invalid "); | ||
// } | ||
const viewId = await getDefaultViewIdFromClassName( | ||
iModelConnection, | ||
viewClassName | ||
); | ||
let seedViewState = await iModelConnection.views.load(viewId); | ||
// this._seedViewStates.set(viewClassName, seedViewState); | ||
return seedViewState; | ||
} | ||
|
||
// code is not D.R.Y but this decision was made to uphold existing contracts | ||
// method shared some implementation with getDefaultViewId | ||
async function getDefaultViewIdFromClassName( | ||
iModelConnection: IModelConnection, | ||
savedViewType: ViewTypes | ||
) { | ||
let viewFullName = undefined; | ||
switch (savedViewType) { | ||
case ViewTypes.ViewDefinition3d: | ||
viewFullName = SpatialViewState.classFullName; | ||
break; | ||
case ViewTypes.DrawingViewDefinition: | ||
viewFullName = DrawingViewState.classFullName; | ||
break; | ||
case ViewTypes.SheetViewDefinition: | ||
viewFullName = SheetViewState.classFullName; | ||
break; | ||
default: | ||
throw new Error("Unrecognized View Type"); | ||
} | ||
// eslint-disable-next-line deprecation/deprecation | ||
const viewId = await iModelConnection.views.queryDefaultViewId(); | ||
const params: ViewQueryParams = {}; | ||
params.from = viewFullName; | ||
params.where = "ECInstanceId=" + viewId; | ||
|
||
// Check validity of default view | ||
const viewProps = | ||
await IModelReadRpcInterface.getClient().queryElementProps( | ||
iModelConnection.getRpcProps(), | ||
params | ||
); | ||
if (viewProps.length === 0) { | ||
// Return the first view we can find | ||
const viewList = await iModelConnection.views.getViewList({ | ||
from: viewFullName, | ||
wantPrivate: false, | ||
}); | ||
if (viewList.length === 0) { | ||
return ""; | ||
} | ||
return viewList[0].id; | ||
} | ||
|
||
return viewId; | ||
} | ||
|
||
/** | ||
* Creates a ViewState from a SavedView object returned by the SavedViewsClient | ||
* @param iModelConnection IModelConnection to use for requesting source view states | ||
* @param savedView SavedView object obtained from SavedViewsClient | ||
*/ | ||
async function createViewState( | ||
iModelConnection: IModelConnection, | ||
savedView: LegacySavedViewBase, | ||
): Promise<ViewState | undefined> { | ||
if (isSpatialSavedView(savedView)) { | ||
return _createSpatialViewState(iModelConnection, savedView as LegacySavedView); | ||
} else if (isDrawingSavedView(savedView)) { | ||
return _createDrawingViewState(iModelConnection, savedView as LegacySavedView2d); | ||
} else if (isSheetSavedView(savedView)) { | ||
return _createSheetViewState(iModelConnection, savedView as LegacySavedView2d); | ||
} | ||
return undefined; | ||
} | ||
|
||
/** Creates a spatial view state from the saved view object props */ | ||
async function _createSpatialViewState( | ||
iModelConnection: IModelConnection, | ||
savedView: LegacySavedView, | ||
): Promise<SpatialViewState | undefined> { | ||
const props: ViewStateProps = { | ||
viewDefinitionProps: savedView.viewDefinitionProps, | ||
categorySelectorProps: savedView.categorySelectorProps, | ||
modelSelectorProps: savedView.modelSelectorProps, | ||
displayStyleProps: savedView.displayStyleProps, | ||
}; | ||
const viewState = SpatialViewState.createFromProps(props, iModelConnection); | ||
await viewState.load(); | ||
return viewState; | ||
} | ||
|
||
/** Creates a drawing view state from the data object */ | ||
async function _createDrawingViewState( | ||
iModelConnection: IModelConnection, | ||
savedView: LegacySavedView2d, | ||
): Promise<DrawingViewState | undefined> { | ||
const props: ViewStateProps = { | ||
viewDefinitionProps: savedView.viewDefinitionProps, | ||
categorySelectorProps: savedView.categorySelectorProps, | ||
displayStyleProps: savedView.displayStyleProps, | ||
}; | ||
const viewState = DrawingViewState.createFromProps(props, iModelConnection) as DrawingViewState; | ||
await viewState.load(); | ||
return viewState; | ||
} | ||
|
||
/** Creates a sheet view state from the data object */ | ||
async function _createSheetViewState( | ||
iModelConnection: IModelConnection, | ||
savedView: LegacySavedView2d, | ||
): Promise<SheetViewState | undefined> { | ||
if ( | ||
savedView.sheetProps === undefined || | ||
savedView.sheetAttachments === undefined | ||
) { | ||
return undefined; | ||
} | ||
const props: ViewStateProps = { | ||
viewDefinitionProps: savedView.viewDefinitionProps, | ||
categorySelectorProps: savedView.categorySelectorProps, | ||
displayStyleProps: savedView.displayStyleProps, | ||
sheetProps: savedView.sheetProps, | ||
sheetAttachments: savedView.sheetAttachments, | ||
}; | ||
const viewState = SheetViewState.createFromProps(props, iModelConnection); | ||
await viewState.load(); | ||
return viewState; | ||
} | ||
|
||
|
||
async function translateLegacySavedViewToITwinJsViewState(legacySavedView: LegacySavedView | LegacySavedView2d, iModelConnection: IModelConnection): Promise<ViewState | undefined> { | ||
return createViewState(iModelConnection, legacySavedView); | ||
} |
84 changes: 84 additions & 0 deletions
84
packages/saved-views-react/src/api/utilities/translation/clipVectorsExtractor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright (c) Bentley Systems, Incorporated. All rights reserved. | ||
import { | ||
type ExtractionFunc, | ||
applyExtraction, | ||
extractArray2d, | ||
extractArrayConditionally, | ||
extractBoolean, | ||
extractNumber, | ||
extractObject, | ||
extractSimpleArray, | ||
simpleTypeOf, | ||
} from "@bentley/itwin-saved-views-utilities"; | ||
|
||
const isPoint = (val: unknown): val is [number, number, number] => | ||
Array.isArray(val) && | ||
val.length === 3 && | ||
val.every((num: unknown) => typeof num === "number"); | ||
|
||
const isTransformRow = ( | ||
value: unknown | ||
): value is [number, number, number, number] => | ||
Array.isArray(value) && | ||
value.length === 4 && | ||
value.every((num: unknown) => typeof num === "number"); | ||
|
||
const clipPrimitiveShapeMappings: ExtractionFunc<void, void>[] = [ | ||
extractObject( | ||
[ | ||
extractSimpleArray(isPoint, "points"), | ||
extractSimpleArray(isTransformRow, "transform", "trans"), | ||
extractNumber("zLow", "zlow"), | ||
extractNumber("zHigh", "zhigh"), | ||
extractBoolean("mask"), | ||
extractBoolean("invisible"), | ||
], | ||
"shape" | ||
), | ||
]; | ||
|
||
const clipPlaneMappings: ExtractionFunc<void, void>[] = [ | ||
extractSimpleArray(simpleTypeOf("number"), "normal"), | ||
extractNumber("dist", "distance"), | ||
extractBoolean("invisible"), | ||
extractBoolean("interior"), | ||
]; | ||
|
||
const clipPrimitivePlaneMappings: ExtractionFunc<void, void>[] = [ | ||
extractObject( | ||
[extractArray2d(clipPlaneMappings, "clips"), extractBoolean("invisible")], | ||
"planes" | ||
), | ||
]; | ||
|
||
const clipVectorMappings: ExtractionFunc<void, void>[] = [ | ||
extractArrayConditionally( | ||
[ | ||
{ | ||
discriminator: "planes", | ||
mappings: [...clipPrimitivePlaneMappings], | ||
}, | ||
{ | ||
discriminator: "shape", | ||
mappings: [...clipPrimitiveShapeMappings], | ||
}, | ||
], | ||
"clip", | ||
"clipVectors" | ||
), | ||
]; | ||
|
||
/** | ||
* Extracts the clip vectors from a PSS View | ||
* @param input | ||
*/ | ||
export const extractClipVectors = (input: object) => { | ||
const viewDetails = input; | ||
if (!("clipVectors" in input)) { | ||
return undefined; | ||
} | ||
|
||
const output: any = {}; | ||
applyExtraction(viewDetails, output, clipVectorMappings); | ||
return output.clipVectors; | ||
}; |
Oops, something went wrong.