@itwin/ecschema-rpcinterface-tests 4.1.0-dev.29 → 4.1.0-dev.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"_a8a9.bundled-tests.js","mappings":";;;;;;;;AAAA","sources":["file:///ignored|D:\\vsts_a\\4\\s\\common\\temp\\node_modules\\.pnpm\\@loaders.gl+worker-utils@3.3.3\\node_modules\\@loaders.gl\\worker-utils\\dist\\esm\\lib\\library-utils|../node/require-utils.node"],"names":[],"sourceRoot":""}
1
+ {"version":3,"file":"_a8a9.bundled-tests.js","mappings":";;;;;;;;AAAA","sources":["file:///ignored|D:\\vsts_a\\7\\s\\common\\temp\\node_modules\\.pnpm\\@loaders.gl+worker-utils@3.3.3\\node_modules\\@loaders.gl\\worker-utils\\dist\\esm\\lib\\library-utils|../node/require-utils.node"],"names":[],"sourceRoot":""}
@@ -73748,8 +73748,12 @@ class BackgroundMapGeometry {
73748
73748
  static getCartesianTransitionDistance(iModel) {
73749
73749
  return BackgroundMapGeometry.getCartesianRange(iModel, scratchRange).diagonal().magnitudeXY() * BackgroundMapGeometry._transitionDistanceMultiplier;
73750
73750
  }
73751
- async dbToCartographicFromGcs(db, result) {
73752
- return this.cartesianRange.containsPoint(_itwin_core_geometry__WEBPACK_IMPORTED_MODULE_1__.Point3d.createFrom(db)) ? this._iModel.spatialToCartographic(db, result) : this.dbToCartographic(db, result);
73751
+ async dbToCartographicFromGcs(db) {
73752
+ const scratch = new _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_1__.Point3d();
73753
+ const promises = db.map(async (p) => {
73754
+ return this.cartesianRange.containsPoint(_itwin_core_geometry__WEBPACK_IMPORTED_MODULE_1__.Point3d.createFrom(p, scratch)) ? this._iModel.spatialToCartographic(p) : this.dbToCartographic(p);
73755
+ });
73756
+ return Promise.all(promises);
73753
73757
  }
73754
73758
  dbToCartographic(db, result) {
73755
73759
  if (undefined === result)
@@ -73763,17 +73767,24 @@ class BackgroundMapGeometry {
73763
73767
  return _itwin_core_common__WEBPACK_IMPORTED_MODULE_2__.Cartographic.fromEcef(ecef, result);
73764
73768
  }
73765
73769
  }
73766
- async cartographicToDbFromGcs(cartographic, result) {
73770
+ async cartographicToDbFromGcs(cartographic) {
73767
73771
  let db;
73768
73772
  if (this.globeMode === _itwin_core_common__WEBPACK_IMPORTED_MODULE_2__.GlobeMode.Plane) {
73769
73773
  const fraction = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_1__.Point2d.create(0, 0);
73770
- this._mercatorTilingScheme.cartographicToFraction(cartographic.latitude, cartographic.longitude, fraction);
73771
- db = this._mercatorFractionToDb.multiplyXYZ(fraction.x, fraction.y, cartographic.height, result);
73774
+ db = cartographic.map((p) => {
73775
+ this._mercatorTilingScheme.cartographicToFraction(p.latitude, p.longitude, fraction);
73776
+ return this._mercatorFractionToDb.multiplyXYZ(fraction.x, fraction.y, p.height);
73777
+ });
73772
73778
  }
73773
73779
  else {
73774
- db = this._ecefToDb.multiplyPoint3d(cartographic.toEcef());
73780
+ db = cartographic.map((p) => this._ecefToDb.multiplyPoint3d(p.toEcef()));
73775
73781
  }
73776
- return (!this._iModel.noGcsDefined && this.cartesianRange.containsPoint(db)) ? this._iModel.cartographicToSpatialFromGcs(cartographic) : db;
73782
+ if (this._iModel.noGcsDefined)
73783
+ return db;
73784
+ const promises = db.map(async (p, i) => {
73785
+ return this.cartesianRange.containsPoint(p) ? this._iModel.cartographicToSpatialFromGcs(cartographic[i]) : p;
73786
+ });
73787
+ return Promise.all(promises);
73777
73788
  }
73778
73789
  cartographicToDb(cartographic, result) {
73779
73790
  if (this.globeMode === _itwin_core_common__WEBPACK_IMPORTED_MODULE_2__.GlobeMode.Plane) {
@@ -78427,6 +78438,9 @@ function cloneXYAndZ(xyz) {
78427
78438
  * @internal exported strictly for tests.
78428
78439
  */
78429
78440
  class CoordinateConverter {
78441
+ get isIdle() {
78442
+ return "idle" === this._state;
78443
+ }
78430
78444
  toXYAndZ(input, output) {
78431
78445
  if (Array.isArray(input)) {
78432
78446
  output.x = input[0] ?? 0;
@@ -78446,8 +78460,12 @@ class CoordinateConverter {
78446
78460
  this._onCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
78447
78461
  // Used for creating cache keys (XYAndZ) from XYZProps without having to allocate temporary objects.
78448
78462
  this._scratchXYZ = { x: 0, y: 0, z: 0 };
78463
+ // If true, [[dispatch]] will schedule another dispatch after it receives a response.
78464
+ // This is needed when all the points requested after the most recent dispatch were included in the currently-in-flight request -
78465
+ // _pending will be empty but new callers will be awaiting the results of the in-flight request.
78466
+ this._redispatchOnCompletion = false;
78449
78467
  this._maxPointsPerRequest = Math.max(1, opts.maxPointsPerRequest ?? 300);
78450
- this._iModel = opts.iModel;
78468
+ this._isIModelClosed = opts.isIModelClosed;
78451
78469
  this._requestPoints = opts.requestPoints;
78452
78470
  this._cache = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Dictionary(compareXYAndZ, cloneXYAndZ);
78453
78471
  this._pending = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.SortedArray(compareXYAndZ, false, cloneXYAndZ);
@@ -78455,7 +78473,7 @@ class CoordinateConverter {
78455
78473
  }
78456
78474
  async dispatch() {
78457
78475
  (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(this._state === "scheduled");
78458
- if (this._iModel.isClosed || this._pending.isEmpty) {
78476
+ if (this._isIModelClosed() || this._pending.isEmpty) {
78459
78477
  this._state = "idle";
78460
78478
  this._onCompleted.raiseEvent();
78461
78479
  return;
@@ -78474,7 +78492,7 @@ class CoordinateConverter {
78474
78492
  for (let i = 0; i < inflight.length; i += this._maxPointsPerRequest) {
78475
78493
  const requests = inflight.slice(i, i + this._maxPointsPerRequest).extractArray();
78476
78494
  const promise = this._requestPoints(requests).then((results) => {
78477
- if (this._iModel.isClosed)
78495
+ if (this._isIModelClosed())
78478
78496
  return;
78479
78497
  if (results.length !== requests.length)
78480
78498
  _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logError(`${_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_2__.FrontendLoggerCategory.Package}.geoservices`, `requested conversion of ${requests.length} points, but received ${results.length} points`);
@@ -78492,8 +78510,10 @@ class CoordinateConverter {
78492
78510
  this._state = "idle";
78493
78511
  this._inflight.clear();
78494
78512
  // If any more pending conversions arrived while awaiting this request, schedule another request.
78495
- if (!this._pending.isEmpty)
78513
+ if (!this._pending.isEmpty || this._redispatchOnCompletion) {
78514
+ this._redispatchOnCompletion = false;
78496
78515
  this.scheduleDispatch(); // eslint-disable-line @typescript-eslint/no-floating-promises
78516
+ }
78497
78517
  // Resolve promises of all callers who were awaiting this request.
78498
78518
  onCompleted.raiseEvent();
78499
78519
  }
@@ -78505,7 +78525,9 @@ class CoordinateConverter {
78505
78525
  const xyz = this.toXYAndZ(point, this._scratchXYZ);
78506
78526
  if (this._cache.get(xyz))
78507
78527
  ++numInCache;
78508
- else if (!this._inflight.contains(xyz))
78528
+ else if (this._inflight.contains(xyz))
78529
+ this._redispatchOnCompletion = true;
78530
+ else
78509
78531
  this._pending.insert(xyz);
78510
78532
  }
78511
78533
  return numInCache;
@@ -78566,25 +78588,19 @@ class CoordinateConverter {
78566
78588
  */
78567
78589
  class GeoConverter {
78568
78590
  /** @internal */
78569
- constructor(iModel, datumOrGCRS) {
78570
- const datum = typeof datumOrGCRS === "object" ? JSON.stringify(datumOrGCRS) : datumOrGCRS;
78591
+ constructor(opts) {
78592
+ /** Used for removing this converter from GeoServices' cache after all requests are completed.
78593
+ * @internal
78594
+ */
78595
+ this.onAllRequestsCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
78596
+ const isIModelClosed = opts.isIModelClosed;
78571
78597
  this._geoToIModel = new CoordinateConverter({
78572
- iModel,
78573
- requestPoints: async (geoCoords) => {
78574
- const request = { source: datum, geoCoords };
78575
- const rpc = _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token);
78576
- const response = await rpc.getIModelCoordinatesFromGeoCoordinates(iModel.getRpcProps(), request);
78577
- return response.iModelCoords;
78578
- },
78598
+ isIModelClosed,
78599
+ requestPoints: async (geoCoords) => opts.toIModelCoords({ source: opts.datum, geoCoords }),
78579
78600
  });
78580
78601
  this._iModelToGeo = new CoordinateConverter({
78581
- iModel,
78582
- requestPoints: async (iModelCoords) => {
78583
- const request = { target: datum, iModelCoords };
78584
- const rpc = _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token);
78585
- const response = await rpc.getGeoCoordinatesFromIModelCoordinates(iModel.getRpcProps(), request);
78586
- return response.geoCoords;
78587
- },
78602
+ isIModelClosed,
78603
+ requestPoints: async (iModelCoords) => opts.fromIModelCoords({ target: opts.datum, iModelCoords }),
78588
78604
  });
78589
78605
  }
78590
78606
  /** Convert the specified geographic coordinates into iModel coordinates. */
@@ -78600,6 +78616,7 @@ class GeoConverter {
78600
78616
  /** @internal */
78601
78617
  async getIModelCoordinatesFromGeoCoordinates(geoPoints) {
78602
78618
  const result = await this._geoToIModel.convert(geoPoints);
78619
+ this.checkCompletion();
78603
78620
  return {
78604
78621
  iModelCoords: result.points,
78605
78622
  fromCache: result.fromCache,
@@ -78608,11 +78625,16 @@ class GeoConverter {
78608
78625
  /** @internal */
78609
78626
  async getGeoCoordinatesFromIModelCoordinates(iModelPoints) {
78610
78627
  const result = await this._iModelToGeo.convert(iModelPoints);
78628
+ this.checkCompletion();
78611
78629
  return {
78612
78630
  geoCoords: result.points,
78613
78631
  fromCache: result.fromCache,
78614
78632
  };
78615
78633
  }
78634
+ checkCompletion() {
78635
+ if (this._geoToIModel.isIdle && this._iModelToGeo.isIdle)
78636
+ this.onAllRequestsCompleted.raiseEvent();
78637
+ }
78616
78638
  /** @internal */
78617
78639
  getCachedIModelCoordinatesFromGeoCoordinates(geoPoints) {
78618
78640
  return this._geoToIModel.findCached(geoPoints);
@@ -78624,8 +78646,35 @@ class GeoConverter {
78624
78646
  */
78625
78647
  class GeoServices {
78626
78648
  /** @internal */
78627
- constructor(iModel) {
78628
- this._iModel = iModel;
78649
+ constructor(options) {
78650
+ /** Each GeoConverter has its own independent request queue and cache of previously-converted points.
78651
+ * Some callers like RealityTileTree obtain a single GeoConverter and reuse it throughout their own lifetime. Therefore they benefit from both batching and caching, and
78652
+ * the cache gets deleted once the RealityTileTree becomes disused.
78653
+ *
78654
+ * Other callers like IModelConnection.spatialToCartographic obtain a new GeoConverter every time they need one, use it to convert a single point(!), and then discard the converter.
78655
+ * This entirely prevents batching - e.g., calling spatialToCartographic 20 times in one frame results in 20 http requests.
78656
+ * To address that, we cache each GeoConverter returned by getConverter until it has converted at least one point and has no further outstanding conversion requests.
78657
+ * In this way, the converter lives for as long as (and no longer than) any caller is awaiting conversion to/from its datum - it and its cache are deleted once it becomes disused.
78658
+ * This makes the coordinate caching generally less useful, but at least bounded - and maximizes batching of requests.
78659
+ */
78660
+ this._cache = new Map();
78661
+ this._options = options;
78662
+ }
78663
+ /** @internal */
78664
+ static createForIModel(iModel) {
78665
+ return new GeoServices({
78666
+ isIModelClosed: () => iModel.isClosed,
78667
+ toIModelCoords: async (request) => {
78668
+ const rpc = _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token);
78669
+ const response = await rpc.getIModelCoordinatesFromGeoCoordinates(iModel.getRpcProps(), request);
78670
+ return response.iModelCoords;
78671
+ },
78672
+ fromIModelCoords: async (request) => {
78673
+ const rpc = _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token);
78674
+ const response = await rpc.getGeoCoordinatesFromIModelCoordinates(iModel.getRpcProps(), request);
78675
+ return response.geoCoords;
78676
+ },
78677
+ });
78629
78678
  }
78630
78679
  /** Obtain a converter that can convert between a geographic coordinate system and the iModel's own coordinate system.
78631
78680
  * @param datumOrGCRS The name or JSON representation of the geographic coordinate system datum - for example, "WGS84".
@@ -78633,7 +78682,19 @@ class GeoServices {
78633
78682
  * @note A [[BlankConnection]] has no connection to a backend, so it is never "open"; therefore it always returns `undefined`.
78634
78683
  */
78635
78684
  getConverter(datumOrGCRS) {
78636
- return this._iModel.isOpen ? new GeoConverter(this._iModel, datumOrGCRS ? datumOrGCRS : "") : undefined;
78685
+ if (this._options.isIModelClosed())
78686
+ return undefined;
78687
+ const datum = (typeof datumOrGCRS === "object" ? JSON.stringify(datumOrGCRS) : datumOrGCRS) ?? "";
78688
+ let converter = this._cache.get(datum);
78689
+ if (!converter) {
78690
+ converter = new GeoConverter({ ...this._options, datum });
78691
+ this._cache.set(datum, converter);
78692
+ converter.onAllRequestsCompleted.addOnce(() => {
78693
+ if (converter === this._cache.get(datum))
78694
+ this._cache.delete(datum);
78695
+ });
78696
+ }
78697
+ return converter;
78637
78698
  }
78638
78699
  }
78639
78700
 
@@ -80283,7 +80344,7 @@ class IModelConnection extends _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.I
80283
80344
  this.selectionSet = new _SelectionSet__WEBPACK_IMPORTED_MODULE_8__.SelectionSet(this);
80284
80345
  this.hilited = new _SelectionSet__WEBPACK_IMPORTED_MODULE_8__.HiliteSet(this);
80285
80346
  this.tiles = new _Tiles__WEBPACK_IMPORTED_MODULE_11__.Tiles(this);
80286
- this.geoServices = new _GeoServices__WEBPACK_IMPORTED_MODULE_4__.GeoServices(this);
80347
+ this.geoServices = _GeoServices__WEBPACK_IMPORTED_MODULE_4__.GeoServices.createForIModel(this);
80287
80348
  /* eslint-disable-next-line deprecation/deprecation */
80288
80349
  this.displayedExtents = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Range3d.fromJSON(this.projectExtents);
80289
80350
  this.onProjectExtentsChanged.addListener(() => {
@@ -80464,6 +80525,7 @@ class IModelConnection extends _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.I
80464
80525
  * @param result If defined, use this for output
80465
80526
  * @returns A Cartographic location
80466
80527
  * @throws IModelError if [[isGeoLocated]] is false or point could not be converted.
80528
+ * @see [[cartographicFromSpatial]] if you have more than one point to convert, or you don't know whether the iModel has a GCS.
80467
80529
  */
80468
80530
  async spatialToCartographicFromGcs(spatial, result) {
80469
80531
  if (!this.isGeoLocated && this.noGcsDefined)
@@ -80484,17 +80546,51 @@ class IModelConnection extends _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.I
80484
80546
  * @param result If defined, use this for output
80485
80547
  * @returns A Cartographic location
80486
80548
  * @throws IModelError if [[isGeoLocated]] is false or point could not be converted.
80487
- * @see [[spatialToCartographicFromGcs]]
80488
- * @see [[spatialToCartographicFromEcef]]
80549
+ * @see [[cartographicFromSpatial]] to convert multiple points at once.
80550
+ * @see [[spatialToCartographicFromEcef]] to synchronously convert points using the iModel's ECEF transform.
80489
80551
  */
80490
80552
  async spatialToCartographic(spatial, result) {
80491
80553
  return (this.noGcsDefined ? this.spatialToCartographicFromEcef(spatial, result) : this.spatialToCartographicFromGcs(spatial, result));
80492
80554
  }
80493
- /** Convert a [[Cartographic]] to a point in this iModel's Spatial coordinates using the Geographic location services for this IModelConnection.
80555
+ /** Convert points in this iModel's spatial coordinate system to [Cartographic]($common) coordinates using either a [[GeoConverter]] or the iModel's [EcefLocation]($common).
80556
+ * @param spatial Coordiantes to be converted from the iModel's spatial coordinate system
80557
+ * @returns The `spatial` coordinates converted to cartographic coordinates, of the same length and order as the `spatial`.
80558
+ * @throws IModelError if [[isGeoLocated]] is false or any point could not be converted.
80559
+ * @see [[spatialFromCartographic]] to perform the inverse conversion.
80560
+ * @see [[spatialToCartographicFromEcef]] to synchronously convert points using the iModel's ECEF transform.
80561
+ */
80562
+ async cartographicFromSpatial(spatial) {
80563
+ if (this.noGcsDefined)
80564
+ return spatial.map((p) => this.spatialToCartographicFromEcef(p));
80565
+ if (!this.isGeoLocated)
80566
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated");
80567
+ if (!this.isOpen)
80568
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not open");
80569
+ if (spatial.length === 0)
80570
+ return [];
80571
+ const geoConverter = this.geoServices.getConverter();
80572
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(undefined !== geoConverter);
80573
+ const coordResponse = await geoConverter.getGeoCoordinatesFromIModelCoordinates(spatial);
80574
+ if (coordResponse.geoCoords.length !== spatial.length)
80575
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated");
80576
+ return coordResponse.geoCoords.map((coord) => {
80577
+ switch (coord.s) {
80578
+ case _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.GeoCoordStatus.NoGCSDefined:
80579
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated");
80580
+ case _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.GeoCoordStatus.Success:
80581
+ const llh = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Point3d.fromJSON(coord.p);
80582
+ return _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.Cartographic.fromDegrees({ longitude: llh.x, latitude: llh.y, height: llh.z });
80583
+ default:
80584
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError((0,_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.mapToGeoServiceStatus)(coord.s), "Error converting spatial to cartographic");
80585
+ }
80586
+ });
80587
+ }
80588
+ /** Convert a [Cartographic]($common) to a point in this iModel's spatial coordinate system using a [[GeoConverter]].
80494
80589
  * @param cartographic A cartographic location
80495
80590
  * @param result If defined, use this for output
80496
80591
  * @returns A point in this iModel's spatial coordinates
80497
80592
  * @throws IModelError if [[isGeoLocated]] is false or cartographic location could not be converted.
80593
+ * @see [[spatialFromCartographic]] to convert multiple points at once, or you don't know whether the iModel has a GCS.
80498
80594
  */
80499
80595
  async cartographicToSpatialFromGcs(cartographic, result) {
80500
80596
  if (!this.isGeoLocated && this.noGcsDefined)
@@ -80512,17 +80608,49 @@ class IModelConnection extends _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.I
80512
80608
  result.setFromJSON(coordResponse.iModelCoords[0].p);
80513
80609
  return result;
80514
80610
  }
80515
- /** Convert a [[Cartographic]] to a point in this iModel's Spatial coordinates using the Geographic location services for this IModelConnection or [[IModel.ecefLocation]].
80611
+ /** Convert a [Cartographic]($common) to a point in this iModel's Spatial coordinates using a [[GeoConverter]] or[[IModel.ecefLocation]($common).
80516
80612
  * @param cartographic A cartographic location
80517
80613
  * @param result If defined, use this for output
80518
80614
  * @returns A point in this iModel's spatial coordinates
80519
80615
  * @throws IModelError if [[isGeoLocated]] is false or cartographic location could not be converted.
80520
- * @see [[cartographicToSpatialFromGcs]]
80521
- * @see [[cartographicToSpatialFromEcef]]
80616
+ * @see [[spatialFromCartographic]] to convert multiple points at once.
80617
+ * @see [[cartographicToSpatialFromEcef]] to synchronously convert points using the iModel's ECEF transform.
80522
80618
  */
80523
80619
  async cartographicToSpatial(cartographic, result) {
80524
80620
  return (this.noGcsDefined ? this.cartographicToSpatialFromEcef(cartographic, result) : this.cartographicToSpatialFromGcs(cartographic, result));
80525
80621
  }
80622
+ /** Convert [Cartographic]($common) coordinates into points in this iModel's spatial coordinate system using a [[GeoConverter]] or the iModel's [EcefLocation]($common).
80623
+ * @param cartographic Coordinates to be converted to the iModel's spatial coordinate system.
80624
+ * @returns The `cartographic` coordinates converted to spatial coordinates, of the same length and order as `cartographic`.
80625
+ * @throws IModelError if [[isGeoLocated]] is false or any point could not be converted.
80626
+ * @see [[cartographicFromSpatial]] to perform the inverse conversion.
80627
+ */
80628
+ async spatialFromCartographic(cartographic) {
80629
+ if (this.noGcsDefined)
80630
+ return cartographic.map((p) => this.cartographicToSpatialFromEcef(p));
80631
+ if (!this.isGeoLocated)
80632
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated");
80633
+ if (!this.isOpen)
80634
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not open");
80635
+ if (cartographic.length === 0)
80636
+ return [];
80637
+ const geoConverter = this.geoServices.getConverter();
80638
+ (0,_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.assert)(undefined !== geoConverter);
80639
+ const geoCoords = cartographic.map((p) => _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(p.longitudeDegrees, p.latitudeDegrees, p.height));
80640
+ const coordResponse = await geoConverter.getIModelCoordinatesFromGeoCoordinates(geoCoords);
80641
+ if (coordResponse.iModelCoords.length !== cartographic.length)
80642
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated");
80643
+ return coordResponse.iModelCoords.map((coord) => {
80644
+ switch (coord.s) {
80645
+ case _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.GeoCoordStatus.NoGCSDefined:
80646
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated");
80647
+ case _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.GeoCoordStatus.Success:
80648
+ return _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Point3d.fromJSON(coord.p);
80649
+ default:
80650
+ throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.IModelError((0,_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.mapToGeoServiceStatus)(coord.s), "Error converting cartographic to spatial");
80651
+ }
80652
+ });
80653
+ }
80526
80654
  /** Expand this iModel's [[displayedExtents]] to include the specified range.
80527
80655
  * This is done automatically when reality models are added to a spatial view. In some cases a [[TiledGraphicsProvider]] may wish to expand
80528
80656
  * the extents explicitly to include its geometry.
@@ -87737,9 +87865,10 @@ function areaToEyeHeight(view3d, area, offset = 0) {
87737
87865
  * @internal
87738
87866
  */
87739
87867
  async function areaToEyeHeightFromGcs(view3d, area, offset = 0) {
87740
- const ne = await view3d.cartographicToRootFromGcs(area.northeast);
87741
- const sw = await view3d.cartographicToRootFromGcs(area.southwest);
87742
- return _areaToEyeHeight(view3d, ne, sw, offset);
87868
+ const corners = await view3d.cartographicToRootUsingGcs([area.northeast, area.southwest]);
87869
+ if (!corners)
87870
+ return 0;
87871
+ return _areaToEyeHeight(view3d, corners[0], corners[1], offset);
87743
87872
  }
87744
87873
  /** Converts a root range (often project extents) to a cartographic area.
87745
87874
  * @internal
@@ -89611,25 +89740,55 @@ class ViewState3d extends ViewState {
89611
89740
  this.turnCameraOff();
89612
89741
  return eyePoint.distance(origEyePoint);
89613
89742
  }
89614
- /** Convert a point in spatial space to a cartographic coordinate. */
89743
+ /** Convert a point in spatial coordinates to a cartographic coordinate. */
89615
89744
  rootToCartographic(root, result) {
89616
89745
  const backgroundMapGeometry = this.displayStyle.getBackgroundMapGeometry();
89617
89746
  return backgroundMapGeometry ? backgroundMapGeometry.dbToCartographic(root, result) : undefined;
89618
89747
  }
89619
- /** Convert a cartographic coordinate to a point in spatial space. */
89748
+ /** Convert a cartographic coordinate to a point in spatial coordinates. */
89620
89749
  cartographicToRoot(cartographic, result) {
89621
89750
  const backgroundMapGeometry = this.displayStyle.getBackgroundMapGeometry();
89622
89751
  return backgroundMapGeometry ? backgroundMapGeometry.cartographicToDb(cartographic, result) : undefined;
89623
89752
  }
89624
- /** Convert a point in spatial space to a cartographic coordinate using the GCS reprojection. */
89753
+ /** Convert a point in spatial coordinates to a cartographic coordinate using the GCS reprojection.
89754
+ * @see [[rootToCartographicUsingGcs]] to convert multiple points at once.
89755
+ * @see [[cartographicToRootFromGcs]] for the inverse conversion.
89756
+ */
89625
89757
  async rootToCartographicFromGcs(root, result) {
89626
89758
  const backgroundMapGeometry = this.displayStyle.getBackgroundMapGeometry();
89627
- return backgroundMapGeometry ? backgroundMapGeometry.dbToCartographicFromGcs(root, result) : undefined;
89759
+ if (!backgroundMapGeometry)
89760
+ return undefined;
89761
+ const carto = (await backgroundMapGeometry.dbToCartographicFromGcs([root]))[0];
89762
+ return carto.clone(result);
89628
89763
  }
89629
- /** Convert a cartographic coordinate to a point in spatial space using the GCS reprojection. */
89764
+ /** Convert spatial coordinates to cartographic coordinates using the GCS reprojection.
89765
+ * @param root Spatial coordinates to be converted
89766
+ * @returns the converted coordinates of the same length and order as `root`, or `undefined` if the conversion cannot be performed.
89767
+ * @see [[cartographicToRootUsingGcs]] for the inverse conversion.
89768
+ */
89769
+ async rootToCartographicUsingGcs(root) {
89770
+ const bgmap = this.displayStyle.getBackgroundMapGeometry();
89771
+ return bgmap?.dbToCartographicFromGcs(root);
89772
+ }
89773
+ /** Convert a cartographic coordinate to a point in spatial coordinates using the GCS reprojection.
89774
+ * @see [[cartographicToRootUsingGcs]] to convert multiple points at once.
89775
+ * @see [[rootToCartographicFromGcs]] for the inverse conversion.
89776
+ */
89630
89777
  async cartographicToRootFromGcs(cartographic, result) {
89631
89778
  const backgroundMapGeometry = this.displayStyle.getBackgroundMapGeometry();
89632
- return backgroundMapGeometry ? backgroundMapGeometry.cartographicToDbFromGcs(cartographic, result) : undefined;
89779
+ if (!backgroundMapGeometry)
89780
+ return undefined;
89781
+ const root = (await backgroundMapGeometry.cartographicToDbFromGcs([cartographic]))[0];
89782
+ return root.clone(result);
89783
+ }
89784
+ /** Convert cartographic coordinates to spatial coordinates using the GCS reprojection.
89785
+ * @param cartographic Cartographic coordinates to be converted
89786
+ * @returns the converted coordinates of the same length and order as `cartographic`, or `undefined` if the conversion cannot be performed.
89787
+ * @see [[rootToCartographicUsingGcs]] for the inverse conversion.
89788
+ */
89789
+ async cartographicToRootUsingGcs(cartographic) {
89790
+ const bgmap = this.displayStyle.getBackgroundMapGeometry();
89791
+ return bgmap?.cartographicToDbFromGcs(cartographic);
89633
89792
  }
89634
89793
  setupFromFrustum(frustum, opts) {
89635
89794
  const stat = super.setupFromFrustum(frustum, opts);
@@ -91480,7 +91639,7 @@ class Viewport {
91480
91639
  const worldPoint = hit.hitPoint.clone();
91481
91640
  const backgroundMapGeometry = hit.viewport.displayStyle.getBackgroundMapGeometry();
91482
91641
  if (undefined !== backgroundMapGeometry) {
91483
- featureInfo.hitPoint = await backgroundMapGeometry.dbToCartographicFromGcs(worldPoint);
91642
+ featureInfo.hitPoint = (await backgroundMapGeometry.dbToCartographicFromGcs([worldPoint]))[0];
91484
91643
  }
91485
91644
  const results = await Promise.all(promises);
91486
91645
  for (const result of results)
@@ -152844,7 +153003,7 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
152844
153003
  const worldPoint = hit.hitPoint.clone();
152845
153004
  let cartoGraphic;
152846
153005
  try {
152847
- cartoGraphic = await backgroundMapGeometry.dbToCartographicFromGcs(worldPoint);
153006
+ cartoGraphic = (await backgroundMapGeometry.dbToCartographicFromGcs([worldPoint]))[0];
152848
153007
  }
152849
153008
  catch {
152850
153009
  }
@@ -284880,7 +285039,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
284880
285039
  /***/ ((module) => {
284881
285040
 
284882
285041
  "use strict";
284883
- module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.1.0-dev.29","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s webpackWorkers && npm run -s copy:workers","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2020 --outDir lib/esm","clean":"rimraf lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:workers":"cpx \\"./lib/workers/webpack/parse-imdl-worker.js\\" ./lib/public/scripts","docs":"betools docs --includes=../../generated-docs/extract --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/primitives,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-eslintrc -c \\"./node_modules/@itwin/eslint-plugin/dist/configs/extension-exports-config.js\\" \\"./src/**/*.ts\\" 1>&2","lint":"eslint -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run -s webpackTests && certa -r chrome","cover":"npm -s test","test:debug":"certa -r chrome --debug","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2 && npm run -s webpackTestWorker","webpackTestWorker":"webpack --config ./src/test/worker/webpack.config.js 1>&2 && cpx \\"./lib/test/test-worker.js\\" ./lib/test","webpackWorkers":"webpack --config ./src/workers/ImdlParser/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:^4.1.0-dev.29","@itwin/core-bentley":"workspace:^4.1.0-dev.29","@itwin/core-common":"workspace:^4.1.0-dev.29","@itwin/core-geometry":"workspace:^4.1.0-dev.29","@itwin/core-orbitgt":"workspace:^4.1.0-dev.29","@itwin/core-quantity":"workspace:^4.1.0-dev.29"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/certa":"workspace:*","@itwin/eslint-plugin":"^4.0.0-dev.33","@types/chai":"4.3.1","@types/chai-as-promised":"^7","@types/mocha":"^8.2.2","@types/node":"^18.11.5","@types/sinon":"^9.0.0","babel-loader":"~8.2.5","babel-plugin-istanbul":"~6.1.1","chai":"^4.1.2","chai-as-promised":"^7","cpx2":"^3.0.0","eslint":"^8.36.0","glob":"^7.1.2","mocha":"^10.0.0","nyc":"^15.1.0","rimraf":"^3.0.2","sinon":"^9.0.2","source-map-loader":"^4.0.0","typescript":"~5.0.2","webpack":"^5.76.0"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/object-storage-azure":"^1.5.0","@itwin/cloud-agnostic-core":"^1.5.0","@itwin/object-storage-core":"^1.5.0","@itwin/core-i18n":"workspace:*","@itwin/core-telemetry":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","fuse.js":"^3.3.0","wms-capabilities":"0.4.0","reflect-metadata":"0.1.13"},"nyc":{"extends":"./node_modules/@itwin/build-tools/.nycrc"},"eslintConfig":{"plugins":["@itwin"],"extends":"plugin:@itwin/itwinjs-recommended","rules":{"@itwin/no-internal-barrel-imports":["error",{"required-barrel-modules":["./src/tile/internal.ts"]}],"@itwin/public-extension-exports":["error",{"releaseTags":["public","preview"],"outputApiFile":false}]},"overrides":[{"files":["*.test.ts","*.test.tsx","**/test/**/*.ts"],"rules":{"@itwin/no-internal-barrel-imports":"off"}}]}}');
285042
+ module.exports = JSON.parse('{"name":"@itwin/core-frontend","version":"4.1.0-dev.30","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s webpackWorkers && npm run -s copy:workers","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2020 --outDir lib/esm","clean":"rimraf lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:workers":"cpx \\"./lib/workers/webpack/parse-imdl-worker.js\\" ./lib/public/scripts","docs":"betools docs --includes=../../generated-docs/extract --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/primitives,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-eslintrc -c \\"./node_modules/@itwin/eslint-plugin/dist/configs/extension-exports-config.js\\" \\"./src/**/*.ts\\" 1>&2","lint":"eslint -f visualstudio \\"./src/**/*.ts\\" 1>&2","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run -s webpackTests && certa -r chrome","cover":"npm -s test","test:debug":"certa -r chrome --debug","webpackTests":"webpack --config ./src/test/utils/webpack.config.js 1>&2 && npm run -s webpackTestWorker","webpackTestWorker":"webpack --config ./src/test/worker/webpack.config.js 1>&2 && cpx \\"./lib/test/test-worker.js\\" ./lib/test","webpackWorkers":"webpack --config ./src/workers/ImdlParser/webpack.config.js 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:^4.1.0-dev.30","@itwin/core-bentley":"workspace:^4.1.0-dev.30","@itwin/core-common":"workspace:^4.1.0-dev.30","@itwin/core-geometry":"workspace:^4.1.0-dev.30","@itwin/core-orbitgt":"workspace:^4.1.0-dev.30","@itwin/core-quantity":"workspace:^4.1.0-dev.30"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/certa":"workspace:*","@itwin/eslint-plugin":"^4.0.0-dev.33","@types/chai":"4.3.1","@types/chai-as-promised":"^7","@types/mocha":"^8.2.2","@types/node":"^18.11.5","@types/sinon":"^9.0.0","babel-loader":"~8.2.5","babel-plugin-istanbul":"~6.1.1","chai":"^4.1.2","chai-as-promised":"^7","cpx2":"^3.0.0","eslint":"^8.36.0","glob":"^7.1.2","mocha":"^10.0.0","nyc":"^15.1.0","rimraf":"^3.0.2","sinon":"^9.0.2","source-map-loader":"^4.0.0","typescript":"~5.0.2","webpack":"^5.76.0"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/object-storage-azure":"^1.5.0","@itwin/cloud-agnostic-core":"^1.5.0","@itwin/object-storage-core":"^1.5.0","@itwin/core-i18n":"workspace:*","@itwin/core-telemetry":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^3.1.6","@loaders.gl/draco":"^3.1.6","fuse.js":"^3.3.0","wms-capabilities":"0.4.0","reflect-metadata":"0.1.13"},"nyc":{"extends":"./node_modules/@itwin/build-tools/.nycrc"},"eslintConfig":{"plugins":["@itwin"],"extends":"plugin:@itwin/itwinjs-recommended","rules":{"@itwin/no-internal-barrel-imports":["error",{"required-barrel-modules":["./src/tile/internal.ts"]}],"@itwin/public-extension-exports":["error",{"releaseTags":["public","preview"],"outputApiFile":false}]},"overrides":[{"files":["*.test.ts","*.test.tsx","**/test/**/*.ts"],"rules":{"@itwin/no-internal-barrel-imports":"off"}}]}}');
284884
285043
 
284885
285044
  /***/ })
284886
285045