export function createScale()

in src/visualComponent/axes/helpers/axisHelper.ts [549:686]


export function createScale(options: ICreateAxisOptions): ICreateScaleResult {
    const {
        pixelSpan,
        metaDataColumn,
        isScalar,
        isVertical,
        forcedTickCount,
        shouldClamp,
        maxTickCount,
        density,
    } = options;

    let { dataDomain } = options;

    const outerPadding: number = options.outerPadding || DefaultOuterPadding;
    const minOrdinalRectThickness: number = options.minOrdinalRectThickness || MinOrdinalRectThickness;

    const dataType: powerbi.ValueTypeDescriptor = getCategoryValueType(metaDataColumn as powerbi.DataViewMetadataColumn, isScalar);

    let maxTicks: number = isVertical
        ? getRecommendedNumberOfTicksForYAxis(pixelSpan)
        : getRecommendedNumberOfTicksForXAxis(pixelSpan, minOrdinalRectThickness);

    if (maxTickCount &&
        maxTicks > maxTickCount) {

        maxTicks = maxTickCount;
    }

    let scalarDomain: number[] = dataDomain
        ? dataDomain.slice()
        : null;

    let bestTickCount: number = maxTicks;
    let scale: ScaleLinear<number, number> | ScalePoint<string>;
    let usingDefaultDomain: boolean = false;

    if (dataDomain == null
        || (dataDomain.length === 2 && dataDomain[0] == null && dataDomain[1] == null)
        || (dataDomain.length !== 2 && isScalar)) {

        usingDefaultDomain = true;

        if (dataType.dateTime || !isOrdinal(dataType)) {
            dataDomain = emptyDomain;
        }
        else { // ordinal
            dataDomain = [];
        }

        if (isOrdinal(dataType)) {
            scale = createPointScale(pixelSpan, dataDomain);
        }
        else {
            scale = createNumericalScale(
                pixelSpan,
                dataDomain,
                outerPadding,
                bestTickCount,
            );
        }
    }
    else {
        if (isScalar && dataDomain.length > 0) {
            bestTickCount = forcedTickCount !== undefined
                ? (maxTicks !== 0 ? forcedTickCount : 0)
                : getBestNumberOfTicks(
                    dataDomain[0],
                    dataDomain[dataDomain.length - 1],
                    [metaDataColumn as powerbi.DataViewMetadataColumn],
                    maxTicks,
                    dataType.dateTime);

            const normalizedRange = normalizeLinearDomain({
                max: dataDomain[dataDomain.length - 1],
                min: dataDomain[0],
            });

            scalarDomain = [
                normalizedRange.min,
                normalizedRange.max,
            ];
        }

        if (isScalar && dataType.numeric && !dataType.dateTime) {
            // Note: Don't pass bestTickCount to createNumericalScale, because it overrides boundaries of the domain.
            scale = createNumericalScale(
                pixelSpan,
                scalarDomain,
                outerPadding,
                null,
                shouldClamp,
            );

            bestTickCount = maxTicks === 0
                ? 0
                : getAmountOfTicksByDensity(Math.floor((pixelSpan - outerPadding) / minOrdinalRectThickness), density);
        }
        else if (isScalar && dataType.dateTime) {
            // Use of a linear scale, instead of a D3.time.scale, is intentional since we want
            // to control the formatting of the time values, since d3"s implementation isn"t
            // in accordance to our design.
            // scalarDomain: should already be in long-int time (via category.values[0].getTime())
            scale = createLinearScale(pixelSpan, scalarDomain, outerPadding, null, shouldClamp); // DO NOT PASS TICKCOUNT

            bestTickCount = maxTicks === 0 ? 0
                : getAmountOfTicksByDensity((Math.max(
                    MinAmountOfTicksForDates,
                    (pixelSpan - outerPadding) / minOrdinalRectThickness)), density);

            bestTickCount = bestTickCount < MinAmountOfTicksForDates
                ? MinAmountOfTicksForDates
                : bestTickCount;
        }
        else if (dataType.text || dataType.dateTime || dataType.numeric || dataType.bool) {
            scale = createPointScale(pixelSpan, scalarDomain);

            bestTickCount = maxTicks === 0
                ? 0
                : getAmountOfTicksByDensity((Math.min(
                    scalarDomain.length,
                    (pixelSpan - outerPadding) / minOrdinalRectThickness)), density);
        }
    }

    // vertical ordinal axis (e.g. categorical bar chart) does not need to reverse
    if (isVertical && isScalar) {
        (scale as ScaleLinear<number, number>).range(scale.range().reverse()); // TODO: check it
    }

    normalizeInfinityInScale(scale as ScaleLinear<number, number>);

    return {
        bestTickCount,
        scale: scale as ScaleLinear<number, number>,
        usingDefaultDomain,
    };
}