/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Rendering
 */
import { Point3d, Range3d, Transform } from "@itwin/core-geometry";
import { MeshBuilderMap } from "./MeshBuilderMap";
import { MeshList } from "./MeshPrimitives";
import { GeometryList } from "./GeometryList";
import { Geometry } from "./GeometryPrimitives";
/** @internal */
export class GeometryAccumulator {
    get surfacesOnly() { return this._surfacesOnly; }
    get transform() { return this._transform; }
    get isEmpty() { return this.geometries.isEmpty; }
    get haveTransform() { return !this._transform.isIdentity; }
    constructor(options) {
        this.geometries = new GeometryList();
        this.tileRange = options?.tileRange ?? Range3d.createNull();
        this._surfacesOnly = true === options?.surfacesOnly;
        this._transform = options?.transform ?? Transform.createIdentity();
        this._analysisDisplacement = options?.analysisStyleDisplacement;
        this.currentFeature = options?.feature;
    }
    getPrimitiveRange(geom) {
        const range = new Range3d();
        geom.range(undefined, range);
        return range.isNull ? undefined : range;
    }
    calculateTransform(transform, range) {
        if (this.haveTransform)
            transform = this._transform.multiplyTransformTransform(transform);
        transform.multiplyRange(range, range);
        return transform;
    }
    addLoop(loop, displayParams, transform, disjoint) {
        const range = this.getPrimitiveRange(loop);
        if (!range)
            return false;
        const xform = this.calculateTransform(transform, range);
        return this.addGeometry(Geometry.createFromLoop(loop, xform, range, displayParams, disjoint, this.currentFeature));
    }
    addLineString(pts, displayParams, transform) {
        // Do this.getPrimitiveRange() manually, so there is no need to create a PointString3d object just to find the range
        const range = Range3d.createNull();
        range.extendArray(pts, undefined);
        if (range.isNull)
            return false;
        const xform = this.calculateTransform(transform, range);
        return this.addGeometry(Geometry.createFromLineString(pts, xform, range, displayParams, this.currentFeature));
    }
    addPointString(pts, displayParams, transform) {
        // Do this.getPrimitiveRange() manually, so there is no need to create a PointString3d object just to find the range
        const range = Range3d.createNull();
        range.extendArray(pts, undefined);
        if (range.isNull)
            return false;
        const xform = this.calculateTransform(transform, range);
        return this.addGeometry(Geometry.createFromPointString(pts, xform, range, displayParams, this.currentFeature));
    }
    addPath(path, displayParams, transform, disjoint) {
        const range = this.getPrimitiveRange(path);
        if (!range)
            return false;
        const xform = this.calculateTransform(transform, range);
        return this.addGeometry(Geometry.createFromPath(path, xform, range, displayParams, disjoint, this.currentFeature));
    }
    addPolyface(pf, displayParams, transform) {
        // Adjust the mesh range based on displacements applied to vertices by analysis style, if applicable.
        let range;
        if (this._analysisDisplacement) {
            const channel = pf.data.auxData?.channels.find((x) => x.name === this._analysisDisplacement.channelName);
            const displacementRange = channel?.computeDisplacementRange(this._analysisDisplacement.scale);
            if (displacementRange && !displacementRange.isNull) {
                range = Range3d.createNull();
                const pt = new Point3d();
                for (let i = 0; i < pf.data.point.length; i++) {
                    pf.data.point.getPoint3dAtUncheckedPointIndex(i, pt);
                    range.extendXYZ(pt.x + displacementRange.low.x, pt.y + displacementRange.low.y, pt.z + displacementRange.low.z);
                    range.extendXYZ(pt.x + displacementRange.high.x, pt.y + displacementRange.high.y, pt.z + displacementRange.high.z);
                }
            }
        }
        if (!range && !(range = this.getPrimitiveRange(pf)))
            return false;
        const xform = this.calculateTransform(transform, range);
        return this.addGeometry(Geometry.createFromPolyface(pf, xform, range, displayParams, this.currentFeature));
    }
    addSolidPrimitive(primitive, displayParams, transform) {
        const range = this.getPrimitiveRange(primitive);
        if (!range)
            return false;
        const xform = this.calculateTransform(transform, range);
        return this.addGeometry(Geometry.createFromSolidPrimitive(primitive, xform, range, displayParams, this.currentFeature));
    }
    addGeometry(geom) {
        this.geometries.push(geom);
        return true;
    }
    clear() { this.geometries.clear(); }
    /**
     * Generates a MeshBuilderMap
     * native: GeometryAccumulator::ToMeshBuilderMap(GeometryOptionsCR options, double tolerance, FeatureTableP featureTable, ViewContextR context) const
     * note  : removed featureTable, ViewContext
     * @param tolerance should derive from Viewport.getPixelSizeAtPoint
     */
    toMeshBuilderMap(options, tolerance, pickable) {
        const { geometries } = this; // declare internal dependencies
        const range = geometries.computeRange();
        const is2d = !range.isNull && range.isAlmostZeroZ;
        return MeshBuilderMap.createFromGeometries(geometries, tolerance, range, is2d, options, pickable);
    }
    toMeshes(options, tolerance, pickable) {
        if (this.geometries.isEmpty)
            return new MeshList();
        const builderMap = this.toMeshBuilderMap(options, tolerance, pickable);
        return builderMap.toMeshes();
    }
}
//# sourceMappingURL=GeometryAccumulator.js.map