import '../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * Cohen-Sutherland line clipping, with the Maillot coding extension
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow } from '../imports.js';
import Vector2 from '../../../dot/js/Vector2.js';
const X_MAX_CODE = 0x1;
const Y_MAX_CODE = 0x2;
const X_MIN_CODE = 0x4;
const Y_MIN_CODE = 0x8;
const TWO_BITS_CODE = 0x10;
class CodedVector2 extends Vector2 {
    constructor(x, y, code) {
        super(x, y);
        this.code = code;
    }
    copy() {
        return new CodedVector2(this.x, this.y, this.code);
    }
    toVector2() {
        return new Vector2(this.x, this.y);
    }
    updateCode(bounds) {
        this.code = CohenSutherlandClipping.getCode(this.x, this.y, bounds);
    }
    static create(p, bounds) {
        return new CodedVector2(p.x, p.y, CohenSutherlandClipping.getCode(p.x, p.y, bounds));
    }
}
export default class CohenSutherlandClipping {
    // Mutates the vectors, returns whether the line segment is at least partially within the bounds
    static clip(p0, p1, bounds) {
        while ((p0.code | p1.code) !== 0) {
            if ((p0.code & p1.code & ~TWO_BITS_CODE) !== 0) {
                return false;
            }
            // Choose the first point not in the window
            const c = p0.code === 0 ? p1.code : p0.code;
            let x;
            let y;
            // Now clip against line corresponding to first nonzero bit
            if ((X_MIN_CODE & c) !== 0) {
                x = bounds.left;
                y = p0.y + (p1.y - p0.y) * (bounds.left - p0.x) / (p1.x - p0.x);
            }
            else if ((X_MAX_CODE & c) !== 0) {
                x = bounds.right;
                y = p0.y + (p1.y - p0.y) * (bounds.right - p0.x) / (p1.x - p0.x);
            }
            else if ((Y_MIN_CODE & c) !== 0) {
                x = p0.x + (p1.x - p0.x) * (bounds.top - p0.y) / (p1.y - p0.y);
                y = bounds.top;
            }
            else if ((Y_MAX_CODE & c) !== 0) {
                x = p0.x + (p1.x - p0.x) * (bounds.bottom - p0.y) / (p1.y - p0.y);
                y = bounds.bottom;
            }
            else {
                throw new Error('cohenSutherlandClip: Unknown case');
            }
            if (c === p0.code) {
                p0.x = x;
                p0.y = y;
                p0.updateCode(bounds);
            }
            else {
                p1.x = x;
                p1.y = y;
                p1.updateCode(bounds);
            }
        }
        return true;
    }
    // The Maillot extension of the Cohen-Sutherland encoding of points
    static getCode(x, y, bounds) {
        if (x < bounds.minX) {
            if (y > bounds.maxY) {
                return 0x16;
            }
            else if (y < bounds.minY) {
                return 0x1c;
            }
            else {
                return 0x4;
            }
        }
        else if (x > bounds.maxX) {
            if (y > bounds.maxY) {
                return 0x13;
            }
            else if (y < bounds.minY) {
                return 0x19;
            }
            else {
                return 0x1;
            }
        }
        else if (y > bounds.maxY) {
            return 0x2;
        }
        else if (y < bounds.minY) {
            return 0x8;
        }
        else {
            return 0;
        }
    }
}
alpenglow.register('CohenSutherlandClipping', CohenSutherlandClipping);
//# sourceMappingURL=CohenSutherlandClipping.js.map