【发布时间】:2014-03-25 08:01:46
【问题描述】:
我正在尝试对位图进行三角测量(为我的 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, 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, len(self.obs[0]) - 1, 0)] == 1 or self.obs[MinMax.NoOver(y + 1, len(self.obs) - 1, 0)][x] == 1)) or (self.obs[y][x] == 1 and (MinMax.WillOver(y - 1, len(self.obs) - 1, 0) or MinMax.WillOver(x - 1, len(self.obs[0]) - 1, 0) or MinMax.WillOver(x + 1, len(self.obs[0]) - 1, 0) or MinMax.WillOver(y + 1, len(self.obs) - 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, len(self.hit) - 1, 0) and MinMax.WontOver(self.allverts[0][-1][0] + xcirc, len(self.hit[0]) - 1, 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, 180, -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, holeright)/2), holetop + (MinMax.AminB(holetop, 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], prevsegpart[1], 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)
感谢您的帮助。
【问题讨论】:
-
我现在有点明白了,我需要用线段包围整个多边形,用顶点包围整个多边形,但我仍然无法让它工作
-
这里是我做错了什么: 1. 段是两个索引指向顶点的 touples 2. 顶点中的所有点(根据图像:不仅仅是红色的) 3. 在第二个参数三角测量函数需要是字母“p”。感谢您的帮助,这是我在这里的第二个问题-第一个问题已关闭,第二个问题尚未回答,我正在寻找第三个问题,我确定您不是:D
-
如果你解决了这个问题。很高兴知道如何。我试图以任何身份找出这个库。我提供了片段。它从未出错,但输出是相同的。此包装器的零文档。
-
这里是一些文档,我通过运行第二个示例来解决这个问题,并将变量打印传递给三角测量。由于我大约 4 个月没有接触那个项目,而且我的英语不太好,我不知道我能否为您提供一个很好的解释。 dzhelil.info/triangle/delaunay.html如果你真的需要我试试,我会的,就写吧:)
标签: python bitmap 2d triangulation