AOI 十字链路 (半径不同)


import math

class CEntity(object):

    def __init__(self,cid,x,y,radius):
        self.cid = cid
        self.x = x
        self.y = y
        self.radius = radius
        self.xpre = None
        self.xnext = None
        self.ypre = None
        self.ynext = None

        self.watcher = set([]) #观察者集合(关注当前对象的集合)
        self.maker = set([])   #被观察者集合(当前对象关注的集合)

    def __str__(self):
        return "[%s:(%s-%s-%s) w:%s m:%s]" % (self.cid,self.x,self.y,self.radius,self.watcher,str(self.maker))

    def xsee(self,entity):
        return math.fabs(self.x - entity.x) <= self.radius
    
    def ysee(self,entity):
        return math.fabs(self.y - entity.y) <= self.radius

    def see(self,entity):
        return self.xsee(entity) and self.ysee(entity)

    def getWatcherSet(self):
        return self.watcher

    def addWatcher(self,cid):
        self.watcher.add(cid)

    def delWatcher(self,cid):
        if cid not in self.watcher:
            return
        self.watcher.remove(cid)

    def getMakerSet(self):
        return self.maker

    def addMaker(self,cid):
        self.maker.add(cid)

    def delMaker(self,cid):
        if cid not in self.maker:
            return
        self.maker.remove(cid)
    
    
class CScene(object):

    def __init__(self):
        self.dstmax = 10
        self.m_mapEntity = {}
        self.head = CEntity(-1,0,0,0)
        self.tail = CEntity(-2,0,0,0)
        self.head.xnext = self.tail
        self.head.ynext = self.tail
        self.tail.xpre = self.head
        self.tail.ypre = self.head

    def addEntity(self,entity):
        cur = self.head.xnext
        while(cur != None):
            if entity.x < cur.x or cur == self.tail:
                pre = cur.xpre
                pre.xnext = entity
                entity.xnext = cur
                cur.xpre = entity
                entity.xpre = pre
                break
            cur = cur.xnext
        
        cur = self.head.ynext
        while(cur != None):
            if entity.y < cur.y or cur == self.tail:
                entity.ynext = cur
                entity.ypre = cur.ypre
                cur.ypre.ynext = entity
                cur.ypre = entity
                break
            cur = cur.ynext

    def delEntity(self,entity):
        if entity == self.head or entity == self.tail:
            return
        entity.xpre.xnext = entity.xnext
        entity.xnext.xpre = entity.xpre
        entity.ypre.ynext = entity.ynext
        entity.ynext.ypre = entity.ypre
        entity.xpre = None
        entity.xnext = None
        entity.ypre = None
        entity.ynext = None
        pass

    def add(self,cid,x,y,distance = 2):
        target = self.m_mapEntity.get(cid,None)
        if target:
            return
        target = CEntity(cid,x,y,distance)
        self.m_mapEntity[cid] = target
        self.addEntity(target)

        #target能看到的对象集合
        makermap = self.getMakers(target)
        for entity in makermap.values():
            target.addMaker(entity.cid)
            entity.addWatcher(target.cid)
            print("notify{0} event:{1}enter".format(target,entity)) #通知target,entity进入视野范围
        
        #能看到cur的对象集合
        watchers = self.getWatchers(target,self.dstmax)
        for entity in watchers.values():
            target.addWatcher(entity.cid)
            entity.addMaker(target.cid)
            print("notify{0} event:{1}enter".format(entity,target)) #通知entity,cur进入视野范围
        print("add entity {0}".format(target))

    def move(self,cid,x,y):
        target = self.m_mapEntity.get(cid,None)
        if not target:
            return
        self.updateEntityPosition(target,x,y)
        #target移动 关注target的对象(watcher列表)也会变化
        curwatcherset = target.getWatcherSet()
        watchers = self.getWatchers(target,self.dstmax)
        newwatcherset = set(watchers.keys())
        outsets = curwatcherset - newwatcherset
        insets = newwatcherset - curwatcherset
        movesets = curwatcherset & newwatcherset
        
        for outcid in outsets:
            entity = self.m_mapEntity.get(outcid,None)
            if not entity:
                continue
            target.delWatcher(outcid)
            entity.delMaker(cid)
            print("notify{0} event:{1}leave".format(entity,target)) #通知entity,target离开视野范围

        for incid in insets:
            entity = self.m_mapEntity.get(incid,None)
            if not entity:
                continue
            target.addWatcher(incid)
            entity.addMaker(cid)
            print("notify{0} event:{1}enter".format(entity,target)) #通知entity,target进入视野范围

        for movecid in movesets:
            entity = self.m_mapEntity.get(movecid,None)
            if not entity:
                continue
            print("notify{0} event:{1}move".format(entity,target)) #通知entity,target移动了

        #target移动 target关注的对象(maker列表)也会变化
        makers = self.getMakers(target)
        curmakerset = target.getMakerSet()
        newmakerset = set(makers.keys())
        outsets = curmakerset - newmakerset
        insets = newmakerset - curmakerset
        movesets = curmakerset & newmakerset
        for outcid in outsets:
            entity = self.m_mapEntity.get(outcid,None)
            if not entity:
                continue
            target.delMaker(outcid)
            entity.delWatcher(cid)
            print("notitfy{0} event:{1}leave".format(target,entity)) #通知target,entity离开视野
        
        for incid in insets:
            entity = self.m_mapEntity.get(incid,None)
            if not entity:
                continue
            target.addMaker(incid)
            entity.addWatcher(cid)
            print("notify{0} event:{1}enter".format(target,entity)) #通知target,entity进入视野

        #不同notify movesets集合的节点target移动了
        print("move entity {0}".format(target))


    def leave(self,cid):
        target = self.m_mapEntity.get(cid,None)
        if not target:
            return
        curwatcherset = target.getWatcherSet()
        for outcid in curwatcherset:
            entity = self.m_mapEntity.get(outcid,None)
            if not entity:
                continue
            entity.delMaker(outcid)
            print("notify{0} event:{1}leave".format(entity,target))
        
        curmakerset = target.getMakerSet()
        for outcid in curmakerset:
            entity = self.m_mapEntity.get(outcid,None)
            if not entity:
                continue
            entity.delWatcher(outcid)
            #删除watcher即可 不用notify
        
        self.delEntity(target)
        self.m_mapEntity.pop(cid,None)
        print("leave entity {0}".format(target))
        target = None


    #pentity周围 pentity可见的对象
    def getMakers(self,pentity):
        maker = {}
        if pentity == None:
            return maker
        cur = pentity.xnext
        while(cur != self.tail):
            if pentity.xsee(cur) and pentity.ysee(cur):
                maker[cur.cid] = cur
            else:
                if pentity.xsee(cur) == False:
                    break
            cur = cur.xnext
        
        cur = pentity.xpre
        while(cur != self.head):
            if pentity.xsee(cur) and pentity.ysee(cur):
                maker[cur.cid] = cur
            else:
                if pentity.xsee(cur) == False:
                    break
            cur = cur.xpre
        return maker

    #pentity周围 dstMax范围内 哪些对象可见pentity
    def getWatchers(self,pentity,dstMax):
        watcher = {}
        if pentity == None:
            return watcher
        cur = pentity.xnext
        while(cur != self.tail):
            if cur.xsee(pentity) and cur.ysee(pentity):
                watcher[cur.cid] = cur
            else:
                if cur.x - pentity.x > dstMax:
                    break
            cur = cur.xnext
        
        cur = pentity.xpre
        while(cur != self.head):
            if cur.xsee(pentity) and cur.ysee(pentity):
                watcher[cur.cid] = cur
            else:
                if pentity.x - cur.x > dstMax:
                    break
            cur = cur.xpre
        return watcher

    def updateEntityPosition(self,pentity,x,y):
        self.delEntity(pentity)
        pentity.x = x
        pentity.y = y
        self.addEntity(pentity)

    def dump(self):
        cur = self.head
        while(cur != None):
            print("xlist:",cur)
            cur = cur.xnext
        
        cur = self.head
        while(cur != None):
            print("ylist:",cur)
            cur = cur.ynext


def main():
    scene = CScene()
    import random
    for i in range(5):
        scene.add(i+ 1,random.randint(1,10),random.randint(1,10),random.randint(3,6))
    scene.dump()

    print("#####################################")
    for i in range(3):
        scene.move(random.randint(1,5),random.randint(1,10),random.randint(1,10))
        scene.dump()

if __name__ == '__main__':
    main()
    

 随机增加5个点(x,y,radius)

1:3-3-6

2:10-6-4

3:2-2-3

4:1-10-4

5:1-7-5

将节点4(1-10-4) 移动到  (4-8-8)

将节点4 (4-8-4) 移动到 (7-6-4)

将节点2 (10-6-4) 移动到 (9-10-4)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值