UNPKG

@itwin/measure-tools-react

Version:
300 lines 14.1 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { IModelApp, QuantityType } from "@itwin/core-frontend"; import { FormatTraits } from "@itwin/core-quantity"; import { MeasureTools } from "../MeasureTools.js"; export var FormatterUtils; (function (FormatterUtils) { const bearingUnitSystems = ["metric", "imperial", "usCustomary", "usSurvey"]; const bearingRegistrationPromises = new Map(); /** * Gets a FormatterSpec by KoQ string with fallback to QuantityType. * @param koqString The Kind of Quantity string to look up. * @param fallbackQuantityType The QuantityType to use if KoQ lookup fails. * @returns A FormatterSpec or undefined if both lookups fail. */ function getFormatterSpecWithFallback(koqString, persistenceUnitName, fallbackQuantityType) { const koqEntry = IModelApp.quantityFormatter.getSpecsByNameAndUnit({ name: koqString, persistenceUnitName }); if (koqEntry) { return koqEntry.formatterSpec; } // Fallback to QuantityType return IModelApp.quantityFormatter.findFormatterSpecByQuantityType(fallbackQuantityType); } FormatterUtils.getFormatterSpecWithFallback = getFormatterSpecWithFallback; /** Returns the handle's formatterSpec, falling back to QuantityType if the handle couldn't resolve its KoQ. */ function getSpecFromHandle(handle, fallback) { return handle.formatterSpec ?? IModelApp.quantityFormatter.findFormatterSpecByQuantityType(fallback); } FormatterUtils.getSpecFromHandle = getSpecFromHandle; /** Formats a sequence of values with spec without the unit label */ function formatValuesWithNoUnitLabel(values, spec) { const oldFormatTraits = spec.format.formatTraits; spec.format.formatTraits &= ~FormatTraits.ShowUnitLabel; // Bit-wise remove ShowUnitLabel trait if exists const strs = values.map((value) => IModelApp.quantityFormatter.formatQuantity(value, spec)); spec.format.formatTraits = oldFormatTraits; // Restore original format traits return strs.join(", "); } async function formatCoordinates(point) { const coordSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.Coordinate); return formatCoordinatesImmediate(point, coordSpec); } FormatterUtils.formatCoordinates = formatCoordinates; function formatCoordinatesImmediate(point, coordSpec) { if (!coordSpec) { coordSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Coordinate); } if (undefined === coordSpec) return ""; return formatValuesWithNoUnitLabel([point.x, point.y, point.z], coordSpec); } FormatterUtils.formatCoordinatesImmediate = formatCoordinatesImmediate; async function formatCoordinatesXY(point) { const coordSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.Coordinate); return formatCoordinatesXYImmediate(point, coordSpec); } FormatterUtils.formatCoordinatesXY = formatCoordinatesXY; function formatCoordinatesXYImmediate(point, coordSpec) { if (!coordSpec) { coordSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Coordinate); } if (undefined === coordSpec) return ""; return formatValuesWithNoUnitLabel([point.x, point.y], coordSpec); } FormatterUtils.formatCoordinatesXYImmediate = formatCoordinatesXYImmediate; /** Formats the input angle into DD°MM'SS.SS" format. * NOTE: uses the same symbols as the IModelApp's quantityFormatter for minute and second. * The minute symbol is an apostrophe ' while it should be a prime (\u2032) * The second symbol is a quotation mark " while it should be a double prime (\u2033) */ function formatAngleToDMS(angleInDegrees) { const isNegative = angleInDegrees < 0; angleInDegrees = Math.abs(angleInDegrees); const d = Math.trunc(angleInDegrees); const m = Math.abs(Math.trunc((angleInDegrees - d) * 60)); const s = Math.abs(((angleInDegrees - d) * 60 - m) * 60); let str = isNegative ? "-" : ""; str += d; str += "\xB0"; str += `00${m}`.slice(-2); str += "\u0027"; str += `00000${s.toFixed(2)}`.slice(-5); str += "\u0022"; return str; } FormatterUtils.formatAngleToDMS = formatAngleToDMS; function formatCartographicToLatLongDMS(c) { const latSuffixKey = 0 < c.latitude ? "MeasureTools:Generic.latitudeNorthSuffix" : "MeasureTools:Generic.latitudeSouthSuffix"; const longSuffixKey = 0 < c.longitude ? "MeasureTools:Generic.longitudeEastSuffix" : "MeasureTools:Generic.longitudeWestSuffix"; let str = FormatterUtils.formatAngleToDMS(Math.abs(c.latitudeDegrees)); str += MeasureTools.localization.getLocalizedString(latSuffixKey); str += ", "; str += FormatterUtils.formatAngleToDMS(Math.abs(c.longitudeDegrees)); str += MeasureTools.localization.getLocalizedString(longSuffixKey); return str; } FormatterUtils.formatCartographicToLatLongDMS = formatCartographicToLatLongDMS; async function formatCartographicToLatLong(c, angleSpec) { if (!angleSpec) { angleSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.LatLong); } return formatCartographicToLatLongImmediate(c, angleSpec); } FormatterUtils.formatCartographicToLatLong = formatCartographicToLatLong; function formatCartographicToLatLongImmediate(c, angleSpec) { if (!angleSpec) { angleSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.LatLong); } if (undefined === angleSpec) return ""; const latSuffixKey = 0 < c.latitude ? "MeasureTools:Generic.latitudeNorthSuffix" : "MeasureTools:Generic.latitudeSouthSuffix"; const longSuffixKey = 0 < c.longitude ? "MeasureTools:Generic.longitudeEastSuffix" : "MeasureTools:Generic.longitudeWestSuffix"; let str = IModelApp.quantityFormatter.formatQuantity(Math.abs(c.latitude), angleSpec); str += MeasureTools.localization.getLocalizedString(latSuffixKey); str += ", "; str += IModelApp.quantityFormatter.formatQuantity(Math.abs(c.longitude), angleSpec); str += MeasureTools.localization.getLocalizedString(longSuffixKey); return str; } FormatterUtils.formatCartographicToLatLongImmediate = formatCartographicToLatLongImmediate; function formatSlope(slopeInPercent, withSlopeRatio) { const fSlope = `${slopeInPercent.toFixed(2)}%`; if (!withSlopeRatio || 0.0 === slopeInPercent) return fSlope; const oneOverSlope = 100.0 / Math.abs(slopeInPercent); const sign = slopeInPercent < 0.0 ? "-" : ""; const fSlopeRatio = `${sign}1 : ${oneOverSlope.toFixed(3)}`; return `${fSlope} (${fSlopeRatio})`; } FormatterUtils.formatSlope = formatSlope; async function formatStation(station, stationSpec) { if (!stationSpec) { stationSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.Stationing); } return formatStationImmediate(station, stationSpec); } FormatterUtils.formatStation = formatStation; function formatStationImmediate(station, stationSpec) { if (!stationSpec) { stationSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Stationing); } return stationSpec ? IModelApp.quantityFormatter.formatQuantity(station, stationSpec) : station.toString(); } FormatterUtils.formatStationImmediate = formatStationImmediate; async function formatLength(length, lengthSpec) { if (!lengthSpec) { lengthSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.LengthEngineering); } return formatLengthImmediate(length, lengthSpec); } FormatterUtils.formatLength = formatLength; function formatLengthImmediate(length, lengthSpec) { if (!lengthSpec) { lengthSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.LengthEngineering); } return lengthSpec ? IModelApp.quantityFormatter.formatQuantity(length, lengthSpec) : length.toString(); } FormatterUtils.formatLengthImmediate = formatLengthImmediate; async function formatAngle(angle, angleSpec) { if (!angleSpec) { angleSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.Angle); } return formatAngleImmediate(angle, angleSpec); } FormatterUtils.formatAngle = formatAngle; function formatAngleImmediate(angle, angleSpec) { if (!angleSpec) { angleSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Angle); } return angleSpec ? IModelApp.quantityFormatter.formatQuantity(angle, angleSpec) : angle.toString(); } FormatterUtils.formatAngleImmediate = formatAngleImmediate; async function formatArea(area, areaSpec) { if (!areaSpec) { areaSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.Area); } return formatAreaImmediate(area, areaSpec); } FormatterUtils.formatArea = formatArea; function formatAreaImmediate(area, areaSpec) { if (!areaSpec) { areaSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Area); } return areaSpec ? IModelApp.quantityFormatter.formatQuantity(area, areaSpec) : area.toString(); } FormatterUtils.formatAreaImmediate = formatAreaImmediate; /** * @returns The bearing in radians, where 0 is North and π/2 is East. */ function calculateBearing(dx, dy) { let bearing = Math.atan2(dx, dy); // radians, 0 = North, π/2 = East if (bearing < 0) bearing += 2 * Math.PI; // Normalize to [0, 2π) return bearing; } FormatterUtils.calculateBearing = calculateBearing; async function getBearingFormatProps(bearingKoQ, system) { try { const formatProps = await IModelApp.formatsProvider.getFormat(bearingKoQ, system); if (formatProps) { return formatProps; } } catch { // fall through to non-system lookup / default format } try { const formatProps = await IModelApp.formatsProvider.getFormat(bearingKoQ); if (formatProps) { return formatProps; } } catch { // fall through to default format } return getDefaultBearingFormatProps(); } async function registerBearingFormatSpecs(bearingKoQ, persistenceUnitName) { for (const system of bearingUnitSystems) { const formatProps = await getBearingFormatProps(bearingKoQ, system); await IModelApp.quantityFormatter.addFormattingSpecsToRegistry({ name: bearingKoQ, persistenceUnitName, formatProps, system, }); } } async function ensureBearingFormatSpecsRegistered(bearingKoQ, persistenceUnitName) { const key = `${bearingKoQ}|${persistenceUnitName}`; let promise = bearingRegistrationPromises.get(key); if (!promise) { promise = registerBearingFormatSpecs(bearingKoQ, persistenceUnitName).catch((err) => { bearingRegistrationPromises.delete(key); throw err; }); bearingRegistrationPromises.set(key, promise); } await promise; } FormatterUtils.ensureBearingFormatSpecsRegistered = ensureBearingFormatSpecsRegistered; /** * Creates a FormatterSpec for bearing using the provided KoQ string with fallback to default bearing format. * @param bearingKoQ The Kind of Quantity string for bearing. * @param persistenceUnitName The persistence unit name for the bearing. * @returns A FormatterSpec for bearing formatting. */ async function getBearingFormatterSpec(bearingKoQ, persistenceUnitName) { const formatProps = await getBearingFormatProps(bearingKoQ); // Create and return the formatter spec return IModelApp.quantityFormatter.createFormatterSpec({ persistenceUnitName, formatProps }); } FormatterUtils.getBearingFormatterSpec = getBearingFormatterSpec; function getDefaultBearingFormatProps() { return { minWidth: 2, precision: 0, type: "Bearing", revolutionUnit: "Units.REVOLUTION", formatTraits: ["showUnitLabel"], uomSeparator: "", composite: { includeZero: true, spacer: "", units: [ { name: "Units.ARC_DEG", label: "°" }, { name: "Units.ARC_MINUTE", label: "'" }, { name: "Units.ARC_SECOND", label: "\"" }, ], }, }; } FormatterUtils.getDefaultBearingFormatProps = getDefaultBearingFormatProps; })(FormatterUtils || (FormatterUtils = {})); //# sourceMappingURL=FormatterUtils.js.map