The Fox is watching you.

基于JS的蒙德里安风格随机色块生成(2) 生成交点

按照自然的思路,我们得到了一种丑陋低效但能用的算法。


思路是遍历所有随机直线,判断该直线与已处理的对应正交直线的交点。显然该直线必定与两正交直线相交,判断究竟是哪两条的依据是随机线的生成原点。在这里,我们定义“特征坐标”为用来确定水平线和竖直线的坐标。具体来说,水平线由其y坐标确定,竖直线由其x坐标确定;反之为非特征坐标。问题转化为判断该直线的非特征坐标与对应正交直线的特征坐标之间的关系,选取最接近的两条对应正交直线生成交点。

但是这种方法有一种缺陷,就是如果对应的正交直线在此之前就已经与该直线类型相同的直线形成了交点,以至于实际上该直线不会与对应的正交直线形成交点,按照这种思路会产生多余的错误交点。因此有必要采用一种方法,来避免或者删除错误交点。可以通过记录已生成直线的端点来实现。具体的方式是初始化了待处理数组,该部分以端点方式而非随机点坐标形式记录直线,此时该数组中的直线降级为线段;在先前思路的之前添加一次端点的判断,要求该直线的特征坐标介于对应正交线段两端点的非特征坐标之间(沿用直线的概念),否则扩大范围。待处理数组按照特征坐标排序,此处采用二分法时间复杂度会更低。但是次数并不多,目前暂未优化,采取了遍历的方式。

这种方法产生交点的过程可以记录交点的类型,为后面生成矩形提供必要信息。


for (let i = 0; i < RANDOM_LINE_COUNT; i++) {
    if (randomLineInfo[i][1] == 'Column') {
        let nearestGreaterJ = processingRow.length - 1;
        let nearestSmallerJ = 0;
        for (let j = processingRow.length - 1; j > 0; j--) {
            if (randomLineInfo[i][0][0] < processingRow[j][1][0] &&
                randomLineInfo[i][0][0] > processingRow[j][0][0]) {
                if (randomLineInfo[i][0][1] < processingRow[j][0][1] &&
                    processingRow[j][0][1] < processingRow[nearestGreaterJ][0][1])
                    nearestGreaterJ = j;
            }
        }
        let j = 0;
        while (j < processingRow.length) {
            if (randomLineInfo[i][0][0] < processingRow[j][1][0] &&
                randomLineInfo[i][0][0] > processingRow[j][0][0]) {
                if (randomLineInfo[i][0][1] > processingRow[j][0][1] &&
                    processingRow[j][0][1] > processingRow[nearestSmallerJ][0][1])
                    nearestSmallerJ = j;
            }
            j++;
        }
        intersectionInfo[intersectionInfo.length] =
            [randomLineInfo[i][0][0],
            processingRow[nearestGreaterJ][0][1],
                'D'];
        intersectionInfo[intersectionInfo.length] =
            [randomLineInfo[i][0][0],
            processingRow[nearestSmallerJ][0][1],
                'U'];
        let instertingArray =
            [[randomLineInfo[i][0][0],
            processingRow[nearestSmallerJ][0][1]],
            [randomLineInfo[i][0][0],
            processingRow[nearestGreaterJ][0][1]]];
        insert3DArray(processingColumn, instertingArray, 0, 0);
    } else {
        let nearestGreaterJ = processingColumn.length - 1;
        let nearestSmallerJ = 0;
        for (let j = processingColumn.length - 1; j > 0; j--) {
            if (randomLineInfo[i][0][1] < processingColumn[j][1][1] &&
                randomLineInfo[i][0][1] > processingColumn[j][0][1]) {
                if (randomLineInfo[i][0][0] < processingColumn[j][0][0] &&
                    processingColumn[j][0][0] < processingColumn[nearestGreaterJ][0][0])
                    nearestGreaterJ = j;
            }
        }
        let j = 0;
        while (j < processingColumn.length) {
            if (randomLineInfo[i][0][1] < processingColumn[j][1][1] &&
                randomLineInfo[i][0][1] > processingColumn[j][0][1]) {
                if (randomLineInfo[i][0][0] > processingColumn[j][0][0 &&
                    processingColumn[j][0][0] > processingColumn[nearestSmallerJ][0][0]])
                    nearestSmallerJ = j;
            }
            j++;
        }
        intersectionInfo[intersectionInfo.length] =
            [processingColumn[nearestGreaterJ][0][0],
            randomLineInfo[i][0][1],
                'R'];
        intersectionInfo[intersectionInfo.length] =
            [processingColumn[nearestSmallerJ][0][0],
            randomLineInfo[i][0][1],
                'L'];
        let instertingArray =
            [[processingColumn[nearestSmallerJ][0][0],
            randomLineInfo[i][0][1]],
            [processingColumn[nearestGreaterJ][0][0],
            randomLineInfo[i][0][1]]];
        insert3DArray(processingRow, instertingArray, 0, 1);
    }
}

添加新评论