加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

在python中有孔的三角剖分

发布时间:2020-12-20 13:40:35 所属栏目:Python 来源:网络整理
导读:我试图对位图进行三角测量(为我的2D游戏制作关卡),我陷入困境.我正在使用Jonathan Shewchuk的Triangle库,使用 this wrapper. 我从图像开始, 然后我检测边缘并确定哪些顶点是孔.我选择每四分之一进行三角测量, 然后我把这些点通过了三角测量,但我最终得到了这
我试图对位图进行三角测量(为我的2D游戏制作关卡),我陷入困境.我正在使用Jonathan Shewchuk的Triangle库,使用 this wrapper.

我从图像开始,

然后我检测边缘并确定哪些顶点是孔.我选择每四分之一进行三角测量,

然后我把这些点通过了三角测量,但我最终得到了这样的东西

我的洞已经消失了.我究竟做错了什么?
另外,为什么我得到一些凸壳而不是三角形多边形?

到目前为止,这是我的代码:

#here i am loading all data,that i will use later on but i had to insert that,just in case
    mapfg = glob(path.join(pathtomapfolder,"Foreground.png"))[0] #Getting map foreground image
    mapob = glob(path.join(pathtomapfolder,"Obstacles.png"))[0] #Getting map file
    mappr = glob(path.join(pathtomapfolder,"Properties.txt"))[0] #Getting map info file
    self.mapprops = [mapob,mapfg,mappr]
    #getting ground and obstacles
    obsbitmap = Image.open(self.mapprops[0])
    lockBitmap = obsbitmap.load()
    compareClr = (0,0)
    for y in xrange(obsbitmap.size[1]):
        tmp = []
        for x in xrange(obsbitmap.size[0]):
            if lockBitmap[x,y][0] == compareClr[0] and lockBitmap[x,y][6] == compareClr[1] and lockBitmap[x,y][7] == compareClr[2]:
                tmp.append(1)
            else:
                tmp.append(0)
        self.obs.append(tmp)
    #detecting edges
    for y in xrange(len(self.obs)):      
        tmphit = []
        for x in xrange(len(self.obs[0])):
            if (self.obs[y][x] == 0 and (self.obs[MinMax.NoOver(y - 1,len(self.obs) - 1,0)][x] == 1 or self.obs[y][MinMax.NoOver(x - 1,len(self.obs[0]) - 1,0)] == 1 or self.obs[y][MinMax.NoOver(x + 1,0)] == 1 or self.obs[MinMax.NoOver(y + 1,0)][x] == 1)) or (self.obs[y][x] == 1 and (MinMax.WillOver(y - 1,0) or MinMax.WillOver(x - 1,0) or MinMax.WillOver(x + 1,0) or MinMax.WillOver(y + 1,0))):
                tmphit.append(True)
            else:
                tmphit.append(False)
        self.hit.append(tmphit)
    #here it starts,first of all i search for vertice,then go CW or CCW and get all vertices from edge of one polygon,i also detect,whether it is hole or not and to which polygon is related to.
    xcirc = ycirc = 0
    coords = []
    coordvalues = []
    parentid = []
    self.allverts = [coords,coordvalues,parentid]
    polyID = 0
    for y in xrange(len(self.obs)):
        for x in xrange(len(self.obs[0])):
            if self.hit[y][x] and not (x,y) in self.allverts[0]:
                left = []
                right = []
                up = []
                down = []
                numobjects = numholes = 0
                type = ""
                parentid = -1
                for v in xrange(len(self.allverts[0])):
                    if self.allverts[0][v][8] == y and self.allverts[0][v][0] < x: left.append(self.allverts[1][v])
                    if self.allverts[0][v][9] == y and self.allverts[0][v][0] > x: right.append(self.allverts[1][v])
                    if self.allverts[0][v][0] == x and self.allverts[0][v][10] < y: up.append(self.allverts[1][v])
                    if self.allverts[0][v][0] == x and self.allverts[0][v][11] > y: down.append(self.allverts[1][v])             
                for id in xrange(polyID):
                    if ("not hole",id) in left and ("not hole",id) in right and ("not hole",id) in up and ("not hole",id) in down:
                        numobjects += 1
                        parentid = id
                    elif ("hole",id) in left and ("hole",id) in right and ("hole",id) in up and ("hole",id) in down:
                        numholes += 1
                if numobjects == 0 or numobjects == numholes: type = "not hole"
                elif numobjects > numholes: type = "hole"
                found = False
                lastangle = -90
                self.allverts[0].append((x,y))
                self.allverts[1].append((type,polyID))
                self.allverts[2].append(parentid)
                v = 1
                while not found:
                    angle = MinMax.Overflow(lastangle - 45,180,-179)
                    lastangle = angle
                    xcirc = int(round(math.cos((math.pi / 180) * angle)))
                    ycirc = int(round(math.sin((math.pi / 180) * angle)))
                    if self.hit[MinMax.NoOver(self.allverts[0][-1][12] + ycirc,len(self.hit) - 1,0)][MinMax.NoOver(self.allverts[0][-1][0] + xcirc,len(self.hit[0]) - 1,0)] and (MinMax.WontOver(self.allverts[0][-1][13] + ycirc,0) and MinMax.WontOver(self.allverts[0][-1][0] + xcirc,0)):                    
                        if not (self.allverts[0][-1][0] + xcirc,self.allverts[0][-1][14] + ycirc) in self.allverts[0]:
                            self.allverts[0].append((self.allverts[0][-1][0] + xcirc,self.allverts[0][-1][15] + ycirc))
                            self.allverts[1].append((type,polyID))
                            self.allverts[2].append(parentid)
                            v += 1
                        else:
                            #self.allverts.append((self.allverts[-1][0] + xcirc,self.allverts[-1][16] + ycirc))
                            found = True
                            if v < 4:
                                polyID -= 1
                                for d in xrange(v):
                                    del self.allverts[0][-1]
                                    del self.allverts[1][-1]
                                    del self.allverts[2][-1]
                        lastangle = MinMax.Overflow(lastangle + 135,-179)
                polyID += 1
    # now i have to convert that data structure to something i can pass to triangulate function 
    objects = []
    objectpoints = []
    idtoindexobj = []
    holes = []
    holepoints = []
    holecoords = []
    holeleft = len(self.hit[0])
    holetop = len(self.hit)
    holeright = holebottom = 0
    idtoindexhole = []
    prevvert = (self.allverts[0][0],self.allverts[1][0],self.allverts[2][0])
    d = 0
    for u in xrange(len(self.allverts[0])):
        vert = (self.allverts[0][u],self.allverts[1][u],self.allverts[2][u])
        if vert[1][17] != prevvert[1][18]:
            d = 0
            if prevvert[1][0] == "not hole":
                objects.append(objectpoints)
                objectpoints = []
                idtoindexobj.append(prevvert[1][19])
            else:
                holes.append(holepoints)
                holepoints = []
                holecoords.append((holeleft + (MinMax.AminB(holeleft,holeright)/2),holetop + (MinMax.AminB(holetop,holebottom)/2)))
                idtoindexhole.append(prevvert[2])
                holeleft = len(self.hit[0])
                holetop = len(self.hit)
                holeright = holebottom = 0
        if vert[1][0] == "not hole":
            if d % 4 == 0:
                objectpoints.append((vert[0][0],vert[0][20]))
        else:
            if d % 4 == 0:
                holepoints.append((vert[0][0],vert[0][21]))
                if vert[0][0] < holeleft: holeleft = vert[0][0]
                if vert[0][0] > holeright: holeright = vert[0][0]
                if vert[0][22] < holetop: holetop = vert[0][23]
                if vert[0][24] > holebottom: holebottom = vert[0][25]
        d+=1
        prevvert = vert
    if prevvert[1][0] == "not hole":
        objects.append(objectpoints)
        objectpoints = []
        idtoindexobj.append(prevvert[1][26])
    else:
        holes.append(holepoints)
        holepoints = []
        holecoords.append((holeleft + (MinMax.AminB(holeleft,holebottom)/2)))
        idtoindexhole.append(prevvert[2])
        holeleft = len(self.hit[0])
        holetop = len(self.hit)
        holeright = holebottom = 0
        objectpoints.append((vert[0][0],vert[0][27]))
    self.polygons = []
    for ind,id in enumerate(idtoindexobj):
        holecoordlist = []
        segments = []
        for k,l in enumerate(idtoindexhole):
            if l == id:
                holecoordlist.append(holecoords[k])
                prevsegpart = False
                for segpart in holes[k]:
                    if not prevsegpart:
                        prevsegpart = segpart
                        continue
                    segments.append((prevsegpart[0],prevsegpart[1],segpart[0],segpart[1]))
                    prevsegpart = segpart
                segments.append((prevsegpart[0],holes[k][0][0],holes[k][0][1]))
        if segments:
            self.polygons.append({"vertices":objects[ind],"segments":segments,"holes":holecoordlist})
        else:
            self.polygons.append({"vertices":objects[ind]})
    indtripolylist = []
    for pol in self.polygons:
        #here i am calling that triangulate function
        indtripolylist.append(triangle.triangulate(pol,opts="q"))
    #and finally convert what has been returned to coordinates of triangles (because it returns list of vertices and touples of indexes pointing to vertices)
    self.tripolylist = []
    for po in indtripolylist:
        tmptriangles = []
        for tr in po["triangles"]:
            tmptriangles.append((po["vertices"][tr[0]],po["vertices"][tr[1]],po["vertices"][tr[2]]))
        self.tripolylist.append(tmptriangles)

谢谢您的帮助.

解决方法

这让我抓了一会儿,你的意见帮我搞定了.

查看您需要传递的数据示例:

triangle.get_data(‘face’)

??

要阻止多边形“填充”并保持凹面,你可以像这样传递段

segments = []
    for i in range(len(verts)-1):
        segments.append([int(i),int(i+1)])
    segments.append([int(i+1),int(0)])
    A = {'vertices':array(verts),'segments':array(segments)}

要添加一个洞,你需要分别标记顶点和段(警告:未经测试的代码)

vertmarks = []
    for i in range(len(verts)):
        vertmarks.append([2])
    for i in range(len(hole)):
        vertmarks.append([4])
    segmarks = []
    for i in range(len(segments)):
        segmarks.append([2])
    for i in range(len(holesegments)):
        segmarks.append([4])
    A = {'vertices':array(verts),'segments':array(segments),'segment_markers':array(segmarks),'vertex_markers':array(vertmarks)}

‘holes’也应该作为[x,y]位置列表传递 – 每个孔内有一个

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读