1.9.0 Change Notes

Upgrade to Electron 6.1.5

  • iModel.js has moved up to Electron version 6.1.5 from the previous version of 4.1.0.

Added Tween library

  • iModel.js now incorporates (a copy of) the tweening library from tween.js.

High-DPI display support

The renderer now takes into account the device pixel ratio ("DPI") of the display by adjusting Viewport resolution to match screen resolution, including any scaling applied by the operating system or browser. This corrects issues like blurriness on high-DPI retina displays. This behavior is enabled by default; to disable it, set RenderSystem.Options.dpiAwareViewports to false when initializing the IModelApp.

All APIs continue to specify pixel-valued inputs as CSS pixels. However, APIs that read and return pixel values now do so in device pixels. The following new APIs can help when dealing with this discrepancy:

  • queryDevicePixelRatio to obtain the device pixel ratio; and
  • cssPixelsToDevicePixels to convert from CSS pixels to device pixels.

The primary affected API is Viewport.readPixels. Below is an example of how to correctly account for DPI scale when using that function:

/** Returns true if the specified element was drawn inside the specified region of the viewport. */
function isElementDrawnInRect(vp: Viewport, rect: ViewRect, elementId: Id64String): boolean {
  let elementFound = false;
  vp.readPixels(rect, Pixel.Selector.Feature, (pixels) => {
  if (undefined === pixels)
    return;

  // Input rect is specified in CSS pixels - convert to device pixels.
  const deviceRect = new ViewRect(cssPixelsToDevicePixels(rect.left), cssPixelsToDevicePixels(rect.top),
    cssPixelsToDevicePixels(rect.right), cssPixelsToDevicePixels(rect.bottom));

  for (let x = deviceRect.left; x < deviceRect.right; x++) {
    for (let y = deviceRect.top; y < deviceRect.bottom; y++) {
    const pixel = pixels.getPixel(x, y);
    if (undefined !== pixel.feature && pixel.feature.elementId === elementId) {
      elementFound = true;
      return;
    }
  });

  return elementFound;
}

Geometry

Ellipsoid and EllipsoidPatch classes

  • Range, ray intersection, and project-point-to-surface for Ellipsoid with patch limits
  • LongitudeLatitudeNumber class to carry position and altitude

Miscellaneous

  • AngleSweep class options for considering period shifts, added as optional args in
    • static AngleSweep.isRadiansInStartEnd(radians: number, radians0: number, radians1: number, allowPeriodShift?: boolean): boolean;
    • instance method mySweep.isRadiansInSweep optional arg for periodic shift.
  • Angle instance property isNorthOrSouthPole
  • static NumberArray.createArrayWithMaxStepSize(low: number, high: number, step: number): number[];
    • new method, returns array of numbers with (max) step size between low and high
  • Plane3dByOriginAndVectors instance methods for extracting normalized directions
    • instance method myPlane.normalizeInPlace (): boolean to normalize the vectors.
    • instance method myPlane.toRigidFrame to extract local normalized frame
    • instance method myPlane.unitNormal to extract unit normal
    • instance method myPlane.unitNormalRay to extract perpendicular ray
    • apply Vector3d instance method normalizeInPlace() to both vectorU and vectorV of the plane
  • Range3d class methods
    • instance method myRange.extendSingleAxis(a: number, axisIndex: AxisIndex): void;
      • branch to one of extendXOnly, extendYOnly, extendZOnly
  • Ray3d class methods
    • instance method myRay.cloneInverseTransformed(transform: Transform): Ray3d | undefined;
      • multiply by inverse of a transform and return the modified ray
  • Transform class methods
    • static `createRigidFromOriginAndColumns(origin: XYZ | undefined, vectorX: Vector3d, vectorY: Vector3d, axisOrder: AxisOrder, result?: Transform): Transform | undefined;
      • Careful logic to avoid object allocation when reusing result.

Last Updated: 02 February, 2022