Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions common/api/core-common.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1864,6 +1864,8 @@ export class ContextRealityModel {
// @beta
readonly rdSourceKey?: RealityDataSourceKey;
readonly realityDataId?: string;
// @alpha
get skipGcsConversion(): boolean;
toJSON(): ContextRealityModelProps;
readonly url: string;
}
Expand All @@ -1884,6 +1886,8 @@ export interface ContextRealityModelProps {
// @beta
rdSourceKey?: RealityDataSourceKey;
realityDataId?: string;
// @alpha
skipGcsConversion?: boolean;
tilesetUrl: string;
}

Expand Down Expand Up @@ -7694,6 +7698,7 @@ export interface RealityDataSourceKey {
id: string;
iTwinId?: string;
provider: string;
skipGcsConversion?: boolean;
}

// @beta
Expand Down
2 changes: 2 additions & 0 deletions common/api/core-frontend.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8420,6 +8420,8 @@ export class RealityTileTree extends TileTree {
// @internal (undocumented)
protected _selectTiles(args: TileDrawArgs): Tile[];
// @internal (undocumented)
readonly skipGcsConversion: boolean;
// @internal (undocumented)
traversalChildrenByDepth: TraversalChildrenDetails[];
// @internal (undocumented)
get viewFlagOverrides(): ViewFlagOverrides;
Expand Down
2 changes: 1 addition & 1 deletion common/api/frontend-devtools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2620,7 +2620,7 @@ export class ViewportAddRealityModel extends Tool {
// (undocumented)
static get minArgs(): number;
parseAndRun(...args: string[]): Promise<boolean>;
run(url: string): Promise<boolean>;
run(url: string, skipGcsConversion: boolean): Promise<boolean>;
// (undocumented)
static toolId: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/core-common",
"comment": "Add skip GCS conversion option to reality tiles.",
"type": "none"
}
],
"packageName": "@itwin/core-common"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/core-frontend",
"comment": "Add skip GCS conversion option to reality tiles.",
"type": "none"
}
],
"packageName": "@itwin/core-frontend"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/frontend-devtools",
"comment": "Add skip GCS conversion option to reality tiles.",
"type": "none"
}
],
"packageName": "@itwin/frontend-devtools"
}
21 changes: 21 additions & 0 deletions core/common/src/ContextRealityModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ export interface RealityDataSourceKey {
id: string;
/** The context id that was used when reality data was attached - if none provided, current session iTwinId will be used */
iTwinId?: string;
/** If true, do not reproject tiles for this model using the GCS from the backend. Instead, just use the basic ECEF transformation. */
skipGcsConversion?: boolean;
}

/**
* RealityDataSourceKey utility functions
* @beta */
Expand Down Expand Up @@ -168,6 +171,11 @@ export interface ContextRealityModelProps {
* @beta
*/
invisible?: boolean;
/**
* See [[ContextRealityModel.skipGcsConversion]]
* @alpha
*/
skipGcsConversion?: boolean;
}

/** @public */
Expand Down Expand Up @@ -214,6 +222,9 @@ export namespace ContextRealityModelProps {
if (input.invisible)
output.invisible = input.invisible;

if (input.skipGcsConversion)
output.skipGcsConversion = input.skipGcsConversion;

return output;
}
}
Expand Down Expand Up @@ -242,6 +253,7 @@ export class ContextRealityModel {
/** An optional identifier that, if present, can be used to elide a request to the reality data service. */
public readonly realityDataId?: string;

private _skipGcsConversion: boolean;
private _invisible: boolean;
private readonly _classifiers: SpatialClassifiers;
/** @alpha */
Expand Down Expand Up @@ -276,6 +288,7 @@ export class ContextRealityModel {
this.realityDataId = props.realityDataId;
this.description = props.description ?? "";
this._invisible = props.invisible ?? false;
this._skipGcsConversion = props.skipGcsConversion ?? false;
this._appearanceOverrides = props.appearanceOverrides ? FeatureAppearance.fromJSON(props.appearanceOverrides) : undefined;
this._displaySettings = RealityModelDisplaySettings.fromJSON(props.displaySettings);

Expand Down Expand Up @@ -334,6 +347,14 @@ export class ContextRealityModel {
this._displaySettings = settings;
}

/**
* If true, do not reproject tiles for this model using the GCS from the backend. Instead, just use the basic ECEF transformation.
* @alpha
*/
public get skipGcsConversion(): boolean {
return this._skipGcsConversion;
}

/** If true, reality model is not drawn.
* @beta
*/
Expand Down
3 changes: 2 additions & 1 deletion core/frontend-devtools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ These keyins take the form `fdt attach <format> maplayer <arguments>` where `for

Reality models can be attached to a display style to provide context when that display style is used. These are sometimes referred to as "contextual" reality models to differentiate them from reality models that are attached to the project as spatial models. The keyins below provide methods to attach, detach and control their display.

* `fdt attach reality model` - Attach a "context" reality model to the currently selected viewport.
* `fdt attach reality model` - Attach a "context" reality model to the currently selected viewport. Arguments, in order, include:
* the URL for the reality model root JSON file.
* optionally, a boolean, which when "true" will skip the backend GCS conversion when displaying this reality model.
* `fdt attach cesium asset` - Attach a "context" reality model from Cesium ion.
* the asset ID.
* the authorization token.
Expand Down
9 changes: 5 additions & 4 deletions core/frontend-devtools/src/tools/ViewportTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,24 +447,25 @@ export class ViewportTileSizeModifierTool extends Tool {
export class ViewportAddRealityModel extends Tool {
public static override toolId = "ViewportAddRealityModel";
public static override get minArgs() { return 1; }
public static override get maxArgs() { return 1; }
public static override get maxArgs() { return 2; }

/** This method runs the tool, adding a reality model to the viewport
* @param url the URL which points to the reality model tileset
*/
public override async run(url: string): Promise<boolean> {
public override async run(url: string, skipGcsConversion: boolean): Promise<boolean> {
const vp = IModelApp.viewManager.selectedView;
if (undefined !== vp)
vp.displayStyle.attachRealityModel({ tilesetUrl: url });
vp.displayStyle.attachRealityModel({ tilesetUrl: url, skipGcsConversion });

return true;
}

/** Executes this tool's run method with args[0] containing the `url` argument.
* args[1] can contain an optional "skipGcsConversion" argument, which if set to "true" will skip the GCS conversion.
* @see [[run]]
*/
public override async parseAndRun(...args: string[]): Promise<boolean> {
return this.run(args[0]);
return this.run(args[0], "true" === args[1] || "1" === args[1] || "yes" === args[1]);
}
}

Expand Down
1 change: 1 addition & 0 deletions core/frontend/src/ContextRealityModelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class ContextRealityModelState extends ContextRealityModel {
name: props.name,
classifiers: this.classifiers,
planarClipMask: this.planarClipMaskSettings,
skipGcsConversion: props.skipGcsConversion,
getDisplaySettings: () => this.displaySettings,
getBackgroundBase: () => displayStyle.settings.mapImagery.backgroundBase,
getBackgroundLayers: () => displayStyle.settings.mapImagery.backgroundLayers,
Expand Down
17 changes: 13 additions & 4 deletions core/frontend/src/internal/tile/RealityModelTileTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ interface RealityTreeId {
maskModelIds?: string;
deduplicateVertices: boolean;
produceGeometry?: boolean;
skipGcsConversion?: boolean;
displaySettings: RealityModelDisplaySettings;
backgroundBase?: BaseLayerSettings;
backgroundLayers?: MapLayerSettings[];
Expand Down Expand Up @@ -78,6 +79,7 @@ namespace RealityTreeId {
compareRealityDataSourceKeys(lhs.rdSourceKey, rhs.rdSourceKey) ||
compareBooleans(lhs.deduplicateVertices, rhs.deduplicateVertices) ||
compareBooleansOrUndefined(lhs.produceGeometry, rhs.produceGeometry) ||
compareBooleansOrUndefined(lhs.skipGcsConversion, rhs.skipGcsConversion) ||
compareStringsOrUndefined(lhs.maskModelIds, rhs.maskModelIds) ||
comparePossiblyUndefined((ltf, rtf) => compareTransforms(ltf, rtf), lhs.transform, rhs.transform)
);
Expand All @@ -99,7 +101,7 @@ class RealityTreeSupplier implements TileTreeSupplier {
if (treeId.maskModelIds)
await iModel.models.load(CompressedId64Set.decompressSet(treeId.maskModelIds));

const opts = { deduplicateVertices: treeId.deduplicateVertices, produceGeometry: treeId.produceGeometry };
const opts = { deduplicateVertices: treeId.deduplicateVertices, produceGeometry: treeId.produceGeometry, skipGcsConversion: treeId.skipGcsConversion };
return RealityModelTileTree.createRealityModelTileTree(treeId.rdSourceKey, iModel, treeId.modelId, treeId.transform, opts);
}

Expand Down Expand Up @@ -273,16 +275,18 @@ class RealityModelTileTreeParams implements RealityTileTreeParams {
public loader: RealityModelTileLoader;
public rootTile: RealityTileParams;
public baseUrl?: string;
public readonly skipGcsConversion?: boolean;

public get location() { return this.loader.tree.location; }
public get yAxisUp() { return this.loader.tree.yAxisUp; }
public get priority() { return this.loader.priority; }

public constructor(tileTreeId: string, iModel: IModelConnection, modelId: Id64String, loader: RealityModelTileLoader, public readonly gcsConverterAvailable: boolean, public readonly rootToEcef: Transform | undefined, baseUrl?: string) {
public constructor(tileTreeId: string, iModel: IModelConnection, modelId: Id64String, loader: RealityModelTileLoader, public readonly gcsConverterAvailable: boolean, public readonly rootToEcef: Transform | undefined, baseUrl?: string, skipGcsConversion?: boolean) {
this.loader = loader;
this.id = tileTreeId;
this.modelId = modelId;
this.iModel = iModel;
this.skipGcsConversion = skipGcsConversion;
const refine = loader.tree.tilesetJson.refine;
this.rootTile = new RealityModelTileProps({
json: loader.tree.tilesetJson,
Expand Down Expand Up @@ -561,6 +565,7 @@ export namespace RealityModelTileTree {
name?: string;
classifiers?: SpatialClassifiersState;
planarClipMask?: PlanarClipMaskSettings;
skipGcsConversion?: boolean;
getDisplaySettings(): RealityModelDisplaySettings;
getBackgroundBase?(): BaseLayerSettings;
getBackgroundLayers?(): MapLayerSettings[];
Expand Down Expand Up @@ -723,7 +728,7 @@ export namespace RealityModelTileTree {
iModel: IModelConnection,
modelId: Id64String,
tilesetToDb: Transform | undefined,
opts?: { deduplicateVertices?: boolean, produceGeometry?: boolean },
opts?: { deduplicateVertices?: boolean, produceGeometry?: boolean, skipGcsConversion?: boolean },
): Promise<TileTree | undefined> {
const rdSource = await RealityDataSource.fromKey(rdSourceKey, iModel.iTwinId);
// If we can get a valid connection from sourceKey, returns the tile tree
Expand All @@ -737,7 +742,7 @@ export namespace RealityModelTileTree {
const gcsConverterAvailable = await getGcsConverterAvailable(iModel);
//The full tileset url is needed so that it includes the url's search parameters if any are present
const baseUrl = rdSource instanceof RealityDataSourceTilesetUrlImpl ? rdSource.getTilesetUrl() : undefined;
const params = new RealityModelTileTreeParams(tileTreeId, iModel, modelId, loader, gcsConverterAvailable, props.tilesetToEcef, baseUrl);
const params = new RealityModelTileTreeParams(tileTreeId, iModel, modelId, loader, gcsConverterAvailable, props.tilesetToEcef, baseUrl, opts?.skipGcsConversion);
return new RealityModelTileTree(params);
}
return undefined;
Expand Down Expand Up @@ -801,11 +806,13 @@ export namespace RealityModelTileTree {
export class RealityTreeReference extends RealityModelTileTree.Reference {
protected _rdSourceKey: RealityDataSourceKey;
private readonly _produceGeometry?: boolean;
private readonly _skipGcsConversion?: boolean;
private readonly _modelId: Id64String;

public constructor(props: RealityModelTileTree.ReferenceProps) {
super(props);
this._produceGeometry = props.produceGeometry;
this._skipGcsConversion = props.skipGcsConversion;

// Maybe we should throw if both props.rdSourceKey && props.url are undefined
if (props.rdSourceKey)
Expand Down Expand Up @@ -835,6 +842,7 @@ export class RealityTreeReference extends RealityModelTileTree.Reference {
maskModelIds: this.maskModelIds,
deduplicateVertices: this._wantWiremesh,
produceGeometry: this._produceGeometry,
skipGcsConversion: this._skipGcsConversion,
displaySettings: this._getDisplaySettings(),
};
}
Expand All @@ -851,6 +859,7 @@ export class RealityTreeReference extends RealityModelTileTree.Reference {
rdSourceKey: this._rdSourceKey,
name: this._name,
produceGeometry: true,
skipGcsConversion: this._skipGcsConversion,
getDisplaySettings: () => RealityModelDisplaySettings.defaults,
});

Expand Down
21 changes: 14 additions & 7 deletions core/frontend/src/tile/RealityTileTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export interface RealityTileTreeParams extends TileTreeParams {
readonly rootTile: RealityTileParams;
readonly rootToEcef?: Transform;
readonly gcsConverterAvailable: boolean;
readonly skipGcsConversion?: boolean;
readonly baseUrl?: string;
}

Expand Down Expand Up @@ -192,6 +193,8 @@ export class RealityTileTree extends TileTree {
protected _ecefToDb?: Transform;
/** @internal */
public readonly baseUrl?: string;
/** @internal */
public readonly skipGcsConversion: boolean;

/** @internal */
public constructor(params: RealityTileTreeParams) {
Expand All @@ -201,6 +204,7 @@ export class RealityTileTree extends TileTree {
this._rootTile = this.createTile(params.rootTile);
this.cartesianRange = BackgroundMapGeometry.getCartesianRange(this.iModel);
this.cartesianTransitionDistance = this.cartesianRange.diagonal().magnitudeXY() * .25; // Transition distance from elliptical to cartesian.
this.skipGcsConversion = true === params.skipGcsConversion;
this._gcsConverter = params.gcsConverterAvailable ? params.iModel.geoServices.getConverter("WGS84") : undefined;
if (params.rootToEcef) {
this._rootToEcef = params.rootToEcef;
Expand Down Expand Up @@ -393,13 +397,16 @@ export class RealityTileTree extends TileTree {
else {
const requestProps = new Array<XYZProps>();

for (const reprojection of reprojectChildren) {
for (const dbPoint of reprojection.dbPoints) {
const ecefPoint = dbToEcef.multiplyPoint3d(dbPoint);
const carto = Cartographic.fromEcef(ecefPoint, scratchCarto);
if (carto)
requestProps.push({ x: carto.longitudeDegrees, y: carto.latitudeDegrees, z: carto.height });

// ###TODO - remove this console.log.
console.log(`reprojectAndResolveChildren, skipGcsConversion=${ this.skipGcsConversion}`);
if (!this.skipGcsConversion) {
for (const reprojection of reprojectChildren) {
for (const dbPoint of reprojection.dbPoints) {
const ecefPoint = dbToEcef.multiplyPoint3d(dbPoint);
const carto = Cartographic.fromEcef(ecefPoint, scratchCarto);
if (carto)
requestProps.push({ x: carto.longitudeDegrees, y: carto.latitudeDegrees, z: carto.height });
}
}
}

Expand Down