zoukankan      html  css  js  c++  java
  • [原]经营类游戏:由轴对齐矩形相交判定到判定菱形构成的平行四边形相交判定(一)

    普通多边形之间的相交测试是个复杂的问题,我们只考虑 轴对齐的 菱形问题即菱形的对角线和坐标轴平行的相交问题。

    和坐标轴平行的矩形的相交问题:

    矩形A B由左上角定点和右下角定点描述, x轴正方向右, y正方向 向下。

                 图1

    设:A的左上定点 x0y0, 右下 x1 y1    B 左上 x2 y2  右下 x3 y3

    二维问题一般降维度处理:

    有 如果两个矩形 在 x轴y轴投影都相交, 则两个矩形相交

    即: x0 < x3  &&  x2 < x1 && y0 < y3 && y2 < y1

    因为两个坐标轴上的相交区域唯一确定一个 矩形

    具体的矩形 范围受 坐标的实际大小关系确定


    现在我们需要考虑菱形的问题:

    菱形的轴是倾斜的, 那么如何求轴上的投影范围, 来进行相交测试呢?

                                图2

    好吧,这样计算的确有些困难, 我们参见图1, 可以有个思路, 首先确定一个菱形的包围盒, 任意一个菱形都有唯一的轴对称包围盒。

    设一个菱形的坐标轴x方向宽度 2* sizeX,  坐标轴y方向  2* sizeY

    考虑:以下三种情况

    我们需要求得这些菱形组合的包围盒的大小:

    设从左上到右下的为菱形的 轴x方向, 从 右上到坐下 为 菱形轴y方向, sx 为x向 菱形的个数, sy 为y方向个数

    情况1:

    除了第一个菱形块之外, 其它菱形块每增加一个宽度增加一个sizeX 高度增加 一个 sizeY


    宽度 = (2+sy-1)*sizeX (sizeX是单个菱形宽度的一半)  

    高度=(2+sy-1)*sizeY (sizeY 是单个菱形高度的一半)

    情况2:(最下面的那个)

    宽度 = (2+sx-1)*sizeX

    高度=(2+sx-1) *sizeY

    最后的复杂情况:

    先考虑 沿x 方向的 值, 再加上 y方向的值

    宽度 = (2+sx-1 + sy-1)*sizeX

    高度 = (2+sx-1 + sy-1)*sizeY


    实际上简化之后:

    宽度 = (sx+sy)*sizeX

    高度 = (sx+sy)*sizeY


    这些拼接图形的中点 , 就是他们 包围盒的中点?

    可以做上辅助线。 我们根据平线线的分割原理就可以证明


    下一个问题是求得这个拼接图形的四个定点的位置; 首先我们需要假定 坐标轴的 0,0点在包围盒的左上角, x向右 ,y向下

    上图就是四个顶点的所在位置的值。


    最后如何判定相交?

    考虑倾斜的轴构成的坐标系:

    求一个点在这两个轴上的投影长度 , 可以采用内积:

    x轴向: (sizeX, sizeY)

    y轴向:(-sizeX, sizeY)

    t1 = (x, y) *(sizeX, sizeY)/ ( |(x, y)|)

    t2 = (x, y)*(-sizeX,  sizeY) /|(x, y)|



    所以向判断 矩形一样判断 t1 t2的范围就可以了



    下面是pyhon代码:

    import math
    sizeX = 135/4
    sizeY = 67/4

    #菱形拼图的x y 长度 和 中心位置
    ab = sx1, sy1, x1, y1 = 2, 2, 0, 0
    bb = sx2, sy2, x2, y2 = 2, 2, -40, 20

    #求得一个拼图的左上角点和右下角点
    def getBoundary(arg):
        sx, sy, x, y = arg
        x0 = x - (sx+sy)/2*sizeX
        y0 = y - (sx+sy)/2*sizeY
        x1 = x0 + sy*sizeX
        y1 = y0
        x2 = x0 + sx*sizeX
        y2 = y0 + (sx+sy)*sizeY
        print [x0, y0, x1, y1, x2, y2, sizeX, sizeY]
        return [x1, y1, x2, y2]

    #求得一个点在x方向的投影
    def getT1(x, y):
        if x == 0 and y == 0:
            return 0
        return (x*sizeX+y*-sizeY)/math.sqrt(x*x+y*y)/math.sqrt(sizeX*sizeX+sizeY*sizeY)
    #求得一个点在y方向的投影
    def getT2(x, y):
        if x == 0 and y == 0:
            return 0
        return (x*-sizeX+y*-sizeY)/math.sqrt(x*x+y*y)/math.sqrt(sizeX*sizeX+sizeY*sizeY)
    def getABound(a):
        a = getBoundary(a)
        t1 = getT1(a[0], a[1])
        t2 = getT2(a[0], a[1])
        t11 = getT1(a[2], a[3])
        t22 = getT2(a[2], a[3])
        print [a, t1, t2, t11, t22]
        return [t1, t2, t11, t22]
    def main():
        aBound = getABound(ab)
        bBound = getABound(bb)
        print aBound
        print bBound
    main()


    错了:

    不能通过 求内积来求 点在菱形边上的投影, 只有当菱形的边互相垂直的时候才成立;

    这是因为 非直角 不是 普通的几何。


    那么该怎么办呢? 如何计算相交?

    这个我 再想想



    如果我们约束 所有的菱形拼图都是 n*n的话, 存在一种解法:

    可以计算两个拼图中心的 x y 差值

    再根据 拼图的 边的宽度 = sx*sizeX,  sx*sizeY    

    只要保证两个拼图的 x , y 差值 不 小于 边的宽度 就可以了


    拼图中心相差的 x y 方向的格子数目, abs(difx)+abs(dify) >= boundA + boundB  则不相交


    作者:liyong748 发表于2012/5/13 15:08:22 原文链接
    阅读:260 评论:0 查看评论
  • 相关阅读:
    (转)位置无关码、位置有关码
    【转载】PM为什么会存在?怎么存在?
    战略是什么?3-互联网产品行业以及竞争对手分析
    【转载】2014,要格外留意这7大投资机会——哈继铭 {key:人口红利、房价、社会结构、贸易逆差}
    2014年书单-30本
    产品经理要树立战略意识——战略是什么2(谈国家限制支付宝的战略分析)
    产品经理要树立战略意识——战略是什么1
    【转载】产品经理入门案例分析——锤子手机策略
    javascript设计模式-工厂模式
    javascript设计模式-单例模式
  • 原文地址:https://www.cnblogs.com/liyonghelpme/p/4273578.html
Copyright © 2011-2022 走看看