如何检查网格上有两条相交/重叠的线?

时间:2014-01-21 02:10:06

标签: objective-c

这是一个相当简单的算法问题,但我的实现使速度和简单性成为所希望的。我有两个Line对象,每个对象以{unsigned int x, unsigned int y}的形式保存两个坐标结构。第一个坐标保持线的起点和第二个坐标的位置,即它的结尾。假设线条在网格上只能是垂直或水平,我如何检查两条线平行重叠或垂直相交。优选地,这被实现为行中的方法:

- (BOOL)intersectsLine:(Line)otherLine;

谢谢!

1 个答案:

答案 0 :(得分:2)

由于我们只讨论水平线或垂直线,所以第一步我会检查线是否具有相同的方向。

typedef (NSUInteger, LineOrientation) {
    HorizontalLine = 0,
    VerticalLine = 1
};

所以,给出一条有两点的线......

LineOrientation line1orientation;
LineOrientation line2orientation;    

if (a.x1 == a.x2) {
    line1orientation = HorizontalLine;
} else {
    line1orientation = VerticalLine;
}

if (b.x1 == b.x2) {
    line2orientation = VerticalLine;
} else {
    line2orientation = Horizontal;
}

现在我们需要检查它们是水平的,垂直的还是每个都是水平的,然后测试特定的值:

if (line1orientation == line2orientation) {
    if (line1orientation == VerticalLine) {
        if (a.x1 != b.x1) {
            return false;
        } else {
            if (a.y1 < a.y2) {
                return ((b.y1 > a.y1 && b.y1 < a.y2) || 
                    (b.y2 > a.y1 && b.y2 < a.y2));
            } else {
                return ((b.y1 > a.y2 && b.y1 < a.y1) ||
                    (b.y2 > a.y2 && b.y2 < a.y1));
            }
        }
    } else {
        if (a.y1 != b.y1) {
            return false;
        } else {
            if (a.x1 < a.x2) {
                return ((b.x1 > a.x1 && b.x1 < a.x2) ||
                    (b.x2 > a.x1 && b.x2 < a.x2));
            } else {
                return ((b.x1 > a.x2 && b.x1 < a.x1) ||
                    (b.x2 > a.x2 && b.x2 < a.x1));
            }
        }
    }
} else {
    if (line1orientation == VerticalLine) {
        if (a.y1 < a.y2) {
            return (((b.y1 > a.y1) && (b.y1 < a.y2)) && ((b.x1 > a.x1 && b.x2 
                < a.x1) || (b.x2 > a.x1 && b.x1 < a.x1)));
        } else {
            return (((b.y1 > a.y2) && (b.y1 < a.y1)) && ((b.x1 > a.x1 && b.x2 
                < a.x1) || (b.x2 > a.x1 && b.x1 < a.x1)))
        }
    } else {
        if (a.x1 < a.x2) {
            return (((b.x1 > a.x1) && (b.x1 < a.x2)) && ((b.y1 > a.y1 && b.y2 
                < a.y2) || (b.y2 > a.y1 && b.y1 < a.y1)));
        } else {
            return (((b.x1 > a.x2) && (b.x1 < a.x1)) && ((b.y1 > a.y1 && b.y2 
                < a.y2) || (b.y2 > a.y1 && b.y1 < a.y1)));
    }
}

如果你开始检查以确保线条不是同一条线,这可能会更有效。