计算包含指定矩形的最小矩形

106 阅读2分钟

需求背景

项目中有一个画布的功能,可以在画布里面添加许多参考线,点击窗口放大时,放大到最小参考线矩形,如下图: 最小矩形2.png 最小矩形1.png

代码实现

interface Rectangle {
    x: number;     // 矩形左上角的 x 坐标
    y: number;     // 矩形左上角的 y 坐标
    width: number; // 矩形的宽度
    height: number; // 矩形的高度
}

/**
 * 根据给定的坐标和尺寸,计算包含该矩形的最小矩形。
 * @param xList - x 轴坐标数组,按升序排列。
 * @param yList - y 轴坐标数组,按升序排列。
 * @param x - 给定矩形的左上角 x 坐标。
 * @param y - 给定矩形的左上角 y 坐标。
 * @param width - 给定矩形的宽度。
 * @param height - 给定矩形的高度。
 * @returns 包含指定矩形的最小矩形的 x、y、宽度和高度。
 * @throws 如果无法找到包含给定矩形的最小矩形,抛出错误。
 */
function findBoundingRectangle(
    xList: number[], 
    yList: number[], 
    x: number, 
    y: number, 
    width: number, 
    height: number
): Rectangle {
    // 计算给定矩形的右边界和下边界
    const rectRight: number = x + width;
    const rectBottom: number = y + height;

    // 找到左边界的 x 坐标(即最接近且小于或等于 x 的坐标)
    const leftX: number | null = xList.filter((hx: number) => hx <= x).pop() ?? null;
    // 找到右边界的 x 坐标(即最接近且大于或等于 rectRight 的坐标)
    const rightX: number | null = xList.find((hx: number) => hx >= rectRight) ?? null;

    // 找到上边界的 y 坐标(即最接近且小于或等于 y 的坐标)
    const upperY: number | null = yList.filter((vy: number) => vy <= y).pop() ?? null;
    // 找到下边界的 y 坐标(即最接近且大于或等于 rectBottom 的坐标)
    const lowerY: number | null = yList.find((vy: number) => vy >= rectBottom) ?? null;

    // 如果找不到任何边界点,则抛出错误
    if (leftX === null || rightX === null || upperY === null || lowerY === null) {
        throw new Error("无法找到包含指定矩形的矩形");
    }

    // 计算包含矩形的最小矩形的宽度和高度
    const newWidth: number = rightX - leftX;
    const newHeight: number = lowerY - upperY;
    
    // 返回包含指定矩形的最小矩形的坐标和尺寸
    return { x: leftX, y: upperY, width: newWidth, height: newHeight };
}

// 示例
const xList: number[] = [1, 3, 5, 7, 9];
const yList: number[] = [2, 4, 6, 8, 10];
const x: number = 4;
const y: number = 5;
const width: number = 2;
const height: number = 3;

const boundingRectangle = findBoundingRectangle(xList, yList, x, y, width, height);
console.log("左上点 x:", boundingRectangle.x);
console.log("左上点 y:", boundingRectangle.y);
console.log("宽度:", boundingRectangle.width);
console.log("高度:", boundingRectangle.height);