import { PenType } from '.';
import { calcCenter, expandRect, rectInFourAngRect, rectToPoints, } from '../rect';
import { deepClone } from '../utils';
export function calcAnchorDock(store, e, curAnchor) {
    let xDock;
    let yDock;
    let x = Infinity;
    let y = Infinity;
    const size = 8;
    for (const pen of store.data.pens) {
        if (pen.calculative.inView === false) {
            continue;
        }
        // 得到图形的全部点
        const points = getPointsByPen(pen);
        points.forEach((pt) => {
            if (pt === e || pt === curAnchor) {
                return;
            }
            let distance = (pen.calculative.worldRect.center.x - e.x) *
                (pen.calculative.worldRect.center.x - e.x) +
                (pen.calculative.worldRect.center.y - e.y) *
                    (pen.calculative.worldRect.center.y - e.y);
            const disX = Math.abs(pt.x - e.x);
            if (disX > 0 && disX < size && distance < x) {
                xDock = {
                    x: Math.round(pt.x) + 0.5,
                    y: Math.round(pt.y) + 0.5,
                    prev: {
                        x: Math.round(e.x) + 0.5,
                        y: Math.round(e.y) + 0.5,
                    },
                    step: pt.x - e.x,
                };
                x = distance;
            }
            const disY = Math.abs(pt.y - e.y);
            if (disY > 0 && disY < size && distance < y) {
                yDock = {
                    x: Math.round(pt.x) + 0.5,
                    y: Math.round(pt.y) + 0.5,
                    prev: {
                        x: Math.round(e.x) + 0.5,
                        y: Math.round(e.y) + 0.5,
                    },
                    step: pt.y - e.y,
                };
                y = distance;
            }
        });
    }
    return {
        xDock,
        yDock,
    };
}
export function calcMoveDock(store, rect, pens, offset) {
    // 找到 points ，深拷贝一下，不影响原值
    let activePoints = [];
    if (pens.length === 1) {
        activePoints = deepClone(getPointsByPen(pens[0]));
        activePoints.forEach((point) => {
            point.x += offset.x;
            point.y += offset.y;
        });
    }
    else {
        calcCenter(rect);
        activePoints = [rect.center, ...rectToPoints(rect)];
    }
    return calcDockByPoints(store, activePoints, rect, true);
}
/**
 * 得到画笔的全部点
 * 线 即全部的 worldAnchors
 * 图形 即全部的 worldAnchors ，加上边缘四个点以及中心点
 * @param pen 画笔
 */
export function getPointsByPen(pen) {
    if (!pen.type) {
        const outerPoints = rectToPoints(pen.calculative.worldRect);
        calcCenter(pen.calculative.worldRect);
        return [
            ...pen.calculative.worldAnchors,
            ...outerPoints,
            pen.calculative.worldRect.center,
        ];
    }
    else if (pen.type === PenType.Line) {
        return pen.calculative.worldAnchors;
    }
}
export function calcResizeDock(store, rect, pens, resizeIndex) {
    const activePoints = rectToPoints(rect);
    return calcDockByPoints(store, activePoints, rect);
}
/**
 * 通过当前 活动层 的所有点 计算 dock
 * @param activePoints 活动层 的所有点
 * @param rect 当前区域
 * @param calcActive 是否与 活动层画笔 的点进行计算
 */
function calcDockByPoints(store, activePoints, rect, calcActive = false) {
    let xDock;
    let yDock;
    let minCloseX = Infinity;
    let minCloseY = Infinity;
    // 临近范围
    const closeSize = 10;
    const paddingRect = expandRect(rect, closeSize);
    store.data.pens.forEach((pen) => {
        const { inView, worldRect, active } = pen.calculative;
        if (inView === false ||
            (!calcActive && active) || // 如果不计算活动层，则过滤掉活动层
            rectInFourAngRect(paddingRect, worldRect) || // 水平和垂直方向 无重合
            (pen.type &&
                store.active.some((active) => isConnectLine(store, active, pen)))) {
            return;
        }
        // 得到图形的全部点
        const points = getPointsByPen(pen);
        if (!points) {
            return;
        }
        // 比对 points 中的点，必须找出最近的点，不可提前跳出
        for (const point of points) {
            for (const activePoint of activePoints) {
                const stepX = point.x - activePoint.x;
                const stepY = point.y - activePoint.y;
                const absStepX = Math.abs(stepX);
                const absStepY = Math.abs(stepY);
                if (!rect.center) {
                    rect.center = {
                        x: rect.x + rect.width / 2,
                        y: rect.y + rect.height / 2,
                    };
                }
                if (absStepX < closeSize && absStepX < minCloseX) {
                    xDock = {
                        x: Math.round(point.x) + 0.5,
                        y: Math.round(point.y) + 0.5,
                        step: stepX,
                        prev: {
                            x: Math.round(activePoint.x) + 0.5,
                            y: Math.round(activePoint.y) + 0.5,
                        },
                        penId: pen.id,
                        anchorId: activePoint.id,
                        dockAnchorId: point.id,
                    };
                    minCloseX = absStepX;
                }
                if (absStepY < closeSize && absStepY < minCloseY) {
                    yDock = {
                        x: Math.round(point.x) + 0.5,
                        y: Math.round(point.y) + 0.5,
                        step: stepY,
                        prev: {
                            x: Math.round(activePoint.x) + 0.5,
                            y: Math.round(activePoint.y) + 0.5,
                        },
                        penId: pen.id,
                        anchorId: activePoint.id,
                        dockAnchorId: point.id,
                    };
                    minCloseY = absStepY;
                }
            }
        }
    });
    return {
        xDock,
        yDock,
    };
}
/**
 * 判断 line 是否是 active 的连接线（并且计算子节点）
 * @param store
 * @param active 本次计算的画笔
 * @param line 连线
 * @returns
 */
function isConnectLine(store, active, line) {
    if (!line.type) {
        return false;
    }
    if (Array.isArray(active?.connectedLines)) {
        for (const cline of active?.connectedLines) {
            if (cline.lineId === line.id) {
                return true;
            }
        }
    }
    // 考虑子节点
    if (Array.isArray(active?.children)) {
        for (const id of active.children) {
            const child = store.pens[id];
            if (isConnectLine(store, child, line)) {
                return true;
            }
        }
    }
    return false;
}
/**
 * 是否近似于 num
 * @param num
 */
export function isEqual(source, target) {
    // @ts-ignore
    return source.toFixed(12) == target;
}
// 获取偏移量比较大的图元（认为是脏数据）
export function findOutliersByZScore(pens, threshold = 4) {
    let points = pens.map((item) => item.calculative.worldRect);
    // 计算x和y的平均值和标准差
    const xValues = points.map((p) => p.x);
    const yValues = points.map((p) => p.y);
    const meanX = xValues.reduce((a, b) => a + b, 0) / xValues.length;
    const meanY = yValues.reduce((a, b) => a + b, 0) / yValues.length;
    const stdX = Math.sqrt(xValues.map((x) => Math.pow(x - meanX, 2)).reduce((a, b) => a + b, 0) /
        xValues.length);
    const stdY = Math.sqrt(yValues.map((y) => Math.pow(y - meanY, 2)).reduce((a, b) => a + b, 0) /
        yValues.length);
    // 计算每个点的综合z-score
    return pens.filter((pen) => {
        let point = pen.calculative.worldRect;
        const zX = (point.x - meanX) / stdX;
        const zY = (point.y - meanY) / stdY;
        const combinedZ = Math.sqrt(zX * zX + zY * zY);
        return combinedZ > threshold;
    });
}
//# sourceMappingURL=math.js.map